// Mount maps an RBD image and mount it on /mnt/ceph/<datastore>/<volume> directory // FIXME: Figure out how to use rbd locks func (cv *CephVolume) Mount(fstype string) error { cd := cv.driver // Directory to mount the volume dataStoreDir := filepath.Join(cd.mountBase, cv.PoolName) volumeDir := filepath.Join(dataStoreDir, cv.VolumeName) devName, err := cv.mapImage() if err != nil { return err } // Create directory to mount if err := os.MkdirAll(cd.mountBase, 0700); err != nil && !os.IsExist(err) { return fmt.Errorf("error creating %q directory: %v", cd.mountBase, err) } if err := os.MkdirAll(dataStoreDir, 0700); err != nil && !os.IsExist(err) { return fmt.Errorf("error creating %q directory: %v", dataStoreDir) } if err := os.MkdirAll(volumeDir, 0777); err != nil && !os.IsExist(err) { return fmt.Errorf("error creating %q directory: %v", volumeDir) } // Mount the RBD if err := unix.Mount(devName, volumeDir, fstype, 0, ""); err != nil && err != unix.EBUSY { return fmt.Errorf("Failed to mount RBD dev %q: %v", devName, err.Error()) } return nil }
func bindMountFile(src, dst string) error { // mount point has to be an existing file f, err := os.Create(dst) if err != nil { return err } f.Close() return unix.Mount(src, dst, "none", unix.MS_BIND, "") }
// Mount a volume. Returns the rbd device and mounted filesystem path. // If you pass in the params what filesystem to use as `filesystem`, it will // prefer that to `ext4` which is the default. func (c *Driver) Mount(do storage.DriverOptions) (*storage.Mount, error) { intName, err := c.internalName(do.Volume.Name) if err != nil { return nil, err } poolName := do.Volume.Params["pool"] volumePath, err := c.mkMountPath(poolName, intName) if err != nil { return nil, err } devName, err := c.mapImage(do) if err != nil { return nil, err } // Create directory to mount if err := os.MkdirAll(c.mountpath, 0700); err != nil && !os.IsExist(err) { return nil, errored.Errorf("error creating %q directory: %v", c.mountpath, err) } if err := os.MkdirAll(volumePath, 0700); err != nil && !os.IsExist(err) { return nil, errored.Errorf("error creating %q directory: %v", volumePath, err) } // Obtain the major and minor node information about the device we're mounting. // This is critical for tuning cgroups and obtaining metrics for this device only. fi, err := os.Stat(devName) if err != nil { return nil, errored.Errorf("Failed to stat rbd device %q: %v", devName, err) } rdev := fi.Sys().(*syscall.Stat_t).Rdev major := rdev >> 8 minor := rdev & 0xFF // Mount the RBD if err := unix.Mount(devName, volumePath, do.FSOptions.Type, 0, ""); err != nil { return nil, errored.Errorf("Failed to mount RBD dev %q: %v", devName, err) } return &storage.Mount{ Device: devName, Path: volumePath, Volume: do.Volume, DevMajor: uint(major), DevMinor: uint(minor), }, nil }
// New creates new namespace at specified path func New(path string) (*Namespace, error) { runtime.LockOSThread() if err := syscall.Unshare(syscall.CLONE_NEWNET); err != nil { return nil, err } f, err := os.Create(path) if err != nil { return nil, err } f.Close() if err := syscall.Mount(fmt.Sprintf("/proc/self/ns/net"), path, "bind", syscall.MS_BIND, ""); err != nil { return nil, err } return &Namespace{Path: path}, nil }
func bindMountFile(src, dst string) (*os.File, error) { // mount point has to be an existing file f, err := os.OpenFile(dst, os.O_CREATE|os.O_EXCL, 0644) if err != nil { return nil, err } f.Close() err = unix.Mount(src, dst, "none", unix.MS_BIND, "") if err != nil { return nil, fmt.Errorf("mount: %s") } return os.Open(dst) }
func MakeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID err := os.MkdirAll("/var/run/netns", 0600) Expect(err).NotTo(HaveOccurred()) // create an empty file at the mount point mountPointFd, err := os.Create(namespace) Expect(err).NotTo(HaveOccurred()) mountPointFd.Close() var wg sync.WaitGroup wg.Add(1) // do namespace work in a dedicated goroutine, so that we can safely // Lock/Unlock OSThread without upsetting the lock/unlock state of // the caller of this function. See block comment above. go (func() { defer wg.Done() runtime.LockOSThread() defer runtime.UnlockOSThread() defer GinkgoRecover() // capture current thread's original netns currentThreadNetNSPath := getCurrentThreadNetNSPath() originalNetNS, err := unix.Open(currentThreadNetNSPath, unix.O_RDONLY, 0) Expect(err).NotTo(HaveOccurred()) defer unix.Close(originalNetNS) // create a new netns on the current thread err = unix.Unshare(unix.CLONE_NEWNET) Expect(err).NotTo(HaveOccurred()) // bind mount the new netns from the current thread onto the mount point err = unix.Mount(currentThreadNetNSPath, namespace, "none", unix.MS_BIND, "") Expect(err).NotTo(HaveOccurred()) // reset current thread's netns to the original _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(originalNetNS), uintptr(unix.CLONE_NEWNET), 0) Expect(e1).To(BeZero()) })() wg.Wait() return namespace }
func main() { // The need for this conversion is not clear to me, but we get an overflow error // on ARM without it. flags := uintptr(unix.MS_MGC_VAL) flag.Parse() a := flag.Args() if len(a) < 2 { log.Fatalf("Usage: mount [-r] [-t fstype] dev path") } dev := a[0] path := a[1] if *RO { flags |= unix.MS_RDONLY } if err := unix.Mount(a[0], a[1], *fsType, flags, ""); err != nil { log.Fatalf("Mount :%s: on :%s: type :%s: flags %x: %v\n", dev, path, *fsType, flags, err) } }
// Mount maps an RBD image and mount it on /mnt/ceph/<datastore>/<volume> directory // FIXME: Figure out how to use rbd locks func (cv *CephVolume) Mount(fstype string) (*CephMount, error) { cd := cv.driver // Directory to mount the volume dataStoreDir := filepath.Join(cd.mountBase, cv.PoolName) volumeDir := filepath.Join(dataStoreDir, cv.VolumeName) devName, err := cv.mapImage() if err != nil { return nil, err } // Create directory to mount if err := os.MkdirAll(cd.mountBase, 0700); err != nil && !os.IsExist(err) { return nil, fmt.Errorf("error creating %q directory: %v", cd.mountBase, err) } if err := os.MkdirAll(volumeDir, 0700); err != nil && !os.IsExist(err) { return nil, fmt.Errorf("error creating %q directory: %v", dataStoreDir) } // Obtain the major and minor node information about the device we're mounting. // This is critical for tuning cgroups and obtaining metrics for this device only. fi, err := os.Stat(devName) if err != nil { return nil, fmt.Errorf("Failed to stat rbd device %q: %v", devName, err) } rdev := fi.Sys().(*syscall.Stat_t).Rdev major := rdev >> 8 minor := rdev & 0xFF // Mount the RBD if err := unix.Mount(devName, volumeDir, fstype, 0, ""); err != nil && err != unix.EBUSY { return nil, fmt.Errorf("Failed to mount RBD dev %q: %v", devName, err.Error()) } return &CephMount{ DeviceName: devName, MountPath: volumeDir, DevMajor: uint(major), DevMinor: uint(minor), }, nil }
func (m *Mounter) IdempotentlyMount(source, target string) error { err := os.MkdirAll(filepath.Dir(target), 0600) if err != nil { return fmt.Errorf("os.MkdirAll failed: %s", err) } fd, err := os.Create(target) if err != nil { return fmt.Errorf("os.Create failed: %s", err) } defer fd.Close() err = unix.Mount(source, target, "none", unix.MS_BIND, "") if err != nil { return fmt.Errorf("mount failed: %s", err) } return nil }
func makeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID pid := unix.Getpid() tid := unix.Gettid() err := os.MkdirAll("/var/run/netns", 0600) Expect(err).NotTo(HaveOccurred()) runtime.LockOSThread() defer runtime.UnlockOSThread() go (func() { defer GinkgoRecover() err = unix.Unshare(unix.CLONE_NEWNET) Expect(err).NotTo(HaveOccurred()) fd, err := os.Create(namespace) Expect(err).NotTo(HaveOccurred()) defer fd.Close() err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "") Expect(err).NotTo(HaveOccurred()) })() Eventually(namespace).Should(BeAnExistingFile()) fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0) Expect(err).NotTo(HaveOccurred()) defer unix.Close(fd) _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0) Expect(e1).To(BeZero()) return namespace }
// Creates a new persistent network namespace and returns an object // representing that namespace, without switching to it func NewNS() (NetNS, error) { const nsRunDir = "/var/run/netns" b := make([]byte, 16) _, err := rand.Reader.Read(b) if err != nil { return nil, fmt.Errorf("failed to generate random netns name: %v", err) } err = os.MkdirAll(nsRunDir, 0755) if err != nil { return nil, err } // create an empty file at the mount point nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) nsPath := path.Join(nsRunDir, nsName) mountPointFd, err := os.Create(nsPath) if err != nil { return nil, err } mountPointFd.Close() // Ensure the mount point is cleaned up on errors; if the namespace // was successfully mounted this will have no effect because the file // is in-use defer os.RemoveAll(nsPath) var wg sync.WaitGroup wg.Add(1) // do namespace work in a dedicated goroutine, so that we can safely // Lock/Unlock OSThread without upsetting the lock/unlock state of // the caller of this function var fd *os.File go (func() { defer wg.Done() runtime.LockOSThread() var origNS NetNS origNS, err = GetNS(getCurrentThreadNetNSPath()) if err != nil { return } defer origNS.Close() // create a new netns on the current thread err = unix.Unshare(unix.CLONE_NEWNET) if err != nil { return } defer origNS.Set() // bind mount the new netns from the current thread onto the mount point err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "") if err != nil { return } fd, err = os.Open(nsPath) if err != nil { return } })() wg.Wait() if err != nil { unix.Unmount(nsPath, unix.MNT_DETACH) return nil, fmt.Errorf("failed to create namespace: %v", err) } return &netNS{file: fd, mounted: true}, nil }