@@ -31,6 +31,7 @@ import (
31
31
csiopv1a1 "github.com/ceph/ceph-csi-operator/api/v1alpha1"
32
32
"github.com/go-logr/logr"
33
33
34
+ groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1"
34
35
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
35
36
ramenv1alpha1 "github.com/ramendr/ramen/api/v1alpha1"
36
37
providerclient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
@@ -56,9 +57,10 @@ const (
56
57
storageClaimAnnotation = "ocs.openshift.io/storageclaim"
57
58
keyRotationAnnotation = "keyrotation.csiaddons.openshift.io/schedule"
58
59
59
- pvClusterIDIndexName = "index:persistentVolumeClusterID"
60
- vscClusterIDIndexName = "index:volumeSnapshotContentCSIDriver"
61
- drClusterConfigCRDName = "drclusterconfigs.ramendr.openshift.io"
60
+ pvClusterIDIndexName = "index:persistentVolumeClusterID"
61
+ vscClusterIDIndexName = "index:volumeSnapshotContentCSIDriver"
62
+ volumeGroupSnapshotClassCrd = "groupsnapshot.storage.k8s.io/volumegroupsnapshotclass"
63
+ drClusterConfigCRDName = "drclusterconfigs.ramendr.openshift.io"
62
64
)
63
65
64
66
// StorageClaimReconciler reconciles a StorageClaim object
@@ -120,11 +122,16 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
120
122
& extv1.CustomResourceDefinition {},
121
123
& handler.EnqueueRequestForObject {},
122
124
builder .WithPredicates (
125
+ utils .NamePredicate (volumeGroupSnapshotClassCrd ),
126
+ utils .CrdCreateAndDeletePredicate (& r .log , volumeGroupSnapshotClassCrd , r .AvailableCrds [volumeGroupSnapshotClassCrd ]),
123
127
utils .NamePredicate (drClusterConfigCRDName ),
124
128
utils .CrdCreateAndDeletePredicate (& r .log , drClusterConfigCRDName , r .AvailableCrds [drClusterConfigCRDName ]),
125
129
),
126
130
builder .OnlyMetadata ,
127
131
)
132
+ if r .AvailableCrds [volumeGroupSnapshotClassCrd ] {
133
+ bldr = bldr .Owns (& groupsnapapi.VolumeGroupSnapshotClass {})
134
+ }
128
135
129
136
if r .AvailableCrds [drClusterConfigCRDName ] {
130
137
bldr = bldr .Owns (& ramenv1alpha1.DRClusterConfig {}, builder .WithPredicates (generationChangePredicate ))
@@ -139,8 +146,10 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
139
146
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete
140
147
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch;create;update;patch;delete
141
148
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotclasses,verbs=get;list;watch;create;delete
149
+ //+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotclasses,verbs=create;delete;get;list;watch
142
150
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
143
151
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotcontents,verbs=get;list;watch
152
+ //+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotcontents,verbs=get;list;watch
144
153
//+kubebuilder:rbac:groups=csi.ceph.io,resources=clientprofiles,verbs=get;list;update;create;watch;delete
145
154
//+kubebuilder:rbac:groups=ramendr.openshift.io,resources=drclusterconfigs,verbs=get;list;update;create;watch;delete
146
155
@@ -160,13 +169,15 @@ func (r *StorageClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
160
169
r .log .Info ("Reconciling StorageClaim." )
161
170
162
171
crd := & metav1.PartialObjectMetadata {}
163
- crd .SetGroupVersionKind (extv1 .SchemeGroupVersion .WithKind ("CustomResourceDefinition" ))
164
- crd .Name = drClusterConfigCRDName
165
- if err := r .Client .Get (ctx , client .ObjectKeyFromObject (crd ), crd ); client .IgnoreNotFound (err ) != nil {
166
- r .log .Error (err , "Failed to get CRD" , "CRD" , drClusterConfigCRDName )
167
- return reconcile.Result {}, err
172
+ for _ , crdName := range []string {volumeGroupSnapshotClassCrd , drClusterConfigCRDName } {
173
+ crd .SetGroupVersionKind (extv1 .SchemeGroupVersion .WithKind ("CustomResourceDefinition" ))
174
+ crd .Name = crdName
175
+ if err := r .Client .Get (ctx , client .ObjectKeyFromObject (crd ), crd ); client .IgnoreNotFound (err ) != nil {
176
+ r .log .Error (err , "Failed to get CRD" , "CRD" , crdName )
177
+ return reconcile.Result {}, err
178
+ }
179
+ utils .AssertEqual (r .AvailableCrds [crdName ], crd .UID != "" , utils .ExitCodeThatShouldRestartTheProcess )
168
180
}
169
- utils .AssertEqual (r .AvailableCrds [drClusterConfigCRDName ], crd .UID != "" , utils .ExitCodeThatShouldRestartTheProcess )
170
181
171
182
// Fetch the StorageClaim instance
172
183
r .storageClaim = & v1alpha1.StorageClaim {}
@@ -422,7 +433,31 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
422
433
return nil
423
434
})
424
435
if err != nil {
425
- return reconcile.Result {}, fmt .Errorf ("failed to create or update VolumeSnapshotClass: %s" , err )
436
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update StorageClass: %s" , err )
437
+ }
438
+ case "VolumeGroupSnapshotClass" :
439
+ // check for CRD availability
440
+ if r .AvailableCrds [("VolumeGroupSnapshotClass" )] {
441
+ var volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass
442
+ data := map [string ]string {}
443
+ err = json .Unmarshal (resource .Data , & data )
444
+ if err != nil {
445
+ return reconcile.Result {}, fmt .Errorf ("failed to unmarshal StorageClaim configuration response: %v" , err )
446
+ }
447
+ data ["csi.storage.k8s.io/group-snapshotter-secret-namespace" ] = r .OperatorNamespace
448
+ // generate a new clusterID for cephfs subvolumegroup, as
449
+ // storageclaim is clusterscoped resources using its
450
+ // hash as the clusterID
451
+ data ["clusterID" ] = r .storageClaimHash
452
+ volumeGroupSnapshotClass = r .getCephDriverVolumeGroupSnapshotClass (resource .Labels , resource .Annotations )
453
+ utils .AddAnnotation (volumeGroupSnapshotClass , storageClaimAnnotation , r .storageClaim .Name )
454
+ err = utils .CreateOrReplace (r .ctx , r .Client , volumeGroupSnapshotClass , func () error {
455
+ volumeGroupSnapshotClass .Parameters = data
456
+ return nil
457
+ })
458
+ if err != nil {
459
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update StorageClass: %s" , err )
460
+ }
426
461
}
427
462
case "ClientProfile" :
428
463
clientProfile := & csiopv1a1.ClientProfile {}
@@ -466,6 +501,11 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
466
501
} else if exist {
467
502
return reconcile.Result {}, fmt .Errorf ("one or more volumesnapshotcontents exist that are dependent on storageclaim %s" , r .storageClaim .Name )
468
503
}
504
+ if exist , err := r .hasVolumeGroupSnapshotContents (); err != nil {
505
+ return reconcile.Result {}, fmt .Errorf ("failed to verify volumegroupsnapshotcontents dependent on storageclaim %q: %v" , r .storageClaim .Name , err )
506
+ } else if exist {
507
+ return reconcile.Result {}, fmt .Errorf ("one or more volumegroupsnapshotcontents exist that are dependent on storageclaim %s" , r .storageClaim .Name )
508
+ }
469
509
470
510
// Call `RevokeStorageClaim` service on the provider server with StorageClaim as a request message.
471
511
// Check if StorageClaim is still exists (it might have been manually removed during the StorageClass
@@ -550,6 +590,20 @@ func (r *StorageClaimReconciler) getCephRBDVolumeSnapshotClass() *snapapi.Volume
550
590
return volumesnapshotclass
551
591
}
552
592
593
+ func (r * StorageClaimReconciler ) getCephDriverVolumeGroupSnapshotClass (
594
+ labels map [string ]string , annotations map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
595
+ volumegroupsnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
596
+ ObjectMeta : metav1.ObjectMeta {
597
+ Name : r .storageClaim .Name ,
598
+ Labels : labels ,
599
+ Annotations : annotations ,
600
+ },
601
+ Driver : templates .RBDDriverName ,
602
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
603
+ }
604
+ return volumegroupsnapshotclass
605
+ }
606
+
553
607
func (r * StorageClaimReconciler ) get (obj client.Object ) error {
554
608
key := client .ObjectKeyFromObject (obj )
555
609
return r .Client .Get (r .ctx , key , obj )
@@ -594,3 +648,17 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
594
648
595
649
return false , nil
596
650
}
651
+
652
+ func (r * StorageClaimReconciler ) hasVolumeGroupSnapshotContents () (bool , error ) {
653
+ vscList := & groupsnapapi.VolumeGroupSnapshotContentList {}
654
+ if err := r .list (vscList , client.MatchingFields {vscClusterIDIndexName : r .storageClaimHash }); err != nil {
655
+ return false , fmt .Errorf ("failed to list volume group snapshot content resources: %v" , err )
656
+ }
657
+
658
+ if len (vscList .Items ) != 0 {
659
+ r .log .Info (fmt .Sprintf ("VolumeGroupSnapshotContent referring storageclaim %q exists" , r .storageClaim .Name ))
660
+ return true , nil
661
+ }
662
+
663
+ return false , nil
664
+ }
0 commit comments