From 060ff8d25e0cb2f7d29fb0f902a482b33e5fca50 Mon Sep 17 00:00:00 2001 From: Poornima G Date: Wed, 28 Aug 2019 09:47:12 +0000 Subject: [PATCH] Add mount option for Cephfs The storage class already takes MountOptions(MountFlags), these are the bind mount options. Some of these options may not be recognised by the cephfs mount. Hence added a new parameterin Storage Class for - cephfs kernel mount options, - ceph-fuse mount options Ceph kernel mount options are different from ceph-fuse options, hence added two different parameters. Signed-off-by: Poornima G --- docs/deploy-cephfs.md | 2 ++ examples/cephfs/storageclass.yaml | 8 +++++++ pkg/cephfs/volumemounter.go | 6 +++++ pkg/cephfs/volumeoptions.go | 40 ++++++++++++++++++++++--------- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/docs/deploy-cephfs.md b/docs/deploy-cephfs.md index 2257cfa81..80e5fe7ca 100644 --- a/docs/deploy-cephfs.md +++ b/docs/deploy-cephfs.md @@ -78,6 +78,8 @@ is used to define in which namespace you want the configmaps to be stored | `fsName` | yes | CephFS filesystem name into which the volume shall be created | | `mounter` | no | Mount method to be used for this volume. Available options are `kernel` for Ceph kernel client and `fuse` for Ceph FUSE driver. Defaults to "default mounter". | | `pool` | no | Ceph pool into which volume data shall be stored | +| `kernelMountOptions` | no | Comma separated string of mount options accepted by cephfs kernel mounter, by default no options are passed. Check man mount.ceph for options. | +| `fuseMountOptions` | no | Comma separated string of mount options accepted by ceph-fuse mounter, by default no options are passed. | | `csi.storage.k8s.io/provisioner-secret-name`, `csi.storage.k8s.io/node-stage-secret-name` | for Kubernetes | Name of the Kubernetes Secret object containing Ceph client credentials. Both parameters should have the same value | | `csi.storage.k8s.io/provisioner-secret-namespace`, `csi.storage.k8s.io/node-stage-secret-namespace` | for Kubernetes | Namespaces of the above Secret objects | diff --git a/examples/cephfs/storageclass.yaml b/examples/cephfs/storageclass.yaml index edbfdbe78..30731b317 100644 --- a/examples/cephfs/storageclass.yaml +++ b/examples/cephfs/storageclass.yaml @@ -20,6 +20,14 @@ parameters: # (optional) Ceph pool into which volume data shall be stored # pool: cephfs_data + # (optional) Comma separated string of Ceph-fuse mount options. + # For eg: + # fuseMountOptions: debug + + # (optional) Comma separated string of Cephfs kernel mount options. + # Check man mount.ceph for mount options. For eg: + # kernelMountOptions: readdir_max_bytes=1048576,norbytes + # The secrets have to contain user and/or Ceph admin credentials. csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret csi.storage.k8s.io/provisioner-secret-namespace: default diff --git a/pkg/cephfs/volumemounter.go b/pkg/cephfs/volumemounter.go index 36d86bb67..a48331016 100644 --- a/pkg/cephfs/volumemounter.go +++ b/pkg/cephfs/volumemounter.go @@ -141,6 +141,9 @@ func mountFuse(ctx context.Context, mountPoint string, cr *util.Credentials, vol "-o", "nonempty", } + if volOptions.FuseMountOptions != "" { + args = append(args, ","+volOptions.FuseMountOptions) + } if volOptions.FsName != "" { args = append(args, "--client_mds_namespace="+volOptions.FsName) } @@ -197,6 +200,9 @@ func mountKernel(ctx context.Context, mountPoint string, cr *util.Credentials, v if volOptions.FsName != "" { optionsStr += fmt.Sprintf(",mds_namespace=%s", volOptions.FsName) } + if volOptions.KernelMountOptions != "" { + optionsStr += fmt.Sprintf(",%s", volOptions.KernelMountOptions) + } args = append(args, "-o", optionsStr) return execCommandErr(ctx, "mount", args[:]...) diff --git a/pkg/cephfs/volumeoptions.go b/pkg/cephfs/volumeoptions.go index 36d5fd072..504019745 100644 --- a/pkg/cephfs/volumeoptions.go +++ b/pkg/cephfs/volumeoptions.go @@ -27,17 +27,19 @@ import ( ) type volumeOptions struct { - RequestName string - Size int64 - ClusterID string - FsName string - FscID int64 - MetadataPool string - Monitors string `json:"monitors"` - Pool string `json:"pool"` - RootPath string `json:"rootPath"` - Mounter string `json:"mounter"` - ProvisionVolume bool `json:"provisionVolume"` + RequestName string + Size int64 + ClusterID string + FsName string + FscID int64 + MetadataPool string + Monitors string `json:"monitors"` + Pool string `json:"pool"` + RootPath string `json:"rootPath"` + Mounter string `json:"mounter"` + ProvisionVolume bool `json:"provisionVolume"` + KernelMountOptions string `json:"kernelMountOptions"` + FuseMountOptions string `json:"fuseMountOptions"` } func validateNonEmptyField(field, fieldName string) error { @@ -147,6 +149,14 @@ func newVolumeOptions(ctx context.Context, requestName string, size int64, volOp return nil, err } + if err = extractOptionalOption(&opts.KernelMountOptions, "kernelMountOptions", volOptions); err != nil { + return nil, err + } + + if err = extractOptionalOption(&opts.FuseMountOptions, "fuseMountOptions", volOptions); err != nil { + return nil, err + } + opts.RequestName = requestName opts.Size = size @@ -223,6 +233,14 @@ func newVolumeOptionsFromVolID(ctx context.Context, volID string, volOpt, secret return nil, nil, err } + if err = extractOptionalOption(&volOptions.KernelMountOptions, "kernelMountOptions", volOpt); err != nil { + return nil, nil, err + } + + if err = extractOptionalOption(&volOptions.FuseMountOptions, "fuseMountOptions", volOpt); err != nil { + return nil, nil, err + } + if err = extractMounter(&volOptions.Mounter, volOpt); err != nil { return nil, nil, err }