Repository: red-hat-storage/ocs-operator
Pull request #3153: add support for distributing day2 volume[group]snapshotclasses
Author: login: leelavg
Labels: name: lgtm
description: Indicates that a PR is ready to be merged.
name: approved
description: Indicates a PR has been approved by an approver from all required OWNERS files.
Created: 2025-04-10T08:23:55Z | Merged: 2025-04-14T22:32:59Z

when the volume[group]storageclass mentioned in storageconsumer doesn't match one of the known names we consider that being unmanaged day2 created v[g]sc and we update the dynamic params corresponding to the driver and then send as a resource to be created & owned by storageclient in client-op.


Diff:
diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml
index 5feaab7eb1..3dbec21a4c 100644
--- a/config/rbac/kustomization.yaml
+++ b/config/rbac/kustomization.yaml
@@ -6,8 +6,8 @@ resources:
 - oauth_proxy_role.yaml
 - oauth_proxy_role_binding.yaml
 - ux_backend_sa.yaml
-- storageclass_cr.yaml
-- storageclass_crb.yaml
+- provider_server_cr.yaml
+- provider_server_crb.yaml
 - provider_sa.yaml
 # Comment the following 4 lines if you want to disable
 # the auth proxy (https://github.com/brancz/kube-rbac-proxy)
diff --git a/config/rbac/provider_server_cr.yaml b/config/rbac/provider_server_cr.yaml
new file mode 100644
index 0000000000..058a5d190f
--- /dev/null
+++ b/config/rbac/provider_server_cr.yaml
@@ -0,0 +1,27 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: provider-server-cr
+rules:
+- apiGroups:
+  - storage.k8s.io
+  resources:
+  - storageclasses
+  verbs:
+  - get
+  - list
+- apiGroups:
+  - snapshot.storage.k8s.io
+  resources:
+  - volumesnapshotclasses
+  verbs:
+  - get
+  - list
+- apiGroups:
+  - groupsnapshot.storage.k8s.io
+  resources:
+  - volumegroupsnapshotclasses
+  verbs:
+  - get
+  - list
diff --git a/config/rbac/storageclass_crb.yaml b/config/rbac/provider_server_crb.yaml
similarity index 79%
rename from config/rbac/storageclass_crb.yaml
rename to config/rbac/provider_server_crb.yaml
index f7e9a4bb26..03f130b132 100644
--- a/config/rbac/storageclass_crb.yaml
+++ b/config/rbac/provider_server_crb.yaml
@@ -1,12 +1,12 @@
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRoleBinding
 metadata:
-  name: provider-server-sc-crb
+  name: provider-server-crb
 subjects:
 - kind: ServiceAccount
   name: ocs-provider-server
   namespace: openshift-storage
 roleRef:
   kind: ClusterRole
-  name: provider-server-sc-cr
+  name: provider-server-cr
   apiGroup: rbac.authorization.k8s.io
diff --git a/config/rbac/storageclass_cr.yaml b/config/rbac/storageclass_cr.yaml
deleted file mode 100644
index 548c0df4ec..0000000000
--- a/config/rbac/storageclass_cr.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
-  name: provider-server-sc-cr
-rules:
-- apiGroups:
-  - storage.k8s.io
-  resources:
-  - storageclasses
-  verbs:
-  - get
-  - list
diff --git a/controllers/util/groupsnapshotclasses.go b/controllers/util/groupsnapshotclasses.go
index 6de63d9c6f..b963af43f7 100644
--- a/controllers/util/groupsnapshotclasses.go
+++ b/controllers/util/groupsnapshotclasses.go
@@ -1,9 +1,12 @@
 package util
 
 import (
+	"context"
 	"fmt"
 
 	ocsv1 "github.com/red-hat-storage/ocs-operator/api/v4/v1"
+	ocsv1a1 "github.com/red-hat-storage/ocs-operator/api/v4/v1alpha1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1beta1"
 	snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
@@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
+	default:
+		return nil, UnsupportedDriver
+	}
+
+	params := gsc.Parameters
+	if params == nil {
+		params = map[string]string{}
+		gsc.Parameters = params
+	}
+	params["clusterID"] = clientProfileName
+	params["csi.storage.k8s.io/group-snapshotter-secret-name"] = provisionerSecretName
+	params["csi.storage.k8s.io/group-snapshotter-secret-namespace"] = operatorNamespace
+	AddLabel(gsc, storageIdLabelKey, storageId)
+	return gsc, nil
+}
diff --git a/controllers/util/snapshotclasses.go b/controllers/util/snapshotclasses.go
index 584b493c05..1ff6fd329b 100644
--- a/controllers/util/snapshotclasses.go
+++ b/controllers/util/snapshotclasses.go
@@ -1,9 +1,14 @@
 package util
 
 import (
+	"context"
+	"errors"
 	"fmt"
+
 	snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
+	ocsv1a1 "github.com/red-hat-storage/ocs-operator/api/v4/v1alpha1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 // SnapshotterType represents a snapshotter type
@@ -15,6 +20,10 @@ const (
 	NfsSnapshotter    SnapshotterType = "nfs"
 )
 
+var (
+	UnsupportedDriver = errors.New("unsupportedDriver")
+)
+
 // GenerateNameForSnapshotClass function generates 'SnapshotClass' name.
 // 'snapshotType' can be: 'RbdSnapshotter' or 'CephfsSnapshotter' or 'NfsSnapshotter'
 func GenerateNameForSnapshotClass(storageClusterName string, snapshotType SnapshotterType) string {
@@ -94,3 +103,51 @@ func NewDefaultNfsSnapshotClass(
 	}
 	return sc
 }
+
+func VolumeSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*snapapi.VolumeSnapshotClass, error) {
+	snapshotClass := &snapapi.VolumeSnapshotClass{}
+	snapshotClass.Name = volumeSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(snapshotClass), snapshotClass); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch snapshotClass.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
+	default:
+		return nil, UnsupportedDriver
+	}
+
+	params := snapshotClass.Parameters
+	if params == nil {
+		params = map[string]string{}
+		snapshotClass.Parameters = params
+	}
+	params["clusterID"] = clientProfileName
+	params["csi.storage.k8s.io/snapshotter-secret-name"] = provisionerSecretName
+	params["csi.storage.k8s.io/snapshotter-secret-namespace"] = operatorNamespace
+	AddLabel(snapshotClass, storageIdLabelKey, storageId)
+	return snapshotClass, nil
+}
diff --git a/deploy/csv-templates/ocs-operator.csv.yaml.in b/deploy/csv-templates/ocs-operator.csv.yaml.in
index 6e3be62826..bb0c335563 100644
--- a/deploy/csv-templates/ocs-operator.csv.yaml.in
+++ b/deploy/csv-templates/ocs-operator.csv.yaml.in
@@ -527,6 +527,20 @@ spec:
           verbs:
           - get
           - list
+        - apiGroups:
+          - snapshot.storage.k8s.io
+          resources:
+          - volumesnapshotclasses
+          verbs:
+          - get
+          - list
+        - apiGroups:
+          - groupsnapshot.storage.k8s.io
+          resources:
+          - volumegroupsnapshotclasses
+          verbs:
+          - get
+          - list
         serviceAccountName: ocs-provider-server
       - rules:
         - apiGroups:
diff --git a/deploy/ocs-operator/manifests/ocs-operator.clusterserviceversion.yaml b/deploy/ocs-operator/manifests/ocs-operator.clusterserviceversion.yaml
index 60ff3a7fe6..79bb6876c9 100644
--- a/deploy/ocs-operator/manifests/ocs-operator.clusterserviceversion.yaml
+++ b/deploy/ocs-operator/manifests/ocs-operator.clusterserviceversion.yaml
@@ -546,6 +546,20 @@ spec:
           verbs:
           - get
           - list
+        - apiGroups:
+          - snapshot.storage.k8s.io
+          resources:
+          - volumesnapshotclasses
+          verbs:
+          - get
+          - list
+        - apiGroups:
+          - groupsnapshot.storage.k8s.io
+          resources:
+          - volumegroupsnapshotclasses
+          verbs:
+          - get
+          - list
         serviceAccountName: ocs-provider-server
       - rules:
         - apiGroups:
diff --git a/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/groupsnapshotclasses.go b/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/groupsnapshotclasses.go
index 6de63d9c6f..b963af43f7 100644
--- a/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/groupsnapshotclasses.go
+++ b/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/groupsnapshotclasses.go
@@ -1,9 +1,12 @@
 package util
 
 import (
+	"context"
 	"fmt"
 
 	ocsv1 "github.com/red-hat-storage/ocs-operator/api/v4/v1"
+	ocsv1a1 "github.com/red-hat-storage/ocs-operator/api/v4/v1alpha1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	groupsnapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1beta1"
 	snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
@@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
+	default:
+		return nil, UnsupportedDriver
+	}
+
+	params := gsc.Parameters
+	if params == nil {
+		params = map[string]string{}
+		gsc.Parameters = params
+	}
+	params["clusterID"] = clientProfileName
+	params["csi.storage.k8s.io/group-snapshotter-secret-name"] = provisionerSecretName
+	params["csi.storage.k8s.io/group-snapshotter-secret-namespace"] = operatorNamespace
+	AddLabel(gsc, storageIdLabelKey, storageId)
+	return gsc, nil
+}
diff --git a/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/snapshotclasses.go b/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/snapshotclasses.go
index 584b493c05..1ff6fd329b 100644
--- a/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/snapshotclasses.go
+++ b/metrics/vendor/github.com/red-hat-storage/ocs-operator/v4/controllers/util/snapshotclasses.go
@@ -1,9 +1,14 @@
 package util
 
 import (
+	"context"
+	"errors"
 	"fmt"
+
 	snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
+	ocsv1a1 "github.com/red-hat-storage/ocs-operator/api/v4/v1alpha1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 // SnapshotterType represents a snapshotter type
@@ -15,6 +20,10 @@ const (
 	NfsSnapshotter    SnapshotterType = "nfs"
 )
 
+var (
+	UnsupportedDriver = errors.New("unsupportedDriver")
+)
+
 // GenerateNameForSnapshotClass function generates 'SnapshotClass' name.
 // 'snapshotType' can be: 'RbdSnapshotter' or 'CephfsSnapshotter' or 'NfsSnapshotter'
 func GenerateNameForSnapshotClass(storageClusterName string, snapshotType SnapshotterType) string {
@@ -94,3 +103,51 @@ func NewDefaultNfsSnapshotClass(
 	}
 	return sc
 }
+
+func VolumeSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*snapapi.VolumeSnapshotClass, error) {
+	snapshotClass := &snapapi.VolumeSnapshotClass{}
+	snapshotClass.Name = volumeSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(snapshotClass), snapshotClass); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch snapshotClass.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
+	default:
+		return nil, UnsupportedDriver
+	}
+
+	params := snapshotClass.Parameters
+	if params == nil {
+		params = map[string]string{}
+		snapshotClass.Parameters = params
+	}
+	params["clusterID"] = clientProfileName
+	params["csi.storage.k8s.io/snapshotter-secret-name"] = provisionerSecretName
+	params["csi.storage.k8s.io/snapshotter-secret-namespace"] = operatorNamespace
+	AddLabel(snapshotClass, storageIdLabelKey, storageId)
+	return snapshotClass, nil
+}
diff --git a/services/provider/server/server.go b/services/provider/server/server.go
index f618d61e73..043164cb31 100644
--- a/services/provider/server/server.go
+++ b/services/provider/server/server.go
@@ -1476,6 +1476,7 @@ func (s *OCSProviderServer) getKubeResources(ctx context.Context, consumer *ocsv
 	}
 
 	kubeResources, err = s.appendVolumeSnapshotClassKubeResources(
+		ctx,
 		kubeResources,
 		consumer,
 		consumerConfig,
@@ -1488,6 +1489,7 @@ func (s *OCSProviderServer) getKubeResources(ctx context.Context, consumer *ocsv
 	}
 
 	kubeResources, err = s.appendVolumeGroupSnapshotClassKubeResources(
+		ctx,
 		kubeResources,
 		consumer,
 		consumerConfig,
@@ -1840,6 +1842,7 @@ func (s *OCSProviderServer) appendStorageClassKubeResources(
 }
 
 func (s *OCSProviderServer) appendVolumeSnapshotClassKubeResources(
+	ctx context.Context,
 	kubeResources []client.Object,
 	consumer *ocsv1alpha1.StorageConsumer,
 	consumerConfig util.StorageConsumerResources,
@@ -1878,21 +1881,40 @@ func (s *OCSProviderServer) appendVolumeSnapshotClassKubeResources(
 		}
 	}
 	for i := range consumer.Spec.VolumeSnapshotClasses {
+		var snapshotClass *snapapi.VolumeSnapshotClass
+		var err error
 		snapshotClassName := consumer.Spec.VolumeSnapshotClasses[i].Name
 		vscGen := vscMap[snapshotClassName]
 		if vscGen != nil {
 			vsc := vscGen()
 			vsc.Name = snapshotClassName
-			kubeResources = append(kubeResources, vsc)
 		} else {
-			//TODO: Day-2 snapshotclass
-			klog.Warningf("encountered an unexpected volume snapshot class: %s", snapshotClassName)
+			snapshotClass, err = util.VolumeSnapshotClassFromExisting(
+				ctx,
+				s.client,
+				snapshotClassName,
+				consumer,
+				consumerConfig,
+				rbdStorageId,
+				cephFsStorageId,
+				cephFsStorageId,
+			)
+		}
+		if kerrors.IsNotFound(err) {
+			klog.Warningf("VolumeSnapshotClass with name %s doesn't exist in the cluster", snapshotClassName)
+		} else if errors.Is(err, util.UnsupportedDriver) {
+			klog.Warningf("Encountered unsupported driver in volume snapshot class %s", snapshotClassName)
+		} else if snapshotClass == nil {
+			klog.Warningf("The name %s does not points to a builtin or an existing volumesnapshot class, skipping", snapshotClassName)
+		} else {
+			kubeResources = append(kubeResources, snapshotClass)
 		}
 	}
 	return kubeResources, nil
 }
 
 func (s *OCSProviderServer) appendVolumeGroupSnapshotClassKubeResources(
+	ctx context.Context,
 	kubeResources []client.Object,
 	consumer *ocsv1alpha1.StorageConsumer,
 	consumerConfig util.StorageConsumerResources,
@@ -1924,15 +1946,33 @@ func (s *OCSProviderServer) appendVolumeGroupSnapshotClassKubeResources(
 		}
 	}
 	for i := range consumer.Spec.VolumeGroupSnapshotClasses {
+		var groupSnapshotClass *groupsnapapi.VolumeGroupSnapshotClass
+		var err error
 		groupSnapshotClassName := consumer.Spec.VolumeGroupSnapshotClasses[i].Name
 		vgscGen := vgscMap[groupSnapshotClassName]
 		if vgscGen != nil {
 			vgsc := vgscGen()
 			vgsc.Name = groupSnapshotClassName
-			kubeResources = append(kubeResources, vgsc)
 		} else {
-			//TODO: Day-2 groupSnapshotclass
-			klog.Warningf("encountered an unexpected volume group snapshot class: %s", groupSnapshotClassName)
+			groupSnapshotClass, err = util.VolumeGroupSnapshotClassFromExisting(
+				ctx,
+				s.client,
+				groupSnapshotClassName,
+				consumer,
+				consumerConfig,
+				rbdStorageId,
+				cephFsStorageId,
+				cephFsStorageId,
+			)
+		}
+		if kerrors.IsNotFound(err) {
+			klog.Warningf("VolumeGroupSnapshotClass with name %s doesn't exist in the cluster", groupSnapshotClassName)
+		} else if errors.Is(err, util.UnsupportedDriver) {
+			klog.Warningf("Encountered unsupported driver in volume group snapshot class %s", groupSnapshotClassName)
+		} else if groupSnapshotClass == nil {
+			klog.Warningf("The name %s does not points to a builtin or an existing volume group snapshot class, skipping", groupSnapshotClassName)
+		} else {
+			kubeResources = append(kubeResources, groupSnapshotClass)
 		}
 	}
 	return kubeResources, nil


Reviews:
user: login: rewantsoni
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-14T13:52:04Z
user: login: leelavg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T14:01:37Z
user: login: leelavg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T14:03:06Z
user: login: nb-ohad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T20:52:47Z

Review comments:
diff_hunk: @@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
path: controllers/util/groupsnapshotclasses.go
user: login: rewantsoni
body: Is the expectation that when the user creates this groupsnapshot class, they will provide it with "pool"/"fsName" parameters? Or do we want to fill in some default values?
created_at: 2025-04-14T13:49:40Z
author_association: MEMBER
diff_hunk: @@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
path: controllers/util/groupsnapshotclasses.go
user: login: rewantsoni
body: NFS groupsnapshot is not supported right?
created_at: 2025-04-14T13:49:59Z
author_association: MEMBER
diff_hunk: @@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
path: controllers/util/groupsnapshotclasses.go
user: login: leelavg
body: > they will provide it with "pool"/"fsName" parameters
- yes, that's the expectation which is inline w/ current [documented](https://docs.redhat.com/en/documentation/red_hat_openshift_data_foundation/4.18/html/managing_and_allocating_storage_resources/storage-classes_rhodf#creating-storage-classes-and-pools_rhodf) procedures
created_at: 2025-04-14T14:01:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
path: controllers/util/groupsnapshotclasses.go
user: login: leelavg
body: then this case will never be hit, I don't think that'll be an issue until we support that and these params will differ.
created_at: 2025-04-14T14:03:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,3 +82,51 @@ func NewDefaultCephFsGroupSnapshotClass(
 	}
 	return gsc
 }
+
+func VolumeGroupSnapshotClassFromExisting(
+	ctx context.Context,
+	kubeClient client.Client,
+	volumeGroupSnapshotClassName string,
+	consumer *ocsv1a1.StorageConsumer,
+	consumerConfig StorageConsumerResources,
+	rbdStorageId,
+	cephFsStorageId,
+	nfsStorageId string,
+) (*groupsnapapi.VolumeGroupSnapshotClass, error) {
+	gsc := &groupsnapapi.VolumeGroupSnapshotClass{}
+	gsc.Name = volumeGroupSnapshotClassName
+	if err := kubeClient.Get(ctx, client.ObjectKeyFromObject(gsc), gsc); err != nil {
+		return nil, err
+	}
+	clientProfileName := ""
+	provisionerSecretName := ""
+	storageId := ""
+	operatorNamespace := consumer.Status.Client.OperatorNamespace
+	switch gsc.Driver {
+	case RbdDriverName:
+		clientProfileName = consumerConfig.GetRbdClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiRbdProvisionerSecretName()
+		storageId = rbdStorageId
+	case CephFSDriverName:
+		clientProfileName = consumerConfig.GetCephFsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiCephFsProvisionerSecretName()
+		storageId = cephFsStorageId
+	case NfsDriverName:
+		clientProfileName = consumerConfig.GetNfsClientProfileName()
+		provisionerSecretName = consumerConfig.GetCsiNfsProvisionerSecretName()
+		storageId = nfsStorageId
path: controllers/util/groupsnapshotclasses.go
user: login: nb-ohad
body: When we do declare support for this the params will NOT differ as out NFS implementatin is just a protocol layer on top of CephFS. Which means, to the best of my understanding, that storageId should and can be the same 
created_at: 2025-04-14T20:52:47Z
author_association: CONTRIBUTOR

PR comments:
user: login: rewantsoni
created_at: 2025-04-10T11:09:52Z
body: I think you are missing RBACs for ocs-provider-server to get V[G]SC
author_association: MEMBER
user: login: leelavg
created_at: 2025-04-14T13:33:46Z
body: rebased on main.
author_association: CONTRIBUTOR
user: login: nb-ohad
created_at: 2025-04-14T20:53:40Z
body: /lgtm
author_association: CONTRIBUTOR
user: login: openshift-ci[bot]
created_at: 2025-04-14T20:53:49Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/red-hat-storage/ocs-operator/pull/3153#" title="Author self-approved">leelavg</a>*, *<a href="https://github.com/red-hat-storage/ocs-operator/pull/3153#issuecomment-2802960900" title="LGTM">nb-ohad</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=red-hat-storage%2Focs-operator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/red-hat-storage/ocs-operator/blob/main/OWNERS)~~ [nb-ohad]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR
user: login: leelavg
created_at: 2025-04-15T03:36:23Z
body: /cherrypick release-4.19
author_association: CONTRIBUTOR
user: login: openshift-cherrypick-robot
created_at: 2025-04-15T03:37:03Z
body: @leelavg: new pull request created: #3161

<details>

In response to [this](https://github.com/red-hat-storage/ocs-operator/pull/3153#issuecomment-2803686347):

>/cherrypick release-4.19


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
author_association: NONE