diff --git a/pkg/kubelet/cm/container_manager_linux_test.go b/pkg/kubelet/cm/container_manager_linux_test.go index 19a9482b985..c255967d73f 100644 --- a/pkg/kubelet/cm/container_manager_linux_test.go +++ b/pkg/kubelet/cm/container_manager_linux_test.go @@ -79,6 +79,22 @@ func (mi *fakeMountInterface) MakeRShared(path string) error { return nil } +func (mi *fakeMountInterface) GetFileType(pathname string) (mount.FileType, error) { + return mount.FileType("fake"), nil +} + +func (mi *fakeMountInterface) MakeDir(pathname string) error { + return nil +} + +func (mi *fakeMountInterface) MakeFile(pathname string) error { + return nil +} + +func (mi *fakeMountInterface) ExistsPath(pathname string) bool { + return true +} + func fakeContainerMgrMountInt() mount.Interface { return &fakeMountInterface{ []mount.MountPoint{ diff --git a/pkg/kubelet/kubelet_volumes.go b/pkg/kubelet/kubelet_volumes.go index 6620cc07e2e..79b0fe3ea3a 100644 --- a/pkg/kubelet/kubelet_volumes.go +++ b/pkg/kubelet/kubelet_volumes.go @@ -69,7 +69,6 @@ func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *v1.Pod, o if err != nil { return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err) } - opts.Containerized = kl.kubeletConfiguration.Containerized physicalMounter, err := plugin.NewMounter(spec, pod, opts) if err != nil { return nil, fmt.Errorf("failed to instantiate mounter for volume: %s using plugin: %s with a root cause: %v", spec.Name(), plugin.GetPluginName(), err) diff --git a/pkg/util/mount/fake.go b/pkg/util/mount/fake.go index 480d15b9a3e..d34510ae2a8 100644 --- a/pkg/util/mount/fake.go +++ b/pkg/util/mount/fake.go @@ -125,7 +125,7 @@ func (f *FakeMounter) List() ([]MountPoint, error) { } 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) { @@ -175,3 +175,19 @@ func (f *FakeMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (strin func (f *FakeMounter) MakeRShared(path string) error { return nil } + +func (f *FakeMounter) GetFileType(pathname string) (FileType, error) { + return FileType("fake"), nil +} + +func (f *FakeMounter) MakeDir(pathname string) error { + return nil +} + +func (f *FakeMounter) MakeFile(pathname string) error { + return nil +} + +func (f *FakeMounter) ExistsPath(pathname string) bool { + return false +} diff --git a/pkg/util/mount/mount.go b/pkg/util/mount/mount.go index 5be3ca40af5..1c09e157f8e 100644 --- a/pkg/util/mount/mount.go +++ b/pkg/util/mount/mount.go @@ -27,10 +27,17 @@ import ( "github.com/golang/glog" ) +type FileType string + const ( // Default mount command if mounter path is not specified - defaultMountCommand = "mount" - MountsInGlobalPDPath = "mounts" + defaultMountCommand = "mount" + MountsInGlobalPDPath = "mounts" + FileTypeDirectory FileType = "Directory" + FileTypeFile FileType = "File" + FileTypeSocket FileType = "Socket" + FileTypeCharDev FileType = "CharDevice" + FileTypeBlockDev FileType = "BlockDevice" ) type Interface interface { @@ -70,6 +77,18 @@ type Interface interface { // MakeRShared checks that given path is on a mount with 'rshared' mount // propagation. If not, it bind-mounts the path as rshared. MakeRShared(path string) error + // GetFileType checks for file/directory/socket/block/character devices. + // Will operate in the host mount namespace if kubelet is running in a container + GetFileType(pathname string) (FileType, error) + // MakeFile creates an empty file. + // Will operate in the host mount namespace if kubelet is running in a container + MakeFile(pathname string) error + // MakeDir creates a new directory. + // Will operate in the host mount namespace if kubelet is running in a container + MakeDir(pathname string) error + // ExistsPath checks whether the path exists. + // Will operate in the host mount namespace if kubelet is running in a container + ExistsPath(pathname string) bool } // Exec executes command where mount utilities are. This can be either the host, diff --git a/pkg/util/mount/mount_linux.go b/pkg/util/mount/mount_linux.go index 0303eb7dc08..8976bd25542 100644 --- a/pkg/util/mount/mount_linux.go +++ b/pkg/util/mount/mount_linux.go @@ -252,17 +252,29 @@ func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) { // PathIsDevice uses FileInfo returned from os.Stat to check if path refers // to a device. func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) { - return pathIsDevice(pathname) + pathType, err := mounter.GetFileType(pathname) + isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev + return isDevice, err } func exclusiveOpenFailsOnDevice(pathname string) (bool, error) { - isDevice, err := pathIsDevice(pathname) + var isDevice bool + finfo, err := os.Stat(pathname) + if os.IsNotExist(err) { + isDevice = false + } + // err in call to os.Stat if err != nil { return false, fmt.Errorf( "PathIsDevice failed for path %q: %v", pathname, err) } + // path refers to a device + if finfo.Mode()&os.ModeDevice != 0 { + isDevice = true + } + if !isDevice { glog.Errorf("Path %q is not refering to a device.", pathname) return false, nil @@ -282,23 +294,6 @@ func exclusiveOpenFailsOnDevice(pathname string) (bool, error) { return false, errno } -func pathIsDevice(pathname string) (bool, error) { - finfo, err := os.Stat(pathname) - if os.IsNotExist(err) { - return false, nil - } - // err in call to os.Stat - if err != nil { - return false, err - } - // path refers to a device - if finfo.Mode()&os.ModeDevice != 0 { - return true, nil - } - // path does not refer to device - return false, nil -} - //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) @@ -353,6 +348,63 @@ func (mounter *Mounter) MakeRShared(path string) error { return doMakeRShared(path, procMountInfoPath) } +func (mounter *Mounter) GetFileType(pathname string) (FileType, error) { + var pathType FileType + finfo, err := os.Stat(pathname) + if os.IsNotExist(err) { + return pathType, fmt.Errorf("path %q does not exist", pathname) + } + // err in call to os.Stat + if err != nil { + return pathType, err + } + + mode := finfo.Sys().(*syscall.Stat_t).Mode + switch mode & syscall.S_IFMT { + case syscall.S_IFSOCK: + return FileTypeSocket, nil + case syscall.S_IFBLK: + return FileTypeBlockDev, nil + case syscall.S_IFCHR: + return FileTypeBlockDev, nil + case syscall.S_IFDIR: + return FileTypeDirectory, nil + case syscall.S_IFREG: + return FileTypeFile, nil + } + + return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") +} + +func (mounter *Mounter) MakeDir(pathname string) error { + err := os.MkdirAll(pathname, os.FileMode(0755)) + if err != nil { + if !os.IsExist(err) { + return err + } + } + return nil +} + +func (mounter *Mounter) MakeFile(pathname string) error { + f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644)) + defer f.Close() + if err != nil { + if !os.IsExist(err) { + return err + } + } + return nil +} + +func (mounter *Mounter) ExistsPath(pathname string) bool { + _, err := os.Stat(pathname) + if err != nil { + return false + } + return true +} + // formatAndMount uses unix utils to format and mount the given disk func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error { options = append(options, "defaults") diff --git a/pkg/util/mount/mount_unsupported.go b/pkg/util/mount/mount_unsupported.go index e0618949d81..865d53d09e5 100644 --- a/pkg/util/mount/mount_unsupported.go +++ b/pkg/util/mount/mount_unsupported.go @@ -18,6 +18,10 @@ limitations under the License. package mount +import ( + "errors" +) + type Mounter struct { mounterPath string } @@ -74,3 +78,23 @@ func (mounter *Mounter) MakeRShared(path string) error { func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error { return nil } + +func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) { + return true, nil +} + +func (mounter *Mounter) GetFileType(pathname string) (FileType, error) { + return FileType("fake"), errors.New("not implemented") +} + +func (mounter *Mounter) MakeDir(pathname string) error { + return nil +} + +func (mounter *Mounter) MakeFile(pathname string) error { + return nil +} + +func (mounter *Mounter) ExistsPath(pathname string) bool { + return true +} diff --git a/pkg/util/mount/mount_windows.go b/pkg/util/mount/mount_windows.go index 2cb890f1b03..50c95caa528 100644 --- a/pkg/util/mount/mount_windows.go +++ b/pkg/util/mount/mount_windows.go @@ -25,6 +25,7 @@ import ( "path/filepath" "strconv" "strings" + "syscall" "github.com/golang/glog" ) @@ -167,6 +168,67 @@ func (mounter *Mounter) MakeRShared(path string) error { return nil } +// GetFileType checks for sockets/block/character devices +func (mounter *Mounter) GetFileType(pathname string) (FileType, error) { + var pathType FileType + info, err := os.Stat(pathname) + if os.IsNotExist(err) { + return pathType, fmt.Errorf("path %q does not exist", pathname) + } + // err in call to os.Stat + if err != nil { + return pathType, err + } + + mode := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes + switch mode & syscall.S_IFMT { + case syscall.S_IFSOCK: + return FileTypeSocket, nil + case syscall.S_IFBLK: + return FileTypeBlockDev, nil + case syscall.S_IFCHR: + return FileTypeCharDev, nil + case syscall.S_IFDIR: + return FileTypeDirectory, nil + case syscall.S_IFREG: + return FileTypeFile, nil + } + + return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") +} + +// MakeFile creates a new directory +func (mounter *Mounter) MakeDir(pathname string) error { + err := os.MkdirAll(pathname, os.FileMode(0755)) + if err != nil { + if !os.IsExist(err) { + return err + } + } + return nil +} + +// MakeFile creates an empty file +func (mounter *Mounter) MakeFile(pathname string) error { + f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644)) + defer f.Close() + if err != nil { + if !os.IsExist(err) { + return err + } + } + return nil +} + +// ExistsPath checks whether the path exists +func (mounter *Mounter) ExistsPath(pathname string) bool { + _, err := os.Stat(pathname) + if err != nil { + return false + } + return true +} + func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error { // Try to mount the disk glog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target) diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/util/mount/nsenter_mount.go index f1f69d24d32..a6c7869b0d8 100644 --- a/pkg/util/mount/nsenter_mount.go +++ b/pkg/util/mount/nsenter_mount.go @@ -209,7 +209,9 @@ func (n *NsenterMounter) DeviceOpened(pathname string) (bool, error) { // PathIsDevice uses FileInfo returned from os.Stat to check if path refers // to a device. func (n *NsenterMounter) PathIsDevice(pathname string) (bool, error) { - return pathIsDevice(pathname) + pathType, err := n.GetFileType(pathname) + isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev + return isDevice, err } //GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts @@ -220,3 +222,51 @@ func (n *NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (st func (n *NsenterMounter) MakeRShared(path string) error { return doMakeRShared(path, hostProcMountinfoPath) } + +func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) { + var pathType FileType + outputBytes, err := mounter.ne.Exec("stat", []string{"-L", `--printf "%F"`, pathname}).CombinedOutput() + if err != nil { + return pathType, err + } + + switch string(outputBytes) { + case "socket": + return FileTypeSocket, nil + case "character special file": + return FileTypeCharDev, nil + case "block special file": + return FileTypeBlockDev, nil + case "directory": + return FileTypeDirectory, nil + case "regular file": + return FileTypeFile, nil + } + + return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") +} + +func (mounter *NsenterMounter) MakeDir(pathname string) error { + args := []string{"-p", pathname} + if _, err := mounter.ne.Exec("mkdir", args).CombinedOutput(); err != nil { + return err + } + return nil +} + +func (mounter *NsenterMounter) MakeFile(pathname string) error { + args := []string{pathname} + if _, err := mounter.ne.Exec("touch", args).CombinedOutput(); err != nil { + return err + } + return nil +} + +func (mounter *NsenterMounter) ExistsPath(pathname string) bool { + args := []string{pathname} + _, err := mounter.ne.Exec("ls", args).CombinedOutput() + if err == nil { + return true + } + return false +} diff --git a/pkg/util/mount/nsenter_mount_unsupported.go b/pkg/util/mount/nsenter_mount_unsupported.go index f881c508711..f4eb692f958 100644 --- a/pkg/util/mount/nsenter_mount_unsupported.go +++ b/pkg/util/mount/nsenter_mount_unsupported.go @@ -18,6 +18,10 @@ limitations under the License. package mount +import ( + "errors" +) + type NsenterMounter struct{} func NewNsenterMounter() *NsenterMounter { @@ -65,3 +69,19 @@ func (*NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (stri 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 { + return true +} diff --git a/pkg/util/removeall/removeall_test.go b/pkg/util/removeall/removeall_test.go index df04e0cbf76..22bdd092ed3 100644 --- a/pkg/util/removeall/removeall_test.go +++ b/pkg/util/removeall/removeall_test.go @@ -34,27 +34,51 @@ var _ mount.Interface = &fakeMounter{} func (mounter *fakeMounter) Mount(source string, target string, fstype string, options []string) error { return errors.New("not implemented") } + func (mounter *fakeMounter) Unmount(target string) error { return errors.New("not implemented") } + func (mounter *fakeMounter) List() ([]mount.MountPoint, error) { return nil, errors.New("not implemented") } + func (mounter fakeMounter) DeviceOpened(pathname string) (bool, error) { return false, errors.New("not implemented") } + func (mounter *fakeMounter) PathIsDevice(pathname string) (bool, error) { return false, errors.New("not implemented") } + func (mounter *fakeMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { return "", errors.New("not implemented") } + func (mounter *fakeMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { - return (mp.Path == dir) + return mp.Path == dir } + func (mounter *fakeMounter) IsNotMountPoint(dir string) (bool, error) { return mount.IsNotMountPoint(mounter, dir) } + +func (mounter *fakeMounter) GetFileType(pathname string) (mount.FileType, error) { + return mount.FileType("fake"), errors.New("not implemented") +} + +func (mounter *fakeMounter) MakeDir(pathname string) error { + return nil +} + +func (mounter *fakeMounter) MakeFile(pathname string) error { + return nil +} + +func (mounter *fakeMounter) ExistsPath(pathname string) bool { + return true +} + func (mounter *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { name := path.Base(file) if strings.HasPrefix(name, "mount") { diff --git a/pkg/volume/host_path/host_path.go b/pkg/volume/host_path/host_path.go index 0ca43cc8585..97e3fa5db55 100644 --- a/pkg/volume/host_path/host_path.go +++ b/pkg/volume/host_path/host_path.go @@ -25,6 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util/volumehelper" "k8s.io/kubernetes/pkg/volume/validation" @@ -113,8 +114,9 @@ func (plugin *hostPathPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts vo pathType = hostPathVolumeSource.Type } return &hostPathMounter{ - hostPath: &hostPath{path: path, pathType: pathType, containerized: opts.Containerized}, + hostPath: &hostPath{path: path, pathType: pathType}, readOnly: readOnly, + mounter: plugin.host.GetMounter(plugin.GetPluginName()), }, nil } @@ -182,9 +184,8 @@ func newProvisioner(options volume.VolumeOptions, host volume.VolumeHost, plugin // HostPath volumes represent a bare host file or directory mount. // The direct at the specified path will be directly exposed to the container. type hostPath struct { - path string - pathType *v1.HostPathType - containerized bool + path string + pathType *v1.HostPathType volume.MetricsNil } @@ -195,6 +196,7 @@ func (hp *hostPath) GetPath() string { type hostPathMounter struct { *hostPath readOnly bool + mounter mount.Interface } var _ volume.Mounter = &hostPathMounter{} @@ -224,7 +226,7 @@ func (b *hostPathMounter) SetUp(fsGroup *int64) error { if *b.pathType == v1.HostPathUnset { return nil } - return checkType(b.GetPath(), b.pathType, b.containerized) + return checkType(b.GetPath(), b.pathType, b.mounter) } // SetUpAt does not make sense for host paths - probably programmer error. @@ -340,132 +342,77 @@ type hostPathTypeChecker interface { GetPath() string } -type fileTypeChecker interface { - getFileType(fileInfo os.FileInfo) (v1.HostPathType, error) -} - -// this is implemented in per-OS files -type defaultFileTypeChecker struct{} - -type osFileTypeChecker struct { +type fileTypeChecker struct { path string exists bool - info os.FileInfo - checker fileTypeChecker + mounter mount.Interface } -func (ftc *osFileTypeChecker) Exists() bool { - return ftc.exists +func (ftc *fileTypeChecker) Exists() bool { + return ftc.mounter.ExistsPath(ftc.path) } -func (ftc *osFileTypeChecker) IsFile() bool { +func (ftc *fileTypeChecker) IsFile() bool { if !ftc.Exists() { return false } - return !ftc.info.IsDir() + return !ftc.IsDir() } -func (ftc *osFileTypeChecker) MakeFile() error { - f, err := os.OpenFile(ftc.path, os.O_CREATE, os.FileMode(0644)) - defer f.Close() - if err != nil { - if !os.IsExist(err) { - return err - } - } - return nil +func (ftc *fileTypeChecker) MakeFile() error { + return ftc.mounter.MakeFile(ftc.path) } -func (ftc *osFileTypeChecker) IsDir() bool { +func (ftc *fileTypeChecker) IsDir() bool { if !ftc.Exists() { return false } - return ftc.info.IsDir() -} - -func (ftc *osFileTypeChecker) MakeDir() error { - err := os.MkdirAll(ftc.path, os.FileMode(0755)) - if err != nil { - if !os.IsExist(err) { - return err - } - } - return nil -} - -func (ftc *osFileTypeChecker) IsBlock() bool { - if !ftc.Exists() { - return false - } - - blkDevType, err := ftc.checker.getFileType(ftc.info) + pathType, err := ftc.mounter.GetFileType(ftc.path) if err != nil { return false } - return blkDevType == v1.HostPathBlockDev + return string(pathType) == string(v1.HostPathDirectory) } -func (ftc *osFileTypeChecker) IsChar() bool { - if !ftc.Exists() { - return false - } +func (ftc *fileTypeChecker) MakeDir() error { + return ftc.mounter.MakeDir(ftc.path) +} - charDevType, err := ftc.checker.getFileType(ftc.info) +func (ftc *fileTypeChecker) IsBlock() bool { + blkDevType, err := ftc.mounter.GetFileType(ftc.path) if err != nil { return false } - return charDevType == v1.HostPathCharDev + return string(blkDevType) == string(v1.HostPathBlockDev) } -func (ftc *osFileTypeChecker) IsSocket() bool { - if !ftc.Exists() { - return false - } - - socketType, err := ftc.checker.getFileType(ftc.info) +func (ftc *fileTypeChecker) IsChar() bool { + charDevType, err := ftc.mounter.GetFileType(ftc.path) if err != nil { return false } - return socketType == v1.HostPathSocket + return string(charDevType) == string(v1.HostPathCharDev) } -func (ftc *osFileTypeChecker) GetPath() string { +func (ftc *fileTypeChecker) IsSocket() bool { + socketType, err := ftc.mounter.GetFileType(ftc.path) + if err != nil { + return false + } + return string(socketType) == string(v1.HostPathSocket) +} + +func (ftc *fileTypeChecker) GetPath() string { return ftc.path } -func newOSFileTypeChecker(path string, checker fileTypeChecker) (hostPathTypeChecker, error) { - ftc := osFileTypeChecker{path: path, checker: checker} - info, err := os.Stat(path) - if err != nil { - ftc.exists = false - if !os.IsNotExist(err) { - return nil, err - } - } else { - ftc.info = info - ftc.exists = true - } - return &ftc, nil +func newFileTypeChecker(path string, mounter mount.Interface) hostPathTypeChecker { + return &fileTypeChecker{path: path, mounter: mounter} } -func checkType(path string, pathType *v1.HostPathType, containerized bool) error { - var ftc hostPathTypeChecker - var err error - if containerized { - // For a containerized kubelet, use nsenter to run commands in - // the host's mount namespace. - // TODO(dixudx): setns into docker's mount namespace, and then run the exact same go code for checks/setup - ftc, err = newNsenterFileTypeChecker(path) - if err != nil { - return err - } - } else { - ftc, err = newOSFileTypeChecker(path, &defaultFileTypeChecker{}) - if err != nil { - return err - } - } - return checkTypeInternal(ftc, pathType) +// checkType checks whether the given path is the exact pathType +func checkType(path string, pathType *v1.HostPathType, mounter mount.Interface) error { + return checkTypeInternal(newFileTypeChecker(path, mounter), pathType) } func checkTypeInternal(ftc hostPathTypeChecker, pathType *v1.HostPathType) error { diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index a421ab731ff..664d0e6b9fb 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -1,5 +1,3 @@ -// +build linux - /* Copyright 2014 The Kubernetes Authors. @@ -30,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/kubernetes/fake" utilfile "k8s.io/kubernetes/pkg/util/file" + utilmount "k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/volume" volumetest "k8s.io/kubernetes/pkg/volume/testing" ) @@ -323,8 +322,58 @@ type fakeFileTypeChecker struct { desiredType string } -func (fftc *fakeFileTypeChecker) getFileType(_ os.FileInfo) (v1.HostPathType, error) { - return *newHostPathType(fftc.desiredType), nil +func (fftc *fakeFileTypeChecker) Mount(source string, target string, fstype string, options []string) error { + return nil +} + +func (fftc *fakeFileTypeChecker) Unmount(target string) error { + return nil +} + +func (fftc *fakeFileTypeChecker) List() ([]utilmount.MountPoint, error) { + return nil, nil +} +func (fftc *fakeFileTypeChecker) IsMountPointMatch(mp utilmount.MountPoint, dir string) bool { + return false +} + +func (fftc *fakeFileTypeChecker) IsNotMountPoint(file string) (bool, error) { + return false, nil +} + +func (fftc *fakeFileTypeChecker) IsLikelyNotMountPoint(file string) (bool, error) { + return false, nil +} + +func (fftc *fakeFileTypeChecker) DeviceOpened(pathname string) (bool, error) { + return false, nil +} +func (fftc *fakeFileTypeChecker) PathIsDevice(pathname string) (bool, error) { + return false, nil +} + +func (fftc *fakeFileTypeChecker) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { + return "fake", nil +} + +func (fftc *fakeFileTypeChecker) MakeRShared(path string) error { + return nil +} + +func (fftc *fakeFileTypeChecker) MakeFile(pathname string) error { + return nil +} + +func (fftc *fakeFileTypeChecker) MakeDir(pathname string) error { + return nil +} + +func (fftc *fakeFileTypeChecker) ExistsPath(pathname string) bool { + return true +} + +func (fftc *fakeFileTypeChecker) GetFileType(_ string) (utilmount.FileType, error) { + return utilmount.FileType(fftc.desiredType), nil } func setUp() error { @@ -363,14 +412,16 @@ func TestOSFileTypeChecker(t *testing.T) { isChar bool }{ { - name: "Existing Folder", - path: "/tmp/ExistingFolder", - isDir: true, + name: "Existing Folder", + path: "/tmp/ExistingFolder", + desiredType: string(utilmount.FileTypeDirectory), + isDir: true, }, { - name: "Existing File", - path: "/tmp/ExistingFolder/foo", - isFile: true, + name: "Existing File", + path: "/tmp/ExistingFolder/foo", + desiredType: string(utilmount.FileTypeFile), + isFile: true, }, { name: "Existing Socket File", @@ -393,11 +444,8 @@ func TestOSFileTypeChecker(t *testing.T) { } for i, tc := range testCases { - oftc, err := newOSFileTypeChecker(tc.path, - &fakeFileTypeChecker{desiredType: tc.desiredType}) - if err != nil { - t.Errorf("[%d: %q] expect nil, but got %v", i, tc.name, err) - } + fakeFTC := &fakeFileTypeChecker{desiredType: tc.desiredType} + oftc := newFileTypeChecker(tc.path, fakeFTC) path := oftc.GetPath() if path != tc.path { diff --git a/pkg/volume/host_path/host_path_unix.go b/pkg/volume/host_path/host_path_unix.go deleted file mode 100644 index 05deaaed5b2..00000000000 --- a/pkg/volume/host_path/host_path_unix.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build linux darwin - -/* -Copyright 2017 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 host_path - -import ( - "fmt" - "os" - "syscall" - - "k8s.io/api/core/v1" -) - -func (dftc *defaultFileTypeChecker) getFileType(info os.FileInfo) (v1.HostPathType, error) { - mode := info.Sys().(*syscall.Stat_t).Mode - switch mode & syscall.S_IFMT { - case syscall.S_IFSOCK: - return v1.HostPathSocket, nil - case syscall.S_IFBLK: - return v1.HostPathBlockDev, nil - case syscall.S_IFCHR: - return v1.HostPathCharDev, nil - } - return "", fmt.Errorf("only recognise socket, block device and character device") -} diff --git a/pkg/volume/host_path/host_path_windows.go b/pkg/volume/host_path/host_path_windows.go deleted file mode 100644 index ff27e49371f..00000000000 --- a/pkg/volume/host_path/host_path_windows.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 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 host_path - -import ( - "fmt" - "os" - "syscall" - - "k8s.io/api/core/v1" -) - -func (dftc *defaultFileTypeChecker) getFileType(info os.FileInfo) (v1.HostPathType, error) { - mode := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes - switch mode & syscall.S_IFMT { - case syscall.S_IFSOCK: - return v1.HostPathSocket, nil - case syscall.S_IFBLK: - return v1.HostPathBlockDev, nil - case syscall.S_IFCHR: - return v1.HostPathCharDev, nil - } - return "", fmt.Errorf("only recognise socket, block device and character device") -} diff --git a/pkg/volume/host_path/nsenter.go b/pkg/volume/host_path/nsenter.go deleted file mode 100644 index c3c3cfece57..00000000000 --- a/pkg/volume/host_path/nsenter.go +++ /dev/null @@ -1,150 +0,0 @@ -// +build linux - -/* -Copyright 2017 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 host_path - -import ( - "fmt" - - "k8s.io/utils/exec" -) - -const ( - hostProcMountsNamespace = "/rootfs/proc/1/ns/mnt" - nsenterCmd = "nsenter" - statCmd = "stat" - touchCmd = "touch" - mkdirCmd = "mkdir" -) - -// nsenterFileTypeChecker is part of experimental support for running the kubelet -// in a container. nsenterFileTypeChecker works by executing "nsenter" to run commands in -// the host's mount namespace. -// -// nsenterFileTypeChecker requires: -// -// 1. The host's root filesystem must be available at "/rootfs"; -// 2. The "nsenter" binary must be on the Kubelet process' PATH in the container's -// filesystem; -// 3. The Kubelet process must have CAP_SYS_ADMIN (required by "nsenter"); at -// the present, this effectively means that the kubelet is running in a -// privileged container; -// 4. The host image must have "stat", "touch", "mkdir" binaries in "/bin", "/usr/sbin", or "/usr/bin"; - -type nsenterFileTypeChecker struct { - path string - exists bool -} - -func newNsenterFileTypeChecker(path string) (hostPathTypeChecker, error) { - ftc := &nsenterFileTypeChecker{path: path} - ftc.Exists() - return ftc, nil -} - -func (ftc *nsenterFileTypeChecker) Exists() bool { - args := []string{ - fmt.Sprintf("--mount=%s", hostProcMountsNamespace), - "--", - "ls", - ftc.path, - } - exec := exec.New() - _, err := exec.Command(nsenterCmd, args...).CombinedOutput() - if err == nil { - ftc.exists = true - } - return ftc.exists -} - -func (ftc *nsenterFileTypeChecker) IsFile() bool { - if !ftc.Exists() { - return false - } - return !ftc.IsDir() -} - -func (ftc *nsenterFileTypeChecker) MakeFile() error { - args := []string{ - fmt.Sprintf("--mount=%s", hostProcMountsNamespace), - "--", - touchCmd, - ftc.path, - } - exec := exec.New() - if _, err := exec.Command(nsenterCmd, args...).CombinedOutput(); err != nil { - return err - } - return nil -} - -func (ftc *nsenterFileTypeChecker) IsDir() bool { - return ftc.checkMimetype("directory") -} - -func (ftc *nsenterFileTypeChecker) MakeDir() error { - args := []string{ - fmt.Sprintf("--mount=%s", hostProcMountsNamespace), - "--", - mkdirCmd, - "-p", - ftc.path, - } - exec := exec.New() - if _, err := exec.Command(nsenterCmd, args...).CombinedOutput(); err != nil { - return err - } - return nil -} - -func (ftc *nsenterFileTypeChecker) IsBlock() bool { - return ftc.checkMimetype("block special file") -} - -func (ftc *nsenterFileTypeChecker) IsChar() bool { - return ftc.checkMimetype("character special file") -} - -func (ftc *nsenterFileTypeChecker) IsSocket() bool { - return ftc.checkMimetype("socket") -} - -func (ftc *nsenterFileTypeChecker) GetPath() string { - return ftc.path -} - -func (ftc *nsenterFileTypeChecker) checkMimetype(checkedType string) bool { - if !ftc.Exists() { - return false - } - - args := []string{ - fmt.Sprintf("--mount=%s", hostProcMountsNamespace), - "--", - statCmd, - "-L", - `--printf "%F"`, - ftc.path, - } - exec := exec.New() - outputBytes, err := exec.Command(nsenterCmd, args...).CombinedOutput() - if err != nil { - return false - } - return string(outputBytes) == checkedType -} diff --git a/pkg/volume/host_path/nsenter_unsupported.go b/pkg/volume/host_path/nsenter_unsupported.go deleted file mode 100644 index 166ef9f0a39..00000000000 --- a/pkg/volume/host_path/nsenter_unsupported.go +++ /dev/null @@ -1,66 +0,0 @@ -// +build !linux - -/* -Copyright 2017 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 host_path - -type nsenterFileTypeChecker struct { - path string - exists bool -} - -func newNsenterFileTypeChecker(path string) (hostPathTypeChecker, error) { - ftc := &nsenterFileTypeChecker{path: path} - ftc.Exists() - return ftc, nil -} - -func (ftc *nsenterFileTypeChecker) Exists() bool { - return false -} - -func (ftc *nsenterFileTypeChecker) IsFile() bool { - return false -} - -func (ftc *nsenterFileTypeChecker) MakeFile() error { - return nil -} - -func (ftc *nsenterFileTypeChecker) IsDir() bool { - return false -} - -func (ftc *nsenterFileTypeChecker) MakeDir() error { - return nil -} - -func (ftc *nsenterFileTypeChecker) IsBlock() bool { - return false -} - -func (ftc *nsenterFileTypeChecker) IsChar() bool { - return false -} - -func (ftc *nsenterFileTypeChecker) IsSocket() bool { - return false -} - -func (ftc *nsenterFileTypeChecker) GetPath() string { - return ftc.path -} diff --git a/pkg/volume/plugins.go b/pkg/volume/plugins.go index eb2f8149ac4..334578b4d1c 100644 --- a/pkg/volume/plugins.go +++ b/pkg/volume/plugins.go @@ -69,8 +69,6 @@ type VolumeOptions struct { CloudTags *map[string]string // Volume provisioning parameters from StorageClass Parameters map[string]string - // This flag helps identify whether kubelet is running in a container - Containerized bool } type DynamicPluginProber interface {