@@ -17,48 +17,20 @@ package gceGCEDriver
17
17
import (
18
18
"fmt"
19
19
"os"
20
- "path"
21
- "path/filepath"
22
- "strings"
23
20
"sync"
24
21
25
22
csi "github.com/container-storage-interface/spec/lib/go/csi/v0"
26
23
"github.com/golang/glog"
27
24
"golang.org/x/net/context"
28
25
"google.golang.org/grpc/codes"
29
26
"google.golang.org/grpc/status"
30
- "k8s.io/apimachinery/pkg/util/sets"
31
- "k8s.io/kubernetes/pkg/util/mount"
32
- "k8s.io/utils/exec"
27
+ mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
33
28
utils "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/utils"
34
29
)
35
30
36
- const (
37
- diskByHostIdPath = "/host/dev/disk/by-id/"
38
- diskByIdPath = "/dev/disk/by-id/"
39
- diskGooglePrefix = "google-"
40
- diskScsiGooglePrefix = "scsi-0Google_PersistentDisk_"
41
- diskPartitionSuffix = "-part"
42
- diskSDPath = "/host/dev/sd"
43
- diskSDPattern = "/host/dev/sd*"
44
- // How many times to retry for a consistent read of /proc/mounts.
45
- maxListTries = 3
46
- // Number of fields per line in /proc/mounts as per the fstab man page.
47
- expectedNumFieldsPerLine = 6
48
- // Location of the mount file to use
49
- procMountsPath = "/proc/mounts"
50
- // Location of the mountinfo file
51
- procMountInfoPath = "/proc/self/mountinfo"
52
- // 'fsck' found errors and corrected them
53
- fsckErrorsCorrected = 1
54
- // 'fsck' found errors but exited without correcting them
55
- fsckErrorsUncorrected = 4
56
- defaultMountCommand = "mount"
57
- )
58
-
59
31
type GCENodeServer struct {
60
32
Driver * GCEDriver
61
- Mounter mount. SafeFormatAndMount
33
+ Mounter mountmanager. MountManager
62
34
// TODO: Only lock mutually exclusive calls and make locking more fine grained
63
35
mux sync.Mutex
64
36
}
@@ -89,7 +61,7 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
89
61
return nil , status .Error (codes .InvalidArgument , "NodePublishVolume Volume Capability must be provided" )
90
62
}
91
63
92
- notMnt , err := ns .Mounter .IsLikelyNotMountPoint (targetPath )
64
+ notMnt , err := ns .Mounter .GetSafeMounter (). Interface . IsLikelyNotMountPoint (targetPath )
93
65
if err != nil && ! os .IsNotExist (err ) {
94
66
glog .Errorf ("cannot validate mount point: %s %v" , targetPath , err )
95
67
return nil , err
@@ -99,7 +71,7 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
99
71
return nil , nil
100
72
}
101
73
102
- if err := ns .Mounter .MakeDir (targetPath ); err != nil {
74
+ if err := ns .Mounter .GetSafeMounter (). Interface . MakeDir (targetPath ); err != nil {
103
75
glog .Errorf ("mkdir failed on disk %s (%v)" , targetPath , err )
104
76
return nil , err
105
77
}
@@ -110,19 +82,19 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
110
82
options = append (options , "ro" )
111
83
}
112
84
113
- err = ns .Mounter .Mount (stagingTargetPath , targetPath , "ext4" , options )
85
+ err = ns .Mounter .GetSafeMounter (). Interface . Mount (stagingTargetPath , targetPath , "ext4" , options )
114
86
if err != nil {
115
- notMnt , mntErr := ns .Mounter .IsLikelyNotMountPoint (targetPath )
87
+ notMnt , mntErr := ns .Mounter .GetSafeMounter (). Interface . IsLikelyNotMountPoint (targetPath )
116
88
if mntErr != nil {
117
89
glog .Errorf ("IsLikelyNotMountPoint check failed: %v" , mntErr )
118
90
return nil , status .Error (codes .Internal , fmt .Sprintf ("TODO: %v" , err ))
119
91
}
120
92
if ! notMnt {
121
- if mntErr = ns .Mounter .Unmount (targetPath ); mntErr != nil {
93
+ if mntErr = ns .Mounter .GetSafeMounter (). Interface . Unmount (targetPath ); mntErr != nil {
122
94
glog .Errorf ("Failed to unmount: %v" , mntErr )
123
95
return nil , status .Error (codes .Internal , fmt .Sprintf ("TODO: %v" , err ))
124
96
}
125
- notMnt , mntErr := ns .Mounter .IsLikelyNotMountPoint (targetPath )
97
+ notMnt , mntErr := ns .Mounter .GetSafeMounter (). Interface . IsLikelyNotMountPoint (targetPath )
126
98
if mntErr != nil {
127
99
glog .Errorf ("IsLikelyNotMountPoint check failed: %v" , mntErr )
128
100
return nil , status .Error (codes .Internal , fmt .Sprintf ("TODO: %v" , err ))
@@ -158,7 +130,7 @@ func (ns *GCENodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeU
158
130
159
131
// TODO: Check volume still exists
160
132
161
- err := ns .Mounter .Unmount (targetPath )
133
+ err := ns .Mounter .GetSafeMounter (). Interface . Unmount (targetPath )
162
134
if err != nil {
163
135
return nil , status .Error (codes .Internal , fmt .Sprintf ("Unmount failed: %v\n Unmounting arguments: %s\n " , err , targetPath ))
164
136
}
@@ -196,8 +168,8 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
196
168
// TODO: Get real partitions
197
169
partition := ""
198
170
199
- devicePaths := getDiskByIdPaths (volumeName , partition )
200
- devicePath , err := verifyDevicePath (devicePaths )
171
+ devicePaths := ns . Mounter . GetDiskByIdPaths (volumeName , partition )
172
+ devicePath , err := ns . Mounter . VerifyDevicePath (devicePaths )
201
173
202
174
if err != nil {
203
175
return nil , status .Error (codes .Internal , fmt .Sprintf ("Error verifying GCE PD (%q) is attached: %v" , volumeName , err ))
@@ -209,10 +181,10 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
209
181
glog .Infof ("Successfully found attached GCE PD %q at device path %s." , volumeName , devicePath )
210
182
211
183
// Part 2: Check if mount already exists at targetpath
212
- notMnt , err := ns .Mounter .IsLikelyNotMountPoint (stagingTargetPath )
184
+ notMnt , err := ns .Mounter .GetSafeMounter (). Interface . IsLikelyNotMountPoint (stagingTargetPath )
213
185
if err != nil {
214
186
if os .IsNotExist (err ) {
215
- if err := ns .Mounter .MakeDir (stagingTargetPath ); err != nil {
187
+ if err := ns .Mounter .GetSafeMounter (). Interface . MakeDir (stagingTargetPath ); err != nil {
216
188
return nil , status .Error (codes .Internal , fmt .Sprintf ("Failed to create directory (%q): %v" , stagingTargetPath , err ))
217
189
}
218
190
notMnt = true
@@ -246,7 +218,7 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
246
218
return nil , status .Error (codes .Unimplemented , fmt .Sprintf ("Block volume support is not yet implemented" ))
247
219
}
248
220
249
- err = ns .Mounter .FormatAndMount (devicePath , stagingTargetPath , fstype , options )
221
+ err = ns .Mounter .GetSafeMounter (). FormatAndMount (devicePath , stagingTargetPath , fstype , options )
250
222
if err != nil {
251
223
return nil , status .Error (codes .Internal ,
252
224
fmt .Sprintf ("Failed to format and mount device from (%q) to (%q) with fstype (%q) and options (%q): %v" ,
@@ -270,7 +242,7 @@ func (ns *GCENodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUns
270
242
return nil , status .Error (codes .InvalidArgument , "NodeUnstageVolume Staging Target Path must be provided" )
271
243
}
272
244
273
- err := ns .Mounter .Unmount (stagingTargetPath )
245
+ err := ns .Mounter .GetSafeMounter (). Interface . Unmount (stagingTargetPath )
274
246
if err != nil {
275
247
return nil , status .Error (codes .Internal , fmt .Sprintf ("NodeUnstageVolume failed to unmount at path %s: %v" , stagingTargetPath , err ))
276
248
}
@@ -305,107 +277,3 @@ func (ns *GCENodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRe
305
277
}
306
278
return resp , nil
307
279
}
308
-
309
- // Returns list of all /dev/disk/by-id/* paths for given PD.
310
- func getDiskByIdPaths (pdName string , partition string ) []string {
311
- devicePaths := []string {
312
- path .Join (diskByIdPath , diskGooglePrefix + pdName ),
313
- path .Join (diskByIdPath , diskScsiGooglePrefix + pdName ),
314
- path .Join (diskByHostIdPath , diskScsiGooglePrefix + pdName ),
315
- path .Join (diskByHostIdPath , diskScsiGooglePrefix + pdName ),
316
- }
317
-
318
- if partition != "" {
319
- for i , path := range devicePaths {
320
- devicePaths [i ] = path + diskPartitionSuffix + partition
321
- }
322
- }
323
-
324
- return devicePaths
325
- }
326
-
327
- // Returns the first path that exists, or empty string if none exist.
328
- func verifyDevicePath (devicePaths []string ) (string , error ) {
329
- sdBefore , err := filepath .Glob (diskSDPattern )
330
- if err != nil {
331
- // Seeing this error means that the diskSDPattern is malformed.
332
- glog .Errorf ("Error filepath.Glob(\" %s\" ): %v\r \n " , diskSDPattern , err )
333
- }
334
- sdBeforeSet := sets .NewString (sdBefore ... )
335
- // TODO: Remove this udevadm stuff. Not applicable because can't access /dev/sd* from container
336
- if err := udevadmChangeToNewDrives (sdBeforeSet ); err != nil {
337
- // udevadm errors should not block disk detachment, log and continue
338
- glog .Errorf ("udevadmChangeToNewDrives failed with: %v" , err )
339
- }
340
-
341
- for _ , path := range devicePaths {
342
- if pathExists , err := pathExists (path ); err != nil {
343
- return "" , fmt .Errorf ("Error checking if path exists: %v" , err )
344
- } else if pathExists {
345
- return path , nil
346
- }
347
- }
348
-
349
- return "" , nil
350
- }
351
-
352
- // Triggers the application of udev rules by calling "udevadm trigger
353
- // --action=change" for newly created "/dev/sd*" drives (exist only in
354
- // after set). This is workaround for Issue #7972. Once the underlying
355
- // issue has been resolved, this may be removed.
356
- func udevadmChangeToNewDrives (sdBeforeSet sets.String ) error {
357
- sdAfter , err := filepath .Glob (diskSDPattern )
358
- if err != nil {
359
- return fmt .Errorf ("Error filepath.Glob(\" %s\" ): %v\r \n " , diskSDPattern , err )
360
- }
361
-
362
- for _ , sd := range sdAfter {
363
- if ! sdBeforeSet .Has (sd ) {
364
- return udevadmChangeToDrive (sd )
365
- }
366
- }
367
-
368
- return nil
369
- }
370
-
371
- // Calls "udevadm trigger --action=change" on the specified drive.
372
- // drivePath must be the block device path to trigger on, in the format "/dev/sd*", or a symlink to it.
373
- // This is workaround for Issue #7972. Once the underlying issue has been resolved, this may be removed.
374
- func udevadmChangeToDrive (drivePath string ) error {
375
- glog .V (5 ).Infof ("udevadmChangeToDrive: drive=%q" , drivePath )
376
-
377
- // Evaluate symlink, if any
378
- drive , err := filepath .EvalSymlinks (drivePath )
379
- if err != nil {
380
- return fmt .Errorf ("udevadmChangeToDrive: filepath.EvalSymlinks(%q) failed with %v." , drivePath , err )
381
- }
382
- glog .V (5 ).Infof ("udevadmChangeToDrive: symlink path is %q" , drive )
383
-
384
- // Check to make sure input is "/dev/sd*"
385
- if ! strings .Contains (drive , diskSDPath ) {
386
- return fmt .Errorf ("udevadmChangeToDrive: expected input in the form \" %s\" but drive is %q." , diskSDPattern , drive )
387
- }
388
-
389
- // Call "udevadm trigger --action=change --property-match=DEVNAME=/dev/sd..."
390
- _ , err = exec .New ().Command (
391
- "udevadm" ,
392
- "trigger" ,
393
- "--action=change" ,
394
- fmt .Sprintf ("--property-match=DEVNAME=%s" , drive )).CombinedOutput ()
395
- if err != nil {
396
- return fmt .Errorf ("udevadmChangeToDrive: udevadm trigger failed for drive %q with %v." , drive , err )
397
- }
398
- return nil
399
- }
400
-
401
- // PathExists returns true if the specified path exists.
402
- func pathExists (path string ) (bool , error ) {
403
- _ , err := os .Stat (path )
404
- if err == nil {
405
- return true , nil
406
- } else if os .IsNotExist (err ) {
407
- return false , nil
408
- } else {
409
- return false , err
410
- }
411
- }
0 commit comments