Skip to content

Commit c0e647a

Browse files
committed
Set new fields in VolumeGroupSnapshotContent objects
This patch improves the sidecar to set the fields introduced by the VolumeGroupSnapshotContent v1beta2 API when dynamically provisioning a VolumeGroupSnapshot. This information is then used by the common snapshot controller to set the status of the member VolumeSnapshotContent objects, allowing the relative fields to be set even when the CSI driver does not implement the ListSnapshots RPC call.
1 parent faf832b commit c0e647a

File tree

4 files changed

+124
-20
lines changed

4 files changed

+124
-20
lines changed

pkg/common-controller/groupsnapshot_controller_helper.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,9 @@ func (ctrl *csiSnapshotCommonController) createSnapshotsForGroupSnapshotContent(
580580
VolumeHandle: &volumeHandle,
581581
},
582582
},
583-
// The status will be set by VolumeSnapshotContent reconciler
584-
// in the CSI snapshotter sidecar.
583+
// The status will be set in a separate patch request by
584+
// common snapshot controller, using the information from
585+
// the VolumeGroupSnapshotContent object.
585586
}
586587

587588
if pv != nil {
@@ -682,6 +683,21 @@ func (ctrl *csiSnapshotCommonController) createSnapshotsForGroupSnapshotContent(
682683
Path: "/status/volumeGroupSnapshotHandle",
683684
Value: groupSnapshotContent.Status.VolumeGroupSnapshotHandle,
684685
},
686+
{
687+
Op: "replace",
688+
Path: "/status/creationTime",
689+
Value: snapshot.CreationTime,
690+
},
691+
{
692+
Op: "replace",
693+
Path: "/status/restoreSize",
694+
Value: snapshot.RestoreSize,
695+
},
696+
{
697+
Op: "replace",
698+
Path: "/status/readyToUse",
699+
Value: snapshot.ReadyToUse,
700+
},
685701
}, ctrl.clientset, "status")
686702
if err != nil {
687703
return groupSnapshotContent, fmt.Errorf(

pkg/sidecar-controller/groupsnapshot_helper.go

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"k8s.io/client-go/tools/cache"
3131
klog "k8s.io/klog/v2"
3232

33+
"github.com/container-storage-interface/spec/lib/go/csi"
3334
crdv1beta2 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1beta2"
3435
crdv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
3536
"github.com/kubernetes-csi/external-snapshotter/v8/pkg/utils"
@@ -439,15 +440,13 @@ func (ctrl *csiSnapshotSideCarController) createGroupSnapshotWrapper(groupSnapsh
439440
}
440441

441442
// Create individual snapshots and snapshot contents
442-
var snapshotContentLinks []snapshotContentNameVolumeHandlePair
443-
for _, snapshot := range snapshots {
444-
snapshotContentLinks = append(snapshotContentLinks, snapshotContentNameVolumeHandlePair{
445-
snapshotHandle: snapshot.SnapshotId,
446-
volumeHandle: snapshot.SourceVolumeId,
447-
})
448-
}
449-
450-
newGroupSnapshotContent, err := ctrl.updateGroupSnapshotContentStatus(groupSnapshotContent, groupSnapshotID, readyToUse, metav1.NewTime(creationTime), snapshotContentLinks)
443+
newGroupSnapshotContent, err := ctrl.updateGroupSnapshotContentStatus(
444+
groupSnapshotContent,
445+
groupSnapshotID,
446+
readyToUse,
447+
metav1.NewTime(creationTime),
448+
snapshots,
449+
)
451450
if err != nil {
452451
klog.Errorf("error updating status for volume group snapshot content %s: %v.", groupSnapshotContent.Name, err)
453452
return groupSnapshotContent, fmt.Errorf("error updating status for volume group snapshot content %s: %v", groupSnapshotContent.Name, err)
@@ -583,7 +582,7 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus(
583582
groupSnapshotHandle string,
584583
readyToUse bool,
585584
createdAt metav1.Time,
586-
snapshotContentLinks []snapshotContentNameVolumeHandlePair,
585+
snapshotList []*csi.Snapshot,
587586
) (*crdv1beta2.VolumeGroupSnapshotContent, error) {
588587
klog.V(5).Infof("updateGroupSnapshotContentStatus: updating VolumeGroupSnapshotContent [%s], groupSnapshotHandle %s, readyToUse %v, createdAt %v", groupSnapshotContent.Name, groupSnapshotHandle, readyToUse, createdAt)
589588

@@ -600,11 +599,13 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus(
600599
ReadyToUse: &readyToUse,
601600
CreationTime: &createdAt,
602601
}
603-
for _, snapshotContentLink := range snapshotContentLinks {
604-
602+
for _, snapshot := range snapshotList {
605603
newStatus.VolumeSnapshotInfoList = append(newStatus.VolumeSnapshotInfoList, crdv1beta2.VolumeSnapshotInfo{
606-
VolumeHandle: snapshotContentLink.volumeHandle,
607-
SnapshotHandle: snapshotContentLink.snapshotHandle,
604+
VolumeHandle: snapshot.SourceVolumeId,
605+
SnapshotHandle: snapshot.SnapshotId,
606+
CreationTime: utils.CsiTimestampToKubernetes(snapshot.CreationTime),
607+
ReadyToUse: &snapshot.ReadyToUse,
608+
RestoreSize: utils.CsiSizeToKubernetes(snapshot.SizeBytes),
608609
})
609610
}
610611

@@ -627,10 +628,13 @@ func (ctrl *csiSnapshotSideCarController) updateGroupSnapshotContentStatus(
627628
updated = true
628629
}
629630
if len(newStatus.VolumeSnapshotInfoList) == 0 {
630-
for _, snapshotContentLink := range snapshotContentLinks {
631+
for _, snapshot := range snapshotList {
631632
newStatus.VolumeSnapshotInfoList = append(newStatus.VolumeSnapshotInfoList, crdv1beta2.VolumeSnapshotInfo{
632-
VolumeHandle: snapshotContentLink.volumeHandle,
633-
SnapshotHandle: snapshotContentLink.snapshotHandle,
633+
VolumeHandle: snapshot.SourceVolumeId,
634+
SnapshotHandle: snapshot.SnapshotId,
635+
CreationTime: utils.CsiTimestampToKubernetes(snapshot.CreationTime),
636+
ReadyToUse: &snapshot.ReadyToUse,
637+
RestoreSize: utils.CsiSizeToKubernetes(snapshot.SizeBytes),
634638
})
635639
}
636640
updated = true
@@ -793,7 +797,7 @@ func (ctrl *csiSnapshotSideCarController) checkandUpdateGroupSnapshotContentStat
793797
}
794798

795799
// TODO: Get a reference to snapshot contents for this volume group snapshot
796-
updatedContent, err := ctrl.updateGroupSnapshotContentStatus(groupSnapshotContent, groupSnapshotID, readyToUse, metav1.NewTime(creationTime), []snapshotContentNameVolumeHandlePair{})
800+
updatedContent, err := ctrl.updateGroupSnapshotContentStatus(groupSnapshotContent, groupSnapshotID, readyToUse, metav1.NewTime(creationTime), []*csi.Snapshot{})
797801
if err != nil {
798802
return groupSnapshotContent, err
799803
}

pkg/utils/conversion.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package utils
18+
19+
import "google.golang.org/protobuf/types/known/timestamppb"
20+
21+
// CsiTimestampToKubernetes converts a CSI timestamp in the format
22+
// used by the Snapshot API
23+
func CsiTimestampToKubernetes(creationTime *timestamppb.Timestamp) *int64 {
24+
if creationTime == nil {
25+
return nil
26+
}
27+
28+
result := creationTime.AsTime().UnixNano()
29+
return &result
30+
}
31+
32+
// CsiSizeToKubernetes converts the size to the format used by
33+
// the Snapshot API
34+
func CsiSizeToKubernetes(sizeBytes int64) *int64 {
35+
if sizeBytes == 0 {
36+
return nil
37+
}
38+
39+
return &sizeBytes
40+
}

pkg/utils/conversion_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package utils
18+
19+
import (
20+
"testing"
21+
22+
"google.golang.org/protobuf/types/known/timestamppb"
23+
)
24+
25+
func TestCsiSizeToKubernetes(t *testing.T) {
26+
if CsiSizeToKubernetes(0) != nil {
27+
t.Error("Expected nil")
28+
}
29+
30+
if *CsiSizeToKubernetes(123) != 123 {
31+
t.Error("Wrong size conversion")
32+
}
33+
}
34+
35+
func TestCsiTimestampToKubernetes(t *testing.T) {
36+
if CsiTimestampToKubernetes(nil) != nil {
37+
t.Error("Expected nil")
38+
}
39+
40+
now := timestamppb.Now()
41+
if *CsiTimestampToKubernetes(now) != now.AsTime().UnixNano() {
42+
t.Error("Expected correct time conversion")
43+
}
44+
}

0 commit comments

Comments
 (0)