diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index d3fdfb3452d..b955b7e57e7 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -19,10 +19,12 @@ package nfs import ( "fmt" "os" + "runtime" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/util/exec" "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" @@ -66,9 +68,29 @@ func (plugin *nfsPlugin) Name() string { return nfsPluginName } +func hasNFSMount() bool { + exe := exec.New() + switch runtime.GOOS { + case "linux": + cmd1 := exe.Command("/bin/ls", "/sbin/mount.nfs") + _, err1 := cmd1.CombinedOutput() + cmd2 := exe.Command("/bin/ls", "/sbin/mount.nfs4") + _, err2 := cmd2.CombinedOutput() + return (err1 == nil || err2 == nil) + case "darwin": + cmd := exe.Command("/bin/ls", "/sbin/mount_nfs") + _, err := cmd.CombinedOutput() + return err == nil + } + return false +} + func (plugin *nfsPlugin) CanSupport(spec *volume.Spec) bool { - return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.NFS != nil) || - (spec.Volume != nil && spec.Volume.NFS != nil) + if (spec.Volume != nil && spec.Volume.NFS == nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.NFS == nil) { + return false + } + // see if /sbin/mount.nfs* is there + return hasNFSMount() } func (plugin *nfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode { diff --git a/pkg/volume/nfs/nfs_test.go b/pkg/volume/nfs/nfs_test.go index 594d6fb707c..11f93b82bb8 100644 --- a/pkg/volume/nfs/nfs_test.go +++ b/pkg/volume/nfs/nfs_test.go @@ -38,12 +38,16 @@ func TestCanSupport(t *testing.T) { if plug.Name() != "kubernetes.io/nfs" { t.Errorf("Wrong name: %s", plug.Name()) } - if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{NFS: &api.NFSVolumeSource{}}}}) { + foundMount := hasNFSMount() + if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{NFS: &api.NFSVolumeSource{}}}}) != foundMount { t.Errorf("Expected true") } - if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{}}}}}) { + if plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{}}}}}) != foundMount { t.Errorf("Expected true") } + if plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{}}}}) { + t.Errorf("Expected false") + } if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) { t.Errorf("Expected false") } @@ -63,6 +67,10 @@ func TestGetAccessModes(t *testing.T) { } func TestRecycler(t *testing.T) { + if foundMount := hasNFSMount(); !foundMount { + // FindRecyclablePluginBySpec will test CanSupport() but mount helper is absent + return + } plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins([]volume.VolumePlugin{&nfsPlugin{nil, newMockRecycler, volume.VolumeConfig{}}}, volume.NewFakeVolumeHost("/tmp/fake", nil, nil))