// doNsenterMount nsenters the host's mount namespace and performs the // requested mount. func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error { glog.V(5).Infof("nsenter Mounting %s %s %s %v", source, target, fstype, options) args := n.makeNsenterArgs(source, target, fstype, options) glog.V(5).Infof("Mount command: %v %v", nsenterPath, args) exec := exec.New() outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput() if len(outputBytes) != 0 { glog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes)) } return err }
// Unmount runs umount(8) in the host's mount namespace. func (n *NsenterMounter) Unmount(target string) error { args := []string{ "--mount=/rootfs/proc/1/ns/mnt", "--", n.absHostPath("umount"), target, } glog.V(5).Infof("Unmount command: %v %v", nsenterPath, args) exec := exec.New() outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput() if len(outputBytes) != 0 { glog.V(5).Infof("Output of unmounting %s: %v", target, string(outputBytes)) } return err }
// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt // in the host's root mount namespace. func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { file, err := filepath.Abs(file) if err != nil { return true, err } // Check the directory exists if _, err = os.Stat(file); os.IsNotExist(err) { glog.V(5).Infof("findmnt: directory %s does not exist", file) return true, err } // Add --first-only option: since we are testing for the absense of a mountpoint, it is sufficient to get only // the first of multiple possible mountpoints using --first-only. // Also add fstype output to make sure that the output of target file will give the full path // TODO: Need more refactoring for this function. Track the solution with issue #26996 args := []string{"--mount=/rootfs/proc/1/ns/mnt", "--", n.absHostPath("findmnt"), "-o", "target,fstype", "--noheadings", "--first-only", "--target", file} glog.V(5).Infof("findmnt command: %v %v", nsenterPath, args) exec := exec.New() out, err := exec.Command(nsenterPath, args...).CombinedOutput() if err != nil { glog.V(2).Infof("Failed findmnt command for path %s: %v", file, err) // Different operating systems behave differently for paths which are not mount points. // On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/". // It's safer to assume that it's not a mount point. return true, nil } mountTarget := strings.Split(string(out), " ")[0] mountTarget = strings.TrimSuffix(mountTarget, "\n") glog.V(5).Infof("IsLikelyNotMountPoint findmnt output for path %s: %v:", file, mountTarget) if mountTarget == file { glog.V(5).Infof("IsLikelyNotMountPoint: %s is a mount point", file) return false, nil } glog.V(5).Infof("IsLikelyNotMountPoint: %s is not a mount point", file) return true, nil }