StorageOS: Use VolumeHost.GetExec() to execute stuff in volume plugins

pull/6/head
Jan Safranek 2017-08-22 15:57:08 +02:00
parent 07dea6b447
commit bf296b3e31
4 changed files with 23 additions and 24 deletions

View File

@ -27,7 +27,6 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
], ],
) )

View File

@ -110,10 +110,10 @@ func (plugin *storageosPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volu
return nil, err return nil, err
} }
return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName())) return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
} }
func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface) (volume.Mounter, error) { func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface, exec mount.Exec) (volume.Mounter, error) {
volName, volNamespace, fsType, readOnly, err := getVolumeInfoFromSpec(spec) volName, volNamespace, fsType, readOnly, err := getVolumeInfoFromSpec(spec)
if err != nil { if err != nil {
@ -132,19 +132,20 @@ func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod
apiCfg: apiCfg, apiCfg: apiCfg,
manager: manager, manager: manager,
mounter: mounter, mounter: mounter,
exec: exec,
plugin: plugin, plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(pod.UID, volNamespace, volName, spec.Name(), plugin.host)), MetricsProvider: volume.NewMetricsStatFS(getPath(pod.UID, volNamespace, volName, spec.Name(), plugin.host)),
}, },
devicePath: storageosDevicePath, devicePath: storageosDevicePath,
diskMounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: plugin.host.GetExec(plugin.GetPluginName())}, diskMounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
}, nil }, nil
} }
func (plugin *storageosPlugin) NewUnmounter(pvName string, podUID types.UID) (volume.Unmounter, error) { func (plugin *storageosPlugin) NewUnmounter(pvName string, podUID types.UID) (volume.Unmounter, error) {
return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName())) return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
} }
func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface) (volume.Unmounter, error) { func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface, exec mount.Exec) (volume.Unmounter, error) {
// Parse volume namespace & name from mountpoint if mounted // Parse volume namespace & name from mountpoint if mounted
volNamespace, volName, err := getVolumeInfo(pvName, podUID, plugin.host) volNamespace, volName, err := getVolumeInfo(pvName, podUID, plugin.host)
@ -160,6 +161,7 @@ func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.
volNamespace: volNamespace, volNamespace: volNamespace,
manager: manager, manager: manager,
mounter: mounter, mounter: mounter,
exec: exec,
plugin: plugin, plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volNamespace, volName, pvName, plugin.host)), MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volNamespace, volName, pvName, plugin.host)),
}, },
@ -303,6 +305,7 @@ type storageos struct {
apiCfg *storageosAPIConfig apiCfg *storageosAPIConfig
manager storageosManager manager storageosManager
mounter mount.Interface mounter mount.Interface
exec mount.Exec
plugin *storageosPlugin plugin *storageosPlugin
volume.MetricsProvider volume.MetricsProvider
} }

View File

@ -184,7 +184,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Couldn't get secret from %v/%v", pod.Namespace, secretName) t.Errorf("Couldn't get secret from %v/%v", pod.Namespace, secretName)
} }
mounter, err := plug.(*storageosPlugin).newMounterInternal(volume.NewSpecFromVolume(spec), pod, apiCfg, fakeManager, &mount.FakeMounter{}) mounter, err := plug.(*storageosPlugin).newMounterInternal(volume.NewSpecFromVolume(spec), pod, apiCfg, fakeManager, &mount.FakeMounter{}, mount.NewFakeExec(nil))
if err != nil { if err != nil {
t.Fatalf("Failed to make a new Mounter: %v", err) t.Fatalf("Failed to make a new Mounter: %v", err)
} }
@ -218,7 +218,7 @@ func TestPlugin(t *testing.T) {
// Test Unmounter // Test Unmounter
fakeManager = &fakePDManager{} fakeManager = &fakePDManager{}
unmounter, err := plug.(*storageosPlugin).newUnmounterInternal("vol1-pvname", types.UID("poduid"), fakeManager, &mount.FakeMounter{}) unmounter, err := plug.(*storageosPlugin).newUnmounterInternal("vol1-pvname", types.UID("poduid"), fakeManager, &mount.FakeMounter{}, mount.NewFakeExec(nil))
if err != nil { if err != nil {
t.Errorf("Failed to make a new Unmounter: %v", err) t.Errorf("Failed to make a new Unmounter: %v", err)
} }
@ -362,7 +362,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
fakeManager := &fakePDManager{} fakeManager := &fakePDManager{}
fakeConfig := &fakeConfig{} fakeConfig := &fakeConfig{}
apiCfg := fakeConfig.GetAPIConfig() apiCfg := fakeConfig.GetAPIConfig()
mounter, err := plug.(*storageosPlugin).newMounterInternal(spec, pod, apiCfg, fakeManager, &mount.FakeMounter{}) mounter, err := plug.(*storageosPlugin).newMounterInternal(spec, pod, apiCfg, fakeManager, &mount.FakeMounter{}, mount.NewFakeExec(nil))
if !mounter.GetAttributes().ReadOnly { if !mounter.GetAttributes().ReadOnly {
t.Errorf("Expected true for mounter.IsReadOnly") t.Errorf("Expected true for mounter.IsReadOnly")

View File

@ -23,7 +23,7 @@ import (
"path" "path"
"strings" "strings"
"k8s.io/utils/exec" "k8s.io/kubernetes/pkg/util/mount"
"github.com/golang/glog" "github.com/golang/glog"
storageosapi "github.com/storageos/go-api" storageosapi "github.com/storageos/go-api"
@ -177,7 +177,7 @@ func (u *storageosUtil) AttachVolume(b *storageosMounter) (string, error) {
case modeBlock: case modeBlock:
return srcPath, nil return srcPath, nil
case modeFile: case modeFile:
return attachFileDevice(srcPath) return attachFileDevice(srcPath, b.exec)
default: default:
return "", fmt.Errorf(ErrDeviceNotSupported) return "", fmt.Errorf(ErrDeviceNotSupported)
} }
@ -192,7 +192,7 @@ func (u *storageosUtil) DetachVolume(b *storageosUnmounter, devicePath string) e
if _, err := os.Stat(devicePath); os.IsNotExist(err) { if _, err := os.Stat(devicePath); os.IsNotExist(err) {
return nil return nil
} }
return removeLoopDevice(devicePath) return removeLoopDevice(devicePath, b.exec)
} }
// Mount mounts the volume on the host. // Mount mounts the volume on the host.
@ -295,8 +295,8 @@ func pathDeviceType(path string) (deviceType, error) {
// attachFileDevice takes a path to a regular file and makes it available as an // attachFileDevice takes a path to a regular file and makes it available as an
// attached block device. // attached block device.
func attachFileDevice(path string) (string, error) { func attachFileDevice(path string, exec mount.Exec) (string, error) {
blockDevicePath, err := getLoopDevice(path) blockDevicePath, err := getLoopDevice(path, exec)
if err != nil && err.Error() != ErrDeviceNotFound { if err != nil && err.Error() != ErrDeviceNotFound {
return "", err return "", err
} }
@ -304,7 +304,7 @@ func attachFileDevice(path string) (string, error) {
// If no existing loop device for the path, create one // If no existing loop device for the path, create one
if blockDevicePath == "" { if blockDevicePath == "" {
glog.V(4).Infof("Creating device for path: %s", path) glog.V(4).Infof("Creating device for path: %s", path)
blockDevicePath, err = makeLoopDevice(path) blockDevicePath, err = makeLoopDevice(path, exec)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -313,7 +313,7 @@ func attachFileDevice(path string) (string, error) {
} }
// Returns the full path to the loop device associated with the given path. // Returns the full path to the loop device associated with the given path.
func getLoopDevice(path string) (string, error) { func getLoopDevice(path string, exec mount.Exec) (string, error) {
_, err := os.Stat(path) _, err := os.Stat(path)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return "", errors.New(ErrNotAvailable) return "", errors.New(ErrNotAvailable)
@ -322,9 +322,8 @@ func getLoopDevice(path string) (string, error) {
return "", fmt.Errorf("not attachable: %v", err) return "", fmt.Errorf("not attachable: %v", err)
} }
exec := exec.New()
args := []string{"-j", path} args := []string{"-j", path}
out, err := exec.Command(losetupPath, args...).CombinedOutput() out, err := exec.Run(losetupPath, args...)
if err != nil { if err != nil {
glog.V(2).Infof("Failed device discover command for path %s: %v", path, err) glog.V(2).Infof("Failed device discover command for path %s: %v", path, err)
return "", err return "", err
@ -332,10 +331,9 @@ func getLoopDevice(path string) (string, error) {
return parseLosetupOutputForDevice(out) return parseLosetupOutputForDevice(out)
} }
func makeLoopDevice(path string) (string, error) { func makeLoopDevice(path string, exec mount.Exec) (string, error) {
exec := exec.New()
args := []string{"-f", "--show", path} args := []string{"-f", "--show", path}
out, err := exec.Command(losetupPath, args...).CombinedOutput() out, err := exec.Run(losetupPath, args...)
if err != nil { if err != nil {
glog.V(2).Infof("Failed device create command for path %s: %v", path, err) glog.V(2).Infof("Failed device create command for path %s: %v", path, err)
return "", err return "", err
@ -343,10 +341,9 @@ func makeLoopDevice(path string) (string, error) {
return parseLosetupOutputForDevice(out) return parseLosetupOutputForDevice(out)
} }
func removeLoopDevice(device string) error { func removeLoopDevice(device string, exec mount.Exec) error {
exec := exec.New()
args := []string{"-d", device} args := []string{"-d", device}
out, err := exec.Command(losetupPath, args...).CombinedOutput() out, err := exec.Run(losetupPath, args...)
if err != nil { if err != nil {
if !strings.Contains(string(out), "No such device or address") { if !strings.Contains(string(out), "No such device or address") {
return err return err