Skip to content

Commit 72acdcf

Browse files
authored
Merge pull request #1124 from savirg/nfs-options
Add mount options support in the createVolume method
2 parents 25d37f7 + c11a73b commit 72acdcf

File tree

4 files changed

+112
-1
lines changed

4 files changed

+112
-1
lines changed

pkg/csi_driver/controller.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const (
7575
attrVolume = "volume"
7676
attrSupportLockRelease = "supportLockRelease"
7777
attrFileProtocol = "fileProtocol"
78+
attrMountOptions = "mountOptions"
7879
)
7980

8081
// CreateVolume parameters
@@ -91,6 +92,7 @@ const (
9192
ParamNfsExportOptions = "nfs-export-options-on-create"
9293
paramMaxVolumeSize = "max-volume-size"
9394
paramFileProtocol = "protocol"
95+
paramMountOptions = "mount-options"
9496

9597
// Keys for PV and PVC parameters as reported by external-provisioner
9698
ParameterKeyPVCName = "csi.storage.k8s.io/pvc/name"
@@ -338,6 +340,12 @@ func (s *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolu
338340
return nil, status.Error(codes.Unavailable, err.Error())
339341
}
340342
resp := &csi.CreateVolumeResponse{Volume: s.fileInstanceToCSIVolume(filer, modeInstance)}
343+
if mountOptions, ok := req.GetParameters()[paramMountOptions]; ok && mountOptions != "" {
344+
if resp.Volume.VolumeContext == nil {
345+
resp.Volume.VolumeContext = make(map[string]string)
346+
}
347+
resp.Volume.VolumeContext[attrMountOptions] = mountOptions
348+
}
341349

342350
klog.Infof("CreateVolume succeeded: %+v", resp)
343351
return resp, nil
@@ -679,7 +687,7 @@ func (s *controllerServer) generateNewFileInstance(name string, capBytes int64,
679687
if s.config.features.FeatureNFSv4Support.Enabled {
680688
fileProtocol = v
681689
}
682-
case ParameterKeyLabels, ParameterKeyPVCName, ParameterKeyPVCNamespace, ParameterKeyPVName:
690+
case ParameterKeyLabels, ParameterKeyPVCName, ParameterKeyPVCNamespace, ParameterKeyPVName, paramMountOptions:
683691
case "csiprovisionersecretname", "csiprovisionersecretnamespace":
684692
default:
685693
return nil, fmt.Errorf("invalid parameter %q", k)

pkg/csi_driver/controller_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,40 @@ func TestCreateVolume(t *testing.T) {
711711
},
712712
},
713713
},
714+
{
715+
name: "create volume with mount options",
716+
req: &csi.CreateVolumeRequest{
717+
Name: testCSIVolume,
718+
VolumeCapabilities: []*csi.VolumeCapability{
719+
{
720+
AccessType: &csi.VolumeCapability_Mount{
721+
Mount: &csi.VolumeCapability_MountVolume{},
722+
},
723+
AccessMode: &csi.VolumeCapability_AccessMode{
724+
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
725+
},
726+
},
727+
},
728+
Parameters: map[string]string{
729+
"tier": zonalTier,
730+
"protocol": v4_1FileProtocol,
731+
"mount-options": "noatime,nodiratime",
732+
},
733+
},
734+
resp: &csi.CreateVolumeResponse{
735+
Volume: &csi.Volume{
736+
CapacityBytes: 1 * util.Tb,
737+
VolumeId: testVolumeID,
738+
VolumeContext: map[string]string{
739+
attrIP: testIP,
740+
attrVolume: newInstanceVolume,
741+
attrFileProtocol: v4_1FileProtocol,
742+
attrMountOptions: "noatime,nodiratime",
743+
},
744+
},
745+
},
746+
features: features,
747+
},
714748
}
715749

716750
for _, test := range cases {

pkg/csi_driver/node.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ func (s *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublish
9595
readOnly := req.GetReadonly()
9696
targetPath := req.GetTargetPath()
9797
stagingTargetPath := req.GetStagingTargetPath()
98+
volumeContext := req.GetVolumeContext()
9899
if len(targetPath) == 0 {
99100
return nil, status.Error(codes.InvalidArgument, "NodePublishVolume target path must be provided")
100101
}
@@ -159,6 +160,10 @@ func (s *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublish
159160
options = append(options, capMount.GetMountFlags()...)
160161
}
161162

163+
if mountOptions := volumeContext[attrMountOptions]; mountOptions != "" {
164+
options = append(options, mountOptions)
165+
}
166+
162167
err = s.mounter.Mount(stagingTargetPath, targetPath, fstype, options)
163168
if err != nil {
164169
klog.Errorf("Mount %q failed on node %s, cleaning up", targetPath, s.driver.config.NodeName)
@@ -334,6 +339,10 @@ func (s *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolu
334339
}
335340
}
336341

342+
if mountOptions := attr[attrMountOptions]; mountOptions != "" {
343+
options = append(options, mountOptions)
344+
}
345+
337346
err = s.mounter.Mount(source, stagingTargetPath, fstype, options)
338347
if err != nil {
339348
klog.Errorf("Mount %q failed on node %s, cleaning up", stagingTargetPath, s.driver.config.NodeName)

pkg/csi_driver/node_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,22 @@ func TestNodePublishVolume(t *testing.T) {
333333
},
334334
expectErr: true,
335335
},
336+
{
337+
name: "valid request with mountOptions in VolumeContext",
338+
req: &csi.NodePublishVolumeRequest{
339+
VolumeId: testVolumeID,
340+
StagingTargetPath: stagingTargetPath,
341+
TargetPath: testTargetPath,
342+
VolumeCapability: testVolumeCapability,
343+
VolumeContext: map[string]string{
344+
attrIP: "1.1.1.1",
345+
attrVolume: "test-volume",
346+
attrMountOptions: "noatime,nodiratime",
347+
},
348+
},
349+
actions: []mount.FakeAction{{Action: mount.FakeActionMount}},
350+
expectedMount: &mount.MountPoint{Device: stagingTargetPath, Path: testTargetPath, Type: "nfs", Opts: []string{"bind", "noatime,nodiratime"}},
351+
},
336352
// TODO: Revisit this (https://github.com/kubernetes-sigs/gcp-filestore-csi-driver/issues/47).
337353
// {
338354
// name: "target path doesn't exist",
@@ -1038,6 +1054,50 @@ func TestNodeStageVolumeUpdateLockInfo(t *testing.T) {
10381054
}
10391055
}
10401056

1057+
func TestNodeStageVolume_AppendsMountOptions(t *testing.T) {
1058+
testEnv := initTestNodeServer(t)
1059+
attr := map[string]string{
1060+
attrIP: "10.0.0.1",
1061+
attrVolume: "vol1",
1062+
attrMountOptions: "hard,intr",
1063+
}
1064+
req := &csi.NodeStageVolumeRequest{
1065+
VolumeId: "vol-test",
1066+
StagingTargetPath: "/tmp/stage",
1067+
VolumeCapability: &csi.VolumeCapability{
1068+
AccessType: &csi.VolumeCapability_Mount{
1069+
Mount: &csi.VolumeCapability_MountVolume{},
1070+
},
1071+
AccessMode: &csi.VolumeCapability_AccessMode{
1072+
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
1073+
},
1074+
},
1075+
VolumeContext: attr,
1076+
}
1077+
1078+
_, err := testEnv.ns.NodeStageVolume(context.Background(), req)
1079+
if err != nil {
1080+
t.Fatalf("NodeStageVolume failed: %v", err)
1081+
}
1082+
1083+
fm := testEnv.fm
1084+
if len(fm.MountPoints) == 0 {
1085+
t.Fatalf("expected a mount call")
1086+
}
1087+
found := false
1088+
for _, mp := range fm.MountPoints {
1089+
for _, opt := range mp.Opts {
1090+
if opt == "hard,intr" {
1091+
found = true
1092+
break
1093+
}
1094+
}
1095+
}
1096+
if !found {
1097+
t.Errorf("expected mount options 'hard,intr' to be present in mount call")
1098+
}
1099+
}
1100+
10411101
func TestNodeUnstageVolumeUpdateLockInfo(t *testing.T) {
10421102
basePath, err := ioutil.TempDir("", "node-publish-")
10431103
if err != nil {

0 commit comments

Comments
 (0)