@@ -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
@@ -327,11 +330,14 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
327
330
// Go over the received objects and operate on them accordingly.
328
331
for _ , resource := range resources {
329
332
data := map [string ]string {}
333
+ labels := map [string ]string {}
330
334
err = json .Unmarshal (resource .Data , & data )
331
335
if err != nil {
332
336
return reconcile.Result {}, fmt .Errorf ("failed to unmarshal StorageClaim configuration response: %v" , err )
333
337
}
334
338
339
+ // SID for RamenDR
340
+ storageID := getMD5Hash (string (r .storageClaim .UID )) + r .storageClaimHash
335
341
// Create the received resources, if necessary.
336
342
switch resource .Kind {
337
343
case "Secret" :
@@ -398,15 +404,35 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
398
404
// storageclaim is clusterscoped resources using its
399
405
// hash as the clusterID
400
406
data ["clusterID" ] = r .storageClaimHash
407
+ labels ["ramendr.openshift.io/replicationID" ] = r .storageClaimHash
408
+ labels ["ramendr.openshift.io/storageID" ] = storageID
401
409
if resource .Name == "cephfs" {
402
- volumeSnapshotClass = r .getCephFSVolumeSnapshotClass (data )
410
+ volumeSnapshotClass = r .getCephFSVolumeSnapshotClass (data , labels )
403
411
} else if resource .Name == "ceph-rbd" {
404
- volumeSnapshotClass = r .getCephRBDVolumeSnapshotClass (data )
412
+ volumeSnapshotClass = r .getCephRBDVolumeSnapshotClass (data , labels )
405
413
}
406
414
utils .AddAnnotation (volumeSnapshotClass , storageClaimAnnotation , r .storageClaim .Name )
407
415
if err := r .createOrReplaceVolumeSnapshotClass (volumeSnapshotClass ); err != nil {
408
416
return reconcile.Result {}, fmt .Errorf ("failed to create or update VolumeSnapshotClass: %s" , err )
409
417
}
418
+ case "VolumeGroupSnapshotClass" :
419
+ var volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass
420
+ data ["csi.storage.k8s.io/snapshotter-secret-namespace" ] = r .OperatorNamespace
421
+ // generate a new clusterID for cephfs subvolumegroup, as
422
+ // storageclaim is clusterscoped resources using its
423
+ // hash as the clusterID
424
+ data ["clusterID" ] = r .storageClaimHash
425
+ labels ["ramendr.openshift.io/replicationID" ] = r .storageClaimHash
426
+ labels ["ramendr.openshift.io/storageID" ] = storageID
427
+ if resource .Name == "cephfs" {
428
+ volumeGroupSnapshotClass = r .getCephFSVolumeGroupSnapshotClass (data , labels )
429
+ } else if resource .Name == "ceph-rbd" {
430
+ volumeGroupSnapshotClass = r .getCephRBDVolumeGroupSnapshotClass (data , labels )
431
+ }
432
+ utils .AddAnnotation (volumeGroupSnapshotClass , storageClaimAnnotation , r .storageClaim .Name )
433
+ if err := r .createOrReplaceVolumeGroupSnapshotClass (volumeGroupSnapshotClass ); err != nil {
434
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update volumeGroupSnapshot: %s" , err )
435
+ }
410
436
}
411
437
}
412
438
@@ -501,10 +527,11 @@ func (r *StorageClaimReconciler) getCephRBDStorageClass(data map[string]string)
501
527
return storageClass
502
528
}
503
529
504
- func (r * StorageClaimReconciler ) getCephFSVolumeSnapshotClass (data map [string ]string ) * snapapi.VolumeSnapshotClass {
530
+ func (r * StorageClaimReconciler ) getCephFSVolumeSnapshotClass (data map [string ]string , labels map [ string ] string ) * snapapi.VolumeSnapshotClass {
505
531
volumesnapshotclass := & snapapi.VolumeSnapshotClass {
506
532
ObjectMeta : metav1.ObjectMeta {
507
- Name : r .storageClaim .Name ,
533
+ Name : r .storageClaim .Name ,
534
+ Labels : labels ,
508
535
},
509
536
Driver : csi .GetCephFSDriverName (),
510
537
DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
@@ -513,10 +540,11 @@ func (r *StorageClaimReconciler) getCephFSVolumeSnapshotClass(data map[string]st
513
540
return volumesnapshotclass
514
541
}
515
542
516
- func (r * StorageClaimReconciler ) getCephRBDVolumeSnapshotClass (data map [string ]string ) * snapapi.VolumeSnapshotClass {
543
+ func (r * StorageClaimReconciler ) getCephRBDVolumeSnapshotClass (data map [string ]string , labels map [ string ] string ) * snapapi.VolumeSnapshotClass {
517
544
volumesnapshotclass := & snapapi.VolumeSnapshotClass {
518
545
ObjectMeta : metav1.ObjectMeta {
519
- Name : r .storageClaim .Name ,
546
+ Name : r .storageClaim .Name ,
547
+ Labels : labels ,
520
548
},
521
549
Driver : csi .GetRBDDriverName (),
522
550
DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
@@ -651,6 +679,68 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
651
679
return false , nil
652
680
}
653
681
682
+ func (r * StorageClaimReconciler ) getCephFSVolumeGroupSnapshotClass (data map [string ]string , labels map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
683
+ volumgroupesnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
684
+ ObjectMeta : metav1.ObjectMeta {
685
+ Name : r .storageClaim .Name ,
686
+ Labels : labels ,
687
+ },
688
+ Driver : csi .GetCephFSDriverName (),
689
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
690
+ Parameters : data ,
691
+ }
692
+ return volumgroupesnapshotclass
693
+ }
694
+
695
+ func (r * StorageClaimReconciler ) getCephRBDVolumeGroupSnapshotClass (data map [string ]string , labels map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
696
+ volumegroupsnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
697
+ ObjectMeta : metav1.ObjectMeta {
698
+ Name : r .storageClaim .Name ,
699
+ Labels : labels ,
700
+ },
701
+ Driver : csi .GetRBDDriverName (),
702
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
703
+ Parameters : data ,
704
+ }
705
+ return volumegroupsnapshotclass
706
+ }
707
+
708
+ func (r * StorageClaimReconciler ) createOrReplaceVolumeGroupSnapshotClass (volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass ) error {
709
+ existing := & groupsnapapi.VolumeGroupSnapshotClass {}
710
+ existing .Name = r .storageClaim .Name
711
+
712
+ if err := r .own (volumeGroupSnapshotClass ); err != nil {
713
+ return fmt .Errorf ("failed to own volumegroupsnapshotclass: %v" , err )
714
+ }
715
+
716
+ if err := r .get (existing ); err != nil && ! errors .IsNotFound (err ) {
717
+ return fmt .Errorf ("failed to get VolumeGroupSnapshotClass: %v" , err )
718
+ }
719
+
720
+ // If present then compare the existing VolumeGroupSnapshotClass parameters with
721
+ // the received VolumeGroupSnapshotClass parameters, and only proceed if they differ.
722
+ if reflect .DeepEqual (existing .Parameters , volumeGroupSnapshotClass .Parameters ) {
723
+ return nil
724
+ }
725
+
726
+ // VolumeGroupSnapshotClass already exists, but parameters have changed. Delete the existing VolumeGroupSnapshotClass and create a new one.
727
+ if existing .UID != "" {
728
+ // Since we have to update the existing VolumeGroupSnapshotClass, so we will delete the existing VolumeGroupSnapshotClass and create a new one.
729
+ r .log .Info ("VolumeGroupSnapshotClass needs to be updated, deleting it." , "Name" , existing .Name )
730
+
731
+ // Delete the VolumeGroupSnapshotClass.
732
+ if err := r .delete (existing ); err != nil {
733
+ r .log .Error (err , "Failed to delete VolumeGroupSnapshotClass." , "Name" , existing .Name )
734
+ return fmt .Errorf ("failed to delete VolumeGroupSnapshotClass: %v" , err )
735
+ }
736
+ }
737
+ r .log .Info ("Creating VolumeGroupSnapshotClass." , "Name" , existing .Name )
738
+ if err := r .Client .Create (r .ctx , volumeGroupSnapshotClass ); err != nil {
739
+ return fmt .Errorf ("failed to create VolumeGroupSnapshotClass: %v" , err )
740
+ }
741
+ return nil
742
+ }
743
+
654
744
func getMD5Hash (text string ) string {
655
745
hash := md5 .Sum ([]byte (text ))
656
746
return hex .EncodeToString (hash [:])
0 commit comments