From c43d1323bada9a1133f59f64f89ff1b651ec7763 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 b5825ee0216..888453bd1db 100644 --- a/docs/deploy-cephfs.md +++ b/docs/deploy-cephfs.md @@ -79,6 +79,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", see command line arguments. | | `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 2db52a0a62e..2e5fa71822c 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 36d86bb6751..a4833101674 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 36d5fd072b3..504019745eb 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 }