@@ -25,7 +25,7 @@ import (
25
25
26
26
"github.com/container-storage-interface/spec/lib/go/csi"
27
27
"k8s.io/klog"
28
- k8sutil "k8s.io/kubernetes/pkg/volume/util"
28
+ "k8s.io/kubernetes/pkg/volume/util"
29
29
30
30
"google.golang.org/grpc/codes"
31
31
"google.golang.org/grpc/status"
@@ -45,7 +45,83 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
45
45
return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
46
46
}
47
47
48
+ source := req .GetStagingTargetPath ()
49
+ if len (source ) == 0 {
50
+ return nil , status .Error (codes .InvalidArgument , "Staging target not provided" )
51
+ }
52
+
53
+ target := req .GetTargetPath ()
54
+ if len (target ) == 0 {
55
+ return nil , status .Error (codes .InvalidArgument , "Target path not provided" )
56
+ }
57
+
58
+ mountOptions := getNodePublishMountOptions (req )
59
+
60
+ if err := d .ensureMountPoint (target ); err != nil {
61
+ return nil , status .Errorf (codes .Internal , "Could not mount target %q: %v" , target , err )
62
+ }
63
+
64
+ readOnly := req .GetReadonly ()
65
+ volumeID := req .GetVolumeId ()
66
+ attrib := req .GetVolumeContext ()
67
+ mountFlags := req .GetVolumeCapability ().GetMount ().GetMountFlags ()
68
+
69
+ klog .V (2 ).Infof ("target %v\n \n readonly %v\n volumeId %v\n Context %v\n mountflags %v\n " ,
70
+ target , readOnly , volumeID , attrib , mountFlags )
71
+
72
+ klog .V (2 ).Infof ("NodePublishVolume: creating dir %s" , target )
73
+ if err := d .mounter .MakeDir (target ); err != nil {
74
+ return nil , status .Errorf (codes .Internal , "Could not create dir %q: %v" , target , err )
75
+ }
76
+
77
+ klog .V (2 ).Infof ("NodePublishVolume: mounting %s at %s with mountOptions: %v" , source , target , mountOptions )
78
+ if err := d .mounter .Mount (source , target , "" , mountOptions ); err != nil {
79
+ if removeErr := os .Remove (target ); removeErr != nil {
80
+ return nil , status .Errorf (codes .Internal , "Could not remove mount target %q: %v" , target , removeErr )
81
+ }
82
+ return nil , status .Errorf (codes .Internal , "Could not mount %q at %q: %v" , source , target , err )
83
+ }
84
+ klog .V (2 ).Infof ("NodePublishVolume: mount %s at %s successfully" , source , target )
85
+
86
+ return & csi.NodePublishVolumeResponse {}, nil
87
+ }
88
+
89
+ // NodeUnpublishVolume unmount the volume from the target path
90
+ func (d * Driver ) NodeUnpublishVolume (ctx context.Context , req * csi.NodeUnpublishVolumeRequest ) (* csi.NodeUnpublishVolumeResponse , error ) {
91
+ klog .V (2 ).Infof ("NodeUnPublishVolume: called with args %+v" , * req )
92
+ if len (req .GetVolumeId ()) == 0 {
93
+ return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
94
+ }
95
+ if len (req .GetTargetPath ()) == 0 {
96
+ return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
97
+ }
48
98
targetPath := req .GetTargetPath ()
99
+ volumeID := req .GetVolumeId ()
100
+
101
+ klog .V (2 ).Infof ("NodeUnpublishVolume: unmounting volume %s on %s" , volumeID , targetPath )
102
+ err := d .mounter .Unmount (req .GetTargetPath ())
103
+ if err != nil {
104
+ return nil , status .Error (codes .Internal , err .Error ())
105
+ }
106
+ klog .V (2 ).Infof ("NodeUnpublishVolume: unmount volume %s on %s successfully" , volumeID , targetPath )
107
+
108
+ return & csi.NodeUnpublishVolumeResponse {}, nil
109
+ }
110
+
111
+ // NodeStageVolume mount the volume to a staging path
112
+ func (d * Driver ) NodeStageVolume (ctx context.Context , req * csi.NodeStageVolumeRequest ) (* csi.NodeStageVolumeResponse , error ) {
113
+ if len (req .GetVolumeId ()) == 0 {
114
+ return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
115
+ }
116
+ targetPath := req .GetStagingTargetPath ()
117
+ if len (targetPath ) == 0 {
118
+ return nil , status .Error (codes .InvalidArgument , "Staging target not provided" )
119
+ }
120
+ volumeCapability := req .GetVolumeCapability ()
121
+ if volumeCapability == nil {
122
+ return nil , status .Error (codes .InvalidArgument , "Volume capability not provided" )
123
+ }
124
+
49
125
notMnt , err := d .mounter .IsLikelyNotMountPoint (targetPath )
50
126
if err != nil && ! os .IsNotExist (err ) {
51
127
return nil , err
@@ -59,7 +135,7 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
59
135
// testing original mount point, make sure the mount link is valid
60
136
if _ , err := ioutil .ReadDir (targetPath ); err == nil {
61
137
klog .V (2 ).Infof ("azureFile - already mounted to target %s" , targetPath )
62
- return & csi.NodePublishVolumeResponse {}, nil
138
+ return & csi.NodeStageVolumeResponse {}, nil
63
139
}
64
140
// todo: mount link is invalid, now unmount and remount later (built-in functionality)
65
141
klog .Warningf ("azureFile - ReadDir %s failed with %v, unmount this directory" , targetPath , err )
@@ -70,27 +146,23 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
70
146
// notMnt = true
71
147
}
72
148
73
- fsType := req .GetVolumeCapability ().GetMount ().GetFsType ()
74
-
75
- readOnly := req .GetReadonly ()
76
149
volumeID := req .GetVolumeId ()
77
- attrib := req .GetVolumeContext ()
150
+ fsType := req .GetVolumeCapability (). GetMount (). GetFsType ()
78
151
mountFlags := req .GetVolumeCapability ().GetMount ().GetMountFlags ()
152
+ attrib := req .GetVolumeContext ()
79
153
secrets := req .GetSecrets ()
80
154
81
155
accountName , accountKey , accountSasToken , containerName , err := d .getStorageAccountAndContainer (ctx , volumeID , attrib , secrets )
82
156
if err != nil {
83
157
return nil , err
84
158
}
85
159
160
+ // Get mountOptions that the volume will be formatted and mounted with
86
161
options := []string {"--use-https=true" }
87
- if readOnly {
88
- options = append (options , "-o ro" )
89
- }
90
- mountOptions := k8sutil .JoinMountOptions (mountFlags , options )
162
+ mountOptions := util .JoinMountOptions (mountFlags , options )
91
163
92
- klog .V (2 ).Infof ("target %v\n fstype %v\n \n readonly %v \ n volumeId %v\n context %v\n mountflags %v\n mountOptions %v\n " ,
93
- targetPath , fsType , readOnly , volumeID , attrib , mountFlags , mountOptions )
164
+ klog .V (2 ).Infof ("target %v\n fstype %v\n \n volumeId %v\n context %v\n mountflags %v\n mountOptions %v\n " ,
165
+ targetPath , fsType , volumeID , attrib , mountFlags , mountOptions )
94
166
95
167
args := targetPath + " " + "--tmp-path=/mnt/" + volumeID + " " + "--container-name=" + containerName
96
168
for _ , opt := range mountOptions {
@@ -134,58 +206,28 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
134
206
return nil , err
135
207
}
136
208
137
- return & csi.NodePublishVolumeResponse {}, nil
209
+ return & csi.NodeStageVolumeResponse {}, nil
138
210
}
139
211
140
- // NodeUnpublishVolume unmount the volume from the target path
141
- func (d * Driver ) NodeUnpublishVolume (ctx context.Context , req * csi.NodeUnpublishVolumeRequest ) (* csi.NodeUnpublishVolumeResponse , error ) {
142
- if len (req .GetVolumeId ()) == 0 {
143
- return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
144
- }
145
- if len (req .GetTargetPath ()) == 0 {
146
- return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
147
- }
148
- targetPath := req .GetTargetPath ()
212
+ // NodeUnstageVolume unmount the volume from the staging path
213
+ func (d * Driver ) NodeUnstageVolume (ctx context.Context , req * csi.NodeUnstageVolumeRequest ) (* csi.NodeUnstageVolumeResponse , error ) {
214
+ klog .V (2 ).Infof ("NodeUnstageVolume: called with args %+v" , * req )
149
215
volumeID := req .GetVolumeId ()
150
-
151
- // Unmounting the image
152
- err := d .mounter .Unmount (req .GetTargetPath ())
153
- if err != nil {
154
- return nil , status .Error (codes .Internal , err .Error ())
216
+ if len (volumeID ) == 0 {
217
+ return nil , status .Error (codes .InvalidArgument , "Volume ID not provided" )
155
218
}
156
- klog .V (4 ).Infof ("blobfuse: volume %s/%s has been unmounted." , targetPath , volumeID )
157
219
158
- return & csi.NodeUnpublishVolumeResponse {}, nil
159
- }
160
-
161
- // NodeStageVolume mount the volume to a staging path
162
- // todo: we may implement this for blobfuse
163
- // The reason that mounting is a two step operation is
164
- // because Kubernetes allows you to use a single volume by multiple pods.
165
- // This is allowed when the storage system supports it or if all pods run on the same node.
166
- func (d * Driver ) NodeStageVolume (ctx context.Context , req * csi.NodeStageVolumeRequest ) (* csi.NodeStageVolumeResponse , error ) {
167
- if len (req .GetVolumeId ()) == 0 {
168
- return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
169
- }
170
- if len (req .GetStagingTargetPath ()) == 0 {
171
- return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
220
+ target := req .GetStagingTargetPath ()
221
+ if len (target ) == 0 {
222
+ return nil , status .Error (codes .InvalidArgument , "Staging target not provided" )
172
223
}
173
224
174
- return & csi.NodeStageVolumeResponse {}, nil
175
- }
176
-
177
- // NodeUnstageVolume unmount the volume from the staging path
178
- // todo: we may implement this for blobfuse
179
- // The reason that mounting is a two step operation is
180
- // because Kubernetes allows you to use a single volume by multiple pods.
181
- // This is allowed when the storage system supports it or if all pods run on the same node.
182
- func (d * Driver ) NodeUnstageVolume (ctx context.Context , req * csi.NodeUnstageVolumeRequest ) (* csi.NodeUnstageVolumeResponse , error ) {
183
- if len (req .GetVolumeId ()) == 0 {
184
- return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
185
- }
186
- if len (req .GetStagingTargetPath ()) == 0 {
187
- return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
225
+ klog .V (2 ).Infof ("NodeUnstageVolume: unmounting %s" , target )
226
+ err := d .mounter .Unmount (target )
227
+ if err != nil {
228
+ return nil , status .Errorf (codes .Internal , "Could not unmount target %q: %v" , target , err )
188
229
}
230
+ klog .V (2 ).Infof ("NodeUnstageVolume: unmount %s successfully" , target )
189
231
190
232
return & csi.NodeUnstageVolumeResponse {}, nil
191
233
}
@@ -217,3 +259,46 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, in *csi.NodeGetVolumeSt
217
259
func (d * Driver ) NodeExpandVolume (ctx context.Context , req * csi.NodeExpandVolumeRequest ) (* csi.NodeExpandVolumeResponse , error ) {
218
260
return nil , status .Error (codes .Unimplemented , fmt .Sprintf ("NodeExpandVolume is not yet implemented" ))
219
261
}
262
+
263
+ func getNodePublishMountOptions (req * csi.NodePublishVolumeRequest ) []string {
264
+ mountFlags := req .GetVolumeCapability ().GetMount ().GetMountFlags ()
265
+ mountOptions := []string {"bind" }
266
+ if req .GetReadonly () {
267
+ mountOptions = append (mountOptions , "ro" )
268
+ }
269
+ mountOptions = util .JoinMountOptions (mountFlags , mountOptions )
270
+
271
+ return mountOptions
272
+ }
273
+
274
+ // ensureMountPoint: ensure mount point to be valid.
275
+ // If it is not existed, it will be created.
276
+ func (d * Driver ) ensureMountPoint (target string ) error {
277
+ notMnt , err := d .mounter .IsLikelyNotMountPoint (target )
278
+ if err != nil && ! os .IsNotExist (err ) {
279
+ return err
280
+ }
281
+
282
+ if ! notMnt {
283
+ // testing original mount point, make sure the mount link is valid
284
+ _ , err := ioutil .ReadDir (target )
285
+ if err == nil {
286
+ klog .V (2 ).Infof ("already mounted to target %s" , target )
287
+ return nil
288
+ }
289
+ // mount link is invalid, now unmount and remount later
290
+ klog .Warningf ("ReadDir %s failed with %v, unmount this directory" , target , err )
291
+ if err := d .mounter .Unmount (target ); err != nil {
292
+ klog .Errorf ("Unmount directory %s failed with %v" , target , err )
293
+ return err
294
+ }
295
+ // notMnt = true
296
+ }
297
+
298
+ if err := os .MkdirAll (target , 0750 ); err != nil {
299
+ klog .Errorf ("mkdir failed on target: %s (%v)" , target , err )
300
+ return err
301
+ }
302
+
303
+ return nil
304
+ }
0 commit comments