@@ -16,15 +16,84 @@ func (s *service) NodeStageVolume(
16
16
req * csi.NodeStageVolumeRequest ) (
17
17
* csi.NodeStageVolumeResponse , error ) {
18
18
19
- return nil , status .Error (codes .Unimplemented , "" )
19
+ device , ok := req .PublishInfo ["device" ]
20
+ if ! ok {
21
+ return nil , status .Error (
22
+ codes .InvalidArgument ,
23
+ "stage volume info 'device' key required" )
24
+ }
25
+
26
+ if len (req .GetVolumeId ()) == 0 {
27
+ return nil , status .Error (codes .InvalidArgument , "Volume ID cannot be empty" )
28
+ }
29
+
30
+ if len (req .GetStagingTargetPath ()) == 0 {
31
+ return nil , status .Error (codes .InvalidArgument , "Staging Target Path cannot be empty" )
32
+ }
33
+
34
+ if req .GetVolumeCapability () == nil {
35
+ return nil , status .Error (codes .InvalidArgument , "Volume Capability cannot be empty" )
36
+ }
37
+
38
+ s .volsRWL .Lock ()
39
+ defer s .volsRWL .Unlock ()
40
+
41
+ i , v := s .findVolNoLock ("id" , req .VolumeId )
42
+ if i < 0 {
43
+ return nil , status .Error (codes .NotFound , req .VolumeId )
44
+ }
45
+
46
+ // nodeStgPathKey is the key in the volume's attributes that is set to a
47
+ // mock stage path if the volume has been published by the node
48
+ nodeStgPathKey := path .Join (s .nodeID , req .StagingTargetPath )
49
+
50
+ // Check to see if the volume has already been staged.
51
+ if v .Attributes [nodeStgPathKey ] != "" {
52
+ return & csi.NodeStageVolumeResponse {}, nil
53
+ }
54
+
55
+ // Stage the volume.
56
+ v .Attributes [nodeStgPathKey ] = device
57
+ s .vols [i ] = v
58
+
59
+ return & csi.NodeStageVolumeResponse {}, nil
20
60
}
21
61
22
62
func (s * service ) NodeUnstageVolume (
23
63
ctx context.Context ,
24
64
req * csi.NodeUnstageVolumeRequest ) (
25
65
* csi.NodeUnstageVolumeResponse , error ) {
26
66
27
- return nil , status .Error (codes .Unimplemented , "" )
67
+ if len (req .GetVolumeId ()) == 0 {
68
+ return nil , status .Error (codes .InvalidArgument , "Volume ID cannot be empty" )
69
+ }
70
+
71
+ if len (req .GetStagingTargetPath ()) == 0 {
72
+ return nil , status .Error (codes .InvalidArgument , "Staging Target Path cannot be empty" )
73
+ }
74
+
75
+ s .volsRWL .Lock ()
76
+ defer s .volsRWL .Unlock ()
77
+
78
+ i , v := s .findVolNoLock ("id" , req .VolumeId )
79
+ if i < 0 {
80
+ return nil , status .Error (codes .NotFound , req .VolumeId )
81
+ }
82
+
83
+ // nodeStgPathKey is the key in the volume's attributes that is set to a
84
+ // mock stage path if the volume has been published by the node
85
+ nodeStgPathKey := path .Join (s .nodeID , req .StagingTargetPath )
86
+
87
+ // Check to see if the volume has already been unstaged.
88
+ if v .Attributes [nodeStgPathKey ] == "" {
89
+ return & csi.NodeUnstageVolumeResponse {}, nil
90
+ }
91
+
92
+ // Unpublish the volume.
93
+ delete (v .Attributes , nodeStgPathKey )
94
+ s .vols [i ] = v
95
+
96
+ return & csi.NodeUnstageVolumeResponse {}, nil
28
97
}
29
98
30
99
func (s * service ) NodePublishVolume (
0 commit comments