Skip to content

Commit 06d721c

Browse files
committed
Refactor out mountmanager middle-man object. Cleaned up interfaces to split mounting and device management
1 parent b95de8b commit 06d721c

11 files changed

+110
-83
lines changed

cmd/main.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ func handle() {
5656
glog.Fatalf("Failed to get cloud provider: %v", err)
5757
}
5858

59-
mounter := mountmanager.NewMounter()
59+
mounter := mountmanager.NewSafeMounter()
60+
deviceUtils := mountmanager.NewDeviceUtils()
6061

61-
err = gceDriver.SetupGCEDriver(cloudProvider, mounter, *driverName, *nodeID, vendorVersion)
62+
err = gceDriver.SetupGCEDriver(cloudProvider, mounter, deviceUtils, *driverName, *nodeID, vendorVersion)
6263
if err != nil {
6364
glog.Fatalf("Failed to initialize GCE CSI Driver: %v", err)
6465
}

pkg/gce-pd-csi-driver/controller_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func TestCreateVolumeArguments(t *testing.T) {
147147
if err != nil {
148148
t.Fatalf("Failed to create fake cloud provider: %v", err)
149149
}
150-
err = gceDriver.SetupGCEDriver(fakeCloudProvider, nil, driver, node, "vendor-version")
150+
err = gceDriver.SetupGCEDriver(fakeCloudProvider, nil, nil, driver, node, "vendor-version")
151151
if err != nil {
152152
t.Fatalf("Failed to setup GCE Driver: %v", err)
153153
}

pkg/gce-pd-csi-driver/gce-pd-driver.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/golang/glog"
2222
"google.golang.org/grpc/codes"
2323
"google.golang.org/grpc/status"
24+
"k8s.io/kubernetes/pkg/util/mount"
2425
gce "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/gce-cloud-provider"
2526
mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
2627
)
@@ -43,7 +44,8 @@ func GetGCEDriver() *GCEDriver {
4344
return &GCEDriver{}
4445
}
4546

46-
func (gceDriver *GCEDriver) SetupGCEDriver(cloudProvider gce.GCECompute, mounter mountmanager.MountManager, name, nodeID, vendorVersion string) error {
47+
func (gceDriver *GCEDriver) SetupGCEDriver(cloudProvider gce.GCECompute, mounter *mount.SafeFormatAndMount,
48+
deviceUtils mountmanager.DeviceUtils, name, nodeID, vendorVersion string) error {
4749
if name == "" {
4850
return fmt.Errorf("Driver name missing")
4951
}
@@ -73,7 +75,7 @@ func (gceDriver *GCEDriver) SetupGCEDriver(cloudProvider gce.GCECompute, mounter
7375

7476
// Set up RPC Servers
7577
gceDriver.ids = NewIdentityServer(gceDriver)
76-
gceDriver.ns = NewNodeServer(gceDriver, mounter)
78+
gceDriver.ns = NewNodeServer(gceDriver, mounter, deviceUtils)
7779
gceDriver.cs = NewControllerServer(gceDriver, cloudProvider)
7880

7981
return nil
@@ -129,10 +131,11 @@ func NewIdentityServer(gceDriver *GCEDriver) *GCEIdentityServer {
129131
}
130132
}
131133

132-
func NewNodeServer(gceDriver *GCEDriver, mounter mountmanager.MountManager) *GCENodeServer {
134+
func NewNodeServer(gceDriver *GCEDriver, mounter *mount.SafeFormatAndMount, deviceUtils mountmanager.DeviceUtils) *GCENodeServer {
133135
return &GCENodeServer{
134-
Driver: gceDriver,
135-
Mounter: mounter,
136+
Driver: gceDriver,
137+
Mounter: mounter,
138+
DeviceUtils: deviceUtils,
136139
}
137140
}
138141

pkg/gce-pd-csi-driver/gce-pd-driver_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func initGCEDriver(t *testing.T) *GCEDriver {
2727
if err != nil {
2828
t.Fatalf("Failed to create fake cloud provider: %v", err)
2929
}
30-
err = gceDriver.SetupGCEDriver(fakeCloudProvider, nil, driver, node, vendorVersion)
30+
err = gceDriver.SetupGCEDriver(fakeCloudProvider, nil, nil, driver, node, vendorVersion)
3131
if err != nil {
3232
t.Fatalf("Failed to setup GCE Driver: %v", err)
3333
}

pkg/gce-pd-csi-driver/identity_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
func TestGetPluginInfo(t *testing.T) {
2525
vendorVersion := "test-vendor"
2626
gceDriver := GetGCEDriver()
27-
err := gceDriver.SetupGCEDriver(nil, nil, driver, node, vendorVersion)
27+
err := gceDriver.SetupGCEDriver(nil, nil, nil, driver, node, vendorVersion)
2828
if err != nil {
2929
t.Fatalf("Failed to setup GCE Driver: %v", err)
3030
}
@@ -46,7 +46,7 @@ func TestGetPluginInfo(t *testing.T) {
4646

4747
func TestGetPluginCapabilities(t *testing.T) {
4848
gceDriver := GetGCEDriver()
49-
err := gceDriver.SetupGCEDriver(nil, nil, driver, node, "test-vendor")
49+
err := gceDriver.SetupGCEDriver(nil, nil, nil, driver, node, "test-vendor")
5050
if err != nil {
5151
t.Fatalf("Failed to setup GCE Driver: %v", err)
5252
}
@@ -67,7 +67,7 @@ func TestGetPluginCapabilities(t *testing.T) {
6767

6868
func TestProbe(t *testing.T) {
6969
gceDriver := GetGCEDriver()
70-
err := gceDriver.SetupGCEDriver(nil, nil, driver, node, "test-vendor")
70+
err := gceDriver.SetupGCEDriver(nil, nil, nil, driver, node, "test-vendor")
7171
if err != nil {
7272
t.Fatalf("Failed to setup GCE Driver: %v", err)
7373
}

pkg/gce-pd-csi-driver/node.go

+17-15
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ import (
2424
"golang.org/x/net/context"
2525
"google.golang.org/grpc/codes"
2626
"google.golang.org/grpc/status"
27+
"k8s.io/kubernetes/pkg/util/mount"
2728
mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
2829
utils "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/utils"
2930
)
3031

3132
type GCENodeServer struct {
32-
Driver *GCEDriver
33-
Mounter mountmanager.MountManager
33+
Driver *GCEDriver
34+
Mounter *mount.SafeFormatAndMount
35+
DeviceUtils mountmanager.DeviceUtils
3436
// TODO: Only lock mutually exclusive calls and make locking more fine grained
3537
mux sync.Mutex
3638
}
@@ -61,7 +63,7 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
6163
return nil, status.Error(codes.InvalidArgument, "NodePublishVolume Volume Capability must be provided")
6264
}
6365

64-
notMnt, err := ns.Mounter.GetSafeMounter().Interface.IsLikelyNotMountPoint(targetPath)
66+
notMnt, err := ns.Mounter.Interface.IsLikelyNotMountPoint(targetPath)
6567
if err != nil && !os.IsNotExist(err) {
6668
glog.Errorf("cannot validate mount point: %s %v", targetPath, err)
6769
return nil, err
@@ -71,7 +73,7 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
7173
return nil, nil
7274
}
7375

74-
if err := ns.Mounter.GetSafeMounter().Interface.MakeDir(targetPath); err != nil {
76+
if err := ns.Mounter.Interface.MakeDir(targetPath); err != nil {
7577
glog.Errorf("mkdir failed on disk %s (%v)", targetPath, err)
7678
return nil, err
7779
}
@@ -82,19 +84,19 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
8284
options = append(options, "ro")
8385
}
8486

85-
err = ns.Mounter.GetSafeMounter().Interface.Mount(stagingTargetPath, targetPath, "ext4", options)
87+
err = ns.Mounter.Interface.Mount(stagingTargetPath, targetPath, "ext4", options)
8688
if err != nil {
87-
notMnt, mntErr := ns.Mounter.GetSafeMounter().Interface.IsLikelyNotMountPoint(targetPath)
89+
notMnt, mntErr := ns.Mounter.Interface.IsLikelyNotMountPoint(targetPath)
8890
if mntErr != nil {
8991
glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr)
9092
return nil, status.Error(codes.Internal, fmt.Sprintf("TODO: %v", err))
9193
}
9294
if !notMnt {
93-
if mntErr = ns.Mounter.GetSafeMounter().Interface.Unmount(targetPath); mntErr != nil {
95+
if mntErr = ns.Mounter.Interface.Unmount(targetPath); mntErr != nil {
9496
glog.Errorf("Failed to unmount: %v", mntErr)
9597
return nil, status.Error(codes.Internal, fmt.Sprintf("TODO: %v", err))
9698
}
97-
notMnt, mntErr := ns.Mounter.GetSafeMounter().Interface.IsLikelyNotMountPoint(targetPath)
99+
notMnt, mntErr := ns.Mounter.Interface.IsLikelyNotMountPoint(targetPath)
98100
if mntErr != nil {
99101
glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr)
100102
return nil, status.Error(codes.Internal, fmt.Sprintf("TODO: %v", err))
@@ -130,7 +132,7 @@ func (ns *GCENodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeU
130132

131133
// TODO: Check volume still exists
132134

133-
err := ns.Mounter.GetSafeMounter().Interface.Unmount(targetPath)
135+
err := ns.Mounter.Interface.Unmount(targetPath)
134136
if err != nil {
135137
return nil, status.Error(codes.Internal, fmt.Sprintf("Unmount failed: %v\nUnmounting arguments: %s\n", err, targetPath))
136138
}
@@ -168,8 +170,8 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
168170
// TODO: Get real partitions
169171
partition := ""
170172

171-
devicePaths := ns.Mounter.GetDiskByIdPaths(volumeName, partition)
172-
devicePath, err := ns.Mounter.VerifyDevicePath(devicePaths)
173+
devicePaths := ns.DeviceUtils.GetDiskByIdPaths(volumeName, partition)
174+
devicePath, err := ns.DeviceUtils.VerifyDevicePath(devicePaths)
173175

174176
if err != nil {
175177
return nil, status.Error(codes.Internal, fmt.Sprintf("Error verifying GCE PD (%q) is attached: %v", volumeName, err))
@@ -181,10 +183,10 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
181183
glog.Infof("Successfully found attached GCE PD %q at device path %s.", volumeName, devicePath)
182184

183185
// Part 2: Check if mount already exists at targetpath
184-
notMnt, err := ns.Mounter.GetSafeMounter().Interface.IsLikelyNotMountPoint(stagingTargetPath)
186+
notMnt, err := ns.Mounter.Interface.IsLikelyNotMountPoint(stagingTargetPath)
185187
if err != nil {
186188
if os.IsNotExist(err) {
187-
if err := ns.Mounter.GetSafeMounter().Interface.MakeDir(stagingTargetPath); err != nil {
189+
if err := ns.Mounter.Interface.MakeDir(stagingTargetPath); err != nil {
188190
return nil, status.Error(codes.Internal, fmt.Sprintf("Failed to create directory (%q): %v", stagingTargetPath, err))
189191
}
190192
notMnt = true
@@ -218,7 +220,7 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
218220
return nil, status.Error(codes.Unimplemented, fmt.Sprintf("Block volume support is not yet implemented"))
219221
}
220222

221-
err = ns.Mounter.GetSafeMounter().FormatAndMount(devicePath, stagingTargetPath, fstype, options)
223+
err = ns.Mounter.FormatAndMount(devicePath, stagingTargetPath, fstype, options)
222224
if err != nil {
223225
return nil, status.Error(codes.Internal,
224226
fmt.Sprintf("Failed to format and mount device from (%q) to (%q) with fstype (%q) and options (%q): %v",
@@ -242,7 +244,7 @@ func (ns *GCENodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUns
242244
return nil, status.Error(codes.InvalidArgument, "NodeUnstageVolume Staging Target Path must be provided")
243245
}
244246

245-
err := ns.Mounter.GetSafeMounter().Interface.Unmount(stagingTargetPath)
247+
err := ns.Mounter.Interface.Unmount(stagingTargetPath)
246248
if err != nil {
247249
return nil, status.Error(codes.Internal, fmt.Sprintf("NodeUnstageVolume failed to unmount at path %s: %v", stagingTargetPath, err))
248250
}

pkg/mount-manager/mount-manager.go renamed to pkg/mount-manager/device-utils.go

+7-25
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323

2424
"github.com/golang/glog"
2525
"k8s.io/apimachinery/pkg/util/sets"
26-
"k8s.io/kubernetes/pkg/util/mount"
2726
"k8s.io/utils/exec"
2827
)
2928

@@ -50,41 +49,24 @@ const (
5049
defaultMountCommand = "mount"
5150
)
5251

53-
// TODO: Info
54-
type MountManager interface {
55-
// TODO: Info
56-
GetSafeMounter() *mount.SafeFormatAndMount
57-
// TODO: Info
52+
type DeviceUtils interface {
5853
GetDiskByIdPaths(pdName string, partition string) []string
5954
// TODO: Info
6055
VerifyDevicePath(devicePaths []string) (string, error)
6156
}
6257

6358
// TODO: Info
64-
type GCEMounter struct {
65-
// TODO: Info
66-
SafeMounter *mount.SafeFormatAndMount
59+
type deviceUtils struct {
6760
}
6861

69-
var _ MountManager = &GCEMounter{}
70-
71-
func NewMounter() *GCEMounter {
72-
realMounter := mount.New("")
73-
realExec := mount.NewOsExec()
74-
return &GCEMounter{
75-
SafeMounter: &mount.SafeFormatAndMount{
76-
Interface: realMounter,
77-
Exec: realExec,
78-
},
79-
}
80-
}
62+
var _ DeviceUtils = &deviceUtils{}
8163

82-
func (m *GCEMounter) GetSafeMounter() *mount.SafeFormatAndMount {
83-
return m.SafeMounter
64+
func NewDeviceUtils() *deviceUtils {
65+
return &deviceUtils{}
8466
}
8567

8668
// Returns list of all /dev/disk/by-id/* paths for given PD.
87-
func (m *GCEMounter) GetDiskByIdPaths(pdName string, partition string) []string {
69+
func (m *deviceUtils) GetDiskByIdPaths(pdName string, partition string) []string {
8870
devicePaths := []string{
8971
path.Join(diskByIdPath, diskGooglePrefix+pdName),
9072
path.Join(diskByIdPath, diskScsiGooglePrefix+pdName),
@@ -102,7 +84,7 @@ func (m *GCEMounter) GetDiskByIdPaths(pdName string, partition string) []string
10284
}
10385

10486
// Returns the first path that exists, or empty string if none exist.
105-
func (m *GCEMounter) VerifyDevicePath(devicePaths []string) (string, error) {
87+
func (m *deviceUtils) VerifyDevicePath(devicePaths []string) (string, error) {
10688
sdBefore, err := filepath.Glob(diskSDPattern)
10789
if err != nil {
10890
// Seeing this error means that the diskSDPattern is malformed.
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
15+
package mountmanager
16+
17+
type fakeDeviceUtils struct {
18+
}
19+
20+
var _ DeviceUtils = &fakeDeviceUtils{}
21+
22+
func NewFakeDeviceUtils() *fakeDeviceUtils {
23+
return &fakeDeviceUtils{}
24+
}
25+
26+
// Returns list of all /dev/disk/by-id/* paths for given PD.
27+
func (m *fakeDeviceUtils) GetDiskByIdPaths(pdName string, partition string) []string {
28+
// Don't need to implement this in the fake because we have no actual device paths
29+
return nil
30+
}
31+
32+
// Returns the first path that exists, or empty string if none exist.
33+
func (m *fakeDeviceUtils) VerifyDevicePath(devicePaths []string) (string, error) {
34+
// Return any random device path to use as mount source
35+
return "/dev/disk/fake-path", nil
36+
}

pkg/mount-manager/fake.go renamed to pkg/mount-manager/fake-safe-mounter.go

+4-29
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,7 @@ package mountmanager
1616

1717
import "k8s.io/kubernetes/pkg/util/mount"
1818

19-
type FakeGCEMounter struct {
20-
// TODO: Info
21-
SafeMounter *mount.SafeFormatAndMount
22-
}
23-
24-
var _ MountManager = &FakeGCEMounter{}
25-
26-
func FakeMounter(mountErrs []error) *FakeGCEMounter {
19+
func NewFakeSafeMounter() *mount.SafeFormatAndMount {
2720
execCallback := func(cmd string, args ...string) ([]byte, error) {
2821
return nil, nil
2922
// TODO: Fill out exec callback for errors
@@ -47,26 +40,8 @@ func FakeMounter(mountErrs []error) *FakeGCEMounter {
4740
}
4841
fakeMounter := &mount.FakeMounter{MountPoints: []mount.MountPoint{}, Log: []mount.FakeAction{}}
4942
fakeExec := mount.NewFakeExec(execCallback)
50-
return &FakeGCEMounter{
51-
SafeMounter: &mount.SafeFormatAndMount{
52-
Interface: fakeMounter,
53-
Exec: fakeExec,
54-
},
43+
return &mount.SafeFormatAndMount{
44+
Interface: fakeMounter,
45+
Exec: fakeExec,
5546
}
5647
}
57-
58-
func (m *FakeGCEMounter) GetSafeMounter() *mount.SafeFormatAndMount {
59-
return m.SafeMounter
60-
}
61-
62-
// Returns list of all /dev/disk/by-id/* paths for given PD.
63-
func (m *FakeGCEMounter) GetDiskByIdPaths(pdName string, partition string) []string {
64-
// Don't need to implement this in the fake because we have no actual device paths
65-
return nil
66-
}
67-
68-
// Returns the first path that exists, or empty string if none exist.
69-
func (m *FakeGCEMounter) VerifyDevicePath(devicePaths []string) (string, error) {
70-
// Return any random device path to use as mount source
71-
return "/dev/disk/fake-path", nil
72-
}

pkg/mount-manager/safe-mounter.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
15+
package mountmanager
16+
17+
import "k8s.io/kubernetes/pkg/util/mount"
18+
19+
func NewSafeMounter() *mount.SafeFormatAndMount {
20+
realMounter := mount.New("")
21+
realExec := mount.NewOsExec()
22+
return &mount.SafeFormatAndMount{
23+
Interface: realMounter,
24+
Exec: realExec,
25+
}
26+
27+
}

0 commit comments

Comments
 (0)