util: added GetCephFSMountOptions method

This commit adds GetCephFSMountOptions util method which returns
KernelMountOptions and fuseMountOptions for cluster `clusterID`.

Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
Praveen M 2023-11-07 15:27:10 +05:30 committed by mergify[bot]
parent 593d9c3b60
commit 1e4ff115a7
3 changed files with 133 additions and 55 deletions

View File

@ -24,6 +24,12 @@ kind: ConfigMap
# The "cephFS.netNamespaceFilePath" fields are the various network namespace # The "cephFS.netNamespaceFilePath" fields are the various network namespace
# path for the Ceph cluster identified by the <cluster-id>, This will be used # path for the Ceph cluster identified by the <cluster-id>, This will be used
# by the CephFS CSI plugin to execute the mount -t in the # by the CephFS CSI plugin to execute the mount -t in the
# The "cephFS.kernelMountOptions" fields are comma separated mount options
# for `Ceph kernel client`. Setting this will override the kernelmountoptions
# command line flag.
# The "cephFS.fuseMountOptions" fields are common separated mount options
# for `Ceph FUSE driver`. Setting this will override the fusemountoptions
# command line flag.
# network namespace specified by the "cephFS.netNamespaceFilePath". # network namespace specified by the "cephFS.netNamespaceFilePath".
# The "nfs.netNamespaceFilePath" fields are the various network namespace # The "nfs.netNamespaceFilePath" fields are the various network namespace
# path for the Ceph cluster identified by the <cluster-id>, This will be used # path for the Ceph cluster identified by the <cluster-id>, This will be used
@ -68,6 +74,8 @@ data:
"cephFS": { "cephFS": {
"subvolumeGroup": "<subvolumegroup for cephFS volumes>" "subvolumeGroup": "<subvolumegroup for cephFS volumes>"
"netNamespaceFilePath": "<kubeletRootPath>/plugins/cephfs.csi.ceph.com/net", "netNamespaceFilePath": "<kubeletRootPath>/plugins/cephfs.csi.ceph.com/net",
"kernelMountOptions": "<kernelMountOptions for cephFS volumes>",
"fuseMountOptions": "<fuseMountOptions for cephFS volumes>"
} }
"nfs": { "nfs": {
"netNamespaceFilePath": "<kubeletRootPath>/plugins/nfs.csi.ceph.com/net", "netNamespaceFilePath": "<kubeletRootPath>/plugins/nfs.csi.ceph.com/net",

View File

@ -43,30 +43,40 @@ type ClusterInfo struct {
// Monitors is monitor list for corresponding cluster ID // Monitors is monitor list for corresponding cluster ID
Monitors []string `json:"monitors"` Monitors []string `json:"monitors"`
// CephFS contains CephFS specific options // CephFS contains CephFS specific options
CephFS struct { CephFS CephFS `json:"cephFS"`
// RBD Contains RBD specific options
RBD RBD `json:"rbd"`
// NFS contains NFS specific options
NFS NFS `json:"nfs"`
// Read affinity map options
ReadAffinity ReadAffinity `json:"readAffinity"`
}
type CephFS struct {
// symlink filepath for the network namespace where we need to execute commands. // symlink filepath for the network namespace where we need to execute commands.
NetNamespaceFilePath string `json:"netNamespaceFilePath"` NetNamespaceFilePath string `json:"netNamespaceFilePath"`
// SubvolumeGroup contains the name of the SubvolumeGroup for CSI volumes // SubvolumeGroup contains the name of the SubvolumeGroup for CSI volumes
SubvolumeGroup string `json:"subvolumeGroup"` SubvolumeGroup string `json:"subvolumeGroup"`
} `json:"cephFS"` // KernelMountOptions contains the kernel mount options for CephFS volumes
KernelMountOptions string `json:"kernelMountOptions"`
// RBD Contains RBD specific options // FuseMountOptions contains the fuse mount options for CephFS volumes
RBD struct { FuseMountOptions string `json:"fuseMountOptions"`
}
type RBD struct {
// symlink filepath for the network namespace where we need to execute commands. // symlink filepath for the network namespace where we need to execute commands.
NetNamespaceFilePath string `json:"netNamespaceFilePath"` NetNamespaceFilePath string `json:"netNamespaceFilePath"`
// RadosNamespace is a rados namespace in the pool // RadosNamespace is a rados namespace in the pool
RadosNamespace string `json:"radosNamespace"` RadosNamespace string `json:"radosNamespace"`
} `json:"rbd"` }
// NFS contains NFS specific options
NFS struct { type NFS struct {
// symlink filepath for the network namespace where we need to execute commands. // symlink filepath for the network namespace where we need to execute commands.
NetNamespaceFilePath string `json:"netNamespaceFilePath"` NetNamespaceFilePath string `json:"netNamespaceFilePath"`
} `json:"nfs"` }
// Read affinity map options
ReadAffinity struct { type ReadAffinity struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
CrushLocationLabels []string `json:"crushLocationLabels"` CrushLocationLabels []string `json:"crushLocationLabels"`
} `json:"readAffinity"`
} }
// Expected JSON structure in the passed in config file is, // Expected JSON structure in the passed in config file is,
@ -226,3 +236,13 @@ func GetCrushLocationLabels(pathToConfig, clusterID string) (bool, string, error
return true, crushLocationLabels, nil return true, crushLocationLabels, nil
} }
// GetCephFSMountOptions returns the `kernelMountOptions` and `fuseMountOptions` for CephFS volumes.
func GetCephFSMountOptions(pathToConfig, clusterID string) (string, string, error) {
cluster, err := readClusterInfo(pathToConfig, clusterID)
if err != nil {
return "", "", err
}
return cluster.CephFS.KernelMountOptions, cluster.CephFS.FuseMountOptions, nil
}

View File

@ -168,20 +168,14 @@ func TestGetRBDNetNamespaceFilePath(t *testing.T) {
{ {
ClusterID: "cluster-1", ClusterID: "cluster-1",
Monitors: []string{"ip-1", "ip-2"}, Monitors: []string{"ip-1", "ip-2"},
RBD: struct { RBD: RBD{
NetNamespaceFilePath string `json:"netNamespaceFilePath"`
RadosNamespace string `json:"radosNamespace"`
}{
NetNamespaceFilePath: "/var/lib/kubelet/plugins/rbd.ceph.csi.com/cluster1-net", NetNamespaceFilePath: "/var/lib/kubelet/plugins/rbd.ceph.csi.com/cluster1-net",
}, },
}, },
{ {
ClusterID: "cluster-2", ClusterID: "cluster-2",
Monitors: []string{"ip-3", "ip-4"}, Monitors: []string{"ip-3", "ip-4"},
RBD: struct { RBD: RBD{
NetNamespaceFilePath string `json:"netNamespaceFilePath"`
RadosNamespace string `json:"radosNamespace"`
}{
NetNamespaceFilePath: "/var/lib/kubelet/plugins/rbd.ceph.csi.com/cluster2-net", NetNamespaceFilePath: "/var/lib/kubelet/plugins/rbd.ceph.csi.com/cluster2-net",
}, },
}, },
@ -244,20 +238,14 @@ func TestGetCephFSNetNamespaceFilePath(t *testing.T) {
{ {
ClusterID: "cluster-1", ClusterID: "cluster-1",
Monitors: []string{"ip-1", "ip-2"}, Monitors: []string{"ip-1", "ip-2"},
CephFS: struct { CephFS: CephFS{
NetNamespaceFilePath string `json:"netNamespaceFilePath"`
SubvolumeGroup string `json:"subvolumeGroup"`
}{
NetNamespaceFilePath: "/var/lib/kubelet/plugins/cephfs.ceph.csi.com/cluster1-net", NetNamespaceFilePath: "/var/lib/kubelet/plugins/cephfs.ceph.csi.com/cluster1-net",
}, },
}, },
{ {
ClusterID: "cluster-2", ClusterID: "cluster-2",
Monitors: []string{"ip-3", "ip-4"}, Monitors: []string{"ip-3", "ip-4"},
CephFS: struct { CephFS: CephFS{
NetNamespaceFilePath string `json:"netNamespaceFilePath"`
SubvolumeGroup string `json:"subvolumeGroup"`
}{
NetNamespaceFilePath: "/var/lib/kubelet/plugins/cephfs.ceph.csi.com/cluster2-net", NetNamespaceFilePath: "/var/lib/kubelet/plugins/cephfs.ceph.csi.com/cluster2-net",
}, },
}, },
@ -320,18 +308,14 @@ func TestGetNFSNetNamespaceFilePath(t *testing.T) {
{ {
ClusterID: "cluster-1", ClusterID: "cluster-1",
Monitors: []string{"ip-1", "ip-2"}, Monitors: []string{"ip-1", "ip-2"},
NFS: struct { NFS: NFS{
NetNamespaceFilePath string `json:"netNamespaceFilePath"`
}{
NetNamespaceFilePath: "/var/lib/kubelet/plugins/nfs.ceph.csi.com/cluster1-net", NetNamespaceFilePath: "/var/lib/kubelet/plugins/nfs.ceph.csi.com/cluster1-net",
}, },
}, },
{ {
ClusterID: "cluster-2", ClusterID: "cluster-2",
Monitors: []string{"ip-3", "ip-4"}, Monitors: []string{"ip-3", "ip-4"},
NFS: struct { NFS: NFS{
NetNamespaceFilePath string `json:"netNamespaceFilePath"`
}{
NetNamespaceFilePath: "/var/lib/kubelet/plugins/nfs.ceph.csi.com/cluster2-net", NetNamespaceFilePath: "/var/lib/kubelet/plugins/nfs.ceph.csi.com/cluster2-net",
}, },
}, },
@ -413,10 +397,7 @@ func TestGetReadAffinityOptions(t *testing.T) {
csiConfig := []ClusterInfo{ csiConfig := []ClusterInfo{
{ {
ClusterID: "cluster-1", ClusterID: "cluster-1",
ReadAffinity: struct { ReadAffinity: ReadAffinity{
Enabled bool `json:"enabled"`
CrushLocationLabels []string `json:"crushLocationLabels"`
}{
Enabled: true, Enabled: true,
CrushLocationLabels: []string{ CrushLocationLabels: []string{
"topology.kubernetes.io/region", "topology.kubernetes.io/region",
@ -427,10 +408,7 @@ func TestGetReadAffinityOptions(t *testing.T) {
}, },
{ {
ClusterID: "cluster-2", ClusterID: "cluster-2",
ReadAffinity: struct { ReadAffinity: ReadAffinity{
Enabled bool `json:"enabled"`
CrushLocationLabels []string `json:"crushLocationLabels"`
}{
Enabled: true, Enabled: true,
CrushLocationLabels: []string{ CrushLocationLabels: []string{
"topology.kubernetes.io/region", "topology.kubernetes.io/region",
@ -439,10 +417,7 @@ func TestGetReadAffinityOptions(t *testing.T) {
}, },
{ {
ClusterID: "cluster-3", ClusterID: "cluster-3",
ReadAffinity: struct { ReadAffinity: ReadAffinity{
Enabled bool `json:"enabled"`
CrushLocationLabels []string `json:"crushLocationLabels"`
}{
Enabled: false, Enabled: false,
CrushLocationLabels: []string{ CrushLocationLabels: []string{
"topology.io/rack", "topology.io/rack",
@ -478,3 +453,78 @@ func TestGetReadAffinityOptions(t *testing.T) {
}) })
} }
} }
func TestGetCephFSMountOptions(t *testing.T) {
t.Parallel()
tests := []struct {
name string
clusterID string
wantKernelMntOptions string
wantFuseMntOptions string
}{
{
name: "cluster-1 with non-empty mount options",
clusterID: "cluster-1",
wantKernelMntOptions: "crc",
wantFuseMntOptions: "ro",
},
{
name: "cluster-2 with empty mount options",
clusterID: "cluster-2",
wantKernelMntOptions: "",
wantFuseMntOptions: "",
},
{
name: "cluster-3 with no mount options",
clusterID: "cluster-3",
wantKernelMntOptions: "",
wantFuseMntOptions: "",
},
}
csiConfig := []ClusterInfo{
{
ClusterID: "cluster-1",
CephFS: CephFS{
KernelMountOptions: "crc",
FuseMountOptions: "ro",
},
},
{
ClusterID: "cluster-2",
CephFS: CephFS{
KernelMountOptions: "",
FuseMountOptions: "",
},
},
{
ClusterID: "cluster-3",
CephFS: CephFS{},
},
}
csiConfigFileContent, err := json.Marshal(csiConfig)
if err != nil {
t.Errorf("failed to marshal csi config info %v", err)
}
tmpConfPath := t.TempDir() + "/ceph-csi.json"
err = os.WriteFile(tmpConfPath, csiConfigFileContent, 0o600)
if err != nil {
t.Errorf("failed to write %s file content: %v", CsiConfigFile, err)
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
kernelMntOptions, fuseMntOptions, err := GetCephFSMountOptions(tmpConfPath, tc.clusterID)
if err != nil {
t.Errorf("GetCephFSMountOptions() error = %v", err)
}
if kernelMntOptions != tc.wantKernelMntOptions || fuseMntOptions != tc.wantFuseMntOptions {
t.Errorf("GetCephFSMountOptions() = (%v, %v), want (%v, %v)",
kernelMntOptions, fuseMntOptions, tc.wantKernelMntOptions, tc.wantFuseMntOptions,
)
}
})
}
}