@@ -32,6 +32,7 @@ import (
32
32
"github.com/red-hat-storage/ocs-client-operator/pkg/utils"
33
33
34
34
"github.com/go-logr/logr"
35
+ groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumegroupsnapshot/v1alpha1"
35
36
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
36
37
providerclient "github.com/red-hat-storage/ocs-operator/v4/services/provider/client"
37
38
corev1 "k8s.io/api/core/v1"
@@ -110,6 +111,7 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
110
111
For (& v1alpha1.StorageClaim {}, builder .WithPredicates (predicate.GenerationChangedPredicate {})).
111
112
Owns (& storagev1.StorageClass {}).
112
113
Owns (& snapapi.VolumeSnapshotClass {}).
114
+ Owns (& groupsnapapi.VolumeGroupSnapshotClass {}).
113
115
Complete (r )
114
116
}
115
117
@@ -119,6 +121,7 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
119
121
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete
120
122
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch;create;update;patch;delete
121
123
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotclasses,verbs=get;list;watch;create;delete
124
+ //+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotclasses,verbs=get;list;watch;create;delete
122
125
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
123
126
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotcontents,verbs=get;list;watch
124
127
@@ -407,6 +410,22 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
407
410
if err := r .createOrReplaceVolumeSnapshotClass (volumeSnapshotClass ); err != nil {
408
411
return reconcile.Result {}, fmt .Errorf ("failed to create or update VolumeSnapshotClass: %s" , err )
409
412
}
413
+ case "VolumeGroupSnapshotClass" :
414
+ var volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass
415
+ data ["csi.storage.k8s.io/snapshotter-secret-namespace" ] = r .OperatorNamespace
416
+ // generate a new clusterID for cephfs subvolumegroup, as
417
+ // storageclaim is clusterscoped resources using its
418
+ // hash as the clusterID
419
+ data ["clusterID" ] = r .storageClaimHash
420
+ if resource .Name == "cephfs" {
421
+ volumeGroupSnapshotClass = r .getCephFSVolumeGroupSnapshotClass (data )
422
+ } else if resource .Name == "ceph-rbd" {
423
+ volumeGroupSnapshotClass = r .getCephRBDVolumeGroupSnapshotClass (data )
424
+ }
425
+ utils .AddAnnotation (volumeGroupSnapshotClass , storageClaimAnnotation , r .storageClaim .Name )
426
+ if err := r .createOrReplaceVolumeGroupSnapshotClass (volumeGroupSnapshotClass ); err != nil {
427
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update volumeGroupSnapshot: %s" , err )
428
+ }
410
429
}
411
430
}
412
431
@@ -651,6 +670,66 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
651
670
return false , nil
652
671
}
653
672
673
+ func (r * StorageClaimReconciler ) getCephFSVolumeGroupSnapshotClass (data map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
674
+ volumgroupesnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
675
+ ObjectMeta : metav1.ObjectMeta {
676
+ Name : r .storageClaim .Name ,
677
+ },
678
+ Driver : csi .GetCephFSDriverName (),
679
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
680
+ Parameters : data ,
681
+ }
682
+ return volumgroupesnapshotclass
683
+ }
684
+
685
+ func (r * StorageClaimReconciler ) getCephRBDVolumeGroupSnapshotClass (data map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
686
+ volumegroupsnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
687
+ ObjectMeta : metav1.ObjectMeta {
688
+ Name : r .storageClaim .Name ,
689
+ },
690
+ Driver : csi .GetRBDDriverName (),
691
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
692
+ Parameters : data ,
693
+ }
694
+ return volumegroupsnapshotclass
695
+ }
696
+
697
+ func (r * StorageClaimReconciler ) createOrReplaceVolumeGroupSnapshotClass (volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass ) error {
698
+ existing := & groupsnapapi.VolumeGroupSnapshotClass {}
699
+ existing .Name = r .storageClaim .Name
700
+
701
+ if err := r .own (volumeGroupSnapshotClass ); err != nil {
702
+ return fmt .Errorf ("failed to own volumegroupsnapshotclass: %v" , err )
703
+ }
704
+
705
+ if err := r .get (existing ); err != nil && ! errors .IsNotFound (err ) {
706
+ return fmt .Errorf ("failed to get VolumeGroupSnapshotClass: %v" , err )
707
+ }
708
+
709
+ // If present then compare the existing VolumeGroupSnapshotClass parameters with
710
+ // the received VolumeGroupSnapshotClass parameters, and only proceed if they differ.
711
+ if reflect .DeepEqual (existing .Parameters , volumeGroupSnapshotClass .Parameters ) {
712
+ return nil
713
+ }
714
+
715
+ // VolumeGroupSnapshotClass already exists, but parameters have changed. Delete the existing VolumeGroupSnapshotClass and create a new one.
716
+ if existing .UID != "" {
717
+ // Since we have to update the existing VolumeGroupSnapshotClass, so we will delete the existing VolumeGroupSnapshotClass and create a new one.
718
+ r .log .Info ("VolumeGroupSnapshotClass needs to be updated, deleting it." , "Name" , existing .Name )
719
+
720
+ // Delete the VolumeGroupSnapshotClass.
721
+ if err := r .delete (existing ); err != nil {
722
+ r .log .Error (err , "Failed to delete VolumeGroupSnapshotClass." , "Name" , existing .Name )
723
+ return fmt .Errorf ("failed to delete VolumeGroupSnapshotClass: %v" , err )
724
+ }
725
+ }
726
+ r .log .Info ("Creating VolumeGroupSnapshotClass." , "Name" , existing .Name )
727
+ if err := r .Client .Create (r .ctx , volumeGroupSnapshotClass ); err != nil {
728
+ return fmt .Errorf ("failed to create VolumeGroupSnapshotClass: %v" , err )
729
+ }
730
+ return nil
731
+ }
732
+
654
733
func getMD5Hash (text string ) string {
655
734
hash := md5 .Sum ([]byte (text ))
656
735
return hex .EncodeToString (hash [:])
0 commit comments