Skip to content

Commit

Permalink
csi: option to customize csi driver name prefix
Browse files Browse the repository at this point in the history
For now we are using the operator namespace name
as the prefix for the csi driver, This PR provides
an option for the users if someone wants to have
their own prefix for the csi driver, if someone tries
to change the prefix for existing csi diver rook
operator will fail to reconcile the csi driver.

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
  • Loading branch information
Madhu-1 committed Jan 25, 2024
1 parent e8002a6 commit 75be669
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 2 deletions.
1 change: 1 addition & 0 deletions Documentation/Helm-Charts/operator-chart.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ The following table lists the configurable parameters of the rook-operator chart
| `csi.csiCephFSPluginVolume` | The volume of the CephCSI CephFS plugin DaemonSet | `nil` |
| `csi.csiCephFSPluginVolumeMount` | The volume mounts of the CephCSI CephFS plugin DaemonSet | `nil` |
| `csi.csiCephFSProvisionerResource` | CEPH CSI CephFS provisioner resource requirement list | see values.yaml |
| `csi.csiDriverNamePrefix` | CSI driver name prefix for cephfs, rbd and nfs. | `namespace name where rook-ceph operator is deployed` |
| `csi.csiLeaderElectionLeaseDuration` | Duration in seconds that non-leader candidates will wait to force acquire leadership. | `137s` |
| `csi.csiLeaderElectionRenewDeadline` | Deadline in seconds that the acting leader will retry refreshing leadership before giving up. | `107s` |
| `csi.csiLeaderElectionRetryPeriod` | Retry period in seconds the LeaderElector clients should wait between tries of actions. | `26s` |
Expand Down
3 changes: 3 additions & 0 deletions deploy/charts/rook-ceph/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ data:
CSI_ENABLE_OMAP_GENERATOR: {{ .Values.csi.enableOMAPGenerator | quote }}
CSI_ENABLE_HOST_NETWORK: {{ .Values.csi.enableCSIHostNetwork | quote }}
CSI_ENABLE_METADATA: {{ .Values.csi.enableMetadata | quote }}
{{- if .Values.csi.csiDriverNamePrefix }}
CSI_DRIVER_NAME_PREFIX: {{ .Values.csi.csiDriverNamePrefix | quote }}
{{- end }}
{{- if .Values.csi.pluginPriorityClassName }}
CSI_PLUGIN_PRIORITY_CLASSNAME: {{ .Values.csi.pluginPriorityClassName | quote }}
{{- end }}
Expand Down
4 changes: 4 additions & 0 deletions deploy/charts/rook-ceph/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ csi:
# @default -- `0`
sidecarLogLevel:

# -- CSI driver name prefix for cephfs, rbd and nfs.
# @default -- `namespace name where rook-ceph operator is deployed`
csiDriverNamePrefix:

# -- CSI RBD plugin daemonset update strategy, supported values are OnDelete and RollingUpdate
# @default -- `RollingUpdate`
rbdPluginUpdateStrategy:
Expand Down
4 changes: 4 additions & 0 deletions deploy/examples/operator-openshift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,10 @@ data:
# (Optional) Retry period in seconds the LeaderElector clients should wait between tries of actions. Defaults to 26 seconds.
# CSI_LEADER_ELECTION_RETRY_PERIOD: "26s"

# csi driver name prefix for cephfs, rbd and nfs. if not specified, default
# will be the namespace name where rook-ceph operator is deployed.
# CSI_DRIVER_NAME_PREFIX: "rook-ceph"

# Rook Discover toleration. Will tolerate all taints with all keys.
# (Optional) Rook Discover tolerations list. Put here list of taints you want to tolerate in YAML format.
# DISCOVER_TOLERATIONS: |
Expand Down
4 changes: 4 additions & 0 deletions deploy/examples/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ data:
# Supported values from 0 to 5. 0 for general useful logs (the default), 5 for trace level verbosity.
# CSI_SIDECAR_LOG_LEVEL: "0"

# csi driver name prefix for cephfs, rbd and nfs. if not specified, default
# will be the namespace name where rook-ceph operator is deployed.
# CSI_DRIVER_NAME_PREFIX: "rook-ceph"

# Set replicas for csi provisioner deployment.
CSI_PROVISIONER_REPLICAS: "2"

Expand Down
3 changes: 3 additions & 0 deletions pkg/operator/ceph/csi/csi.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,5 +320,8 @@ func (r *ReconcileCSI) setParams(ver *version.Info) error {
if strings.EqualFold(k8sutil.GetValue(r.opConfig.Parameters, "CSI_NFS_ATTACH_REQUIRED", "true"), "false") {
CSIParam.NFSAttachRequired = false
}

CSIParam.DriverNamePrefix = k8sutil.GetValue(r.opConfig.Parameters, "CSI_DRIVER_NAME_PREFIX", "")

return nil
}
92 changes: 90 additions & 2 deletions pkg/operator/ceph/csi/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
_ "embed"
"fmt"
"strings"
"time"

"github.com/rook/rook/pkg/operator/ceph/cluster/telemetry"
Expand All @@ -36,6 +37,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes"

cephcsi "github.com/ceph/ceph-csi/api/deploy/kubernetes"
)
Expand Down Expand Up @@ -263,11 +265,17 @@ const (
csiCephFSProvisioner = "csi-cephfsplugin-provisioner"
csiNFSProvisioner = "csi-nfsplugin-provisioner"

// cephcsi container names
csiRBDContainerName = "csi-rbdplugin"
csiCephFSContainerName = "csi-cephfsplugin"
csiNFSContainerName = "csi-nfsplugin"

RBDDriverShortName = "rbd"
CephFSDriverShortName = "cephfs"
NFSDriverShortName = "nfs"
rbdDriverSuffix = "rbd.csi.ceph.com"
cephFSDriverSuffix = "cephfs.csi.ceph.com"
nfsDriverSuffix = "nfs.csi.ceph.com"
)

func CSIEnabled() bool {
Expand Down Expand Up @@ -307,11 +315,55 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
Namespace: r.opConfig.OperatorNamespace,
}

tp.DriverNamePrefix = fmt.Sprintf("%s.", r.opConfig.OperatorNamespace)
if strings.HasSuffix(tp.DriverNamePrefix, ".") {
// As operator is adding a dot at the end of the prefix, we should not
// allow the user to add a dot at the end of the prefix. as it will
// result in two dots at the end of the prefix. which cases the csi
// driver name creation failure
return errors.Errorf("driver name prefix %q should not end with a dot", tp.DriverNamePrefix)
}

if EnableRBD {
rbdDriverNamePrefix, err := getCSIDriverNamePrefixFromDeployment(r.opManagerContext, r.context.Clientset, r.opConfig.OperatorNamespace, csiRBDProvisioner, "csi-rbdplugin")
if err != nil {
return err
}
if rbdDriverNamePrefix != "" && rbdDriverNamePrefix != tp.DriverNamePrefix {
return errors.Errorf("rbd driver already exists with prefix %q, cannot use prefix %q", rbdDriverNamePrefix, tp.DriverNamePrefix)
}
}

if EnableCephFS {
cephFSDriverNamePrefix, err := getCSIDriverNamePrefixFromDeployment(r.opManagerContext, r.context.Clientset, r.opConfig.OperatorNamespace, csiCephFSProvisioner, "csi-cephfsplugin")
if err != nil {
return err
}
if cephFSDriverNamePrefix != "" && cephFSDriverNamePrefix != tp.DriverNamePrefix {
return errors.Errorf("cephFS driver already exists with prefix %q, cannot use prefix %q", cephFSDriverNamePrefix, tp.DriverNamePrefix)
}
}

if EnableNFS {
nfsDriverNamePrefix, err := getCSIDriverNamePrefixFromDeployment(r.opManagerContext, r.context.Clientset, r.opConfig.OperatorNamespace, csiNFSProvisioner, "csi-nfsplugin")
if err != nil {
return err
}
if nfsDriverNamePrefix != "" && nfsDriverNamePrefix != tp.DriverNamePrefix {
return errors.Errorf("nfs driver already exists with prefix %q, cannot use prefix %q", nfsDriverNamePrefix, tp.DriverNamePrefix)
}
}

// If the driver name prefix is not set, set it to the operator namespace.
if tp.DriverNamePrefix == "" {
tp.DriverNamePrefix = r.opConfig.OperatorNamespace
}
// Add a dot at the end of the prefix for having the driver name prefix
// with format <prefix>.<driver-name>
tp.DriverNamePrefix = fmt.Sprintf("%s.", tp.DriverNamePrefix)

CephFSDriverName = tp.DriverNamePrefix + cephFSDriverSuffix
RBDDriverName = tp.DriverNamePrefix + rbdDriverSuffix
NFSDriverName = tp.DriverNamePrefix + "nfs.csi.ceph.com"
NFSDriverName = tp.DriverNamePrefix + nfsDriverSuffix

tp.Param.MountCustomCephConf = CustomCSICephConfigExists

Expand Down Expand Up @@ -935,3 +987,39 @@ func GenerateNetNamespaceFilePath(ctx context.Context, client client.Client, clu
func generateNetNamespaceFilePath(kubeletDirPath, driverFullName, clusterNamespace string) string {
return fmt.Sprintf("%s/plugins/%s/%s.net.ns", kubeletDirPath, driverFullName, clusterNamespace)
}

func getCSIDriverNamePrefixFromDeployment(ctx context.Context, clientset kubernetes.Interface, namespace, deploymentName, containerName string) (string, error) {
deployment, err := clientset.AppsV1().Deployments(namespace).Get(ctx, deploymentName, metav1.GetOptions{})
if kerrors.IsNotFound(err) {
return "", nil
}
if err != nil {
return "", errors.Wrapf(err, "failed to get deployment %q", deploymentName)
}

for _, container := range deployment.Spec.Template.Spec.Containers {
if container.Name == containerName {
for _, arg := range container.Args {
if prefix, ok := getPrefixFromArg(arg); ok {
return prefix, nil
}
}
}
}

return "", errors.Errorf("failed to get CSI driver name from deployment %q", deploymentName)
}

func getPrefixFromArg(arg string) (string, bool) {
if strings.Contains(arg, "--drivername=") {
driverName := strings.Split(arg, "=")[1]

for _, suffix := range []string{rbdDriverSuffix, cephFSDriverSuffix, nfsDriverSuffix} {
// Add a dot as we are adding it to the Prefix
if prefix, ok := strings.CutSuffix(driverName, "."+suffix); ok {
return prefix, true
}
}
}
return "", false
}
90 changes: 90 additions & 0 deletions pkg/operator/ceph/csi/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ import (
"github.com/rook/rook/pkg/operator/k8sutil"
testop "github.com/rook/rook/pkg/operator/test"
"github.com/stretchr/testify/assert"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
kfake "k8s.io/client-go/kubernetes/fake"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

Expand Down Expand Up @@ -129,3 +131,91 @@ func TestGenerateNetNamespaceFilePath(t *testing.T) {
assert.Equal(t, "/foo/plugins/rook-ceph.cephfs.csi.ceph.com/rook-ceph.net.ns", netNsFilePath)
})
}

func Test_getCSIDriverNamePrefixFromDeployment(t *testing.T) {
namespace := "test"
deployment := func(name, containerName, drivernameSuffix string) *apps.Deployment {
return &apps.Deployment{
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
Spec: apps.DeploymentSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: containerName,
Args: []string{
"--drivername=test-prefix." + drivernameSuffix,
},
},
},
},
},
},
}
}
clientset := kfake.NewSimpleClientset()

ctx := context.TODO()
csidrivers := []struct {
testCaseName string
deploymentName string
containerName string
driverNameSuffix string
expectedPrefix string
}{
{
"get csi driver name prefix for rbd when deployment exists",
csiRBDProvisioner,
csiRBDContainerName,
rbdDriverSuffix,
"test-prefix",
},
{
"get csi driver name prefix for rbd when deployment does not exist",
"",
"csi-rbdplugin",
"",
"",
},
{
"get csi driver name prefix for cephfs when deployment exists",
csiCephFSProvisioner,
csiCephFSContainerName,
cephFSDriverSuffix,
"test-prefix",
},
{
"get csi driver name prefix for cephfs when deployment does not exist",
"",
"csi-cephfsplugin",
"",
"",
},
{
"get csi driver name prefix for nfs when deployment exists",
csiNFSProvisioner,
csiNFSContainerName,
nfsDriverSuffix,
"test-prefix",
},
{
"get csi driver name prefix for nfs when deployment does not exist",
"",
"csi-nfsplugin",
"",
"",
},
}

for _, c := range csidrivers {
t.Run(c.testCaseName, func(t *testing.T) {
if c.deploymentName != "" {
_, err := clientset.AppsV1().Deployments(namespace).Create(ctx, deployment(c.deploymentName, c.containerName, c.driverNameSuffix), metav1.CreateOptions{})
assert.NoError(t, err)
}
prefix, err := getCSIDriverNamePrefixFromDeployment(ctx, clientset, namespace, c.deploymentName, c.containerName)
assert.NoError(t, err)
assert.Equal(t, c.expectedPrefix, prefix)
})
}
}

0 comments on commit 75be669

Please sign in to comment.