Commit 894b9b2a authored by Chakravarthy Nelluri's avatar Chakravarthy Nelluri

Remove controller node plugin driver dependency for non-attachable flex volume drivers (Ex: NFS).

parent 289de0ee
...@@ -83,7 +83,7 @@ unmount() { ...@@ -83,7 +83,7 @@ unmount() {
op=$1 op=$1
if [ "$op" = "init" ]; then if [ "$op" = "init" ]; then
log "{\"status\": \"Success\"}" log "{\"status\": \"Success\", \"capabilities\": {\"attach\": false}}"
exit 0 exit 0
fi fi
...@@ -100,9 +100,6 @@ case "$op" in ...@@ -100,9 +100,6 @@ case "$op" in
unmount) unmount)
unmount $* unmount $*
;; ;;
getvolumename)
getvolumename $*
;;
*) *)
log "{ \"status\": \"Not supported\" }" log "{ \"status\": \"Not supported\" }"
exit 0 exit 0
......
...@@ -17,8 +17,6 @@ limitations under the License. ...@@ -17,8 +17,6 @@ limitations under the License.
package flexvolume package flexvolume
import ( import (
"fmt"
"path"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
...@@ -33,30 +31,24 @@ type attacherDefaults flexVolumeAttacher ...@@ -33,30 +31,24 @@ type attacherDefaults flexVolumeAttacher
// Attach is part of the volume.Attacher interface // Attach is part of the volume.Attacher interface
func (a *attacherDefaults) Attach(spec *volume.Spec, hostName types.NodeName) (string, error) { func (a *attacherDefaults) Attach(spec *volume.Spec, hostName types.NodeName) (string, error) {
glog.Warning(logPrefix(a.plugin), "using default Attach for volume ", spec.Name, ", host ", hostName) glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default Attach for volume ", spec.Name, ", host ", hostName)
return "", nil return "", nil
} }
// WaitForAttach is part of the volume.Attacher interface // WaitForAttach is part of the volume.Attacher interface
func (a *attacherDefaults) WaitForAttach(spec *volume.Spec, devicePath string, timeout time.Duration) (string, error) { func (a *attacherDefaults) WaitForAttach(spec *volume.Spec, devicePath string, timeout time.Duration) (string, error) {
glog.Warning(logPrefix(a.plugin), "using default WaitForAttach for volume ", spec.Name, ", device ", devicePath) glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default WaitForAttach for volume ", spec.Name, ", device ", devicePath)
return devicePath, nil return devicePath, nil
} }
// GetDeviceMountPath is part of the volume.Attacher interface // GetDeviceMountPath is part of the volume.Attacher interface
func (a *attacherDefaults) GetDeviceMountPath(spec *volume.Spec, mountsDir string) (string, error) { func (a *attacherDefaults) GetDeviceMountPath(spec *volume.Spec, mountsDir string) (string, error) {
glog.Warning(logPrefix(a.plugin), "using default GetDeviceMountPath for volume ", spec.Name, ", mountsDir ", mountsDir) return a.plugin.getDeviceMountPath(spec)
volumeName, err := a.plugin.GetVolumeName(spec)
if err != nil {
return "", fmt.Errorf("GetVolumeName failed from GetDeviceMountPath: %s", err)
}
return path.Join(mountsDir, volumeName), nil
} }
// MountDevice is part of the volume.Attacher interface // MountDevice is part of the volume.Attacher interface
func (a *attacherDefaults) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mounter mount.Interface) error { func (a *attacherDefaults) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mounter mount.Interface) error {
glog.Warning(logPrefix(a.plugin), "using default MountDevice for volume ", spec.Name, ", device ", devicePath, ", deviceMountPath ", deviceMountPath) glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default MountDevice for volume ", spec.Name, ", device ", devicePath, ", deviceMountPath ", deviceMountPath)
volSource, readOnly := getVolumeSource(spec) volSource, readOnly := getVolumeSource(spec)
options := make([]string, 0) options := make([]string, 0)
......
...@@ -17,7 +17,6 @@ limitations under the License. ...@@ -17,7 +17,6 @@ limitations under the License.
package flexvolume package flexvolume
import ( import (
"path"
"time" "time"
"github.com/golang/glog" "github.com/golang/glog"
...@@ -26,7 +25,7 @@ import ( ...@@ -26,7 +25,7 @@ import (
) )
type flexVolumeAttacher struct { type flexVolumeAttacher struct {
plugin *flexVolumePlugin plugin *flexVolumeAttachablePlugin
} }
var _ volume.Attacher = &flexVolumeAttacher{} var _ volume.Attacher = &flexVolumeAttacher{}
...@@ -64,9 +63,7 @@ func (a *flexVolumeAttacher) WaitForAttach(spec *volume.Spec, devicePath string, ...@@ -64,9 +63,7 @@ func (a *flexVolumeAttacher) WaitForAttach(spec *volume.Spec, devicePath string,
// GetDeviceMountPath is part of the volume.Attacher interface // GetDeviceMountPath is part of the volume.Attacher interface
func (a *flexVolumeAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) { func (a *flexVolumeAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) {
mountsDir := path.Join(a.plugin.host.GetPluginDir(flexVolumePluginName), a.plugin.driverName, "mounts") return a.plugin.getDeviceMountPath(spec)
return (*attacherDefaults)(a).GetDeviceMountPath(spec, mountsDir)
} }
// MountDevice is part of the volume.Attacher interface // MountDevice is part of the volume.Attacher interface
......
...@@ -28,16 +28,18 @@ import ( ...@@ -28,16 +28,18 @@ import (
volumetesting "k8s.io/kubernetes/pkg/volume/testing" volumetesting "k8s.io/kubernetes/pkg/volume/testing"
) )
func testPlugin() (*flexVolumePlugin, string) { func testPlugin() (*flexVolumeAttachablePlugin, string) {
rootDir, err := utiltesting.MkTmpdir("flexvolume_test") rootDir, err := utiltesting.MkTmpdir("flexvolume_test")
if err != nil { if err != nil {
panic("error creating temp dir: " + err.Error()) panic("error creating temp dir: " + err.Error())
} }
return &flexVolumePlugin{ return &flexVolumeAttachablePlugin{
driverName: "test", flexVolumePlugin: &flexVolumePlugin{
execPath: "/plugin", driverName: "test",
host: volumetesting.NewFakeVolumeHost(rootDir, nil, nil), execPath: "/plugin",
unsupportedCommands: []string{}, host: volumetesting.NewFakeVolumeHost(rootDir, nil, nil),
unsupportedCommands: []string{},
},
}, rootDir }, rootDir
} }
...@@ -77,11 +79,11 @@ func fakeResultOutput(result interface{}) exec.FakeCombinedOutputAction { ...@@ -77,11 +79,11 @@ func fakeResultOutput(result interface{}) exec.FakeCombinedOutputAction {
} }
func successOutput() exec.FakeCombinedOutputAction { func successOutput() exec.FakeCombinedOutputAction {
return fakeResultOutput(&DriverStatus{StatusSuccess, "", "", "", true}) return fakeResultOutput(&DriverStatus{StatusSuccess, "", "", "", true, nil})
} }
func notSupportedOutput() exec.FakeCombinedOutputAction { func notSupportedOutput() exec.FakeCombinedOutputAction {
return fakeResultOutput(&DriverStatus{StatusNotSupported, "", "", "", false}) return fakeResultOutput(&DriverStatus{StatusNotSupported, "", "", "", false, nil})
} }
func sameArgs(args, expectedArgs []string) bool { func sameArgs(args, expectedArgs []string) bool {
...@@ -126,7 +128,7 @@ func fakePersistentVolumeSpec() *volume.Spec { ...@@ -126,7 +128,7 @@ func fakePersistentVolumeSpec() *volume.Spec {
return volume.NewSpecFromPersistentVolume(vol, false) return volume.NewSpecFromPersistentVolume(vol, false)
} }
func specJson(plugin *flexVolumePlugin, spec *volume.Spec, extraOptions map[string]string) string { func specJson(plugin *flexVolumeAttachablePlugin, spec *volume.Spec, extraOptions map[string]string) string {
o, err := NewOptionsForDriver(spec, plugin.host, extraOptions) o, err := NewOptionsForDriver(spec, plugin.host, extraOptions)
if err != nil { if err != nil {
panic("Failed to convert spec: " + err.Error()) panic("Failed to convert spec: " + err.Error())
......
...@@ -28,18 +28,18 @@ type detacherDefaults flexVolumeDetacher ...@@ -28,18 +28,18 @@ type detacherDefaults flexVolumeDetacher
// Detach is part of the volume.Detacher interface. // Detach is part of the volume.Detacher interface.
func (d *detacherDefaults) Detach(deviceName string, hostName types.NodeName) error { func (d *detacherDefaults) Detach(deviceName string, hostName types.NodeName) error {
glog.Warning(logPrefix(d.plugin), "using default Detach for device ", deviceName, ", host ", hostName) glog.Warning(logPrefix(d.plugin.flexVolumePlugin), "using default Detach for device ", deviceName, ", host ", hostName)
return nil return nil
} }
// WaitForDetach is part of the volume.Detacher interface. // WaitForDetach is part of the volume.Detacher interface.
func (d *detacherDefaults) WaitForDetach(devicePath string, timeout time.Duration) error { func (d *detacherDefaults) WaitForDetach(devicePath string, timeout time.Duration) error {
glog.Warning(logPrefix(d.plugin), "using default WaitForDetach for device ", devicePath) glog.Warning(logPrefix(d.plugin.flexVolumePlugin), "using default WaitForDetach for device ", devicePath)
return nil return nil
} }
// UnmountDevice is part of the volume.Detacher interface. // UnmountDevice is part of the volume.Detacher interface.
func (d *detacherDefaults) UnmountDevice(deviceMountPath string) error { func (d *detacherDefaults) UnmountDevice(deviceMountPath string) error {
glog.Warning(logPrefix(d.plugin), "using default UnmountDevice for device mount path ", deviceMountPath) glog.Warning(logPrefix(d.plugin.flexVolumePlugin), "using default UnmountDevice for device mount path ", deviceMountPath)
return util.UnmountPath(deviceMountPath, d.plugin.host.GetMounter()) return util.UnmountPath(deviceMountPath, d.plugin.host.GetMounter())
} }
...@@ -28,7 +28,7 @@ import ( ...@@ -28,7 +28,7 @@ import (
) )
type flexVolumeDetacher struct { type flexVolumeDetacher struct {
plugin *flexVolumePlugin plugin *flexVolumeAttachablePlugin
} }
var _ volume.Detacher = &flexVolumeDetacher{} var _ volume.Detacher = &flexVolumeDetacher{}
......
...@@ -58,6 +58,8 @@ const ( ...@@ -58,6 +58,8 @@ const (
optionKeyPodUID = "kubernetes.io/pod.uid" optionKeyPodUID = "kubernetes.io/pod.uid"
optionKeyServiceAccountName = "kubernetes.io/serviceAccount.name" optionKeyServiceAccountName = "kubernetes.io/serviceAccount.name"
attachCapability = "attach"
) )
const ( const (
...@@ -201,6 +203,10 @@ type DriverStatus struct { ...@@ -201,6 +203,10 @@ type DriverStatus struct {
VolumeName string `json:"volumeName,omitempty"` VolumeName string `json:"volumeName,omitempty"`
// Represents volume is attached on the node // Represents volume is attached on the node
Attached bool `json:"attached,omitempty"` Attached bool `json:"attached,omitempty"`
// Returns capabilities of the driver.
// By default we assume all the capabilities are supported.
// If the plugin does not support a capability, it can return false for that capability.
Capabilities map[string]bool
} }
// isCmdNotSupportedErr checks if the error corresponds to command not supported by // isCmdNotSupportedErr checks if the error corresponds to command not supported by
......
...@@ -17,8 +17,6 @@ limitations under the License. ...@@ -17,8 +17,6 @@ limitations under the License.
package flexvolume package flexvolume
import ( import (
"fmt"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
...@@ -32,13 +30,9 @@ type mounterDefaults flexVolumeMounter ...@@ -32,13 +30,9 @@ type mounterDefaults flexVolumeMounter
func (f *mounterDefaults) SetUpAt(dir string, fsGroup *types.UnixGroupID) error { func (f *mounterDefaults) SetUpAt(dir string, fsGroup *types.UnixGroupID) error {
glog.Warning(logPrefix(f.plugin), "using default SetUpAt to ", dir) glog.Warning(logPrefix(f.plugin), "using default SetUpAt to ", dir)
a, err := f.plugin.NewAttacher() src, err := f.plugin.getDeviceMountPath(f.spec)
if err != nil {
return fmt.Errorf("NewAttacher failed: %v", err)
}
src, err := a.GetDeviceMountPath(f.spec)
if err != nil { if err != nil {
return fmt.Errorf("GetDeviceMountPath failed: %v", err) return err
} }
if err := doMount(f.mounter, src, dir, "auto", []string{"bind"}); err != nil { if err := doMount(f.mounter, src, dir, "auto", []string{"bind"}); err != nil {
......
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package flexvolume package flexvolume
import ( import (
"fmt"
"path" "path"
"strings" "strings"
"sync" "sync"
...@@ -27,6 +28,7 @@ import ( ...@@ -27,6 +28,7 @@ import (
api "k8s.io/kubernetes/pkg/api/v1" api "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/util/exec" "k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
utilstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
...@@ -43,9 +45,56 @@ type flexVolumePlugin struct { ...@@ -43,9 +45,56 @@ type flexVolumePlugin struct {
unsupportedCommands []string unsupportedCommands []string
} }
var _ volume.AttachableVolumePlugin = &flexVolumePlugin{} type flexVolumeAttachablePlugin struct {
*flexVolumePlugin
}
var _ volume.AttachableVolumePlugin = &flexVolumeAttachablePlugin{}
var _ volume.PersistentVolumePlugin = &flexVolumePlugin{} var _ volume.PersistentVolumePlugin = &flexVolumePlugin{}
func NewFlexVolumePlugin(pluginDir, name string) (volume.VolumePlugin, error) {
execPath := path.Join(pluginDir, name)
driverName := utilstrings.UnescapePluginName(name)
flexPlugin := &flexVolumePlugin{
driverName: driverName,
execPath: execPath,
runner: exec.New(),
unsupportedCommands: []string{},
}
// Check whether the plugin is attachable.
ok, err := isAttachable(flexPlugin)
if err != nil {
return nil, err
}
if ok {
// Plugin supports attach/detach, so return flexVolumeAttachablePlugin
return &flexVolumeAttachablePlugin{flexVolumePlugin: flexPlugin}, nil
} else {
return flexPlugin, nil
}
}
func isAttachable(plugin *flexVolumePlugin) (bool, error) {
call := plugin.NewDriverCall(initCmd)
res, err := call.Run()
if err != nil {
return false, err
}
// By default all plugins are attachable, unless they report otherwise.
cap, ok := res.Capabilities[attachCapability]
if ok {
// cap is false, so plugin does not support attach/detach calls.
return cap, nil
}
return true, nil
}
// Init is part of the volume.VolumePlugin interface. // Init is part of the volume.VolumePlugin interface.
func (plugin *flexVolumePlugin) Init(host volume.VolumeHost) error { func (plugin *flexVolumePlugin) Init(host volume.VolumeHost) error {
plugin.host = host plugin.host = host
...@@ -155,12 +204,12 @@ func (plugin *flexVolumePlugin) newUnmounterInternal(volName string, podUID type ...@@ -155,12 +204,12 @@ func (plugin *flexVolumePlugin) newUnmounterInternal(volName string, podUID type
} }
// NewAttacher is part of the volume.AttachableVolumePlugin interface. // NewAttacher is part of the volume.AttachableVolumePlugin interface.
func (plugin *flexVolumePlugin) NewAttacher() (volume.Attacher, error) { func (plugin *flexVolumeAttachablePlugin) NewAttacher() (volume.Attacher, error) {
return &flexVolumeAttacher{plugin}, nil return &flexVolumeAttacher{plugin}, nil
} }
// NewDetacher is part of the volume.AttachableVolumePlugin interface. // NewDetacher is part of the volume.AttachableVolumePlugin interface.
func (plugin *flexVolumePlugin) NewDetacher() (volume.Detacher, error) { func (plugin *flexVolumeAttachablePlugin) NewDetacher() (volume.Detacher, error) {
return &flexVolumeDetacher{plugin}, nil return &flexVolumeDetacher{plugin}, nil
} }
...@@ -208,3 +257,13 @@ func (plugin *flexVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]st ...@@ -208,3 +257,13 @@ func (plugin *flexVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([]st
mounter := plugin.host.GetMounter() mounter := plugin.host.GetMounter()
return mount.GetMountRefs(mounter, deviceMountPath) return mount.GetMountRefs(mounter, deviceMountPath)
} }
func (plugin *flexVolumePlugin) getDeviceMountPath(spec *volume.Spec) (string, error) {
volumeName, err := plugin.GetVolumeName(spec)
if err != nil {
return "", fmt.Errorf("GetVolumeName failed from getDeviceMountPath: %s", err)
}
mountsDir := path.Join(plugin.host.GetPluginDir(flexVolumePluginName), plugin.driverName, "mounts")
return path.Join(mountsDir, volumeName), nil
}
...@@ -18,10 +18,7 @@ package flexvolume ...@@ -18,10 +18,7 @@ package flexvolume
import ( import (
"io/ioutil" "io/ioutil"
"path"
"k8s.io/kubernetes/pkg/util/exec"
utilstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
) )
...@@ -37,13 +34,12 @@ func ProbeVolumePlugins(pluginDir string) []volume.VolumePlugin { ...@@ -37,13 +34,12 @@ func ProbeVolumePlugins(pluginDir string) []volume.VolumePlugin {
// e.g. dirname = vendor~cifs // e.g. dirname = vendor~cifs
// then, executable will be pluginDir/dirname/cifs // then, executable will be pluginDir/dirname/cifs
if f.IsDir() { if f.IsDir() {
execPath := path.Join(pluginDir, f.Name()) plugin, err := NewFlexVolumePlugin(pluginDir, f.Name())
plugins = append(plugins, &flexVolumePlugin{ if err != nil {
driverName: utilstrings.UnescapePluginName(f.Name()), continue
execPath: execPath, }
runner: exec.New(),
unsupportedCommands: []string{}, plugins = append(plugins, plugin)
})
} }
} }
return plugins return plugins
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment