Skip to content

Commit

Permalink
controllers: Generates VGSClass
Browse files Browse the repository at this point in the history
Signed-off-by: raaizik <[email protected]>
  • Loading branch information
raaizik committed Jun 6, 2024
1 parent 484006e commit 63d1586
Show file tree
Hide file tree
Showing 7 changed files with 936 additions and 0 deletions.
10 changes: 10 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ rules:
- get
- list
- watch
- apiGroups:
- groupsnapshot.storage.k8s.io
resources:
- volumegroupsnapshotclasses
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- monitoring.coreos.com
resources:
Expand Down
87 changes: 87 additions & 0 deletions controllers/storageclaim_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/red-hat-storage/ocs-client-operator/pkg/utils"

"github.com/go-logr/logr"
groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumegroupsnapshot/v1alpha1"
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
providerclient "github.com/red-hat-storage/ocs-operator/v4/services/provider/client"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -110,6 +111,7 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
For(&v1alpha1.StorageClaim{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
Owns(&storagev1.StorageClass{}).
Owns(&snapapi.VolumeSnapshotClass{}).
Owns(&groupsnapapi.VolumeGroupSnapshotClass{}).
Complete(r)
}

Expand All @@ -119,6 +121,7 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;delete
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotclasses,verbs=get;list;watch;create;delete
//+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotclasses,verbs=get;list;watch;create;delete
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotcontents,verbs=get;list;watch

Expand Down Expand Up @@ -327,12 +330,14 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
// Go over the received objects and operate on them accordingly.
for _, resource := range resources {
data := map[string]string{}
labels := map[string]string{}
err = json.Unmarshal(resource.Data, &data)
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed to unmarshal StorageClaim configuration response: %v", err)
}

// Create the received resources, if necessary.
storageID := getMD5Hash(string(r.storageClaim.UID)) + r.storageClaimHash
switch resource.Kind {
case "Secret":
secret := &corev1.Secret{}
Expand Down Expand Up @@ -398,6 +403,8 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
// storageclaim is clusterscoped resources using its
// hash as the clusterID
data["clusterID"] = r.storageClaimHash
labels["ramendr.openshift.io/replicationID"] = r.storageClaimHash
labels["ramendr.openshift.io/storageID"] = storageID
if resource.Name == "cephfs" {
volumeSnapshotClass = r.getCephFSVolumeSnapshotClass(data)
} else if resource.Name == "ceph-rbd" {
Expand All @@ -407,6 +414,24 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
if err := r.createOrReplaceVolumeSnapshotClass(volumeSnapshotClass); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to create or update VolumeSnapshotClass: %s", err)
}
case "VolumeGroupSnapshotClass":
var volumeGroupSnapshotClass *groupsnapapi.VolumeGroupSnapshotClass
data["csi.storage.k8s.io/snapshotter-secret-namespace"] = r.OperatorNamespace
// generate a new clusterID for cephfs subvolumegroup, as
// storageclaim is clusterscoped resources using its
// hash as the clusterID
data["clusterID"] = r.storageClaimHash
labels["ramendr.openshift.io/replicationID"] = r.storageClaimHash
labels["ramendr.openshift.io/storageID"] = storageID
if resource.Name == "cephfs" {
volumeGroupSnapshotClass = r.getCephFSVolumeGroupSnapshotClass(data, labels)
} else if resource.Name == "ceph-rbd" {
volumeGroupSnapshotClass = r.getCephRBDVolumeGroupSnapshotClass(data, labels)
}
utils.AddAnnotation(volumeGroupSnapshotClass, storageClaimAnnotation, r.storageClaim.Name)
if err := r.createOrReplaceVolumeGroupSnapshotClass(volumeGroupSnapshotClass); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to create or update volumeGroupSnapshot: %s", err)
}
}
}

Expand Down Expand Up @@ -651,6 +676,68 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {
return false, nil
}

func (r *StorageClaimReconciler) getCephFSVolumeGroupSnapshotClass(data map[string]string, labels map[string]string) *groupsnapapi.VolumeGroupSnapshotClass {
volumgroupesnapshotclass := &groupsnapapi.VolumeGroupSnapshotClass{
ObjectMeta: metav1.ObjectMeta{
Name: r.storageClaim.Name,
Labels: labels,
},
Driver: csi.GetCephFSDriverName(),
DeletionPolicy: snapapi.VolumeSnapshotContentDelete,
Parameters: data,
}
return volumgroupesnapshotclass
}

func (r *StorageClaimReconciler) getCephRBDVolumeGroupSnapshotClass(data map[string]string, labels map[string]string) *groupsnapapi.VolumeGroupSnapshotClass {
volumegroupsnapshotclass := &groupsnapapi.VolumeGroupSnapshotClass{
ObjectMeta: metav1.ObjectMeta{
Name: r.storageClaim.Name,
Labels: labels,
},
Driver: csi.GetRBDDriverName(),
DeletionPolicy: snapapi.VolumeSnapshotContentDelete,
Parameters: data,
}
return volumegroupsnapshotclass
}

func (r *StorageClaimReconciler) createOrReplaceVolumeGroupSnapshotClass(volumeGroupSnapshotClass *groupsnapapi.VolumeGroupSnapshotClass) error {
existing := &groupsnapapi.VolumeGroupSnapshotClass{}
existing.Name = r.storageClaim.Name

if err := r.own(volumeGroupSnapshotClass); err != nil {
return fmt.Errorf("failed to own volumegroupsnapshotclass: %v", err)
}

if err := r.get(existing); err != nil && !errors.IsNotFound(err) {
return fmt.Errorf("failed to get VolumeGroupSnapshotClass: %v", err)
}

// If present then compare the existing VolumeGroupSnapshotClass parameters with
// the received VolumeGroupSnapshotClass parameters, and only proceed if they differ.
if reflect.DeepEqual(existing.Parameters, volumeGroupSnapshotClass.Parameters) {
return nil
}

// VolumeGroupSnapshotClass already exists, but parameters have changed. Delete the existing VolumeGroupSnapshotClass and create a new one.
if existing.UID != "" {
// Since we have to update the existing VolumeGroupSnapshotClass, so we will delete the existing VolumeGroupSnapshotClass and create a new one.
r.log.Info("VolumeGroupSnapshotClass needs to be updated, deleting it.", "Name", existing.Name)

// Delete the VolumeGroupSnapshotClass.
if err := r.delete(existing); err != nil {
r.log.Error(err, "Failed to delete VolumeGroupSnapshotClass.", "Name", existing.Name)
return fmt.Errorf("failed to delete VolumeGroupSnapshotClass: %v", err)
}
}
r.log.Info("Creating VolumeGroupSnapshotClass.", "Name", existing.Name)
if err := r.Client.Create(r.ctx, volumeGroupSnapshotClass); err != nil {
return fmt.Errorf("failed to create VolumeGroupSnapshotClass: %v", err)
}
return nil
}

func getMD5Hash(text string) string {
hash := md5.Sum([]byte(text))
return hex.EncodeToString(hash[:])
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 63d1586

Please sign in to comment.