Skip to content

Commit bdc133f

Browse files
authored
Merge pull request #126 from NetApp/mount-options
Support mount options
2 parents 6ba243b + 65ecdc4 commit bdc133f

File tree

2 files changed

+113
-14
lines changed

2 files changed

+113
-14
lines changed

pkg/controller/controller.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ const (
110110
var _ controller.Provisioner = &csiProvisioner{}
111111

112112
var (
113-
accessType = &csi.VolumeCapability_Mount{
114-
Mount: &csi.VolumeCapability_MountVolume{},
115-
}
116113
// Each provisioner have a identify string to distinguish with others. This
117114
// identify string will be added in PV annoations under this key.
118115
provisionerIDKey = "storage.kubernetes.io/csiProvisionerIdentity"
@@ -364,9 +361,27 @@ func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis
364361
return nil, err
365362
}
366363

364+
fsType := ""
365+
for k, v := range options.Parameters {
366+
switch strings.ToLower(k) {
367+
case "fstype":
368+
fsType = v
369+
}
370+
}
371+
if len(fsType) == 0 {
372+
fsType = defaultFSType
373+
}
374+
367375
capacity := options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
368376
volSizeBytes := capacity.Value()
369377

378+
accessType := &csi.VolumeCapability_Mount{
379+
Mount: &csi.VolumeCapability_MountVolume{
380+
FsType: fsType,
381+
MountFlags: options.MountOptions,
382+
},
383+
}
384+
370385
// Get access mode
371386
volumeCaps := make([]*csi.VolumeCapability, 0)
372387
for _, cap := range options.PVC.Spec.AccessModes {
@@ -506,24 +521,14 @@ func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis
506521
return nil, capErr
507522
}
508523

509-
fsType := ""
510-
for k, v := range options.Parameters {
511-
switch strings.ToLower(k) {
512-
case "fstype":
513-
fsType = v
514-
}
515-
}
516-
if len(fsType) == 0 {
517-
fsType = defaultFSType
518-
}
519-
520524
pv := &v1.PersistentVolume{
521525
ObjectMeta: metav1.ObjectMeta{
522526
Name: pvName,
523527
},
524528
Spec: v1.PersistentVolumeSpec{
525529
PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy,
526530
AccessModes: options.PVC.Spec.AccessModes,
531+
MountOptions: options.MountOptions,
527532
Capacity: v1.ResourceList{
528533
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(respCap),
529534
},

pkg/controller/controller_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,62 @@ func TestProvision(t *testing.T) {
10391039
volWithLessCap: true,
10401040
expectErr: true,
10411041
},
1042+
"provision with mount options": {
1043+
volOpts: controller.VolumeOptions{
1044+
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
1045+
PVName: "test-name",
1046+
PVC: &v1.PersistentVolumeClaim{
1047+
ObjectMeta: metav1.ObjectMeta{
1048+
UID: "testid",
1049+
},
1050+
Spec: v1.PersistentVolumeClaimSpec{
1051+
Selector: nil,
1052+
Resources: v1.ResourceRequirements{
1053+
Requests: v1.ResourceList{
1054+
v1.ResourceName(v1.ResourceStorage): resource.MustParse(strconv.FormatInt(requestedBytes, 10)),
1055+
},
1056+
},
1057+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
1058+
},
1059+
},
1060+
MountOptions: []string{"foo=bar", "baz=qux"},
1061+
Parameters: map[string]string{},
1062+
},
1063+
expectedPVSpec: &pvSpec{
1064+
Name: "test-testi",
1065+
ReclaimPolicy: v1.PersistentVolumeReclaimDelete,
1066+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
1067+
Capacity: v1.ResourceList{
1068+
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(requestedBytes),
1069+
},
1070+
CSIPVS: &v1.CSIPersistentVolumeSource{
1071+
Driver: "test-driver",
1072+
VolumeHandle: "test-volume-id",
1073+
FSType: "ext4",
1074+
VolumeAttributes: map[string]string{
1075+
"storage.kubernetes.io/csiProvisionerIdentity": "test-provisioner",
1076+
},
1077+
},
1078+
},
1079+
expectCreateVolDo: func(ctx context.Context, req *csi.CreateVolumeRequest) {
1080+
if len(req.GetVolumeCapabilities()) != 1 {
1081+
t.Errorf("Incorrect length in volume capabilities")
1082+
}
1083+
cap := req.GetVolumeCapabilities()[0]
1084+
if cap.GetAccessMode() == nil {
1085+
t.Errorf("Expected access mode to be set")
1086+
}
1087+
if cap.GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER {
1088+
t.Errorf("Expected multi reade only")
1089+
}
1090+
if cap.GetMount() == nil {
1091+
t.Errorf("Expected access type to be mount")
1092+
}
1093+
if !reflect.DeepEqual(cap.GetMount().MountFlags, []string{"foo=bar", "baz=qux"}) {
1094+
t.Errorf("Expected 2 mount options")
1095+
}
1096+
},
1097+
},
10421098
}
10431099

10441100
mockController, driver, identityServer, controllerServer, csiConn, err := createMockServer(t)
@@ -1570,3 +1626,41 @@ func TestProvisionWithTopology(t *testing.T) {
15701626
t.Errorf("expected node affinity %v; got: %v", expectedNodeAffinity, pv.Spec.NodeAffinity)
15711627
}
15721628
}
1629+
1630+
// TestProvisionWithMountOptions is a test of provisioner integration with mount options.
1631+
func TestProvisionWithMountOptions(t *testing.T) {
1632+
expectedOptions := []string{"foo=bar", "baz=qux"}
1633+
const requestBytes = 100
1634+
mockController, driver, identityServer, controllerServer, csiConn, err := createMockServer(t)
1635+
if err != nil {
1636+
t.Fatal(err)
1637+
}
1638+
defer mockController.Finish()
1639+
defer driver.Stop()
1640+
1641+
clientSet := fakeclientset.NewSimpleClientset()
1642+
csiClientSet := fakecsiclientset.NewSimpleClientset()
1643+
csiProvisioner := NewCSIProvisioner(clientSet, csiClientSet, driver.Address(), 5*time.Second, "test-provisioner", "test", 5, csiConn.conn, nil)
1644+
1645+
out := &csi.CreateVolumeResponse{
1646+
Volume: &csi.Volume{
1647+
CapacityBytes: requestBytes,
1648+
Id: "test-volume-id",
1649+
},
1650+
}
1651+
1652+
provisionWithTopologyMockServerSetupExpectations(identityServer, controllerServer)
1653+
controllerServer.EXPECT().CreateVolume(gomock.Any(), gomock.Any()).Return(out, nil).Times(1)
1654+
1655+
pv, err := csiProvisioner.Provision(controller.VolumeOptions{
1656+
PVC: createFakePVC(requestBytes), // dummy PVC
1657+
MountOptions: expectedOptions,
1658+
})
1659+
if err != nil {
1660+
t.Errorf("got error from Provision call: %v", err)
1661+
}
1662+
1663+
if !reflect.DeepEqual(pv.Spec.MountOptions, expectedOptions) {
1664+
t.Errorf("expected mount options %v; got: %v", expectedOptions, pv.Spec.MountOptions)
1665+
}
1666+
}

0 commit comments

Comments
 (0)