Merge pull request #76047 from codenrhoden/mv-nsenter-mount

Move nsenter mounter to pkg/volume/util/nsenter
This commit is contained in:
Kubernetes Prow Robot 2019-04-09 09:55:59 -07:00 committed by GitHub
commit c62cd6e3a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 375 additions and 295 deletions

View File

@ -108,6 +108,7 @@ go_library(
"//pkg/volume/scaleio:go_default_library", "//pkg/volume/scaleio:go_default_library",
"//pkg/volume/secret:go_default_library", "//pkg/volume/secret:go_default_library",
"//pkg/volume/storageos: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/util/subpath:go_default_library",
"//pkg/volume/vsphere_volume:go_default_library", "//pkg/volume/vsphere_volume:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",

View File

@ -96,6 +96,7 @@ import (
"k8s.io/kubernetes/pkg/util/rlimit" "k8s.io/kubernetes/pkg/util/rlimit"
"k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/version/verflag" "k8s.io/kubernetes/pkg/version/verflag"
nsutil "k8s.io/kubernetes/pkg/volume/util/nsenter"
"k8s.io/kubernetes/pkg/volume/util/subpath" "k8s.io/kubernetes/pkg/volume/util/subpath"
"k8s.io/utils/exec" "k8s.io/utils/exec"
"k8s.io/utils/nsenter" "k8s.io/utils/nsenter"
@ -373,7 +374,7 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
mounter = mount.NewNsenterMounter(s.RootDirectory, ne) mounter = nsutil.NewMounter(s.RootDirectory, ne)
// NSenter only valid on Linux // NSenter only valid on Linux
subpather = subpath.NewNSEnter(mounter, ne, s.RootDirectory) subpather = subpath.NewNSEnter(mounter, ne, s.RootDirectory)
// an exec interface which can use nsenter for flex plugin calls // an exec interface which can use nsenter for flex plugin calls

View File

@ -15,8 +15,6 @@ go_library(
"mount_linux.go", "mount_linux.go",
"mount_unsupported.go", "mount_unsupported.go",
"mount_windows.go", "mount_windows.go",
"nsenter_mount.go",
"nsenter_mount_unsupported.go",
], ],
importpath = "k8s.io/kubernetes/pkg/util/mount", importpath = "k8s.io/kubernetes/pkg/util/mount",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
@ -24,42 +22,13 @@ go_library(
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library",
] + select({ ] + 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": [ "@io_bazel_rules_go//go/platform:linux": [
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/k8s.io/utils/io: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", "//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": [ "@io_bazel_rules_go//go/platform:windows": [
"//vendor/k8s.io/utils/keymutex:go_default_library", "//vendor/k8s.io/utils/keymutex:go_default_library",
"//vendor/k8s.io/utils/nsenter:go_default_library",
"//vendor/k8s.io/utils/path:go_default_library", "//vendor/k8s.io/utils/path:go_default_library",
], ],
"//conditions:default": [], "//conditions:default": [],
@ -74,7 +43,6 @@ go_test(
"mount_linux_test.go", "mount_linux_test.go",
"mount_test.go", "mount_test.go",
"mount_windows_test.go", "mount_windows_test.go",
"nsenter_mount_test.go",
"safe_format_and_mount_test.go", "safe_format_and_mount_test.go",
], ],
embed = [":go_default_library"], embed = [":go_default_library"],
@ -83,7 +51,6 @@ go_test(
] + select({ ] + select({
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/nsenter:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:windows": [ "@io_bazel_rules_go//go/platform:windows": [
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",

View File

@ -44,7 +44,7 @@ var _ Interface = &execMounter{}
// Mount runs mount(8) using given exec interface. // Mount runs mount(8) using given exec interface.
func (m *execMounter) Mount(source string, target string, fstype string, options []string) error { 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 { if bind {
err := m.doExecMount(source, target, fstype, bindOpts) 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 <what> <where>) using given exec interface. // doExecMount calls exec(mount <what> <where>) using given exec interface.
func (m *execMounter) doExecMount(source, target, fstype string, options []string) error { 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) 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...) output, err := m.exec.Run("mount", mountArgs...)
klog.V(5).Infof("Exec mounted %v: %v: %s", mountArgs, err, string(output)) klog.V(5).Infof("Exec mounted %v: %v: %s", mountArgs, err, string(output))
if err != nil { if err != nil {
@ -116,10 +116,6 @@ func (m *execMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return m.wrappedMounter.IsMountPointMatch(mp, dir) 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 { func (m *execMounter) MakeRShared(path string) error {
return m.wrappedMounter.MakeRShared(path) return m.wrappedMounter.MakeRShared(path)
} }

View File

@ -47,10 +47,6 @@ func (mounter *execMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return (mp.Path == dir) return (mp.Path == dir)
} }
func (mounter *execMounter) IsNotMountPoint(dir string) (bool, error) {
return isNotMountPoint(mounter, dir)
}
func (mounter *execMounter) IsLikelyNotMountPoint(file string) (bool, error) { func (mounter *execMounter) IsLikelyNotMountPoint(file string) (bool, error) {
return true, nil return true, nil
} }

View File

@ -136,10 +136,6 @@ func (f *FakeMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return mp.Path == dir return mp.Path == dir
} }
func (f *FakeMounter) IsNotMountPoint(dir string) (bool, error) {
return isNotMountPoint(f, dir)
}
func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
f.mutex.Lock() f.mutex.Lock()
defer f.mutex.Unlock() defer f.mutex.Unlock()

View File

@ -50,14 +50,6 @@ type Interface interface {
List() ([]MountPoint, error) List() ([]MountPoint, error)
// IsMountPointMatch determines if the mountpoint matches the dir // IsMountPointMatch determines if the mountpoint matches the dir
IsMountPointMatch(mp MountPoint, dir string) bool 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 // IsLikelyNotMountPoint uses heuristics to determine if a directory
// is a mountpoint. // is a mountpoint.
// It should return ErrNotExist when the directory does not exist. // 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 return device, refCount, nil
} }
// isNotMountPoint implements Mounter.IsNotMountPoint and is shared by mounter // IsNotMountPoint determines if a directory is a mountpoint.
// implementations. // It should return ErrNotExist when the directory does not exist.
func isNotMountPoint(mounter Interface, file string) (bool, error) { // 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 // IsLikelyNotMountPoint provides a quick check
// to determine whether file IS A mountpoint // to determine whether file IS A mountpoint
notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file) notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
@ -263,11 +260,11 @@ func isNotMountPoint(mounter Interface, file string) (bool, error) {
return notMnt, nil 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. // use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
// The list equals: // The list equals:
// options - 'bind' + 'remount' (no duplicate) // 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 // 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 // needs to be included, otherwise the mount target will error as busy if you
// remount as readonly. // remount as readonly.

View File

@ -55,7 +55,7 @@ func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPoin
var notMnt bool var notMnt bool
var err error var err error
if extensiveMountPointCheck { if extensiveMountPointCheck {
notMnt, err = mounter.IsNotMountPoint(mountPath) notMnt, err = IsNotMountPoint(mounter, mountPath)
} else { } else {
notMnt, err = mounter.IsLikelyNotMountPoint(mountPath) notMnt, err = mounter.IsLikelyNotMountPoint(mountPath)
} }

View File

@ -80,7 +80,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. // 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. // All Linux distros are expected to be shipped with a mount utility that a support bind mounts.
mounterPath := "" mounterPath := ""
bind, bindOpts, bindRemountOpts := isBind(options) bind, bindOpts, bindRemountOpts := IsBind(options)
if bind { if bind {
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts) err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts)
if err != nil { if err != nil {
@ -103,7 +103,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. // 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 { 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 { if len(mounterPath) > 0 {
mountArgs = append([]string{mountCmd}, mountArgs...) mountArgs = append([]string{mountCmd}, mountArgs...)
mountCmd = mounterPath mountCmd = mounterPath
@ -132,7 +132,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 // systemd-mount is not used because it's too new for older distros
// (CentOS 7, Debian Jessie). // (CentOS 7, Debian Jessie).
mountCmd, mountArgs = addSystemdScope("systemd-run", target, mountCmd, mountArgs) mountCmd, mountArgs = AddSystemdScope("systemd-run", target, mountCmd, mountArgs)
} else { } else {
// No systemd-run on the host (or we failed to check it), assume kubelet // No systemd-run on the host (or we failed to check it), assume kubelet
// does not run as a systemd service. // does not run as a systemd service.
@ -176,8 +176,9 @@ func detectSystemd() bool {
return true return true
} }
// makeMountArgs makes the arguments to the mount(8) command. // MakeMountArgs makes the arguments to the mount(8) command.
func makeMountArgs(source, target, fstype string, options []string) []string { // Implementation is shared with NsEnterMounter
func MakeMountArgs(source, target, fstype string, options []string) []string {
// Build mount command as follows: // Build mount command as follows:
// mount [-t $fstype] [-o $options] [$source] $target // mount [-t $fstype] [-o $options] [$source] $target
mountArgs := []string{} mountArgs := []string{}
@ -195,8 +196,9 @@ func makeMountArgs(source, target, fstype string, options []string) []string {
return mountArgs return mountArgs
} }
// addSystemdScope adds "system-run --scope" to given command line // AddSystemdScope adds "system-run --scope" to given command line
func addSystemdScope(systemdRunPath, mountName, command string, args []string) (string, []string) { // 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) descriptionArg := fmt.Sprintf("--description=Kubernetes transient mount for %s", mountName)
systemdRunArgs := []string{descriptionArg, "--scope", "--", command} systemdRunArgs := []string{descriptionArg, "--scope", "--", command}
return systemdRunPath, append(systemdRunArgs, args...) return systemdRunPath, append(systemdRunArgs, args...)
@ -215,7 +217,7 @@ func (mounter *Mounter) Unmount(target string) error {
// List returns a list of all mounted filesystems. // List returns a list of all mounted filesystems.
func (*Mounter) List() ([]MountPoint, error) { func (*Mounter) List() ([]MountPoint, error) {
return listProcMounts(procMountsPath) return ListProcMounts(procMountsPath)
} }
func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool { func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
@ -223,10 +225,6 @@ func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return ((mp.Path == dir) || (mp.Path == deletedDir)) 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. // IsLikelyNotMountPoint determines if a directory is not a mountpoint.
// It is fast but not necessarily ALWAYS correct. If the path is in fact // 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. // a bind mount from one part of a mount to another it will not be detected.
@ -256,7 +254,7 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
// If open returns nil, return false with nil error. // If open returns nil, return false with nil error.
// Otherwise, return false with error // Otherwise, return false with error
func (mounter *Mounter) DeviceOpened(pathname string) (bool, 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 // PathIsDevice uses FileInfo returned from os.Stat to check if path refers
@ -267,7 +265,8 @@ func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
return isDevice, err return isDevice, err
} }
func exclusiveOpenFailsOnDevice(pathname string) (bool, error) { // ExclusiveOpenFailsOnDevice is shared with NsEnterMounter
func ExclusiveOpenFailsOnDevice(pathname string) (bool, error) {
var isDevice bool var isDevice bool
finfo, err := os.Stat(pathname) finfo, err := os.Stat(pathname)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -306,13 +305,18 @@ func exclusiveOpenFailsOnDevice(pathname string) (bool, error) {
//GetDeviceNameFromMount: given a mount point, find the device name from its global mount point //GetDeviceNameFromMount: given a mount point, find the device name from its global mount point
func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { 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 // 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 // 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) refs, err := mounter.GetMountRefs(mountPath)
if err != nil { if err != nil {
klog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err) klog.V(4).Infof("GetMountRefs failed for mount path %q: %v", mountPath, err)
@ -337,7 +341,8 @@ func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (str
return path.Base(mountPath), nil 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) content, err := utilio.ConsistentRead(mountFilePath, maxListTries)
if err != nil { if err != nil {
return nil, err return nil, err
@ -383,7 +388,7 @@ func parseProcMounts(content []byte) ([]MountPoint, error) {
} }
func (mounter *Mounter) MakeRShared(path string) error { func (mounter *Mounter) MakeRShared(path string) error {
return doMakeRShared(path, procMountInfoPath) return DoMakeRShared(path, procMountInfoPath)
} }
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) { func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
@ -672,11 +677,11 @@ func findMountInfo(path, mountInfoPath string) (mountInfo, error) {
return *info, nil 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 // 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 <path> <path>' and '--make-rshared <path>' to mountArgs. // '--bind <path> <path>' and '--make-rshared <path>' to mountArgs.
func doMakeRShared(path string, mountInfoFilename string) error { func DoMakeRShared(path string, mountInfoFilename string) error {
shared, err := isShared(path, mountInfoFilename) shared, err := isShared(path, mountInfoFilename)
if err != nil { if err != nil {
return err return err
@ -700,8 +705,8 @@ func doMakeRShared(path string, mountInfoFilename string) error {
return nil return nil
} }
// getSELinuxSupport is common implementation of GetSELinuxSupport on Linux. // GetSELinux is common implementation of GetSELinuxSupport on Linux.
func getSELinuxSupport(path string, mountInfoFilename string) (bool, error) { func GetSELinux(path string, mountInfoFilename string) (bool, error) {
info, err := findMountInfo(path, mountInfoFilename) info, err := findMountInfo(path, mountInfoFilename)
if err != nil { if err != nil {
return false, err return false, err
@ -735,11 +740,11 @@ func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return searchMountPoints(realpath, procMountInfoPath) return SearchMountPoints(realpath, procMountInfoPath)
} }
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) { func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
return getSELinuxSupport(pathname, procMountInfoPath) return GetSELinux(pathname, procMountInfoPath)
} }
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) { func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
@ -747,15 +752,16 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
return getFSGroup(realpath) return GetFSGroupLinux(realpath)
} }
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) { func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
return getMode(pathname) return GetModeLinux(pathname)
} }
// This implementation is shared between Linux and NsEnterMounter // GetFSGroupLinux is shared between Linux and NsEnterMounter
func getFSGroup(pathname string) (int64, error) { // pathname must already be evaluated for symlinks
func GetFSGroupLinux(pathname string) (int64, error) {
info, err := os.Stat(pathname) info, err := os.Stat(pathname)
if err != nil { if err != nil {
return 0, err return 0, err
@ -763,8 +769,8 @@ func getFSGroup(pathname string) (int64, error) {
return int64(info.Sys().(*syscall.Stat_t).Gid), nil return int64(info.Sys().(*syscall.Stat_t).Gid), nil
} }
// This implementation is shared between Linux and NsEnterMounter // GetModeLinux is shared between Linux and NsEnterMounter
func getMode(pathname string) (os.FileMode, error) { func GetModeLinux(pathname string) (os.FileMode, error) {
info, err := os.Stat(pathname) info, err := os.Stat(pathname)
if err != nil { if err != nil {
return 0, err return 0, err
@ -772,14 +778,14 @@ func getMode(pathname string) (os.FileMode, error) {
return info.Mode(), nil 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. // mountpoints.
// This function assumes source cannot be device. // This function assumes source cannot be device.
// Some filesystems may share a source name, e.g. tmpfs. And for bind mounting, // 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 // 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. // root path and major:minor to represent mount source uniquely.
// This implementation is shared between Linux and NsEnterMounter // 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) mis, err := parseMountInfo(mountInfoPath)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -631,7 +631,7 @@ func TestGetSELinuxSupport(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
out, err := getSELinuxSupport(test.mountPoint, filename) out, err := GetSELinux(test.mountPoint, filename)
if err != nil { if err != nil {
t.Errorf("Test %s failed with error: %s", test.name, err) 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.Seek(0, 0)
tmpFile.WriteString(v.mountInfos) tmpFile.WriteString(v.mountInfos)
tmpFile.Sync() tmpFile.Sync()
refs, err := searchMountPoints(v.source, tmpFile.Name()) refs, err := SearchMountPoints(v.source, tmpFile.Name())
if !reflect.DeepEqual(refs, v.expectedRefs) { if !reflect.DeepEqual(refs, v.expectedRefs) {
t.Errorf("test %q: expected Refs: %#v, got %#v", v.name, v.expectedRefs, refs) t.Errorf("test %q: expected Refs: %#v, got %#v", v.name, v.expectedRefs, refs)
} }

View File

@ -43,7 +43,7 @@ func TestIsBind(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
bind, bindOpts, bindRemountOpts := isBind(test.mountOption) bind, bindOpts, bindRemountOpts := IsBind(test.mountOption)
if bind != test.isBind { if bind != test.isBind {
t.Errorf("Expected bind to be %v but got %v", test.isBind, bind) t.Errorf("Expected bind to be %v but got %v", test.isBind, bind)
} }

View File

@ -54,10 +54,6 @@ func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return (mp.Path == dir) return (mp.Path == dir)
} }
func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) {
return isNotMountPoint(mounter, dir)
}
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
return true, unsupportedErr return true, unsupportedErr
} }

View File

@ -72,7 +72,7 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio
bindSource := source bindSource := source
// tell it's going to mount azure disk or azure file according to options // 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 // mount azure disk
bindSource = normalizeWindowsPath(source) bindSource = normalizeWindowsPath(source)
} else { } else {
@ -173,11 +173,6 @@ func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return mp.Path == dir 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. // IsLikelyNotMountPoint determines if a directory is not a mountpoint.
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
stat, err := os.Lstat(file) stat, err := os.Lstat(file)

View File

@ -1,110 +0,0 @@
// +build !linux
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package mount
import (
"errors"
"os"
"k8s.io/utils/nsenter"
)
type NsenterMounter struct{}
func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter {
return &NsenterMounter{}
}
var _ = Interface(&NsenterMounter{})
func (*NsenterMounter) Mount(source string, target string, fstype string, options []string) error {
return nil
}
func (*NsenterMounter) Unmount(target string) error {
return nil
}
func (*NsenterMounter) List() ([]MountPoint, error) {
return []MountPoint{}, nil
}
func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) {
return isNotMountPoint(m, dir)
}
func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
return (mp.Path == dir)
}
func (*NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) {
return true, nil
}
func (*NsenterMounter) DeviceOpened(pathname string) (bool, error) {
return false, nil
}
func (*NsenterMounter) PathIsDevice(pathname string) (bool, error) {
return true, nil
}
func (*NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
return "", nil
}
func (*NsenterMounter) MakeRShared(path string) error {
return nil
}
func (*NsenterMounter) GetFileType(_ string) (FileType, error) {
return FileType("fake"), errors.New("not implemented")
}
func (*NsenterMounter) MakeDir(pathname string) error {
return nil
}
func (*NsenterMounter) MakeFile(pathname string) error {
return nil
}
func (*NsenterMounter) ExistsPath(pathname string) (bool, error) {
return true, errors.New("not implemented")
}
func (*NsenterMounter) EvalHostSymlinks(pathname string) (string, error) {
return "", errors.New("not implemented")
}
func (*NsenterMounter) GetMountRefs(pathname string) ([]string, error) {
return nil, errors.New("not implemented")
}
func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) {
return -1, errors.New("not implemented")
}
func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) {
return false, errors.New("not implemented")
}
func (*NsenterMounter) GetMode(pathname string) (os.FileMode, error) {
return 0, errors.New("not implemented")
}

View File

@ -441,7 +441,7 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
return fmt.Errorf("invalid path: %s %v", m.globalPath, err) 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) 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) { if err != nil && !os.IsNotExist(err) {
klog.Errorf("cannot validate mount point: %s %v", dir, 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) err = m.mounter.Mount(globalPath, dir, "", mountOptions)
if err != nil { if err != nil {
klog.Errorf("Mount of volume %s failed: %v", dir, err) 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 { if mntErr != nil {
klog.Errorf("IsNotMountPoint check failed: %v", mntErr) klog.Errorf("IsNotMountPoint check failed: %v", mntErr)
return err return err
@ -502,7 +502,7 @@ func (m *localVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
klog.Errorf("Failed to unmount: %v", mntErr) klog.Errorf("Failed to unmount: %v", mntErr)
return err return err
} }
notMnt, mntErr = m.mounter.IsNotMountPoint(dir) notMnt, mntErr = mount.IsNotMountPoint(m.mounter, dir)
if mntErr != nil { if mntErr != nil {
klog.Errorf("IsNotMountPoint check failed: %v", mntErr) klog.Errorf("IsNotMountPoint check failed: %v", mntErr)
return err return err

View File

@ -238,7 +238,7 @@ func (b *nfsMounter) SetUp(fsGroup *int64) error {
} }
func (b *nfsMounter) SetUpAt(dir string, 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) klog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return err return err
@ -257,7 +257,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error {
mountOptions := util.JoinMountOptions(b.mountOptions, options) mountOptions := util.JoinMountOptions(b.mountOptions, options)
err = b.mounter.Mount(source, dir, "nfs", mountOptions) err = b.mounter.Mount(source, dir, "nfs", mountOptions)
if err != nil { if err != nil {
notMnt, mntErr := b.mounter.IsNotMountPoint(dir) notMnt, mntErr := mount.IsNotMountPoint(b.mounter, dir)
if mntErr != nil { if mntErr != nil {
klog.Errorf("IsNotMountPoint check failed: %v", mntErr) klog.Errorf("IsNotMountPoint check failed: %v", mntErr)
return err return err
@ -267,7 +267,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error {
klog.Errorf("Failed to unmount: %v", mntErr) klog.Errorf("Failed to unmount: %v", mntErr)
return err return err
} }
notMnt, mntErr := b.mounter.IsNotMountPoint(dir) notMnt, mntErr := mount.IsNotMountPoint(b.mounter, dir)
if mntErr != nil { if mntErr != nil {
klog.Errorf("IsNotMountPoint check failed: %v", mntErr) klog.Errorf("IsNotMountPoint check failed: %v", mntErr)
return err return err

View File

@ -86,6 +86,7 @@ filegroup(
":package-srcs", ":package-srcs",
"//pkg/volume/util/fs:all-srcs", "//pkg/volume/util/fs:all-srcs",
"//pkg/volume/util/nestedpendingoperations:all-srcs", "//pkg/volume/util/nestedpendingoperations:all-srcs",
"//pkg/volume/util/nsenter:all-srcs",
"//pkg/volume/util/operationexecutor:all-srcs", "//pkg/volume/util/operationexecutor:all-srcs",
"//pkg/volume/util/recyclerclient:all-srcs", "//pkg/volume/util/recyclerclient:all-srcs",
"//pkg/volume/util/subpath:all-srcs", "//pkg/volume/util/subpath:all-srcs",

View File

@ -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"],
)

View File

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package mount package nsenter
import ( import (
"fmt" "fmt"
@ -25,6 +25,7 @@ import (
"strings" "strings"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/utils/nsenter" "k8s.io/utils/nsenter"
utilpath "k8s.io/utils/path" utilpath "k8s.io/utils/path"
) )
@ -36,30 +37,31 @@ const (
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo" hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
) )
// Mounter implements mount.Interface
// Currently, all docker containers receive their own mount namespaces. // Currently, all docker containers receive their own mount namespaces.
// NsenterMounter works by executing nsenter to run commands in // Mounter works by executing nsenter to run commands in
// the host's mount namespace. // the host's mount namespace.
type NsenterMounter struct { type Mounter struct {
ne *nsenter.Nsenter ne *nsenter.Nsenter
// rootDir is location of /var/lib/kubelet directory. // rootDir is location of /var/lib/kubelet directory.
rootDir string rootDir string
} }
// NewNsenterMounter creates a new mounter for kubelet that runs as a container. // NewMounter creates a new mounter for kubelet that runs as a container.
func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { func NewMounter(rootDir string, ne *nsenter.Nsenter) *Mounter {
return &NsenterMounter{ return &Mounter{
rootDir: rootDir, rootDir: rootDir,
ne: ne, ne: ne,
} }
} }
// NsenterMounter implements mount.Interface // Mounter implements mount.Interface
var _ = Interface(&NsenterMounter{}) var _ = mount.Interface(&Mounter{})
// Mount runs mount(8) in the host's root mount namespace. Aside from this // 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() // 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 { func (n *Mounter) Mount(source string, target string, fstype string, options []string) error {
bind, bindOpts, bindRemountOpts := isBind(options) bind, bindOpts, bindRemountOpts := mount.IsBind(options)
if bind { if bind {
err := n.doNsenterMount(source, target, fstype, bindOpts) err := n.doNsenterMount(source, target, fstype, bindOpts)
@ -74,7 +76,7 @@ func (n *NsenterMounter) Mount(source string, target string, fstype string, opti
// doNsenterMount nsenters the host's mount namespace and performs the // doNsenterMount nsenters the host's mount namespace and performs the
// requested mount. // requested mount.
func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error { func (n *Mounter) doNsenterMount(source, target, fstype string, options []string) error {
klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options) klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options)
cmd, args := n.makeNsenterArgs(source, target, fstype, options) cmd, args := n.makeNsenterArgs(source, target, fstype, options)
outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput() outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput()
@ -86,9 +88,9 @@ func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options [
// makeNsenterArgs makes a list of argument to nsenter in order to do the // makeNsenterArgs makes a list of argument to nsenter in order to do the
// requested mount. // requested mount.
func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) { func (n *Mounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) {
mountCmd := n.ne.AbsHostPath("mount") 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 { if systemdRunPath, hasSystemd := n.ne.SupportsSystemd(); hasSystemd {
// Complete command line: // Complete command line:
@ -106,7 +108,7 @@ func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options
// Kubelet container can be restarted and the fuse daemon survives. // Kubelet container can be restarted and the fuse daemon survives.
// * When the daemon dies (e.g. during unmount) systemd removes the // * When the daemon dies (e.g. during unmount) systemd removes the
// scope automatically. // scope automatically.
mountCmd, mountArgs = addSystemdScope(systemdRunPath, target, mountCmd, mountArgs) mountCmd, mountArgs = mount.AddSystemdScope(systemdRunPath, target, mountCmd, mountArgs)
} else { } else {
// Fall back to simple mount when the host has no systemd. // Fall back to simple mount when the host has no systemd.
// Complete command line: // Complete command line:
@ -124,7 +126,7 @@ func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options
} }
// Unmount runs umount(8) in the host's mount namespace. // Unmount runs umount(8) in the host's mount namespace.
func (n *NsenterMounter) Unmount(target string) error { func (n *Mounter) Unmount(target string) error {
args := []string{target} args := []string{target}
// No need to execute systemd-run here, it's enough that unmount is executed // No need to execute systemd-run here, it's enough that unmount is executed
// in the host's mount namespace. It will finish appropriate fuse daemon(s) // in the host's mount namespace. It will finish appropriate fuse daemon(s)
@ -138,22 +140,19 @@ func (n *NsenterMounter) Unmount(target string) error {
} }
// List returns a list of all mounted filesystems in the host's mount namespace. // List returns a list of all mounted filesystems in the host's mount namespace.
func (*NsenterMounter) List() ([]MountPoint, error) { func (*Mounter) List() ([]mount.MountPoint, error) {
return listProcMounts(hostProcMountsPath) return mount.ListProcMounts(hostProcMountsPath)
} }
func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) { // IsMountPointMatch tests if dir and mp are the same path
return isNotMountPoint(m, dir) func (*Mounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
}
func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
deletedDir := fmt.Sprintf("%s\\040(deleted)", dir) deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
return (mp.Path == dir) || (mp.Path == deletedDir) return (mp.Path == dir) || (mp.Path == deletedDir)
} }
// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt // IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt
// in the host's root mount namespace. // in the host's root mount namespace.
func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { func (n *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
file, err := filepath.Abs(file) file, err := filepath.Abs(file)
if err != nil { if err != nil {
return true, err return true, err
@ -216,30 +215,32 @@ func parseFindMnt(out string) (string, error) {
// Returns true if open returns errno EBUSY, and false if errno is nil. // Returns true if open returns errno EBUSY, and false if errno is nil.
// Returns an error if errno is any error other than EBUSY. // Returns an error if errno is any error other than EBUSY.
// Returns with error if pathname is not a device. // Returns with error if pathname is not a device.
func (n *NsenterMounter) DeviceOpened(pathname string) (bool, error) { func (n *Mounter) DeviceOpened(pathname string) (bool, error) {
return exclusiveOpenFailsOnDevice(pathname) return mount.ExclusiveOpenFailsOnDevice(pathname)
} }
// PathIsDevice uses FileInfo returned from os.Stat to check if path refers // PathIsDevice uses FileInfo returned from os.Stat to check if path refers
// to a device. // to a device.
func (n *NsenterMounter) PathIsDevice(pathname string) (bool, error) { func (n *Mounter) PathIsDevice(pathname string) (bool, error) {
pathType, err := n.GetFileType(pathname) pathType, err := n.GetFileType(pathname)
isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev isDevice := pathType == mount.FileTypeCharDev || pathType == mount.FileTypeBlockDev
return isDevice, err return isDevice, err
} }
//GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts //GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts
func (n *NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { func (n *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
return getDeviceNameFromMount(n, mountPath, pluginDir) return mount.GetDeviceNameFromMountLinux(n, mountPath, pluginDir)
} }
func (n *NsenterMounter) MakeRShared(path string) error { // MakeRShared checks if path is shared and bind-mounts it as rshared if needed.
return doMakeRShared(path, hostProcMountinfoPath) func (n *Mounter) MakeRShared(path string) error {
return mount.DoMakeRShared(path, hostProcMountinfoPath)
} }
func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) { // GetFileType checks for file/directory/socket/block/character devices.
var pathType FileType func (n *Mounter) GetFileType(pathname string) (mount.FileType, error) {
outputBytes, err := mounter.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput() var pathType mount.FileType
outputBytes, err := n.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput()
if err != nil { if err != nil {
if strings.Contains(string(outputBytes), "No such file") { if strings.Contains(string(outputBytes), "No such file") {
err = fmt.Errorf("%s does not exist", pathname) err = fmt.Errorf("%s does not exist", pathname)
@ -251,83 +252,94 @@ func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) {
switch string(outputBytes) { switch string(outputBytes) {
case "socket": case "socket":
return FileTypeSocket, nil return mount.FileTypeSocket, nil
case "character special file": case "character special file":
return FileTypeCharDev, nil return mount.FileTypeCharDev, nil
case "block special file": case "block special file":
return FileTypeBlockDev, nil return mount.FileTypeBlockDev, nil
case "directory": case "directory":
return FileTypeDirectory, nil return mount.FileTypeDirectory, nil
case "regular file": case "regular file":
return FileTypeFile, nil return mount.FileTypeFile, nil
} }
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
} }
func (mounter *NsenterMounter) MakeDir(pathname string) error { // MakeDir creates a new directory.
func (n *Mounter) MakeDir(pathname string) error {
args := []string{"-p", pathname} args := []string{"-p", pathname}
if _, err := mounter.ne.Exec("mkdir", args).CombinedOutput(); err != nil { if _, err := n.ne.Exec("mkdir", args).CombinedOutput(); err != nil {
return err return err
} }
return nil return nil
} }
func (mounter *NsenterMounter) MakeFile(pathname string) error { // MakeFile creates an empty file.
func (n *Mounter) MakeFile(pathname string) error {
args := []string{pathname} args := []string{pathname}
if _, err := mounter.ne.Exec("touch", args).CombinedOutput(); err != nil { if _, err := n.ne.Exec("touch", args).CombinedOutput(); err != nil {
return err return err
} }
return nil return nil
} }
func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) { // ExistsPath checks if pathname exists.
// Error is returned on any other error than "file not found".
func (n *Mounter) ExistsPath(pathname string) (bool, error) {
// Resolve the symlinks but allow the target not to exist. EvalSymlinks // Resolve the symlinks but allow the target not to exist. EvalSymlinks
// would return an generic error when the target does not exist. // would return an generic error when the target does not exist.
hostPath, err := mounter.ne.EvalSymlinks(pathname, false /* mustExist */) hostPath, err := n.ne.EvalSymlinks(pathname, false /* mustExist */)
if err != nil { if err != nil {
return false, err return false, err
} }
kubeletpath := mounter.ne.KubeletPath(hostPath) kubeletpath := n.ne.KubeletPath(hostPath)
return utilpath.Exists(utilpath.CheckFollowSymlink, kubeletpath) return utilpath.Exists(utilpath.CheckFollowSymlink, kubeletpath)
} }
func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) { // EvalHostSymlinks returns the path name after evaluating symlinks.
return mounter.ne.EvalSymlinks(pathname, true) func (n *Mounter) EvalHostSymlinks(pathname string) (string, error) {
return n.ne.EvalSymlinks(pathname, true)
} }
func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) { // GetMountRefs finds all mount references to the path, returns a
pathExists, pathErr := PathExists(pathname) // list of paths. Path could be a mountpoint path, device or a normal
if !pathExists || IsCorruptedMnt(pathErr) { // directory (for bind mount).
func (n *Mounter) GetMountRefs(pathname string) ([]string, error) {
pathExists, pathErr := mount.PathExists(pathname)
if !pathExists || mount.IsCorruptedMnt(pathErr) {
return []string{}, nil return []string{}, nil
} else if pathErr != nil { } else if pathErr != nil {
return nil, fmt.Errorf("Error checking path %s: %v", pathname, pathErr) return nil, fmt.Errorf("Error checking path %s: %v", pathname, pathErr)
} }
hostpath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) hostpath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return searchMountPoints(hostpath, hostProcMountinfoPath) return mount.SearchMountPoints(hostpath, hostProcMountinfoPath)
} }
func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { // GetFSGroup returns FSGroup of pathname.
hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) func (n *Mounter) GetFSGroup(pathname string) (int64, error) {
hostPath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
if err != nil { if err != nil {
return -1, err return -1, err
} }
kubeletpath := mounter.ne.KubeletPath(hostPath) kubeletpath := n.ne.KubeletPath(hostPath)
return getFSGroup(kubeletpath) return mount.GetFSGroupLinux(kubeletpath)
} }
func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { // GetSELinuxSupport tests if pathname is on a mount that supports SELinux.
return getSELinuxSupport(pathname, hostProcMountsPath) func (n *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
return mount.GetSELinux(pathname, hostProcMountsPath)
} }
func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { // GetMode returns permissions of pathname.
hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) func (n *Mounter) GetMode(pathname string) (os.FileMode, error) {
hostPath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
if err != nil { if err != nil {
return 0, err return 0, err
} }
kubeletpath := mounter.ne.KubeletPath(hostPath) kubeletpath := n.ne.KubeletPath(hostPath)
return getMode(kubeletpath) return mount.GetModeLinux(kubeletpath)
} }

View File

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package mount package nsenter
import ( import (
"io/ioutil" "io/ioutil"
@ -74,7 +74,7 @@ func TestParseFindMnt(t *testing.T) {
} }
} }
func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *NsenterMounter, rootfsPath string, varlibPath string, err error) { func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *Mounter, rootfsPath string, varlibPath string, err error) {
rootfsPath = filepath.Join(tmpdir, "rootfs") rootfsPath = filepath.Join(tmpdir, "rootfs")
if err := os.Mkdir(rootfsPath, 0755); err != nil { if err := os.Mkdir(rootfsPath, 0755); err != nil {
return nil, "", "", err return nil, "", "", err
@ -89,7 +89,7 @@ func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *NsenterMounter
return nil, "", "", err return nil, "", "", err
} }
return NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, nil return NewMounter(varlibPath, ne), rootfsPath, varlibPath, nil
} }
func TestNsenterExistsFile(t *testing.T) { func TestNsenterExistsFile(t *testing.T) {

View File

@ -0,0 +1,139 @@
// +build !linux
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package nsenter
import (
"errors"
"os"
"k8s.io/utils/nsenter"
"k8s.io/kubernetes/pkg/util/mount"
)
// Mounter provides the mount.Interface implementation for unsupported
// platforms.
type Mounter struct{}
// NewMounter returns a new Mounter for the current system
func NewMounter(rootDir string, ne *nsenter.Nsenter) *Mounter {
return &Mounter{}
}
var _ = mount.Interface(&Mounter{})
// Mount mounts the source to the target. It is a noop for unsupported systems
func (*Mounter) Mount(source string, target string, fstype string, options []string) error {
return nil
}
// Unmount unmounts the target path from the system. it is a noop for unsupported
// systems
func (*Mounter) Unmount(target string) error {
return nil
}
// List returns a list of all mounted filesystems. It is a noop for unsupported systems
func (*Mounter) List() ([]mount.MountPoint, error) {
return []mount.MountPoint{}, nil
}
// IsMountPointMatch tests if dir and mp are the same path
func (*Mounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
return (mp.Path == dir)
}
// IsLikelyNotMountPoint determines if a directory is not a mountpoint.
// It is a noop on unsupported systems
func (*Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
return true, nil
}
// DeviceOpened checks if block device in use. I tis a noop for unsupported systems
func (*Mounter) DeviceOpened(pathname string) (bool, error) {
return false, nil
}
// PathIsDevice checks if pathname refers to a device. It is a noop for unsupported
// systems
func (*Mounter) PathIsDevice(pathname string) (bool, error) {
return true, nil
}
// GetDeviceNameFromMount finds the device name from its global mount point using the
// given mountpath and plugin location. It is a noop of unsupported platforms
func (*Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
return "", nil
}
// MakeRShared checks if path is shared and bind-mounts it as rshared if needed.
// It is a noop on unsupported platforms
func (*Mounter) MakeRShared(path string) error {
return nil
}
// GetFileType checks for file/directory/socket/block/character devices.
// Always returns an error and "fake" filetype on unsupported platforms
func (*Mounter) GetFileType(_ string) (mount.FileType, error) {
return mount.FileType("fake"), errors.New("not implemented")
}
// MakeDir creates a new directory. Noop on unsupported platforms
func (*Mounter) MakeDir(pathname string) error {
return nil
}
// MakeFile creats an empty file. Noop on unsupported platforms
func (*Mounter) MakeFile(pathname string) error {
return nil
}
// ExistsPath checks if pathname exists. Always returns an error on unsupported
// platforms
func (*Mounter) ExistsPath(pathname string) (bool, error) {
return true, errors.New("not implemented")
}
// EvalHostSymlinks returns the path name after evaluating symlinks. Always
// returns an error on unsupported platforms
func (*Mounter) EvalHostSymlinks(pathname string) (string, error) {
return "", errors.New("not implemented")
}
// GetMountRefs finds all mount references to the path, returns a
// list of paths. Always returns an error on unsupported platforms
func (*Mounter) GetMountRefs(pathname string) ([]string, error) {
return nil, errors.New("not implemented")
}
// GetFSGroup returns FSGroup of pathname. Always returns an error on unsupported platforms
func (*Mounter) GetFSGroup(pathname string) (int64, error) {
return -1, errors.New("not implemented")
}
// GetSELinuxSupport tests if pathname is on a mount that supports SELinux.
// Always returns an error on unsupported platforms
func (*Mounter) GetSELinuxSupport(pathname string) (bool, error) {
return false, errors.New("not implemented")
}
// GetMode returns permissions of pathname. Always returns an error on unsupported platforms
func (*Mounter) GetMode(pathname string) (os.FileMode, error) {
return 0, errors.New("not implemented")
}

View File

@ -74,6 +74,7 @@ go_test(
deps = select({ deps = select({
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//pkg/util/mount:go_default_library", "//pkg/util/mount:go_default_library",
"//pkg/volume/util/nsenter:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/nsenter:go_default_library", "//vendor/k8s.io/utils/nsenter:go_default_library",

View File

@ -101,7 +101,7 @@ func safeOpenSubPath(mounter mount.Interface, subpath Subpath) (int, error) {
func prepareSubpathTarget(mounter mount.Interface, subpath Subpath) (bool, string, error) { func prepareSubpathTarget(mounter mount.Interface, subpath Subpath) (bool, string, error) {
// Early check for already bind-mounted subpath. // Early check for already bind-mounted subpath.
bindPathTarget := getSubpathBindTarget(subpath) bindPathTarget := getSubpathBindTarget(subpath)
notMount, err := mounter.IsNotMountPoint(bindPathTarget) notMount, err := mount.IsNotMountPoint(mounter, bindPathTarget)
if err != nil { if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return false, "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err) return false, "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err)

View File

@ -29,7 +29,7 @@ import (
"k8s.io/utils/nsenter" "k8s.io/utils/nsenter"
"k8s.io/kubernetes/pkg/util/mount" nsutil "k8s.io/kubernetes/pkg/volume/util/nsenter"
) )
func TestCheckDeviceInode(t *testing.T) { 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.Mounter, string, string, *nsenter.Nsenter, error) {
rootfsPath := filepath.Join(tmpdir, "rootfs") rootfsPath := filepath.Join(tmpdir, "rootfs")
if err := os.Mkdir(rootfsPath, 0755); err != nil { if err := os.Mkdir(rootfsPath, 0755); err != nil {
return nil, "", "", nil, err return nil, "", "", nil, err
@ -121,7 +121,7 @@ func newFakeNsenterMounter(tmpdir string, t *testing.T) (*mount.NsenterMounter,
return nil, "", "", nil, err return nil, "", "", nil, err
} }
return mount.NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, ne, nil return nsutil.NewMounter(varlibPath, ne), rootfsPath, varlibPath, ne, nil
} }
func TestNsenterSafeMakeDir(t *testing.T) { func TestNsenterSafeMakeDir(t *testing.T) {