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 Dec 11, 2024
1 parent 273a0c9 commit 5af8ff3
Show file tree
Hide file tree
Showing 14 changed files with 1,234 additions and 25 deletions.
18 changes: 18 additions & 0 deletions bundle/manifests/ocs-client-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,24 @@ spec:
- list
- update
- watch
- apiGroups:
- groupsnapshot.storage.k8s.io
resources:
- volumegroupsnapshotclasses
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- groupsnapshot.storage.k8s.io
resources:
- volumegroupsnapshotcontents
verbs:
- get
- list
- watch
- apiGroups:
- monitoring.coreos.com
resources:
Expand Down
18 changes: 18 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ rules:
- list
- update
- watch
- apiGroups:
- groupsnapshot.storage.k8s.io
resources:
- volumegroupsnapshotclasses
verbs:
- create
- delete
- get
- list
- watch
- apiGroups:
- groupsnapshot.storage.k8s.io
resources:
- volumegroupsnapshotcontents
verbs:
- get
- list
- watch
- apiGroups:
- monitoring.coreos.com
resources:
Expand Down
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.22.7
replace (
github.com/portworx/sched-ops => github.com/portworx/sched-ops v0.20.4-openstorage-rc3 // required by Rook v1.12
github.com/red-hat-storage/ocs-client-operator/api => ./api
k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.29.0
vbom.ml/util => github.com/fvbommel/util v0.0.0-20180919145318-efcd4e0f9787
)

Expand All @@ -18,20 +19,22 @@ exclude (
)

require (
github.com/ceph/ceph-csi-operator/api v0.0.0-20241114115439-f325f74205d3
github.com/ceph/ceph-csi-operator/api v0.0.0-20241119082218-62dc94e55c32
github.com/csi-addons/kubernetes-csi-addons v0.10.0
github.com/go-logr/logr v1.4.2
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.34.2
github.com/openshift/api v0.0.0-20240828125535-01b3675ba7b3
github.com/operator-framework/api v0.27.0
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.0
github.com/ramendr/ramen/api v0.0.0-20241001141243-29d6f22ad237
github.com/ramendr/ramen/api v0.0.0-20241105140706-d8587766acb3
github.com/red-hat-storage/ocs-client-operator/api v0.0.0-00010101000000-000000000000
github.com/red-hat-storage/ocs-operator/services/provider/api/v4 v4.0.0-20241120160011-2e7cf0127dd4
github.com/stretchr/testify v1.9.0
google.golang.org/grpc v1.68.0
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.31.1
k8s.io/apiextensions-apiserver v0.31.0
k8s.io/apimachinery v0.31.1
Expand All @@ -46,10 +49,8 @@ require (
github.com/klauspost/compress v1.17.9 // indirect
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1 // indirect
github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/component-base v0.31.0 // indirect
sigs.k8s.io/container-object-storage-interface-api v0.1.0 // indirect
)
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/ceph/ceph-csi-operator/api v0.0.0-20241114115439-f325f74205d3 h1:ft8h5V7BfQqIGJAyiTvn6x86Oi/yMs8yqW7rfKvN9SQ=
github.com/ceph/ceph-csi-operator/api v0.0.0-20241114115439-f325f74205d3/go.mod h1:odEUoarG26wXBCC2l4O4nMWhAz6VTKr2FRkv9yELgi8=
github.com/ceph/ceph-csi-operator/api v0.0.0-20241119082218-62dc94e55c32 h1:IawGJ9fPalvY77XtDElI4ZoVfU5aLnEKL3kwWBn3YEA=
github.com/ceph/ceph-csi-operator/api v0.0.0-20241119082218-62dc94e55c32/go.mod h1:odEUoarG26wXBCC2l4O4nMWhAz6VTKr2FRkv9yELgi8=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
Expand Down Expand Up @@ -256,8 +256,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1 h1:dQEHhTfi+bSIOSViQrKY9PqJvZenD6tFz+3lPzux58o=
github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1/go.mod h1:my+EVjOJLeQ9lUR9uVkxRvNNkhO2saSGIgzV8GZT9HY=
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0 h1:mjQG0Vakr2h246kEDR85U8y8ZhPgT3bguTCajRa/jaw=
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y=
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 h1:Q3jQ1NkFqv5o+F8dMmHd8SfEmlcwNeo1immFApntEwE=
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
Expand Down Expand Up @@ -325,8 +325,8 @@ github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVho
github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/ramendr/ramen/api v0.0.0-20241001141243-29d6f22ad237 h1:ig6ePD0yopC5Qi5BRmhsIsKaOkdsGXTSmG3HTYIpquo=
github.com/ramendr/ramen/api v0.0.0-20241001141243-29d6f22ad237/go.mod h1:nO6VM/+PEhcPGyFIQJdhY6ip822cA61PAy/s6IjenAA=
github.com/ramendr/ramen/api v0.0.0-20241105140706-d8587766acb3 h1:q4UjNvv3jzKOeG/S+S1Ms2FV3WajBIE6266/7BIxdX4=
github.com/ramendr/ramen/api v0.0.0-20241105140706-d8587766acb3/go.mod h1:O7VpTy8MMrh31DF4fv+2SZBSouAr8NlzIY4KYx7K75U=
github.com/red-hat-storage/ocs-operator/services/provider/api/v4 v4.0.0-20241120160011-2e7cf0127dd4 h1:ppE7R+yh9I2PZuGPaUDdwQ45ZFV8YfHFNKccOxTo8tg=
github.com/red-hat-storage/ocs-operator/services/provider/api/v4 v4.0.0-20241120160011-2e7cf0127dd4/go.mod h1:XEZxUtzjlARPV8YvzcX2p7iiRbrUbDP4Q/CXx9ly5lw=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
Expand Down
4 changes: 4 additions & 0 deletions internal/controller/operatorconfigmap_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ func (c *OperatorConfigMapReconciler) reconcileDelegatedCSI() error {
templates.CSIOperatorConfigSpec.DeepCopyInto(&csiOperatorConfig.Spec)
csiOperatorConfig.Spec.DriverSpecDefaults.ImageSet = &corev1.LocalObjectReference{Name: cmName}
csiOperatorConfig.Spec.DriverSpecDefaults.ClusterName = ptr.To(string(clusterVersion.Spec.ClusterID))
if c.AvailableCrds[volumeGroupSnapshotClassCrd] {
csiOperatorConfig.Spec.DriverSpecDefaults.SnapshotPolicy = csiopv1a1.VolumeGroupSnapshotPolicy
}

return nil
}); err != nil {
return fmt.Errorf("failed to reconcile csi operator config: %v", err)
Expand Down
125 changes: 118 additions & 7 deletions internal/controller/storageclaim_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,23 @@ import (
"context"
"encoding/json"
"fmt"
"slices"
"strings"

v1alpha1 "github.com/red-hat-storage/ocs-client-operator/api/v1alpha1"
"github.com/red-hat-storage/ocs-client-operator/pkg/templates"
"github.com/red-hat-storage/ocs-client-operator/pkg/utils"
"slices"
"strings"

csiopv1a1 "github.com/ceph/ceph-csi-operator/api/v1alpha1"
"github.com/go-logr/logr"

replicationv1alpha1 "github.com/csi-addons/kubernetes-csi-addons/api/replication.storage/v1alpha1"
groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1beta1"
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
providerclient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
corev1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -42,6 +45,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
Expand All @@ -52,8 +56,11 @@ const (
storageClaimAnnotation = "ocs.openshift.io/storageclaim"
keyRotationAnnotation = "keyrotation.csiaddons.openshift.io/schedule"

pvClusterIDIndexName = "index:persistentVolumeClusterID"
vscClusterIDIndexName = "index:volumeSnapshotContentCSIDriver"
pvClusterIDIndexName = "index:persistentVolumeClusterID"
vscClusterIDIndexName = "index:volumeSnapshotContentCSIDriver"
vgscClusterIDIndexName = "index:volumeGroupSnapshotContentCSIDriver"
volumeGroupSnapshotClassCrd = "groupsnapshot.storage.k8s.io/volumegroupsnapshotclass"
drClusterConfigCRDName = "drclusterconfigs.ramendr.openshift.io"
)

// StorageClaimReconciler reconciles a StorageClaim object
Expand All @@ -62,6 +69,7 @@ type StorageClaimReconciler struct {
cache.Cache
Scheme *runtime.Scheme
OperatorNamespace string
AvailableCrds map[string]bool

log logr.Logger
ctx context.Context
Expand Down Expand Up @@ -104,13 +112,46 @@ func (r *StorageClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
return fmt.Errorf("unable to set up FieldIndexer for VSC csi driver name: %v", err)
}

if err := mgr.GetCache().IndexField(ctx, &groupsnapapi.VolumeGroupSnapshotContent{}, vgscClusterIDIndexName, func(o client.Object) []string {
vgsc := o.(*groupsnapapi.VolumeGroupSnapshotContent)
if vgsc != nil &&
slices.Contains(csiDrivers, vgsc.Spec.Driver) &&
vgsc.Status != nil &&
vgsc.Status.VolumeGroupSnapshotHandle != nil {
parts := strings.Split(*vgsc.Status.VolumeGroupSnapshotHandle, "-")
if len(parts) == 9 {
// second entry in the volumeID is clusterID which is unique across the cluster
return []string{parts[2]}
}
}
return nil
}); err != nil {
return fmt.Errorf("unable to set up FieldIndexer for VSC csi driver name: %v", err)
}

generationChangePredicate := predicate.GenerationChangedPredicate{}
bldr := ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.StorageClaim{}, builder.WithPredicates(generationChangePredicate)).
Owns(&storagev1.StorageClass{}).
Owns(&snapapi.VolumeSnapshotClass{}).
Owns(&replicationv1alpha1.VolumeReplicationClass{}, builder.WithPredicates(generationChangePredicate)).
Owns(&csiopv1a1.ClientProfile{}, builder.WithPredicates(generationChangePredicate))
Owns(&csiopv1a1.ClientProfile{}, builder.WithPredicates(generationChangePredicate)).
Watches(
&extv1.CustomResourceDefinition{},
&handler.EnqueueRequestForObject{},
builder.WithPredicates(
utils.NamePredicate(volumeGroupSnapshotClassCrd),
utils.EventTypePredicate(
!r.AvailableCrds[volumeGroupSnapshotClassCrd],
false,
r.AvailableCrds[volumeGroupSnapshotClassCrd],
false,
),
),
builder.OnlyMetadata,
)
if r.AvailableCrds[volumeGroupSnapshotClassCrd] {
bldr = bldr.Owns(&groupsnapapi.VolumeGroupSnapshotClass{})
}

return bldr.Complete(r)
}
Expand All @@ -121,8 +162,10 @@ 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=create;delete;get;list;watch
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
//+kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshotcontents,verbs=get;list;watch
//+kubebuilder:rbac:groups=groupsnapshot.storage.k8s.io,resources=volumegroupsnapshotcontents,verbs=get;list;watch
//+kubebuilder:rbac:groups=csi.ceph.io,resources=clientprofiles,verbs=get;list;update;create;watch;delete
//+kubebuilder:rbac:groups=replication.storage.openshift.io,resources=volumereplicationclasses,verbs=get;list;watch;create;delete

Expand All @@ -141,6 +184,17 @@ func (r *StorageClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
r.ctx = ctrllog.IntoContext(ctx, r.log)
r.log.Info("Reconciling StorageClaim.")

crd := &metav1.PartialObjectMetadata{}
for _, crdName := range []string{volumeGroupSnapshotClassCrd, drClusterConfigCRDName} {
crd.SetGroupVersionKind(extv1.SchemeGroupVersion.WithKind("CustomResourceDefinition"))
crd.Name = crdName
if err := r.Client.Get(ctx, client.ObjectKeyFromObject(crd), crd); client.IgnoreNotFound(err) != nil {
r.log.Error(err, "Failed to get CRD", "CRD", crdName)
return reconcile.Result{}, err
}
}
utils.AssertEqual(r.AvailableCrds[crd.Name], crd.UID != "", utils.ExitCodeThatShouldRestartTheProcess)

// Fetch the StorageClaim instance
r.storageClaim = &v1alpha1.StorageClaim{}
r.storageClaim.Name = req.Name
Expand Down Expand Up @@ -401,7 +455,31 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
return nil
})
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed to create or update VolumeSnapshotClass: %s", err)
return reconcile.Result{}, fmt.Errorf("failed to create or update StorageClass: %s", err)
}
case "VolumeGroupSnapshotClass":
// check for CRD availability
if r.AvailableCrds[("VolumeGroupSnapshotClass")] {
var volumeGroupSnapshotClass *groupsnapapi.VolumeGroupSnapshotClass
data := 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)
}
data["csi.storage.k8s.io/group-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
volumeGroupSnapshotClass = r.getCephDriverVolumeGroupSnapshotClass(resource.Labels, resource.Annotations)
utils.AddAnnotation(volumeGroupSnapshotClass, storageClaimAnnotation, r.storageClaim.Name)
err = utils.CreateOrReplace(r.ctx, r.Client, volumeGroupSnapshotClass, func() error {
volumeGroupSnapshotClass.Parameters = data
return nil
})
if err != nil {
return reconcile.Result{}, fmt.Errorf("failed to create or update StorageClass: %s", err)
}
}
case "VolumeReplicationClass":
vrc := &replicationv1alpha1.VolumeReplicationClass{}
Expand Down Expand Up @@ -466,6 +544,11 @@ func (r *StorageClaimReconciler) reconcilePhases() (reconcile.Result, error) {
} else if exist {
return reconcile.Result{}, fmt.Errorf("one or more volumesnapshotcontents exist that are dependent on storageclaim %s", r.storageClaim.Name)
}
if exist, err := r.hasVolumeGroupSnapshotContents(); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to verify volumegroupsnapshotcontents dependent on storageclaim %q: %v", r.storageClaim.Name, err)
} else if exist {
return reconcile.Result{}, fmt.Errorf("one or more volumegroupsnapshotcontents exist that are dependent on storageclaim %s", r.storageClaim.Name)
}

// Call `RevokeStorageClaim` service on the provider server with StorageClaim as a request message.
// Check if StorageClaim is still exists (it might have been manually removed during the StorageClass
Expand Down Expand Up @@ -550,6 +633,20 @@ func (r *StorageClaimReconciler) getCephRBDVolumeSnapshotClass() *snapapi.Volume
return volumesnapshotclass
}

func (r *StorageClaimReconciler) getCephDriverVolumeGroupSnapshotClass(
labels map[string]string, annotations map[string]string) *groupsnapapi.VolumeGroupSnapshotClass {
volumegroupsnapshotclass := &groupsnapapi.VolumeGroupSnapshotClass{
ObjectMeta: metav1.ObjectMeta{
Name: r.storageClaim.Name,
Labels: labels,
Annotations: annotations,
},
Driver: templates.RBDDriverName,
DeletionPolicy: snapapi.VolumeSnapshotContentDelete,
}
return volumegroupsnapshotclass
}

func (r *StorageClaimReconciler) get(obj client.Object) error {
key := client.ObjectKeyFromObject(obj)
return r.Client.Get(r.ctx, key, obj)
Expand Down Expand Up @@ -594,3 +691,17 @@ func (r *StorageClaimReconciler) hasVolumeSnapshotContents() (bool, error) {

return false, nil
}

func (r *StorageClaimReconciler) hasVolumeGroupSnapshotContents() (bool, error) {
vscList := &groupsnapapi.VolumeGroupSnapshotContentList{}
if err := r.list(vscList, client.MatchingFields{vgscClusterIDIndexName: r.storageClaimHash}); err != nil {
return false, fmt.Errorf("failed to list volume group snapshot content resources: %v", err)
}

if len(vscList.Items) != 0 {
r.log.Info(fmt.Sprintf("VolumeGroupSnapshotContent referring storageclaim %q exists", r.storageClaim.Name))
return true, nil
}

return false, nil
}

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

Loading

0 comments on commit 5af8ff3

Please sign in to comment.