@@ -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
@@ -398,6 +401,8 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
398
401
// storageclaim is clusterscoped resources using its
399
402
// hash as the clusterID
400
403
data ["clusterID" ] = r .storageClaimHash
404
+ data ["ramendr.openshift.io/storageID" ] = r .storageClaimHash
405
+ data ["ramendr.openshift.io/replicationID" ] = r .storageClaimHash
401
406
if resource .Name == "cephfs" {
402
407
volumeSnapshotClass = r .getCephFSVolumeSnapshotClass (data )
403
408
} else if resource .Name == "ceph-rbd" {
@@ -407,6 +412,24 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
407
412
if err := r .createOrReplaceVolumeSnapshotClass (volumeSnapshotClass ); err != nil {
408
413
return reconcile.Result {}, fmt .Errorf ("failed to create or update VolumeSnapshotClass: %s" , err )
409
414
}
415
+ case "VolumeGroupSnapshotClass" :
416
+ var volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass
417
+ data ["csi.storage.k8s.io/snapshotter-secret-namespace" ] = r .OperatorNamespace
418
+ // generate a new clusterID for cephfs subvolumegroup, as
419
+ // storageclaim is clusterscoped resources using its
420
+ // hash as the clusterID
421
+ data ["clusterID" ] = r .storageClaimHash
422
+ data ["ramendr.openshift.io/storageID" ] = r .storageClaimHash
423
+ data ["ramendr.openshift.io/replicationID" ] = r .storageClaimHash
424
+ if resource .Name == "cephfs" {
425
+ volumeGroupSnapshotClass = r .getCephFSVolumeGroupSnapshotClass (data )
426
+ } else if resource .Name == "ceph-rbd" {
427
+ volumeGroupSnapshotClass = r .getCephRBDVolumeGroupSnapshotClass (data )
428
+ }
429
+ utils .AddAnnotation (volumeGroupSnapshotClass , storageClaimAnnotation , r .storageClaim .Name )
430
+ if err := r .createOrReplaceVolumeGroupSnapshotClass (volumeGroupSnapshotClass ); err != nil {
431
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update volumeGroupSnapshot: %s" , err )
432
+ }
410
433
}
411
434
}
412
435
@@ -651,6 +674,66 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
651
674
return false , nil
652
675
}
653
676
677
+ func (r * StorageClaimReconciler ) getCephFSVolumeGroupSnapshotClass (data map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
678
+ volumgroupesnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
679
+ ObjectMeta : metav1.ObjectMeta {
680
+ Name : r .storageClaim .Name ,
681
+ },
682
+ Driver : csi .GetCephFSDriverName (),
683
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
684
+ Parameters : data ,
685
+ }
686
+ return volumgroupesnapshotclass
687
+ }
688
+
689
+ func (r * StorageClaimReconciler ) getCephRBDVolumeGroupSnapshotClass (data map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
690
+ volumegroupsnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
691
+ ObjectMeta : metav1.ObjectMeta {
692
+ Name : r .storageClaim .Name ,
693
+ },
694
+ Driver : csi .GetRBDDriverName (),
695
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
696
+ Parameters : data ,
697
+ }
698
+ return volumegroupsnapshotclass
699
+ }
700
+
701
+ func (r * StorageClaimReconciler ) createOrReplaceVolumeGroupSnapshotClass (volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass ) error {
702
+ existing := & groupsnapapi.VolumeGroupSnapshotClass {}
703
+ existing .Name = r .storageClaim .Name
704
+
705
+ if err := r .own (volumeGroupSnapshotClass ); err != nil {
706
+ return fmt .Errorf ("failed to own volumegroupsnapshotclass: %v" , err )
707
+ }
708
+
709
+ if err := r .get (existing ); err != nil && ! errors .IsNotFound (err ) {
710
+ return fmt .Errorf ("failed to get VolumeGroupSnapshotClass: %v" , err )
711
+ }
712
+
713
+ // If present then compare the existing VolumeGroupSnapshotClass parameters with
714
+ // the received VolumeGroupSnapshotClass parameters, and only proceed if they differ.
715
+ if reflect .DeepEqual (existing .Parameters , volumeGroupSnapshotClass .Parameters ) {
716
+ return nil
717
+ }
718
+
719
+ // VolumeGroupSnapshotClass already exists, but parameters have changed. Delete the existing VolumeGroupSnapshotClass and create a new one.
720
+ if existing .UID != "" {
721
+ // Since we have to update the existing VolumeGroupSnapshotClass, so we will delete the existing VolumeGroupSnapshotClass and create a new one.
722
+ r .log .Info ("VolumeGroupSnapshotClass needs to be updated, deleting it." , "Name" , existing .Name )
723
+
724
+ // Delete the VolumeGroupSnapshotClass.
725
+ if err := r .delete (existing ); err != nil {
726
+ r .log .Error (err , "Failed to delete VolumeGroupSnapshotClass." , "Name" , existing .Name )
727
+ return fmt .Errorf ("failed to delete VolumeGroupSnapshotClass: %v" , err )
728
+ }
729
+ }
730
+ r .log .Info ("Creating VolumeGroupSnapshotClass." , "Name" , existing .Name )
731
+ if err := r .Client .Create (r .ctx , volumeGroupSnapshotClass ); err != nil {
732
+ return fmt .Errorf ("failed to create VolumeGroupSnapshotClass: %v" , err )
733
+ }
734
+ return nil
735
+ }
736
+
654
737
func getMD5Hash (text string ) string {
655
738
hash := md5 .Sum ([]byte (text ))
656
739
return hex .EncodeToString (hash [:])
0 commit comments