@@ -14,6 +14,55 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
+ /*
18
+ This file defines block volume related methods for CSI driver.
19
+ CSI driver is responsible for staging/publishing volumes to their staging/publish paths.
20
+ Mapping and unmapping of a device in a publish path to its global map path and its
21
+ pod device map path are done by operation_executor through MapBlockVolume/UnmapBlockVolume
22
+ (MapBlockVolume and UnmapBlockVolume take care for lock, symlink, and bind mount).
23
+
24
+ Summary of block volume related CSI driver's methods are as follows:
25
+ - GetGlobalMapPath returns a global map path,
26
+ - GetPodDeviceMapPath returns a pod device map path and filename,
27
+ - SetUpDevice calls CSI's NodeStageVolume and stage a volume to its staging path,
28
+ - MapPodDevice calls CSI's NodePublishVolume and publish a volume to its publish path,
29
+ - UnmapPodDevice calls CSI's NodeUnpublishVolume and unpublish a volume from its publish path,
30
+ - TearDownDevice calls CSI's NodeUnstageVolume and unstage a volume from its staging path.
31
+
32
+ These methods are called by below sequences:
33
+ - operation_executor.MountVolume
34
+ - csi.GetGlobalMapPath
35
+ - csi.SetupDevice
36
+ - NodeStageVolume
37
+ - ASW.MarkDeviceAsMounted
38
+ - csi.GetPodDeviceMapPath
39
+ - csi.MapPodDevice
40
+ - NodePublishVolume
41
+ - util.MapBlockVolume
42
+ - ASW.MarkVolumeAsMounted
43
+
44
+ - operation_executor.UnmountVolume
45
+ - csi.GetPodDeviceMapPath
46
+ - util.UnmapBlockVolume
47
+ - csi.UnmapPodDevice
48
+ - NodeUnpublishVolume
49
+ - ASW.MarkVolumeAsUnmounted
50
+
51
+ - operation_executor.UnmountDevice
52
+ - csi.TearDownDevice
53
+ - NodeUnstageVolume
54
+ - ASW.MarkDeviceAsUnmounted
55
+
56
+ After successful MountVolume for block volume, directory structure will be like below:
57
+ /dev/loopX ... Descriptor lock(Loopback device to mapFile under global map path)
58
+ /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices/{specName}/dev/ ... Global map path
59
+ /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices/{specName}/dev/{podUID} ... MapFile(Bind mount to publish Path)
60
+ /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices/staging/{specName} ... Staging path
61
+ /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices/publish/{specName}/{podUID} ... Publish path
62
+ /var/lib/kubelet/pods/{podUID}/volumeDevices/kubernetes.io~csi/ ... Pod device map path
63
+ /var/lib/kubelet/pods/{podUID}/volumeDevices/kubernetes.io~csi/{specName} ... MapFile(Symlink to publish path)
64
+ */
65
+
17
66
package csi
18
67
19
68
import (
@@ -71,7 +120,7 @@ func (m *csiBlockMapper) getPublishPath() string {
71
120
}
72
121
73
122
// GetPodDeviceMapPath returns pod's device file which will be mapped to a volume
74
- // returns: pods/{podUid }/volumeDevices/kubernetes.io~csi, {specName}
123
+ // returns: pods/{podUID }/volumeDevices/kubernetes.io~csi, {specName}
75
124
func (m * csiBlockMapper ) GetPodDeviceMapPath () (string , string ) {
76
125
path := m .plugin .host .GetPodVolumeDeviceDir (m .podUID , utilstrings .EscapeQualifiedName (CSIPluginName ))
77
126
klog .V (4 ).Infof (log ("blockMapper.GetPodDeviceMapPath [path=%s; name=%s]" , path , m .specName ))
@@ -147,7 +196,6 @@ func (m *csiBlockMapper) publishVolumeForBlock(
147
196
accessMode v1.PersistentVolumeAccessMode ,
148
197
csiSource * v1.CSIPersistentVolumeSource ,
149
198
attachment * storage.VolumeAttachment ,
150
- stagingPath string ,
151
199
) (string , error ) {
152
200
klog .V (4 ).Infof (log ("blockMapper.publishVolumeForBlock called" ))
153
201
@@ -183,7 +231,7 @@ func (m *csiBlockMapper) publishVolumeForBlock(
183
231
ctx ,
184
232
m .volumeID ,
185
233
m .readOnly ,
186
- stagingPath ,
234
+ m . getStagingPath () ,
187
235
publishPath ,
188
236
accessMode ,
189
237
publishVolumeInfo ,
@@ -249,13 +297,7 @@ func (m *csiBlockMapper) SetUpDevice() error {
249
297
}
250
298
251
299
// Call NodeStageVolume
252
- stagingPath , err := m .stageVolumeForBlock (ctx , csiClient , accessMode , csiSource , attachment )
253
- if err != nil {
254
- return err
255
- }
256
-
257
- // Call NodePublishVolume
258
- _ , err = m .publishVolumeForBlock (ctx , csiClient , accessMode , csiSource , attachment , stagingPath )
300
+ _ , err = m .stageVolumeForBlock (ctx , csiClient , accessMode , csiSource , attachment )
259
301
if err != nil {
260
302
return err
261
303
}
@@ -264,7 +306,59 @@ func (m *csiBlockMapper) SetUpDevice() error {
264
306
}
265
307
266
308
func (m * csiBlockMapper ) MapPodDevice () (string , error ) {
267
- return m .getPublishPath (), nil
309
+ if ! m .plugin .blockEnabled {
310
+ return "" , errors .New ("CSIBlockVolume feature not enabled" )
311
+ }
312
+ klog .V (4 ).Infof (log ("blockMapper.MapPodDevice called" ))
313
+
314
+ // Get csiSource from spec
315
+ if m .spec == nil {
316
+ return "" , errors .New (log ("blockMapper.MapPodDevice spec is nil" ))
317
+ }
318
+
319
+ csiSource , err := getCSISourceFromSpec (m .spec )
320
+ if err != nil {
321
+ return "" , errors .New (log ("blockMapper.MapPodDevice failed to get CSI persistent source: %v" , err ))
322
+ }
323
+
324
+ driverName := csiSource .Driver
325
+ skip , err := m .plugin .skipAttach (driverName )
326
+ if err != nil {
327
+ return "" , errors .New (log ("blockMapper.MapPodDevice failed to check CSIDriver for %s: %v" , driverName , err ))
328
+ }
329
+
330
+ var attachment * storage.VolumeAttachment
331
+ if ! skip {
332
+ // Search for attachment by VolumeAttachment.Spec.Source.PersistentVolumeName
333
+ nodeName := string (m .plugin .host .GetNodeName ())
334
+ attachID := getAttachmentName (csiSource .VolumeHandle , csiSource .Driver , nodeName )
335
+ attachment , err = m .k8s .StorageV1 ().VolumeAttachments ().Get (attachID , meta.GetOptions {})
336
+ if err != nil {
337
+ return "" , errors .New (log ("blockMapper.MapPodDevice failed to get volume attachment [id=%v]: %v" , attachID , err ))
338
+ }
339
+ }
340
+
341
+ //TODO (vladimirvivien) implement better AccessModes mapping between k8s and CSI
342
+ accessMode := v1 .ReadWriteOnce
343
+ if m .spec .PersistentVolume .Spec .AccessModes != nil {
344
+ accessMode = m .spec .PersistentVolume .Spec .AccessModes [0 ]
345
+ }
346
+
347
+ ctx , cancel := context .WithTimeout (context .Background (), csiTimeout )
348
+ defer cancel ()
349
+
350
+ csiClient , err := m .csiClientGetter .Get ()
351
+ if err != nil {
352
+ return "" , errors .New (log ("blockMapper.MapPodDevice failed to get CSI client: %v" , err ))
353
+ }
354
+
355
+ // Call NodePublishVolume
356
+ publishPath , err := m .publishVolumeForBlock (ctx , csiClient , accessMode , csiSource , attachment )
357
+ if err != nil {
358
+ return "" , err
359
+ }
360
+
361
+ return publishPath , nil
268
362
}
269
363
270
364
var _ volume.BlockVolumeUnmapper = & csiBlockMapper {}
@@ -319,8 +413,6 @@ func (m *csiBlockMapper) TearDownDevice(globalMapPath, devicePath string) error
319
413
return errors .New ("CSIBlockVolume feature not enabled" )
320
414
}
321
415
322
- klog .V (4 ).Infof (log ("unmapper.TearDownDevice(globalMapPath=%s; devicePath=%s)" , globalMapPath , devicePath ))
323
-
324
416
ctx , cancel := context .WithTimeout (context .Background (), csiTimeout )
325
417
defer cancel ()
326
418
@@ -329,21 +421,6 @@ func (m *csiBlockMapper) TearDownDevice(globalMapPath, devicePath string) error
329
421
return errors .New (log ("blockMapper.TearDownDevice failed to get CSI client: %v" , err ))
330
422
}
331
423
332
- // Call NodeUnpublishVolume
333
- publishPath := m .getPublishPath ()
334
- if _ , err := os .Stat (publishPath ); err != nil {
335
- if os .IsNotExist (err ) {
336
- klog .V (4 ).Infof (log ("blockMapper.TearDownDevice publishPath(%s) has already been deleted, skip calling NodeUnpublishVolume" , publishPath ))
337
- } else {
338
- return err
339
- }
340
- } else {
341
- err := m .unpublishVolumeForBlock (ctx , csiClient , publishPath )
342
- if err != nil {
343
- return err
344
- }
345
- }
346
-
347
424
// Call NodeUnstageVolume
348
425
stagingPath := m .getStagingPath ()
349
426
if _ , err := os .Stat (stagingPath ); err != nil {
@@ -364,5 +441,32 @@ func (m *csiBlockMapper) TearDownDevice(globalMapPath, devicePath string) error
364
441
365
442
// UnmapPodDevice unmaps the block device path.
366
443
func (m * csiBlockMapper ) UnmapPodDevice () error {
444
+ if ! m .plugin .blockEnabled {
445
+ return errors .New ("CSIBlockVolume feature not enabled" )
446
+ }
447
+ publishPath := m .getPublishPath ()
448
+
449
+ csiClient , err := m .csiClientGetter .Get ()
450
+ if err != nil {
451
+ return errors .New (log ("blockMapper.UnmapPodDevice failed to get CSI client: %v" , err ))
452
+ }
453
+
454
+ ctx , cancel := context .WithTimeout (context .Background (), csiTimeout )
455
+ defer cancel ()
456
+
457
+ // Call NodeUnpublishVolume
458
+ if _ , err := os .Stat (publishPath ); err != nil {
459
+ if os .IsNotExist (err ) {
460
+ klog .V (4 ).Infof (log ("blockMapper.UnmapPodDevice publishPath(%s) has already been deleted, skip calling NodeUnpublishVolume" , publishPath ))
461
+ } else {
462
+ return err
463
+ }
464
+ } else {
465
+ err := m .unpublishVolumeForBlock (ctx , csiClient , publishPath )
466
+ if err != nil {
467
+ return err
468
+ }
469
+ }
470
+
367
471
return nil
368
472
}
0 commit comments