@@ -17,6 +17,7 @@ limitations under the License.
17
17
package smb
18
18
19
19
import (
20
+ "bufio"
20
21
"encoding/base64"
21
22
"fmt"
22
23
"os"
@@ -40,7 +41,6 @@ import (
40
41
azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
41
42
)
42
43
43
- // NodePublishVolume mount the volume from staging to target path
44
44
func (d * Driver ) NodePublishVolume (ctx context.Context , req * csi.NodePublishVolumeRequest ) (* csi.NodePublishVolumeResponse , error ) {
45
45
volCap := req .GetVolumeCapability ()
46
46
if volCap == nil {
@@ -51,27 +51,31 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
51
51
return nil , status .Error (codes .InvalidArgument , "Volume ID missing in request" )
52
52
}
53
53
54
- target := req .GetTargetPath ()
55
- if len (target ) == 0 {
54
+ // Strip cred hash suffix if present
55
+ cleanID := strings .SplitN (volumeID , "#cred=" , 2 )[0 ]
56
+
57
+ targetPath := req .GetTargetPath ()
58
+ if len (targetPath ) == 0 {
56
59
return nil , status .Error (codes .InvalidArgument , "Target path not provided" )
57
60
}
58
61
59
62
context := req .GetVolumeContext ()
60
63
if context != nil && strings .EqualFold (context [ephemeralField ], trueValue ) {
61
64
// ephemeral volume
62
65
util .SetKeyValueInMap (context , secretNamespaceField , context [podNamespaceField ])
63
- klog .V (2 ).Infof ("NodePublishVolume: ephemeral volume(%s) mount on %s" , volumeID , target )
66
+ klog .V (2 ).Infof ("NodePublishVolume: ephemeral volume(%s) mount on %s" , volumeID , targetPath )
64
67
_ , err := d .NodeStageVolume (ctx , & csi.NodeStageVolumeRequest {
65
- StagingTargetPath : target ,
68
+ StagingTargetPath : targetPath ,
66
69
VolumeContext : context ,
67
70
VolumeCapability : volCap ,
68
- VolumeId : volumeID ,
71
+ VolumeId : cleanID ,
69
72
})
70
73
return & csi.NodePublishVolumeResponse {}, err
71
74
}
72
75
73
- source := req .GetStagingTargetPath ()
74
- if len (source ) == 0 {
76
+ // Get staging path
77
+ stagingPath := req .GetStagingTargetPath ()
78
+ if len (stagingPath ) == 0 {
75
79
return nil , status .Error (codes .InvalidArgument , "Staging target not provided" )
76
80
}
77
81
@@ -80,31 +84,31 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
80
84
mountOptions = append (mountOptions , "ro" )
81
85
}
82
86
83
- mnt , err := d .ensureMountPoint (target )
87
+ mnt , err := d .ensureMountPoint (targetPath )
84
88
if err != nil {
85
- return nil , status .Errorf (codes .Internal , "Could not mount target %q: %v" , target , err )
89
+ return nil , status .Errorf (codes .Internal , "Could not mount target %q: %v" , targetPath , err )
86
90
}
87
91
if mnt {
88
- klog .V (2 ).Infof ("NodePublishVolume: %s is already mounted" , target )
92
+ klog .V (2 ).Infof ("NodePublishVolume: %s is already mounted" , targetPath )
89
93
return & csi.NodePublishVolumeResponse {}, nil
90
94
}
91
95
92
- if err = preparePublishPath (target , d .mounter ); err != nil {
93
- return nil , fmt .Errorf ("prepare publish failed for %s with error: %v" , target , err )
96
+ if err = preparePublishPath (targetPath , d .mounter ); err != nil {
97
+ return nil , fmt .Errorf ("prepare publish failed for %s with error: %v" , targetPath , err )
94
98
}
95
99
96
- klog .V (2 ).Infof ("NodePublishVolume: mounting %s at %s with mountOptions : %v volumeID(%s) " , source , target , mountOptions , volumeID )
97
- if err := d .mounter .Mount (source , target , "" , mountOptions ); err != nil {
98
- if removeErr := os .Remove (target ); removeErr != nil {
99
- return nil , status .Errorf (codes .Internal , "Could not remove mount target %q: %v" , target , removeErr )
100
+ klog .V (2 ).Infof ("NodePublishVolume: bind mounting %s to %s with options : %v" , stagingPath , targetPath , mountOptions )
101
+ if err := d .mounter .Mount (stagingPath , targetPath , "" , mountOptions ); err != nil {
102
+ if removeErr := os .Remove (targetPath ); removeErr != nil {
103
+ return nil , status .Errorf (codes .Internal , "Could not remove mount target %q: %v" , targetPath , removeErr )
100
104
}
101
- return nil , status .Errorf (codes .Internal , "Could not mount %q at %q: %v" , source , target , err )
105
+ return nil , status .Errorf (codes .Internal , "Could not mount %q at %q: %v" , stagingPath , targetPath , err )
102
106
}
103
- klog .V (2 ).Infof ("NodePublishVolume: mount %s at %s volumeID(%s) successfully" , source , target , volumeID )
107
+
108
+ klog .V (2 ).Infof ("NodePublishVolume: mount %s at %s volumeID(%s) successfully" , stagingPath , targetPath , volumeID )
104
109
return & csi.NodePublishVolumeResponse {}, nil
105
110
}
106
111
107
- // NodeUnpublishVolume unmount the volume from the target path
108
112
func (d * Driver ) NodeUnpublishVolume (_ context.Context , req * csi.NodeUnpublishVolumeRequest ) (* csi.NodeUnpublishVolumeResponse , error ) {
109
113
volumeID := req .GetVolumeId ()
110
114
if len (volumeID ) == 0 {
@@ -115,12 +119,28 @@ func (d *Driver) NodeUnpublishVolume(_ context.Context, req *csi.NodeUnpublishVo
115
119
return nil , status .Error (codes .InvalidArgument , "Target path missing in request" )
116
120
}
117
121
118
- klog .V (2 ).Infof ("NodeUnpublishVolume: unmounting volume %s on %s" , volumeID , targetPath )
119
- err := CleanupMountPoint (d .mounter , targetPath , true /*extensiveMountPointCheck*/ )
120
- if err != nil {
122
+ klog .V (2 ).Infof ("NodeUnpublishVolume: unmounting volume %s from %s" , volumeID , targetPath )
123
+
124
+ notMnt , err := d .mounter .IsLikelyNotMountPoint (targetPath )
125
+ if err != nil && ! os .IsNotExist (err ) {
126
+ return nil , status .Errorf (codes .Internal , "failed to check mount point %q: %v" , targetPath , err )
127
+ }
128
+ if notMnt {
129
+ klog .V (2 ).Infof ("NodeUnpublishVolume: target %s is already unmounted" , targetPath )
130
+ if err := os .Remove (targetPath ); err != nil && ! os .IsNotExist (err ) {
131
+ return nil , status .Errorf (codes .Internal , "failed to remove target path %q: %v" , targetPath , err )
132
+ }
133
+ return & csi.NodeUnpublishVolumeResponse {}, nil
134
+ }
135
+
136
+ if err := d .mounter .Unmount (targetPath ); err != nil {
121
137
return nil , status .Errorf (codes .Internal , "failed to unmount target %q: %v" , targetPath , err )
122
138
}
123
- klog .V (2 ).Infof ("NodeUnpublishVolume: unmount volume %s on %s successfully" , volumeID , targetPath )
139
+ if err := os .Remove (targetPath ); err != nil && ! os .IsNotExist (err ) {
140
+ return nil , status .Errorf (codes .Internal , "failed to remove target path %q after unmount: %v" , targetPath , err )
141
+ }
142
+
143
+ klog .V (2 ).Infof ("NodeUnpublishVolume: successfully unmounted and removed %s for volume %s" , targetPath , volumeID )
124
144
return & csi.NodeUnpublishVolumeResponse {}, nil
125
145
}
126
146
@@ -142,8 +162,8 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
142
162
}
143
163
144
164
context := req .GetVolumeContext ()
145
- mountFlags := req . GetVolumeCapability () .GetMount ().GetMountFlags ()
146
- volumeMountGroup := req . GetVolumeCapability () .GetMount ().GetVolumeMountGroup ()
165
+ mountFlags := volumeCapability .GetMount ().GetMountFlags ()
166
+ volumeMountGroup := volumeCapability .GetMount ().GetVolumeMountGroup ()
147
167
secrets := req .GetSecrets ()
148
168
gidPresent := checkGidPresentInMountFlags (mountFlags )
149
169
@@ -199,7 +219,6 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
199
219
mountFlags = strings .Split (ephemeralVolMountOptions , "," )
200
220
}
201
221
202
- // in guest login, username and password options are not needed
203
222
requireUsernamePwdOption := ! hasGuestMountOptions (mountFlags )
204
223
if ephemeralVol && requireUsernamePwdOption {
205
224
klog .V (2 ).Infof ("NodeStageVolume: getting username and password from secret %s in namespace %s" , secretName , secretNamespace )
@@ -264,7 +283,6 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
264
283
if subDir != "" {
265
284
// replace pv/pvc name namespace metadata in subDir
266
285
subDir = replaceWithMap (subDir , subDirReplaceMap )
267
-
268
286
source = strings .TrimRight (source , "/" )
269
287
source = fmt .Sprintf ("%s/%s" , source , subDir )
270
288
}
@@ -281,7 +299,7 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
281
299
return & csi.NodeStageVolumeResponse {}, nil
282
300
}
283
301
284
- // NodeUnstageVolume unmount the volume from the staging path
302
+ // NodeUnstageVolume unmounts the volume from the staging path
285
303
func (d * Driver ) NodeUnstageVolume (_ context.Context , req * csi.NodeUnstageVolumeRequest ) (* csi.NodeUnstageVolumeResponse , error ) {
286
304
volumeID := req .GetVolumeId ()
287
305
if len (volumeID ) == 0 {
@@ -298,16 +316,51 @@ func (d *Driver) NodeUnstageVolume(_ context.Context, req *csi.NodeUnstageVolume
298
316
}
299
317
defer d .volumeLocks .Release (lockKey )
300
318
301
- klog .V (2 ).Infof ("NodeUnstageVolume: CleanupMountPoint on %s with volume %s" , stagingTargetPath , volumeID )
302
- if err := CleanupSMBMountPoint (d .mounter , stagingTargetPath , true /*extensiveMountPointCheck*/ , volumeID ); err != nil {
303
- return nil , status .Errorf (codes .Internal , "failed to unmount staging target %q: %v" , stagingTargetPath , err )
319
+ // Check if any other mounts still reference the staging path
320
+ f , err := os .Open ("/proc/mounts" )
321
+ if err != nil {
322
+ return nil , status .Errorf (codes .Internal , "failed to open /proc/mounts: %v" , err )
323
+ }
324
+ defer f .Close ()
325
+
326
+ scanner := bufio .NewScanner (f )
327
+ refCount := 0
328
+ for scanner .Scan () {
329
+ line := scanner .Text ()
330
+ fields := strings .Fields (line )
331
+ if len (fields ) >= 2 {
332
+ mountPoint := fields [1 ]
333
+ if strings .HasPrefix (mountPoint , stagingTargetPath ) && mountPoint != stagingTargetPath {
334
+ refCount ++
335
+ }
336
+ }
337
+ }
338
+ if refCount > 0 {
339
+ klog .V (2 ).Infof ("NodeUnstageVolume: staging path %s is still in use by %d other mounts" , stagingTargetPath , refCount )
340
+ return & csi.NodeUnstageVolumeResponse {}, nil
341
+ }
342
+
343
+ notMnt , err := d .mounter .IsLikelyNotMountPoint (stagingTargetPath )
344
+ if err != nil && ! os .IsNotExist (err ) {
345
+ return nil , status .Errorf (codes .Internal , "failed to check mount point %q: %v" , stagingTargetPath , err )
346
+ }
347
+ if notMnt {
348
+ klog .V (2 ).Infof ("NodeUnstageVolume: staging path %s is already unmounted" , stagingTargetPath )
349
+ if err := os .Remove (stagingTargetPath ); err != nil && ! os .IsNotExist (err ) {
350
+ return nil , status .Errorf (codes .Internal , "failed to remove staging path %q: %v" , stagingTargetPath , err )
351
+ }
352
+ return & csi.NodeUnstageVolumeResponse {}, nil
304
353
}
305
354
306
- if err := deleteKerberosCache (d .krb5CacheDirectory , volumeID ); err != nil {
307
- return nil , status .Errorf (codes .Internal , "failed to delete kerberos cache: %v" , err )
355
+ klog .V (2 ).Infof ("NodeUnstageVolume: unmounting %s for volume %s" , stagingTargetPath , volumeID )
356
+ if err := d .mounter .Unmount (stagingTargetPath ); err != nil {
357
+ return nil , status .Errorf (codes .Internal , "failed to unmount staging path %q: %v" , stagingTargetPath , err )
358
+ }
359
+ if err := os .Remove (stagingTargetPath ); err != nil && ! os .IsNotExist (err ) {
360
+ return nil , status .Errorf (codes .Internal , "failed to remove staging path %q after unmount: %v" , stagingTargetPath , err )
308
361
}
309
362
310
- klog .V (2 ).Infof ("NodeUnstageVolume: unmount volume %s on %s successfully " , volumeID , stagingTargetPath )
363
+ klog .V (2 ).Infof ("NodeUnstageVolume: successfully unmounted and cleaned up %s for volume %s " , stagingTargetPath , volumeID )
311
364
return & csi.NodeUnstageVolumeResponse {}, nil
312
365
}
313
366
0 commit comments