diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index 5e9cf6fc816..6395f9d30f3 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -108,6 +108,7 @@ go_library( "//pkg/volume/scaleio:go_default_library", "//pkg/volume/secret:go_default_library", "//pkg/volume/storageos:go_default_library", + "//pkg/volume/util/nsenter:go_default_library", "//pkg/volume/util/subpath:go_default_library", "//pkg/volume/vsphere_volume:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 420c585fdaf..ff9907e703d 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -96,6 +96,7 @@ import ( "k8s.io/kubernetes/pkg/util/rlimit" "k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version/verflag" + nsutil "k8s.io/kubernetes/pkg/volume/util/nsenter" "k8s.io/kubernetes/pkg/volume/util/subpath" "k8s.io/utils/exec" "k8s.io/utils/nsenter" @@ -373,7 +374,7 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err if err != nil { return nil, err } - mounter = mount.NewNsenterMounter(s.RootDirectory, ne) + mounter = nsutil.NewNsenterMounter(s.RootDirectory, ne) // NSenter only valid on Linux subpather = subpath.NewNSEnter(mounter, ne, s.RootDirectory) // an exec interface which can use nsenter for flex plugin calls diff --git a/pkg/util/mount/BUILD b/pkg/util/mount/BUILD index 3a61d016a81..d677306752b 100644 --- a/pkg/util/mount/BUILD +++ b/pkg/util/mount/BUILD @@ -15,8 +15,6 @@ go_library( "mount_linux.go", "mount_unsupported.go", "mount_windows.go", - "nsenter_mount.go", - "nsenter_mount_unsupported.go", ], importpath = "k8s.io/kubernetes/pkg/util/mount", visibility = ["//visibility:public"], @@ -24,43 +22,14 @@ go_library( "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ - "@io_bazel_rules_go//go/platform:android": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:darwin": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:dragonfly": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:freebsd": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], "@io_bazel_rules_go//go/platform:linux": [ "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/utils/io:go_default_library", - "//vendor/k8s.io/utils/nsenter:go_default_library", "//vendor/k8s.io/utils/path:go_default_library", ], - "@io_bazel_rules_go//go/platform:nacl": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:netbsd": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:openbsd": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:plan9": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], - "@io_bazel_rules_go//go/platform:solaris": [ - "//vendor/k8s.io/utils/nsenter:go_default_library", - ], "@io_bazel_rules_go//go/platform:windows": [ "//vendor/k8s.io/utils/keymutex:go_default_library", - "//vendor/k8s.io/utils/nsenter:go_default_library", "//vendor/k8s.io/utils/path:go_default_library", ], "//conditions:default": [], @@ -75,7 +44,6 @@ go_test( "mount_linux_test.go", "mount_test.go", "mount_windows_test.go", - "nsenter_mount_test.go", "safe_format_and_mount_test.go", ], embed = [":go_default_library"], @@ -84,7 +52,6 @@ go_test( ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "//vendor/k8s.io/utils/exec:go_default_library", - "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/pkg/util/mount/exec_mount.go b/pkg/util/mount/exec_mount.go index b30f6f0218f..cdddb635989 100644 --- a/pkg/util/mount/exec_mount.go +++ b/pkg/util/mount/exec_mount.go @@ -44,7 +44,7 @@ var _ Interface = &execMounter{} // Mount runs mount(8) using given exec interface. func (m *execMounter) Mount(source string, target string, fstype string, options []string) error { - bind, bindOpts, bindRemountOpts := isBind(options) + bind, bindOpts, bindRemountOpts := IsBind(options) if bind { err := m.doExecMount(source, target, fstype, bindOpts) @@ -60,7 +60,7 @@ func (m *execMounter) Mount(source string, target string, fstype string, options // doExecMount calls exec(mount ) using given exec interface. func (m *execMounter) doExecMount(source, target, fstype string, options []string) error { klog.V(5).Infof("Exec Mounting %s %s %s %v", source, target, fstype, options) - mountArgs := makeMountArgs(source, target, fstype, options) + mountArgs := MakeMountArgs(source, target, fstype, options) output, err := m.exec.Run("mount", mountArgs...) klog.V(5).Infof("Exec mounted %v: %v: %s", mountArgs, err, string(output)) if err != nil { @@ -116,10 +116,6 @@ func (m *execMounter) IsMountPointMatch(mp MountPoint, dir string) bool { return m.wrappedMounter.IsMountPointMatch(mp, dir) } -func (m *execMounter) IsNotMountPoint(dir string) (bool, error) { - return m.wrappedMounter.IsNotMountPoint(dir) -} - func (m *execMounter) MakeRShared(path string) error { return m.wrappedMounter.MakeRShared(path) } diff --git a/pkg/util/mount/exec_mount_unsupported.go b/pkg/util/mount/exec_mount_unsupported.go index 698c136e019..328b383fd4d 100644 --- a/pkg/util/mount/exec_mount_unsupported.go +++ b/pkg/util/mount/exec_mount_unsupported.go @@ -47,10 +47,6 @@ func (mounter *execMounter) IsMountPointMatch(mp MountPoint, dir string) bool { return (mp.Path == dir) } -func (mounter *execMounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(mounter, dir) -} - func (mounter *execMounter) IsLikelyNotMountPoint(file string) (bool, error) { return true, nil } diff --git a/pkg/util/mount/fake.go b/pkg/util/mount/fake.go index f8abc216b87..29ffbc98238 100644 --- a/pkg/util/mount/fake.go +++ b/pkg/util/mount/fake.go @@ -136,10 +136,6 @@ func (f *FakeMounter) IsMountPointMatch(mp MountPoint, dir string) bool { return mp.Path == dir } -func (f *FakeMounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(f, dir) -} - func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { f.mutex.Lock() defer f.mutex.Unlock() diff --git a/pkg/util/mount/mount.go b/pkg/util/mount/mount.go index b0ad41ceffd..40de6ed7c96 100644 --- a/pkg/util/mount/mount.go +++ b/pkg/util/mount/mount.go @@ -50,14 +50,6 @@ type Interface interface { List() ([]MountPoint, error) // IsMountPointMatch determines if the mountpoint matches the dir IsMountPointMatch(mp MountPoint, dir string) bool - // IsNotMountPoint determines if a directory is a mountpoint. - // It should return ErrNotExist when the directory does not exist. - // IsNotMountPoint is more expensive than IsLikelyNotMountPoint. - // IsNotMountPoint detects bind mounts in linux. - // IsNotMountPoint enumerates all the mountpoints using List() and - // the list of mountpoints may be large, then it uses - // IsMountPointMatch to evaluate whether the directory is a mountpoint - IsNotMountPoint(file string) (bool, error) // IsLikelyNotMountPoint uses heuristics to determine if a directory // is a mountpoint. // It should return ErrNotExist when the directory does not exist. @@ -222,9 +214,14 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e return device, refCount, nil } -// isNotMountPoint implements Mounter.IsNotMountPoint and is shared by mounter -// implementations. -func isNotMountPoint(mounter Interface, file string) (bool, error) { +// IsNotMountPoint determines if a directory is a mountpoint. +// It should return ErrNotExist when the directory does not exist. +// IsNotMountPoint is more expensive than IsLikelyNotMountPoint. +// IsNotMountPoint detects bind mounts in linux. +// IsNotMountPoint enumerates all the mountpoints using List() and +// the list of mountpoints may be large, then it uses +// IsMountPointMatch to evaluate whether the directory is a mountpoint +func IsNotMountPoint(mounter Interface, file string) (bool, error) { // IsLikelyNotMountPoint provides a quick check // to determine whether file IS A mountpoint notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file) @@ -263,11 +260,11 @@ func isNotMountPoint(mounter Interface, file string) (bool, error) { return notMnt, nil } -// isBind detects whether a bind mount is being requested and makes the remount options to +// IsBind detects whether a bind mount is being requested and makes the remount options to // use in case of bind mount, due to the fact that bind mount doesn't respect mount options. // The list equals: // options - 'bind' + 'remount' (no duplicate) -func isBind(options []string) (bool, []string, []string) { +func IsBind(options []string) (bool, []string, []string) { // Because we have an FD opened on the subpath bind mount, the "bind" option // needs to be included, otherwise the mount target will error as busy if you // remount as readonly. diff --git a/pkg/util/mount/mount_helper_common.go b/pkg/util/mount/mount_helper_common.go index cff1d89588e..75b128473cb 100644 --- a/pkg/util/mount/mount_helper_common.go +++ b/pkg/util/mount/mount_helper_common.go @@ -55,7 +55,7 @@ func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPoin var notMnt bool var err error if extensiveMountPointCheck { - notMnt, err = mounter.IsNotMountPoint(mountPath) + notMnt, err = IsNotMountPoint(mounter, mountPath) } else { notMnt, err = mounter.IsLikelyNotMountPoint(mountPath) } diff --git a/pkg/util/mount/mount_linux.go b/pkg/util/mount/mount_linux.go index 9ffd766a51b..5b661fab7c8 100644 --- a/pkg/util/mount/mount_linux.go +++ b/pkg/util/mount/mount_linux.go @@ -81,7 +81,7 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio // Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty. // All Linux distros are expected to be shipped with a mount utility that a support bind mounts. mounterPath := "" - bind, bindOpts, bindRemountOpts := isBind(options) + bind, bindOpts, bindRemountOpts := IsBind(options) if bind { err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts) if err != nil { @@ -99,7 +99,7 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio // doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used. func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string) error { - mountArgs := makeMountArgs(source, target, fstype, options) + mountArgs := MakeMountArgs(source, target, fstype, options) if len(mounterPath) > 0 { mountArgs = append([]string{mountCmd}, mountArgs...) mountCmd = mounterPath @@ -128,7 +128,7 @@ func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, ta // // systemd-mount is not used because it's too new for older distros // (CentOS 7, Debian Jessie). - mountCmd, mountArgs = addSystemdScope("systemd-run", target, mountCmd, mountArgs) + mountCmd, mountArgs = AddSystemdScope("systemd-run", target, mountCmd, mountArgs) } else { // No systemd-run on the host (or we failed to check it), assume kubelet // does not run as a systemd service. @@ -172,8 +172,9 @@ func detectSystemd() bool { return true } -// makeMountArgs makes the arguments to the mount(8) command. -func makeMountArgs(source, target, fstype string, options []string) []string { +// MakeMountArgs makes the arguments to the mount(8) command. +// Implementation is shared with NsEnterMounter +func MakeMountArgs(source, target, fstype string, options []string) []string { // Build mount command as follows: // mount [-t $fstype] [-o $options] [$source] $target mountArgs := []string{} @@ -191,8 +192,9 @@ func makeMountArgs(source, target, fstype string, options []string) []string { return mountArgs } -// addSystemdScope adds "system-run --scope" to given command line -func addSystemdScope(systemdRunPath, mountName, command string, args []string) (string, []string) { +// AddSystemdScope adds "system-run --scope" to given command line +// implementation is shared with NsEnterMounter +func AddSystemdScope(systemdRunPath, mountName, command string, args []string) (string, []string) { descriptionArg := fmt.Sprintf("--description=Kubernetes transient mount for %s", mountName) systemdRunArgs := []string{descriptionArg, "--scope", "--", command} return systemdRunPath, append(systemdRunArgs, args...) @@ -211,7 +213,7 @@ func (mounter *Mounter) Unmount(target string) error { // List returns a list of all mounted filesystems. func (*Mounter) List() ([]MountPoint, error) { - return listProcMounts(procMountsPath) + return ListProcMounts(procMountsPath) } func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool { @@ -219,10 +221,6 @@ func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool { return ((mp.Path == dir) || (mp.Path == deletedDir)) } -func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(mounter, dir) -} - // IsLikelyNotMountPoint determines if a directory is not a mountpoint. // It is fast but not necessarily ALWAYS correct. If the path is in fact // a bind mount from one part of a mount to another it will not be detected. @@ -252,7 +250,7 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { // If open returns nil, return false with nil error. // Otherwise, return false with error func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) { - return exclusiveOpenFailsOnDevice(pathname) + return ExclusiveOpenFailsOnDevice(pathname) } // PathIsDevice uses FileInfo returned from os.Stat to check if path refers @@ -263,7 +261,8 @@ func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) { return isDevice, err } -func exclusiveOpenFailsOnDevice(pathname string) (bool, error) { +// ExclusiveOpenFailsOnDevice is shared with NsEnterMounter +func ExclusiveOpenFailsOnDevice(pathname string) (bool, error) { var isDevice bool finfo, err := os.Stat(pathname) if os.IsNotExist(err) { @@ -302,13 +301,18 @@ func exclusiveOpenFailsOnDevice(pathname string) (bool, error) { //GetDeviceNameFromMount: given a mount point, find the device name from its global mount point func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return getDeviceNameFromMount(mounter, mountPath, pluginDir) + return GetDeviceNameFromMountLinux(mounter, mountPath, pluginDir) } -// getDeviceNameFromMount find the device name from /proc/mounts in which +func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) { + return GetDeviceNameFromMountLinux(mounter, mountPath, pluginDir) +} + +// GetDeviceNameFromMountLinux find the device name from /proc/mounts in which // the mount path reference should match the given plugin directory. In case no mount path reference // matches, returns the volume name taken from its given mountPath -func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) { +// This implementation is shared with NsEnterMounter +func GetDeviceNameFromMountLinux(mounter Interface, mountPath, pluginDir string) (string, error) { refs, err := mounter.GetMountRefs(mountPath) if err != nil { klog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err) @@ -333,7 +337,8 @@ func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (str return path.Base(mountPath), nil } -func listProcMounts(mountFilePath string) ([]MountPoint, error) { +// ListProcMounts is shared with NsEnterMounter +func ListProcMounts(mountFilePath string) ([]MountPoint, error) { content, err := utilio.ConsistentRead(mountFilePath, maxListTries) if err != nil { return nil, err @@ -379,7 +384,7 @@ func parseProcMounts(content []byte) ([]MountPoint, error) { } func (mounter *Mounter) MakeRShared(path string) error { - return doMakeRShared(path, procMountInfoPath) + return DoMakeRShared(path, procMountInfoPath) } func (mounter *Mounter) GetFileType(pathname string) (FileType, error) { @@ -668,11 +673,11 @@ func findMountInfo(path, mountInfoPath string) (mountInfo, error) { return *info, nil } -// doMakeRShared is common implementation of MakeRShared on Linux. It checks if +// DoMakeRShared is common implementation of MakeRShared on Linux. It checks if // path is shared and bind-mounts it as rshared if needed. mountCmd and -// mountArgs are expected to contain mount-like command, doMakeRShared will add +// mountArgs are expected to contain mount-like command, DoMakeRShared will add // '--bind ' and '--make-rshared ' to mountArgs. -func doMakeRShared(path string, mountInfoFilename string) error { +func DoMakeRShared(path string, mountInfoFilename string) error { shared, err := isShared(path, mountInfoFilename) if err != nil { return err @@ -696,8 +701,8 @@ func doMakeRShared(path string, mountInfoFilename string) error { return nil } -// getSELinuxSupport is common implementation of GetSELinuxSupport on Linux. -func getSELinuxSupport(path string, mountInfoFilename string) (bool, error) { +// GetSELinux is common implementation of GetSELinuxSupport on Linux. +func GetSELinux(path string, mountInfoFilename string) (bool, error) { info, err := findMountInfo(path, mountInfoFilename) if err != nil { return false, err @@ -731,11 +736,11 @@ func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) { if err != nil { return nil, err } - return searchMountPoints(realpath, procMountInfoPath) + return SearchMountPoints(realpath, procMountInfoPath) } func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { - return getSELinuxSupport(pathname, procMountInfoPath) + return GetSELinux(pathname, procMountInfoPath) } func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { @@ -743,15 +748,16 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { if err != nil { return 0, err } - return getFSGroup(realpath) + return GetFSGroupLinux(realpath) } func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { - return getMode(pathname) + return GetModeLinux(pathname) } -// This implementation is shared between Linux and NsEnterMounter -func getFSGroup(pathname string) (int64, error) { +// GetFSGroupLinux is shared between Linux and NsEnterMounter +// pathname must already be evaluated for symlinks +func GetFSGroupLinux(pathname string) (int64, error) { info, err := os.Stat(pathname) if err != nil { return 0, err @@ -759,8 +765,8 @@ func getFSGroup(pathname string) (int64, error) { return int64(info.Sys().(*syscall.Stat_t).Gid), nil } -// This implementation is shared between Linux and NsEnterMounter -func getMode(pathname string) (os.FileMode, error) { +// GetModeLinux is shared between Linux and NsEnterMounter +func GetModeLinux(pathname string) (os.FileMode, error) { info, err := os.Stat(pathname) if err != nil { return 0, err @@ -768,14 +774,14 @@ func getMode(pathname string) (os.FileMode, error) { return info.Mode(), nil } -// searchMountPoints finds all mount references to the source, returns a list of +// SearchMountPoints finds all mount references to the source, returns a list of // mountpoints. // This function assumes source cannot be device. // Some filesystems may share a source name, e.g. tmpfs. And for bind mounting, // it's possible to mount a non-root path of a filesystem, so we need to use // root path and major:minor to represent mount source uniquely. // This implementation is shared between Linux and NsEnterMounter -func searchMountPoints(hostSource, mountInfoPath string) ([]string, error) { +func SearchMountPoints(hostSource, mountInfoPath string) ([]string, error) { mis, err := parseMountInfo(mountInfoPath) if err != nil { return nil, err diff --git a/pkg/util/mount/mount_linux_test.go b/pkg/util/mount/mount_linux_test.go index ee2769a8270..6a53e266239 100644 --- a/pkg/util/mount/mount_linux_test.go +++ b/pkg/util/mount/mount_linux_test.go @@ -631,7 +631,7 @@ func TestGetSELinuxSupport(t *testing.T) { } for _, test := range tests { - out, err := getSELinuxSupport(test.mountPoint, filename) + out, err := GetSELinux(test.mountPoint, filename) if err != nil { t.Errorf("Test %s failed with error: %s", test.name, err) } @@ -907,7 +907,7 @@ func TestSearchMountPoints(t *testing.T) { tmpFile.Seek(0, 0) tmpFile.WriteString(v.mountInfos) tmpFile.Sync() - refs, err := searchMountPoints(v.source, tmpFile.Name()) + refs, err := SearchMountPoints(v.source, tmpFile.Name()) if !reflect.DeepEqual(refs, v.expectedRefs) { t.Errorf("test %q: expected Refs: %#v, got %#v", v.name, v.expectedRefs, refs) } diff --git a/pkg/util/mount/mount_test.go b/pkg/util/mount/mount_test.go index 26ba8d79d36..6479bd759cc 100644 --- a/pkg/util/mount/mount_test.go +++ b/pkg/util/mount/mount_test.go @@ -43,7 +43,7 @@ func TestIsBind(t *testing.T) { }, } for _, test := range tests { - bind, bindOpts, bindRemountOpts := isBind(test.mountOption) + bind, bindOpts, bindRemountOpts := IsBind(test.mountOption) if bind != test.isBind { t.Errorf("Expected bind to be %v but got %v", test.isBind, bind) } diff --git a/pkg/util/mount/mount_unsupported.go b/pkg/util/mount/mount_unsupported.go index 58f1acc7299..638b941e2fa 100644 --- a/pkg/util/mount/mount_unsupported.go +++ b/pkg/util/mount/mount_unsupported.go @@ -54,10 +54,6 @@ func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool { return (mp.Path == dir) } -func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(mounter, dir) -} - func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { return true, unsupportedErr } diff --git a/pkg/util/mount/mount_windows.go b/pkg/util/mount/mount_windows.go index 4e2efbffb15..026d42196c5 100644 --- a/pkg/util/mount/mount_windows.go +++ b/pkg/util/mount/mount_windows.go @@ -72,7 +72,7 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio bindSource := source // tell it's going to mount azure disk or azure file according to options - if bind, _, _ := isBind(options); bind { + if bind, _, _ := IsBind(options); bind { // mount azure disk bindSource = normalizeWindowsPath(source) } else { @@ -173,11 +173,6 @@ func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool { return mp.Path == dir } -// IsNotMountPoint determines if a directory is a mountpoint. -func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(mounter, dir) -} - // IsLikelyNotMountPoint determines if a directory is not a mountpoint. func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { stat, err := os.Lstat(file) diff --git a/pkg/volume/local/local.go b/pkg/volume/local/local.go index c6a6a5fa889..72915cc2f47 100644 --- a/pkg/volume/local/local.go +++ b/pkg/volume/local/local.go @@ -441,7 +441,7 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { return fmt.Errorf("invalid path: %s %v", m.globalPath, err) } - notMnt, err := m.mounter.IsNotMountPoint(dir) + notMnt, err := mount.IsNotMountPoint(m.mounter, dir) klog.V(4).Infof("LocalVolume mount setup: PodDir(%s) VolDir(%s) Mounted(%t) Error(%v), ReadOnly(%t)", dir, m.globalPath, !notMnt, err, m.readOnly) if err != nil && !os.IsNotExist(err) { klog.Errorf("cannot validate mount point: %s %v", dir, err) @@ -492,7 +492,7 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { err = m.mounter.Mount(globalPath, dir, "", mountOptions) if err != nil { klog.Errorf("Mount of volume %s failed: %v", dir, err) - notMnt, mntErr := m.mounter.IsNotMountPoint(dir) + notMnt, mntErr := mount.IsNotMountPoint(m.mounter, dir) if mntErr != nil { klog.Errorf("IsNotMountPoint check failed: %v", mntErr) return err @@ -502,7 +502,7 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { klog.Errorf("Failed to unmount: %v", mntErr) return err } - notMnt, mntErr = m.mounter.IsNotMountPoint(dir) + notMnt, mntErr = mount.IsNotMountPoint(m.mounter, dir) if mntErr != nil { klog.Errorf("IsNotMountPoint check failed: %v", mntErr) return err diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index 5a7eeed98da..4390bb0ec55 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -238,7 +238,7 @@ func (b *nfsMounter) SetUp(fsGroup *int64) error { } func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { - notMnt, err := b.mounter.IsNotMountPoint(dir) + notMnt, err := mount.IsNotMountPoint(b.mounter, dir) klog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { return err @@ -257,7 +257,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { mountOptions := util.JoinMountOptions(b.mountOptions, options) err = b.mounter.Mount(source, dir, "nfs", mountOptions) if err != nil { - notMnt, mntErr := b.mounter.IsNotMountPoint(dir) + notMnt, mntErr := mount.IsNotMountPoint(b.mounter, dir) if mntErr != nil { klog.Errorf("IsNotMountPoint check failed: %v", mntErr) return err @@ -267,7 +267,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { klog.Errorf("Failed to unmount: %v", mntErr) return err } - notMnt, mntErr := b.mounter.IsNotMountPoint(dir) + notMnt, mntErr := mount.IsNotMountPoint(b.mounter, dir) if mntErr != nil { klog.Errorf("IsNotMountPoint check failed: %v", mntErr) return err diff --git a/pkg/volume/util/BUILD b/pkg/volume/util/BUILD index 0dec3818138..dac92b53ea1 100644 --- a/pkg/volume/util/BUILD +++ b/pkg/volume/util/BUILD @@ -86,6 +86,7 @@ filegroup( ":package-srcs", "//pkg/volume/util/fs:all-srcs", "//pkg/volume/util/nestedpendingoperations:all-srcs", + "//pkg/volume/util/nsenter:all-srcs", "//pkg/volume/util/operationexecutor:all-srcs", "//pkg/volume/util/recyclerclient:all-srcs", "//pkg/volume/util/subpath:all-srcs", diff --git a/pkg/volume/util/nsenter/BUILD b/pkg/volume/util/nsenter/BUILD new file mode 100644 index 00000000000..ab5b6aa7a8b --- /dev/null +++ b/pkg/volume/util/nsenter/BUILD @@ -0,0 +1,86 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "nsenter_mount.go", + "nsenter_mount_unsupported.go", + ], + importpath = "k8s.io/kubernetes/pkg/volume/util/nsenter", + visibility = ["//visibility:public"], + deps = select({ + "@io_bazel_rules_go//go/platform:android": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:darwin": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:dragonfly": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:freebsd": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:linux": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + "//vendor/k8s.io/utils/path:go_default_library", + ], + "@io_bazel_rules_go//go/platform:nacl": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:netbsd": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:openbsd": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:plan9": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:solaris": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "@io_bazel_rules_go//go/platform:windows": [ + "//pkg/util/mount:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "//conditions:default": [], + }), +) + +go_test( + name = "go_default_test", + srcs = ["nsenter_mount_test.go"], + embed = [":go_default_library"], + deps = select({ + "@io_bazel_rules_go//go/platform:linux": [ + "//vendor/k8s.io/utils/nsenter:go_default_library", + ], + "//conditions:default": [], + }), +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/volume/util/nsenter/nsenter_mount.go similarity index 88% rename from pkg/util/mount/nsenter_mount.go rename to pkg/volume/util/nsenter/nsenter_mount.go index a7407315c48..8ab76f256e4 100644 --- a/pkg/util/mount/nsenter_mount.go +++ b/pkg/volume/util/nsenter/nsenter_mount.go @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package mount +package nsenter import ( "fmt" @@ -25,6 +25,7 @@ import ( "strings" "k8s.io/klog" + "k8s.io/kubernetes/pkg/util/mount" "k8s.io/utils/nsenter" utilpath "k8s.io/utils/path" ) @@ -54,12 +55,12 @@ func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { } // NsenterMounter implements mount.Interface -var _ = Interface(&NsenterMounter{}) +var _ = mount.Interface(&NsenterMounter{}) // Mount runs mount(8) in the host's root mount namespace. Aside from this // aspect, Mount has the same semantics as the mounter returned by mount.New() func (n *NsenterMounter) Mount(source string, target string, fstype string, options []string) error { - bind, bindOpts, bindRemountOpts := isBind(options) + bind, bindOpts, bindRemountOpts := mount.IsBind(options) if bind { err := n.doNsenterMount(source, target, fstype, bindOpts) @@ -88,7 +89,7 @@ func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options [ // requested mount. func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) { mountCmd := n.ne.AbsHostPath("mount") - mountArgs := makeMountArgs(source, target, fstype, options) + mountArgs := mount.MakeMountArgs(source, target, fstype, options) if systemdRunPath, hasSystemd := n.ne.SupportsSystemd(); hasSystemd { // Complete command line: @@ -106,7 +107,7 @@ func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options // Kubelet container can be restarted and the fuse daemon survives. // * When the daemon dies (e.g. during unmount) systemd removes the // scope automatically. - mountCmd, mountArgs = addSystemdScope(systemdRunPath, target, mountCmd, mountArgs) + mountCmd, mountArgs = mount.AddSystemdScope(systemdRunPath, target, mountCmd, mountArgs) } else { // Fall back to simple mount when the host has no systemd. // Complete command line: @@ -138,15 +139,11 @@ func (n *NsenterMounter) Unmount(target string) error { } // List returns a list of all mounted filesystems in the host's mount namespace. -func (*NsenterMounter) List() ([]MountPoint, error) { - return listProcMounts(hostProcMountsPath) +func (*NsenterMounter) List() ([]mount.MountPoint, error) { + return mount.ListProcMounts(hostProcMountsPath) } -func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(m, dir) -} - -func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool { +func (*NsenterMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { deletedDir := fmt.Sprintf("%s\\040(deleted)", dir) return (mp.Path == dir) || (mp.Path == deletedDir) } @@ -217,28 +214,28 @@ func parseFindMnt(out string) (string, error) { // Returns an error if errno is any error other than EBUSY. // Returns with error if pathname is not a device. func (n *NsenterMounter) DeviceOpened(pathname string) (bool, error) { - return exclusiveOpenFailsOnDevice(pathname) + return mount.ExclusiveOpenFailsOnDevice(pathname) } // PathIsDevice uses FileInfo returned from os.Stat to check if path refers // to a device. func (n *NsenterMounter) PathIsDevice(pathname string) (bool, error) { pathType, err := n.GetFileType(pathname) - isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev + isDevice := pathType == mount.FileTypeCharDev || pathType == mount.FileTypeBlockDev return isDevice, err } //GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts func (n *NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return getDeviceNameFromMount(n, mountPath, pluginDir) + return mount.GetDeviceNameFromMountLinux(n, mountPath, pluginDir) } func (n *NsenterMounter) MakeRShared(path string) error { - return doMakeRShared(path, hostProcMountinfoPath) + return mount.DoMakeRShared(path, hostProcMountinfoPath) } -func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) { - var pathType FileType +func (mounter *NsenterMounter) GetFileType(pathname string) (mount.FileType, error) { + var pathType mount.FileType outputBytes, err := mounter.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput() if err != nil { if strings.Contains(string(outputBytes), "No such file") { @@ -251,15 +248,15 @@ func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) { switch string(outputBytes) { case "socket": - return FileTypeSocket, nil + return mount.FileTypeSocket, nil case "character special file": - return FileTypeCharDev, nil + return mount.FileTypeCharDev, nil case "block special file": - return FileTypeBlockDev, nil + return mount.FileTypeBlockDev, nil case "directory": - return FileTypeDirectory, nil + return mount.FileTypeDirectory, nil case "regular file": - return FileTypeFile, nil + return mount.FileTypeFile, nil } return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") @@ -297,8 +294,8 @@ func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) } func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) { - pathExists, pathErr := PathExists(pathname) - if !pathExists || IsCorruptedMnt(pathErr) { + pathExists, pathErr := mount.PathExists(pathname) + if !pathExists || mount.IsCorruptedMnt(pathErr) { return []string{}, nil } else if pathErr != nil { return nil, fmt.Errorf("Error checking path %s: %v", pathname, pathErr) @@ -307,7 +304,7 @@ func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) { if err != nil { return nil, err } - return searchMountPoints(hostpath, hostProcMountinfoPath) + return mount.SearchMountPoints(hostpath, hostProcMountinfoPath) } func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { @@ -316,11 +313,11 @@ func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { return -1, err } kubeletpath := mounter.ne.KubeletPath(hostPath) - return getFSGroup(kubeletpath) + return mount.GetFSGroupLinux(kubeletpath) } func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { - return getSELinuxSupport(pathname, hostProcMountsPath) + return mount.GetSELinux(pathname, hostProcMountsPath) } func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { @@ -329,5 +326,5 @@ func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { return 0, err } kubeletpath := mounter.ne.KubeletPath(hostPath) - return getMode(kubeletpath) + return mount.GetModeLinux(kubeletpath) } diff --git a/pkg/util/mount/nsenter_mount_test.go b/pkg/volume/util/nsenter/nsenter_mount_test.go similarity index 99% rename from pkg/util/mount/nsenter_mount_test.go rename to pkg/volume/util/nsenter/nsenter_mount_test.go index 84d04b164d5..8ec03a12286 100644 --- a/pkg/util/mount/nsenter_mount_test.go +++ b/pkg/volume/util/nsenter/nsenter_mount_test.go @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package mount +package nsenter import ( "io/ioutil" diff --git a/pkg/util/mount/nsenter_mount_unsupported.go b/pkg/volume/util/nsenter/nsenter_mount_unsupported.go similarity index 84% rename from pkg/util/mount/nsenter_mount_unsupported.go rename to pkg/volume/util/nsenter/nsenter_mount_unsupported.go index 4679b7e150c..34dfde51ee6 100644 --- a/pkg/util/mount/nsenter_mount_unsupported.go +++ b/pkg/volume/util/nsenter/nsenter_mount_unsupported.go @@ -16,13 +16,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package mount +package nsenter import ( "errors" "os" "k8s.io/utils/nsenter" + + "k8s.io/kubernetes/pkg/util/mount" ) type NsenterMounter struct{} @@ -31,7 +33,7 @@ func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { return &NsenterMounter{} } -var _ = Interface(&NsenterMounter{}) +var _ = mount.Interface(&NsenterMounter{}) func (*NsenterMounter) Mount(source string, target string, fstype string, options []string) error { return nil @@ -41,15 +43,11 @@ func (*NsenterMounter) Unmount(target string) error { return nil } -func (*NsenterMounter) List() ([]MountPoint, error) { - return []MountPoint{}, nil +func (*NsenterMounter) List() ([]mount.MountPoint, error) { + return []mount.MountPoint{}, nil } -func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) { - return isNotMountPoint(m, dir) -} - -func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool { +func (*NsenterMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { return (mp.Path == dir) } @@ -73,8 +71,8 @@ func (*NsenterMounter) MakeRShared(path string) error { return nil } -func (*NsenterMounter) GetFileType(_ string) (FileType, error) { - return FileType("fake"), errors.New("not implemented") +func (*NsenterMounter) GetFileType(_ string) (mount.FileType, error) { + return mount.FileType("fake"), errors.New("not implemented") } func (*NsenterMounter) MakeDir(pathname string) error { diff --git a/pkg/volume/util/subpath/BUILD b/pkg/volume/util/subpath/BUILD index ebbbd4d138e..a5b54c47dea 100644 --- a/pkg/volume/util/subpath/BUILD +++ b/pkg/volume/util/subpath/BUILD @@ -74,6 +74,7 @@ go_test( deps = select({ "@io_bazel_rules_go//go/platform:linux": [ "//pkg/util/mount:go_default_library", + "//pkg/volume/util/nsenter:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/nsenter:go_default_library", diff --git a/pkg/volume/util/subpath/subpath_linux.go b/pkg/volume/util/subpath/subpath_linux.go index 977f7d2da4d..cd99c9131f2 100644 --- a/pkg/volume/util/subpath/subpath_linux.go +++ b/pkg/volume/util/subpath/subpath_linux.go @@ -101,7 +101,7 @@ func safeOpenSubPath(mounter mount.Interface, subpath Subpath) (int, error) { func prepareSubpathTarget(mounter mount.Interface, subpath Subpath) (bool, string, error) { // Early check for already bind-mounted subpath. bindPathTarget := getSubpathBindTarget(subpath) - notMount, err := mounter.IsNotMountPoint(bindPathTarget) + notMount, err := mount.IsNotMountPoint(mounter, bindPathTarget) if err != nil { if !os.IsNotExist(err) { return false, "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err) diff --git a/pkg/volume/util/subpath/subpath_nsenter_test.go b/pkg/volume/util/subpath/subpath_nsenter_test.go index 865d449f5c9..c8e6270dc95 100644 --- a/pkg/volume/util/subpath/subpath_nsenter_test.go +++ b/pkg/volume/util/subpath/subpath_nsenter_test.go @@ -29,7 +29,7 @@ import ( "k8s.io/utils/nsenter" - "k8s.io/kubernetes/pkg/util/mount" + nsutil "k8s.io/kubernetes/pkg/volume/util/nsenter" ) func TestCheckDeviceInode(t *testing.T) { @@ -106,7 +106,7 @@ func TestCheckDeviceInode(t *testing.T) { } } -func newFakeNsenterMounter(tmpdir string, t *testing.T) (*mount.NsenterMounter, string, string, *nsenter.Nsenter, error) { +func newFakeNsenterMounter(tmpdir string, t *testing.T) (*nsutil.NsenterMounter, string, string, *nsenter.Nsenter, error) { rootfsPath := filepath.Join(tmpdir, "rootfs") if err := os.Mkdir(rootfsPath, 0755); err != nil { return nil, "", "", nil, err @@ -121,7 +121,7 @@ func newFakeNsenterMounter(tmpdir string, t *testing.T) (*mount.NsenterMounter, return nil, "", "", nil, err } - return mount.NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, ne, nil + return nsutil.NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, ne, nil } func TestNsenterSafeMakeDir(t *testing.T) {