mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-06 10:43:56 +00:00
Merge pull request #6269 from ddysher/extend-mount
Abstract IsMountPoint and improve FakeMounter
This commit is contained in:
commit
ee98731a2a
@ -39,11 +39,19 @@ func (f *FakeMounter) ResetLog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeMounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
func (f *FakeMounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
||||||
|
f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: target, Type: fstype})
|
||||||
f.Log = append(f.Log, FakeAction{Action: FakeActionMount, Target: target, Source: source, FSType: fstype})
|
f.Log = append(f.Log, FakeAction{Action: FakeActionMount, Target: target, Source: source, FSType: fstype})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeMounter) Unmount(target string, flags int) error {
|
func (f *FakeMounter) Unmount(target string, flags int) error {
|
||||||
|
newMountpoints := []MountPoint{}
|
||||||
|
for _, mp := range f.MountPoints {
|
||||||
|
if mp.Path != target {
|
||||||
|
newMountpoints = append(newMountpoints, MountPoint{Device: mp.Device, Path: mp.Path, Type: mp.Type})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.MountPoints = newMountpoints
|
||||||
f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: target})
|
f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: target})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -51,3 +59,12 @@ func (f *FakeMounter) Unmount(target string, flags int) error {
|
|||||||
func (f *FakeMounter) List() ([]MountPoint, error) {
|
func (f *FakeMounter) List() ([]MountPoint, error) {
|
||||||
return f.MountPoints, nil
|
return f.MountPoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FakeMounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
for _, mp := range f.MountPoints {
|
||||||
|
if mp.Path == file {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
@ -24,20 +24,15 @@ package mount
|
|||||||
type Interface interface {
|
type Interface interface {
|
||||||
// Mount wraps syscall.Mount().
|
// Mount wraps syscall.Mount().
|
||||||
Mount(source string, target string, fstype string, flags uintptr, data string) error
|
Mount(source string, target string, fstype string, flags uintptr, data string) error
|
||||||
|
|
||||||
// Umount wraps syscall.Mount().
|
// Umount wraps syscall.Mount().
|
||||||
Unmount(target string, flags int) error
|
Unmount(target string, flags int) error
|
||||||
|
|
||||||
// List returns a list of all mounted filesystems. This can be large.
|
// List returns a list of all mounted filesystems. This can be large.
|
||||||
// On some platforms, reading mounts is not guaranteed consistent (i.e.
|
// On some platforms, reading mounts is not guaranteed consistent (i.e.
|
||||||
// it could change between chunked reads). This is guaranteed to be
|
// it could change between chunked reads). This is guaranteed to be
|
||||||
// consistent.
|
// consistent.
|
||||||
List() ([]MountPoint, error)
|
List() ([]MountPoint, error)
|
||||||
}
|
// IsMountPoint determines if a directory is a mountpoint.
|
||||||
|
IsMountPoint(file string) (bool, error)
|
||||||
// New returns a mount.Interface for the current system.
|
|
||||||
func New() Interface {
|
|
||||||
return &Mounter{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This represents a single line in /proc/mounts or /etc/fstab.
|
// This represents a single line in /proc/mounts or /etc/fstab.
|
||||||
@ -50,7 +45,12 @@ type MountPoint struct {
|
|||||||
Pass int
|
Pass int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Examines /proc/mounts to find all other references to the device referenced
|
// New returns a mount.Interface for the current system.
|
||||||
|
func New() Interface {
|
||||||
|
return &Mounter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMountRefs finds all other references to the device referenced
|
||||||
// by mountPath; returns a list of paths.
|
// by mountPath; returns a list of paths.
|
||||||
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
|
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
|
||||||
mps, err := mounter.List()
|
mps, err := mounter.List()
|
||||||
|
@ -34,15 +34,16 @@ import (
|
|||||||
const FlagBind = syscall.MS_BIND
|
const FlagBind = syscall.MS_BIND
|
||||||
const FlagReadOnly = syscall.MS_RDONLY
|
const FlagReadOnly = syscall.MS_RDONLY
|
||||||
|
|
||||||
|
// Mounter implements mount.Interface for linux platform.
|
||||||
type Mounter struct{}
|
type Mounter struct{}
|
||||||
|
|
||||||
// Wraps syscall.Mount()
|
// Mount wraps syscall.Mount()
|
||||||
func (mounter *Mounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
func (mounter *Mounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
||||||
glog.V(5).Infof("Mounting %s %s %s %d %s", source, target, fstype, flags, data)
|
glog.V(5).Infof("Mounting %s %s %s %d %s", source, target, fstype, flags, data)
|
||||||
return syscall.Mount(source, target, fstype, flags, data)
|
return syscall.Mount(source, target, fstype, flags, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps syscall.Unmount()
|
// Unmount wraps syscall.Unmount()
|
||||||
func (mounter *Mounter) Unmount(target string, flags int) error {
|
func (mounter *Mounter) Unmount(target string, flags int) error {
|
||||||
return syscall.Unmount(target, flags)
|
return syscall.Unmount(target, flags)
|
||||||
}
|
}
|
||||||
@ -50,6 +51,7 @@ func (mounter *Mounter) Unmount(target string, flags int) error {
|
|||||||
// How many times to retry for a consistent read of /proc/mounts.
|
// How many times to retry for a consistent read of /proc/mounts.
|
||||||
const maxListTries = 3
|
const maxListTries = 3
|
||||||
|
|
||||||
|
// List returns a list of all mounted filesystems.
|
||||||
func (*Mounter) List() ([]MountPoint, error) {
|
func (*Mounter) List() ([]MountPoint, error) {
|
||||||
hash1, err := readProcMounts(nil)
|
hash1, err := readProcMounts(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -71,11 +73,27 @@ func (*Mounter) List() ([]MountPoint, error) {
|
|||||||
return nil, fmt.Errorf("failed to get a consistent snapshot of /proc/mounts after %d tries", maxListTries)
|
return nil, fmt.Errorf("failed to get a consistent snapshot of /proc/mounts after %d tries", maxListTries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMountPoint determines if a directory is a mountpoint, by comparing the device for the
|
||||||
|
// directory with the device for it's parent. If they are the same, it's not a mountpoint,
|
||||||
|
// if they're different, it is.
|
||||||
|
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
stat, err := os.Stat(file)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
rootStat, err := os.Lstat(file + "/..")
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// If the directory has the same device as parent, then it's not a mountpoint.
|
||||||
|
return stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev, nil
|
||||||
|
}
|
||||||
|
|
||||||
// As per the fstab man page.
|
// As per the fstab man page.
|
||||||
const expectedNumFieldsPerLine = 6
|
const expectedNumFieldsPerLine = 6
|
||||||
|
|
||||||
// Read /proc/mounts and produces a hash of the contents. If the out argument
|
// readProcMounts reads /proc/mounts and produces a hash of the contents. If the out
|
||||||
// is not nil, this fills it with MountPoint structs.
|
// argument is not nil, this fills it with MountPoint structs.
|
||||||
func readProcMounts(out *[]MountPoint) (uint32, error) {
|
func readProcMounts(out *[]MountPoint) (uint32, error) {
|
||||||
file, err := os.Open("/proc/mounts")
|
file, err := os.Open("/proc/mounts")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -34,3 +34,7 @@ func (mounter *Mounter) Unmount(target string, flags int) error {
|
|||||||
func (mounter *Mounter) List() ([]MountPoint, error) {
|
func (mounter *Mounter) List() ([]MountPoint, error) {
|
||||||
return []MountPoint{}, nil
|
return []MountPoint{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
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 (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Determine if a directory is a mountpoint, by comparing the device for the directory
|
|
||||||
// with the device for it's parent. If they are the same, it's not a mountpoint, if they're
|
|
||||||
// different, it is.
|
|
||||||
func IsMountPoint(file string) (bool, error) {
|
|
||||||
stat, err := os.Stat(file)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
rootStat, err := os.Lstat(file + "/..")
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
// If the directory has the same device as parent, then it's not a mountpoint.
|
|
||||||
return stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev, nil
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
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 (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Dummy implementation for Windows
|
|
||||||
func IsMountPoint(file string) (bool, error) {
|
|
||||||
return false, fmt.Errorf("unimplemented")
|
|
||||||
}
|
|
@ -82,7 +82,7 @@ func (plugin *emptyDirPlugin) CanSupport(spec *api.Volume) bool {
|
|||||||
|
|
||||||
func (plugin *emptyDirPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
|
func (plugin *emptyDirPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
|
||||||
// Inject real implementations here, test through the internal function.
|
// Inject real implementations here, test through the internal function.
|
||||||
return plugin.newBuilderInternal(spec, podRef, plugin.mounter, &realMountDetector{})
|
return plugin.newBuilderInternal(spec, podRef, plugin.mounter, &realMountDetector{plugin.mounter})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.ObjectReference, mounter mount.Interface, mountDetector mountDetector) (volume.Builder, error) {
|
func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.ObjectReference, mounter mount.Interface, mountDetector mountDetector) (volume.Builder, error) {
|
||||||
@ -107,7 +107,7 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *api.Volume, podRef *api.O
|
|||||||
|
|
||||||
func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
|
func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
|
||||||
// Inject real implementations here, test through the internal function.
|
// Inject real implementations here, test through the internal function.
|
||||||
return plugin.newCleanerInternal(volName, podUID, plugin.mounter, &realMountDetector{})
|
return plugin.newCleanerInternal(volName, podUID, plugin.mounter, &realMountDetector{plugin.mounter})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface, mountDetector mountDetector) (volume.Cleaner, error) {
|
func (plugin *emptyDirPlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface, mountDetector mountDetector) (volume.Cleaner, error) {
|
||||||
|
@ -27,10 +27,12 @@ import (
|
|||||||
const linuxTmpfsMagic = 0x01021994
|
const linuxTmpfsMagic = 0x01021994
|
||||||
|
|
||||||
// realMountDetector implements mountDetector in terms of syscalls.
|
// realMountDetector implements mountDetector in terms of syscalls.
|
||||||
type realMountDetector struct{}
|
type realMountDetector struct {
|
||||||
|
mounter mount.Interface
|
||||||
|
}
|
||||||
|
|
||||||
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
||||||
isMnt, err := mount.IsMountPoint(path)
|
isMnt, err := m.mounter.IsMountPoint(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false, fmt.Errorf("IsMountPoint(%q): %v", path, err)
|
return 0, false, fmt.Errorf("IsMountPoint(%q): %v", path, err)
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,12 @@ limitations under the License.
|
|||||||
|
|
||||||
package empty_dir
|
package empty_dir
|
||||||
|
|
||||||
|
import "github.com/GoogleCloudPlatform/kubernetes/pkg/util/mount"
|
||||||
|
|
||||||
// realMountDetector pretends to implement mediumer.
|
// realMountDetector pretends to implement mediumer.
|
||||||
type realMountDetector struct{}
|
type realMountDetector struct {
|
||||||
|
mounter mount.Interface
|
||||||
|
}
|
||||||
|
|
||||||
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
|
||||||
return mediumUnknown, false, nil
|
return mediumUnknown, false, nil
|
||||||
|
@ -183,7 +183,7 @@ func (pd *gcePersistentDisk) SetUpAt(dir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle failed mounts here.
|
// TODO: handle failed mounts here.
|
||||||
mountpoint, err := mount.IsMountPoint(dir)
|
mountpoint, err := pd.mounter.IsMountPoint(dir)
|
||||||
glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, mountpoint, err)
|
glog.V(4).Infof("PersistentDisk set up: %s %v %v", dir, mountpoint, err)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
@ -211,7 +211,7 @@ func (pd *gcePersistentDisk) SetUpAt(dir string) error {
|
|||||||
// Perform a bind mount to the full path to allow duplicate mounts of the same PD.
|
// Perform a bind mount to the full path to allow duplicate mounts of the same PD.
|
||||||
err = pd.mounter.Mount(globalPDPath, dir, "", mount.FlagBind|flags, "")
|
err = pd.mounter.Mount(globalPDPath, dir, "", mount.FlagBind|flags, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mountpoint, mntErr := mount.IsMountPoint(dir)
|
mountpoint, mntErr := pd.mounter.IsMountPoint(dir)
|
||||||
if mntErr != nil {
|
if mntErr != nil {
|
||||||
glog.Errorf("isMountpoint check failed: %v", mntErr)
|
glog.Errorf("isMountpoint check failed: %v", mntErr)
|
||||||
return err
|
return err
|
||||||
@ -221,7 +221,7 @@ func (pd *gcePersistentDisk) SetUpAt(dir string) error {
|
|||||||
glog.Errorf("Failed to unmount: %v", mntErr)
|
glog.Errorf("Failed to unmount: %v", mntErr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mountpoint, mntErr := mount.IsMountPoint(dir)
|
mountpoint, mntErr := pd.mounter.IsMountPoint(dir)
|
||||||
if mntErr != nil {
|
if mntErr != nil {
|
||||||
glog.Errorf("isMountpoint check failed: %v", mntErr)
|
glog.Errorf("isMountpoint check failed: %v", mntErr)
|
||||||
return err
|
return err
|
||||||
@ -262,7 +262,7 @@ func (pd *gcePersistentDisk) TearDown() error {
|
|||||||
// Unmounts the bind mount, and detaches the disk only if the PD
|
// Unmounts the bind mount, and detaches the disk only if the PD
|
||||||
// resource was the last reference to that disk on the kubelet.
|
// resource was the last reference to that disk on the kubelet.
|
||||||
func (pd *gcePersistentDisk) TearDownAt(dir string) error {
|
func (pd *gcePersistentDisk) TearDownAt(dir string) error {
|
||||||
mountpoint, err := mount.IsMountPoint(dir)
|
mountpoint, err := pd.mounter.IsMountPoint(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -287,7 +287,7 @@ func (pd *gcePersistentDisk) TearDownAt(dir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mountpoint, mntErr := mount.IsMountPoint(dir)
|
mountpoint, mntErr := pd.mounter.IsMountPoint(dir)
|
||||||
if mntErr != nil {
|
if mntErr != nil {
|
||||||
glog.Errorf("isMountpoint check failed: %v", mntErr)
|
glog.Errorf("isMountpoint check failed: %v", mntErr)
|
||||||
return err
|
return err
|
||||||
|
@ -68,7 +68,7 @@ func (util *GCEDiskUtil) AttachAndMountDisk(pd *gcePersistentDisk, globalPDPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only mount the PD globally once.
|
// Only mount the PD globally once.
|
||||||
mountpoint, err := mount.IsMountPoint(globalPDPath)
|
mountpoint, err := pd.mounter.IsMountPoint(globalPDPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
if err := os.MkdirAll(globalPDPath, 0750); err != nil {
|
if err := os.MkdirAll(globalPDPath, 0750); err != nil {
|
||||||
|
@ -67,5 +67,6 @@ func (mounter *nfsMounter) List() ([]mount.MountPoint, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *nfsMounter) IsMountPoint(dir string) (bool, error) {
|
func (mounter *nfsMounter) IsMountPoint(dir string) (bool, error) {
|
||||||
return mount.IsMountPoint(dir)
|
isMounter := mount.New()
|
||||||
|
return isMounter.IsMountPoint(dir)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user