Skip to content

Commit 523d103

Browse files
committed
controllers: Generates VGSClass
Signed-off-by: raaizik <[email protected]>
1 parent 284e512 commit 523d103

File tree

10 files changed

+1069
-10
lines changed

10 files changed

+1069
-10
lines changed

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

+18
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,24 @@ spec:
197197
- list
198198
- update
199199
- watch
200+
- apiGroups:
201+
- groupsnapshot.storage.k8s.io
202+
resources:
203+
- volumegroupsnapshotclasses
204+
verbs:
205+
- create
206+
- delete
207+
- get
208+
- list
209+
- watch
210+
- apiGroups:
211+
- groupsnapshot.storage.k8s.io
212+
resources:
213+
- volumegroupsnapshotcontents
214+
verbs:
215+
- get
216+
- list
217+
- watch
200218
- apiGroups:
201219
- monitoring.coreos.com
202220
resources:

cmd/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ func main() {
203203
Scheme: mgr.GetScheme(),
204204
OperatorNamespace: utils.GetOperatorNamespace(),
205205
ConsolePort: int32(consolePort),
206+
AvailCrds: availCrds,
206207
}).SetupWithManager(mgr); err != nil {
207208
setupLog.Error(err, "unable to create controller", "controller", "OperatorConfigMapReconciler")
208209
os.Exit(1)

config/rbac/role.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,24 @@ rules:
154154
- list
155155
- update
156156
- watch
157+
- apiGroups:
158+
- groupsnapshot.storage.k8s.io
159+
resources:
160+
- volumegroupsnapshotclasses
161+
verbs:
162+
- create
163+
- delete
164+
- get
165+
- list
166+
- watch
167+
- apiGroups:
168+
- groupsnapshot.storage.k8s.io
169+
resources:
170+
- volumegroupsnapshotcontents
171+
verbs:
172+
- get
173+
- list
174+
- watch
157175
- apiGroups:
158176
- monitoring.coreos.com
159177
resources:

internal/controller/operatorconfigmap_controller.go

+5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ type OperatorConfigMapReconciler struct {
7979
OperatorNamespace string
8080
ConsolePort int32
8181
Scheme *runtime.Scheme
82+
AvailCrds map[string]bool
8283

8384
log logr.Logger
8485
ctx context.Context
@@ -327,6 +328,10 @@ func (c *OperatorConfigMapReconciler) reconcileDelegatedCSI() error {
327328
templates.CSIOperatorConfigSpec.DeepCopyInto(&csiOperatorConfig.Spec)
328329
csiOperatorConfig.Spec.DriverSpecDefaults.ImageSet = &corev1.LocalObjectReference{Name: cmName}
329330
csiOperatorConfig.Spec.DriverSpecDefaults.ClusterName = ptr.To(string(clusterVersion.Spec.ClusterID))
331+
if c.AvailCrds[volumeGroupSnapshotClassCrd] {
332+
csiOperatorConfig.Spec.DriverSpecDefaults.SnapshotPolicy = csiopv1a1.VolumeGroupSnapshotPolicy
333+
}
334+
330335
return nil
331336
}); err != nil {
332337
return fmt.Errorf("failed to reconcile csi operator config: %v", err)

internal/controller/storageclaim_controller.go

+78-10
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
csiopv1a1 "github.com/ceph/ceph-csi-operator/api/v1alpha1"
3232
"github.com/go-logr/logr"
3333

34+
groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1alpha1"
3435
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
3536
ramenv1alpha1 "github.com/ramendr/ramen/api/v1alpha1"
3637
providerclient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
@@ -56,9 +57,10 @@ const (
5657
storageClaimAnnotation = "ocs.openshift.io/storageclaim"
5758
keyRotationAnnotation = "keyrotation.csiaddons.openshift.io/schedule"
5859

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"
6264
)
6365

6466
// StorageClaimReconciler reconciles a StorageClaim object
@@ -120,11 +122,16 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
120122
&extv1.CustomResourceDefinition{},
121123
&handler.EnqueueRequestForObject{},
122124
builder.WithPredicates(
125+
utils.NamePredicate(volumeGroupSnapshotClassCrd),
126+
utils.CrdCreateAndDeletePredicate(&r.log, volumeGroupSnapshotClassCrd, r.AvailableCrds[volumeGroupSnapshotClassCrd]),
123127
utils.NamePredicate(drClusterConfigCRDName),
124128
utils.CrdCreateAndDeletePredicate(&r.log, drClusterConfigCRDName, r.AvailableCrds[drClusterConfigCRDName]),
125129
),
126130
builder.OnlyMetadata,
127131
)
132+
if r.AvailableCrds[volumeGroupSnapshotClassCrd] {
133+
bldr = bldr.Owns(&groupsnapapi.VolumeGroupSnapshotClass{})
134+
}
128135

129136
if r.AvailableCrds[drClusterConfigCRDName] {
130137
bldr = bldr.Owns(&ramenv1alpha1.DRClusterConfig{}, builder.WithPredicates(generationChangePredicate))
@@ -139,8 +146,10 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
139146
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete
140147
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch;create;update;patch;delete
141148
//+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
142150
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
143151
//+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
144153
//+kubebuilder:rbac:groups=csi.ceph.io,resources=clientprofiles,verbs=get;list;update;create;watch;delete
145154
//+kubebuilder:rbac:groups=ramendr.openshift.io,resources=drclusterconfigs,verbs=get;list;update;create;watch;delete
146155

@@ -160,13 +169,15 @@ func (r *StorageClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
160169
r.log.Info("Reconciling StorageClaim.")
161170

162171
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)
168180
}
169-
utils.AssertEqual(r.AvailableCrds[drClusterConfigCRDName], crd.UID != "", utils.ExitCodeThatShouldRestartTheProcess)
170181

171182
// Fetch the StorageClaim instance
172183
r.storageClaim = &v1alpha1.StorageClaim{}
@@ -422,7 +433,31 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
422433
return nil
423434
})
424435
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+
}
426461
}
427462
case "ClientProfile":
428463
clientProfile := &csiopv1a1.ClientProfile{}
@@ -466,6 +501,11 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
466501
} else if exist {
467502
return reconcile.Result{}, fmt.Errorf("one or more volumesnapshotcontents exist that are dependent on storageclaim %s", r.storageClaim.Name)
468503
}
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+
}
469509

470510
// Call `RevokeStorageClaim` service on the provider server with StorageClaim as a request message.
471511
// 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
550590
return volumesnapshotclass
551591
}
552592

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+
553607
func (r *StorageClaimReconciler) get(obj client.Object) error {
554608
key := client.ObjectKeyFromObject(obj)
555609
return r.Client.Get(r.ctx, key, obj)
@@ -594,3 +648,17 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
594648

595649
return false, nil
596650
}
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+
}

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)