@@ -29,7 +29,7 @@ import (
29
29
csiopv1a1 "github.com/ceph/ceph-csi-operator/api/v1alpha1"
30
30
"github.com/go-logr/logr"
31
31
32
- replicationv1alpha1 "github.com/csi-addons/ kubernetes-csi-addons/api/replication.storage /v1alpha1"
32
+ groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot /v1alpha1"
33
33
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
34
34
providerclient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
35
35
corev1 "k8s.io/api/core/v1"
@@ -52,8 +52,10 @@ const (
52
52
storageClaimAnnotation = "ocs.openshift.io/storageclaim"
53
53
keyRotationAnnotation = "keyrotation.csiaddons.openshift.io/schedule"
54
54
55
- pvClusterIDIndexName = "index:persistentVolumeClusterID"
56
- vscClusterIDIndexName = "index:volumeSnapshotContentCSIDriver"
55
+ pvClusterIDIndexName = "index:persistentVolumeClusterID"
56
+ vscClusterIDIndexName = "index:volumeSnapshotContentCSIDriver"
57
+ volumeGroupSnapshotClassCrd = "groupsnapshot.storage.k8s.io/volumegroupsnapshotclass"
58
+ drClusterConfigCRDName = "drclusterconfigs.ramendr.openshift.io"
57
59
)
58
60
59
61
// StorageClaimReconciler reconciles a StorageClaim object
@@ -109,8 +111,25 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
109
111
For (& v1alpha1.StorageClaim {}, builder .WithPredicates (generationChangePredicate )).
110
112
Owns (& storagev1.StorageClass {}).
111
113
Owns (& snapapi.VolumeSnapshotClass {}).
112
- Owns (& replicationv1alpha1.VolumeReplicationClass {}, builder .WithPredicates (generationChangePredicate )).
113
- Owns (& csiopv1a1.ClientProfile {}, builder .WithPredicates (generationChangePredicate ))
114
+ Owns (& csiopv1a1.ClientProfile {}, builder .WithPredicates (generationChangePredicate )).
115
+ Watches (
116
+ & extv1.CustomResourceDefinition {},
117
+ & handler.EnqueueRequestForObject {},
118
+ builder .WithPredicates (
119
+ utils .NamePredicate (volumeGroupSnapshotClassCrd ),
120
+ utils .CrdCreateAndDeletePredicate (& r .log , volumeGroupSnapshotClassCrd , r .AvailableCrds [volumeGroupSnapshotClassCrd ]),
121
+ utils .NamePredicate (drClusterConfigCRDName ),
122
+ utils .CrdCreateAndDeletePredicate (& r .log , drClusterConfigCRDName , r .AvailableCrds [drClusterConfigCRDName ]),
123
+ ),
124
+ builder .OnlyMetadata ,
125
+ )
126
+ if r .AvailableCrds [volumeGroupSnapshotClassCrd ] {
127
+ bldr = bldr .Owns (& groupsnapapi.VolumeGroupSnapshotClass {})
128
+ }
129
+
130
+ if r .AvailableCrds [drClusterConfigCRDName ] {
131
+ bldr = bldr .Owns (& ramenv1alpha1.DRClusterConfig {}, builder .WithPredicates (generationChangePredicate ))
132
+ }
114
133
115
134
return bldr .Complete (r )
116
135
}
@@ -121,8 +140,10 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
121
140
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete
122
141
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch;create;update;patch;delete
123
142
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotclasses,verbs=get;list;watch;create;delete
143
+ //+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotclasses,verbs=create;delete;get;list;watch
124
144
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
125
145
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotcontents,verbs=get;list;watch
146
+ //+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotcontents,verbs=get;list;watch
126
147
//+kubebuilder:rbac:groups=csi.ceph.io,resources=clientprofiles,verbs=get;list;update;create;watch;delete
127
148
//+kubebuilder:rbac:groups=replication.storage.openshift.io,resources=volumereplicationclass,verbs=get;list;watch;create;delete
128
149
@@ -141,11 +162,18 @@ func (r *StorageClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
141
162
r .ctx = ctrllog .IntoContext (ctx , r .log )
142
163
r .log .Info ("Reconciling StorageClaim." )
143
164
165
+ crd := & metav1.PartialObjectMetadata {}
166
+ for _ , crdName := range []string {volumeGroupSnapshotClassCrd , drClusterConfigCRDName } {
167
+ crd .SetGroupVersionKind (extv1 .SchemeGroupVersion .WithKind ("CustomResourceDefinition" ))
168
+ r .log .Error (err , "Failed to get CRD" , "CRD" , crdName )
169
+ return reconcile.Result {}, err
170
+ }
171
+ utils .AssertEqual (r .AvailableCrds [crdName ], crd .UID != "" , utils .ExitCodeThatShouldRestartTheProcess )
172
+
144
173
// Fetch the StorageClaim instance
145
174
r .storageClaim = & v1alpha1.StorageClaim {}
146
175
r .storageClaim .Name = req .Name
147
176
148
- if err := r .get (r .storageClaim ); err != nil {
149
177
if errors .IsNotFound (err ) {
150
178
r .log .Info ("StorageClaim resource not found. Ignoring since object must be deleted." )
151
179
return reconcile.Result {}, nil
@@ -401,7 +429,31 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
401
429
return nil
402
430
})
403
431
if err != nil {
404
- return reconcile.Result {}, fmt .Errorf ("failed to create or update VolumeSnapshotClass: %s" , err )
432
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update StorageClass: %s" , err )
433
+ }
434
+ case "VolumeGroupSnapshotClass" :
435
+ // check for CRD availability
436
+ if r .AvailableCrds [("VolumeGroupSnapshotClass" )] {
437
+ var volumeGroupSnapshotClass * groupsnapapi.VolumeGroupSnapshotClass
438
+ data := map [string ]string {}
439
+ err = json .Unmarshal (resource .Data , & data )
440
+ if err != nil {
441
+ return reconcile.Result {}, fmt .Errorf ("failed to unmarshal StorageClaim configuration response: %v" , err )
442
+ }
443
+ data ["csi.storage.k8s.io/group-snapshotter-secret-namespace" ] = r .OperatorNamespace
444
+ // generate a new clusterID for cephfs subvolumegroup, as
445
+ // storageclaim is clusterscoped resources using its
446
+ // hash as the clusterID
447
+ data ["clusterID" ] = r .storageClaimHash
448
+ volumeGroupSnapshotClass = r .getCephDriverVolumeGroupSnapshotClass (resource .Labels , resource .Annotations )
449
+ utils .AddAnnotation (volumeGroupSnapshotClass , storageClaimAnnotation , r .storageClaim .Name )
450
+ err = utils .CreateOrReplace (r .ctx , r .Client , volumeGroupSnapshotClass , func () error {
451
+ volumeGroupSnapshotClass .Parameters = data
452
+ return nil
453
+ })
454
+ if err != nil {
455
+ return reconcile.Result {}, fmt .Errorf ("failed to create or update StorageClass: %s" , err )
456
+ }
405
457
}
406
458
case "VolumeReplicationClass" :
407
459
vrc := & replicationv1alpha1.VolumeReplicationClass {}
@@ -466,6 +518,11 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
466
518
} else if exist {
467
519
return reconcile.Result {}, fmt .Errorf ("one or more volumesnapshotcontents exist that are dependent on storageclaim %s" , r .storageClaim .Name )
468
520
}
521
+ if exist , err := r .hasVolumeGroupSnapshotContents (); err != nil {
522
+ return reconcile.Result {}, fmt .Errorf ("failed to verify volumegroupsnapshotcontents dependent on storageclaim %q: %v" , r .storageClaim .Name , err )
523
+ } else if exist {
524
+ return reconcile.Result {}, fmt .Errorf ("one or more volumegroupsnapshotcontents exist that are dependent on storageclaim %s" , r .storageClaim .Name )
525
+ }
469
526
470
527
// Call `RevokeStorageClaim` service on the provider server with StorageClaim as a request message.
471
528
// Check if StorageClaim is still exists (it might have been manually removed during the StorageClass
@@ -550,6 +607,20 @@ func (r *StorageClaimReconciler) getCephRBDVolumeSnapshotClass() *snapapi.Volume
550
607
return volumesnapshotclass
551
608
}
552
609
610
+ func (r * StorageClaimReconciler ) getCephDriverVolumeGroupSnapshotClass (
611
+ labels map [string ]string , annotations map [string ]string ) * groupsnapapi.VolumeGroupSnapshotClass {
612
+ volumegroupsnapshotclass := & groupsnapapi.VolumeGroupSnapshotClass {
613
+ ObjectMeta : metav1.ObjectMeta {
614
+ Name : r .storageClaim .Name ,
615
+ Labels : labels ,
616
+ Annotations : annotations ,
617
+ },
618
+ Driver : templates .RBDDriverName ,
619
+ DeletionPolicy : snapapi .VolumeSnapshotContentDelete ,
620
+ }
621
+ return volumegroupsnapshotclass
622
+ }
623
+
553
624
func (r * StorageClaimReconciler ) get (obj client.Object ) error {
554
625
key := client .ObjectKeyFromObject (obj )
555
626
return r .Client .Get (r .ctx , key , obj )
@@ -594,3 +665,17 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
594
665
595
666
return false , nil
596
667
}
668
+
669
+ func (r * StorageClaimReconciler ) hasVolumeGroupSnapshotContents () (bool , error ) {
670
+ vscList := & groupsnapapi.VolumeGroupSnapshotContentList {}
671
+ if err := r .list (vscList , client.MatchingFields {vscClusterIDIndexName : r .storageClaimHash }); err != nil {
672
+ return false , fmt .Errorf ("failed to list volume group snapshot content resources: %v" , err )
673
+ }
674
+
675
+ if len (vscList .Items ) != 0 {
676
+ r .log .Info (fmt .Sprintf ("VolumeGroupSnapshotContent referring storageclaim %q exists" , r .storageClaim .Name ))
677
+ return true , nil
678
+ }
679
+
680
+ return false , nil
681
+ }
0 commit comments