@@ -95,18 +95,60 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
95
95
return & csi.NodePublishVolumeResponse {}, nil
96
96
}
97
97
98
- if err := ns .Mounter .Interface .MakeDir (targetPath ); err != nil {
99
- glog .Errorf ("mkdir failed on disk %s (%v)" , targetPath , err )
100
- return nil , err
101
- }
102
-
103
98
// Perform a bind mount to the full path to allow duplicate mounts of the same PD.
99
+ fstype := ""
100
+ sourcePath := ""
104
101
options := []string {"bind" }
105
102
if readOnly {
106
103
options = append (options , "ro" )
107
104
}
108
105
109
- err = ns .Mounter .Interface .Mount (stagingTargetPath , targetPath , "ext4" , options )
106
+ if mnt := volumeCapability .GetMount (); mnt != nil {
107
+ if mnt .FsType != "" {
108
+ fstype = mnt .FsType
109
+ } else {
110
+ // Default fstype is ext4
111
+ fstype = "ext4"
112
+ }
113
+
114
+ glog .V (4 ).Infof ("NodePublishVolume with filesystem %s" , fstype )
115
+
116
+ for _ , flag := range mnt .MountFlags {
117
+ options = append (options , flag )
118
+ }
119
+
120
+ sourcePath = stagingTargetPath
121
+
122
+ if err := ns .Mounter .Interface .MakeDir (targetPath ); err != nil {
123
+ glog .Errorf ("mkdir failed on disk %s (%v)" , targetPath , err )
124
+ return nil , err
125
+ }
126
+ } else if blk := volumeCapability .GetBlock (); blk != nil {
127
+ glog .V (4 ).Infof ("NodePublishVolume with block volume mode" )
128
+
129
+ partition := ""
130
+ if part , ok := req .GetVolumeContext ()[common .VolumeAttributePartition ]; ok {
131
+ partition = part
132
+ }
133
+
134
+ sourcePath , err = ns .getDevicePath (volumeID , partition )
135
+ if err != nil {
136
+ return nil , status .Error (codes .Internal , fmt .Sprintf ("Error when getting device path: %v" , err ))
137
+ }
138
+
139
+ // Expose block volume as file at target path
140
+ err = ns .Mounter .MakeFile (targetPath )
141
+ if err != nil {
142
+ if removeErr := os .Remove (targetPath ); removeErr != nil {
143
+ return nil , status .Error (codes .Internal , fmt .Sprintf ("Error removing block file at target path %v: %v" , targetPath , removeErr ))
144
+ }
145
+ return nil , status .Error (codes .Internal , fmt .Sprintf ("Failed to create block file at target path %v: %v" , targetPath , err ))
146
+ }
147
+ } else {
148
+ return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("NodePublishVolume volume capability must specify either mount or block mode" ))
149
+ }
150
+
151
+ err = ns .Mounter .Interface .Mount (sourcePath , targetPath , fstype , options )
110
152
if err != nil {
111
153
notMnt , mntErr := ns .Mounter .Interface .IsLikelyNotMountPoint (targetPath )
112
154
if mntErr != nil {
@@ -197,19 +239,9 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
197
239
partition = part
198
240
}
199
241
200
- deviceName , err := common . GetDeviceName ( volumeKey )
242
+ devicePath , err := ns . getDevicePath ( volumeID , partition )
201
243
if err != nil {
202
- status .Error (codes .Internal , fmt .Sprintf ("error getting device name: %v" , err ))
203
- }
204
-
205
- devicePaths := ns .DeviceUtils .GetDiskByIdPaths (deviceName , partition )
206
- devicePath , err := ns .DeviceUtils .VerifyDevicePath (devicePaths )
207
-
208
- if err != nil {
209
- return nil , status .Error (codes .Internal , fmt .Sprintf ("Error verifying GCE PD (%q) is attached: %v" , volumeKey .Name , err ))
210
- }
211
- if devicePath == "" {
212
- return nil , status .Error (codes .Internal , fmt .Sprintf ("Unable to find device path out of attempted paths: %v" , devicePaths ))
244
+ return nil , status .Error (codes .Internal , fmt .Sprintf ("Error when getting device path: %v" , err ))
213
245
}
214
246
215
247
glog .V (4 ).Infof ("Successfully found attached GCE PD %q at device path %s." , volumeKey .Name , devicePath )
@@ -251,8 +283,8 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
251
283
options = append (options , flag )
252
284
}
253
285
} else if blk := volumeCapability .GetBlock (); blk != nil {
254
- // TODO(#64): Block volume support
255
- return nil , status . Error ( codes . Unimplemented , fmt . Sprintf ( "Block volume support is not yet implemented" ))
286
+ // Noop for Block NodeStageVolume
287
+ return & csi. NodeStageVolumeResponse {}, nil
256
288
}
257
289
258
290
err = ns .Mounter .FormatAndMount (devicePath , stagingTargetPath , fstype , options )
@@ -333,3 +365,25 @@ func (ns *GCENodeServer) GetVolumeLimits() (int64, error) {
333
365
}
334
366
return volumeLimits , nil
335
367
}
368
+
369
+ func (ns * GCENodeServer ) getDevicePath (volumeID string , partition string ) (string , error ) {
370
+ volumeKey , err := common .VolumeIDToKey (volumeID )
371
+ if err != nil {
372
+ return "" , err
373
+ }
374
+ deviceName , err := common .GetDeviceName (volumeKey )
375
+ if err != nil {
376
+ return "" , fmt .Errorf ("error getting device name: %v" , err )
377
+ }
378
+
379
+ devicePaths := ns .DeviceUtils .GetDiskByIdPaths (deviceName , partition )
380
+ devicePath , err := ns .DeviceUtils .VerifyDevicePath (devicePaths )
381
+
382
+ if err != nil {
383
+ return "" , fmt .Errorf ("error verifying GCE PD (%q) is attached: %v" , volumeKey .Name , err )
384
+ }
385
+ if devicePath == "" {
386
+ return "" , fmt .Errorf ("unable to find device path out of attempted paths: %v" , devicePaths )
387
+ }
388
+ return devicePath , nil
389
+ }
0 commit comments