Skip to content

Commit 1652c39

Browse files
committed
controllers: Generates VGSClass
Signed-off-by: raaizik <[email protected]>
1 parent 672e703 commit 1652c39

File tree

9 files changed

+1081
-7
lines changed

9 files changed

+1081
-7
lines changed

bundle/manifests/ocs-client-operator.clusterserviceversion.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,24 @@ spec:
208208
- list
209209
- update
210210
- watch
211+
- apiGroups:
212+
- groupsnapshot.storage.k8s.io
213+
resources:
214+
- volumegroupsnapshotclasses
215+
verbs:
216+
- create
217+
- delete
218+
- get
219+
- list
220+
- watch
221+
- apiGroups:
222+
- groupsnapshot.storage.k8s.io
223+
resources:
224+
- volumegroupsnapshotcontents
225+
verbs:
226+
- get
227+
- list
228+
- watch
211229
- apiGroups:
212230
- monitoring.coreos.com
213231
resources:

config/rbac/role.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,24 @@ rules:
165165
- list
166166
- update
167167
- watch
168+
- apiGroups:
169+
- groupsnapshot.storage.k8s.io
170+
resources:
171+
- volumegroupsnapshotclasses
172+
verbs:
173+
- create
174+
- delete
175+
- get
176+
- list
177+
- watch
178+
- apiGroups:
179+
- groupsnapshot.storage.k8s.io
180+
resources:
181+
- volumegroupsnapshotcontents
182+
verbs:
183+
- get
184+
- list
185+
- watch
168186
- apiGroups:
169187
- monitoring.coreos.com
170188
resources:

internal/controller/operatorconfigmap_controller.go

+4
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ func (c *OperatorConfigMapReconciler) reconcileDelegatedCSI() error {
351351
templates.CSIOperatorConfigSpec.DeepCopyInto(&csiOperatorConfig.Spec)
352352
csiOperatorConfig.Spec.DriverSpecDefaults.ImageSet = &corev1.LocalObjectReference{Name: cmName}
353353
csiOperatorConfig.Spec.DriverSpecDefaults.ClusterName = ptr.To(string(clusterVersion.Spec.ClusterID))
354+
if c.AvailCrds[volumeGroupSnapshotClassCrd] {
355+
csiOperatorConfig.Spec.DriverSpecDefaults.SnapshotPolicy = csiopv1a1.VolumeGroupSnapshotPolicy
356+
}
357+
354358
return nil
355359
}); err != nil {
356360
return fmt.Errorf("failed to reconcile csi operator config: %v", err)

internal/controller/storageclaim_controller.go

+92-7
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
csiopv1a1 "github.com/ceph/ceph-csi-operator/api/v1alpha1"
3030
"github.com/go-logr/logr"
3131

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"
3333
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
3434
providerclient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
3535
corev1 "k8s.io/api/core/v1"
@@ -52,8 +52,10 @@ const (
5252
storageClaimAnnotation = "ocs.openshift.io/storageclaim"
5353
keyRotationAnnotation = "keyrotation.csiaddons.openshift.io/schedule"
5454

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"
5759
)
5860

5961
// StorageClaimReconciler reconciles a StorageClaim object
@@ -109,8 +111,25 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
109111
For(&v1alpha1.StorageClaim{}, builder.WithPredicates(generationChangePredicate)).
110112
Owns(&storagev1.StorageClass{}).
111113
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+
}
114133

115134
return bldr.Complete(r)
116135
}
@@ -121,8 +140,10 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
121140
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete
122141
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch;create;update;patch;delete
123142
//+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
124144
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
125145
//+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
126147
//+kubebuilder:rbac:groups=csi.ceph.io,resources=clientprofiles,verbs=get;list;update;create;watch;delete
127148
//+kubebuilder:rbac:groups=replication.storage.openshift.io,resources=volumereplicationclass,verbs=get;list;watch;create;delete
128149

@@ -141,11 +162,18 @@ func (r *StorageClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
141162
r.ctx = ctrllog.IntoContext(ctx, r.log)
142163
r.log.Info("Reconciling StorageClaim.")
143164

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+
144173
// Fetch the StorageClaim instance
145174
r.storageClaim = &v1alpha1.StorageClaim{}
146175
r.storageClaim.Name = req.Name
147176

148-
if err := r.get(r.storageClaim); err != nil {
149177
if errors.IsNotFound(err) {
150178
r.log.Info("StorageClaim resource not found. Ignoring since object must be deleted.")
151179
return reconcile.Result{}, nil
@@ -401,7 +429,31 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
401429
return nil
402430
})
403431
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+
}
405457
}
406458
case "VolumeReplicationClass":
407459
vrc := &replicationv1alpha1.VolumeReplicationClass{}
@@ -466,6 +518,11 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
466518
} else if exist {
467519
return reconcile.Result{}, fmt.Errorf("one or more volumesnapshotcontents exist that are dependent on storageclaim %s", r.storageClaim.Name)
468520
}
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+
}
469526

470527
// Call `RevokeStorageClaim` service on the provider server with StorageClaim as a request message.
471528
// 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
550607
return volumesnapshotclass
551608
}
552609

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+
553624
func (r *StorageClaimReconciler) get(obj client.Object) error {
554625
key := client.ObjectKeyFromObject(obj)
555626
return r.Client.Get(r.ctx, key, obj)
@@ -594,3 +665,17 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
594665

595666
return false, nil
596667
}
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+
}

vendor/github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1/doc.go

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1/register.go

+57
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)