Move mount logic into root package

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2015-02-09 14:22:52 -08:00
parent b0e274c0d2
commit 1c895b409a
2 changed files with 98 additions and 126 deletions

View File

@ -1,17 +1,5 @@
package configs
import (
"fmt"
"os"
"path/filepath"
"syscall"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/libcontainer/label"
)
const DefaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
type Mount struct {
Type string `json:"type,omitempty"`
Source string `json:"source,omitempty"` // Source path, in the host namespace
@ -21,113 +9,3 @@ type Mount struct {
Private bool `json:"private,omitempty"`
Slave bool `json:"slave,omitempty"`
}
func (m *Mount) Mount(rootfs, mountLabel string) error {
switch m.Type {
case "bind":
return m.bindMount(rootfs, mountLabel)
case "tmpfs":
return m.tmpfsMount(rootfs, mountLabel)
default:
return fmt.Errorf("unsupported mount type %s for %s", m.Type, m.Destination)
}
}
func (m *Mount) bindMount(rootfs, mountLabel string) error {
var (
flags = syscall.MS_BIND | syscall.MS_REC
dest = filepath.Join(rootfs, m.Destination)
)
if !m.Writable {
flags = flags | syscall.MS_RDONLY
}
if m.Slave {
flags = flags | syscall.MS_SLAVE
}
stat, err := os.Stat(m.Source)
if err != nil {
return err
}
// TODO: (crosbymichael) This does not belong here and should be done a layer above
dest, err = symlink.FollowSymlinkInScope(dest, rootfs)
if err != nil {
return err
}
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
return fmt.Errorf("creating new bind mount target %s", err)
}
if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil {
return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err)
}
if !m.Writable {
if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil {
return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
}
}
if m.Relabel != "" {
if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil {
return fmt.Errorf("relabeling %s to %s %s", m.Source, mountLabel, err)
}
}
if m.Private {
if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
return fmt.Errorf("mounting %s private %s", dest, err)
}
}
return nil
}
func (m *Mount) tmpfsMount(rootfs, mountLabel string) error {
var (
err error
l = label.FormatMountLabel("", mountLabel)
dest = filepath.Join(rootfs, m.Destination)
)
// TODO: (crosbymichael) This does not belong here and should be done a layer above
if dest, err = symlink.FollowSymlinkInScope(dest, rootfs); err != nil {
return err
}
if err := createIfNotExists(dest, true); err != nil {
return fmt.Errorf("creating new tmpfs mount target %s", err)
}
if err := syscall.Mount("tmpfs", dest, "tmpfs", uintptr(DefaultMountFlags), l); err != nil {
return fmt.Errorf("%s mounting %s in tmpfs", err, dest)
}
return nil
}
func createIfNotExists(path string, isDir bool) error {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
if isDir {
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
} else {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
f, err := os.OpenFile(path, os.O_CREATE, 0755)
if err != nil {
return err
}
f.Close()
}
}
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"path/filepath"
"syscall"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/libcontainer/configs"
"github.com/docker/libcontainer/label"
)
@ -34,7 +35,7 @@ func setupRootfs(config *configs.Config) (err error) {
}
// apply any user specified mounts within the new mount namespace
for _, m := range config.Mounts {
if err := m.Mount(config.Rootfs, config.MountLabel); err != nil {
if err := mountUserMount(m, config.Rootfs, config.MountLabel); err != nil {
return err
}
}
@ -68,7 +69,7 @@ func setupRootfs(config *configs.Config) (err error) {
}
if config.Readonlyfs {
if err := setReadonly(); err != nil {
return fmt.Errorf("set readonly %s", err)
return err
}
}
syscall.Umask(0022)
@ -80,10 +81,10 @@ func setupRootfs(config *configs.Config) (err error) {
func mountSystem(config *configs.Config) error {
for _, m := range newSystemMounts(config.Rootfs, config.MountLabel, config.RestrictSys) {
if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) {
return fmt.Errorf("mkdirall %s %s", m.path, err)
return err
}
if err := syscall.Mount(m.source, m.path, m.device, uintptr(m.flags), m.data); err != nil {
return fmt.Errorf("mounting %s into %s %s", m.source, m.path, err)
return err
}
}
return nil
@ -277,3 +278,96 @@ func msMoveRoot(rootfs string) error {
}
return syscall.Chdir("/")
}
func mountUserMount(m *configs.Mount, rootfs, mountLabel string) error {
switch m.Type {
case "bind":
return bindMount(m, rootfs, mountLabel)
case "tmpfs":
return tmpfsMount(m, rootfs, mountLabel)
default:
return fmt.Errorf("unsupported mount type %s for %s", m.Type, m.Destination)
}
}
func bindMount(m *configs.Mount, rootfs, mountLabel string) error {
var (
flags = syscall.MS_BIND | syscall.MS_REC
dest = filepath.Join(rootfs, m.Destination)
)
if !m.Writable {
flags = flags | syscall.MS_RDONLY
}
if m.Slave {
flags = flags | syscall.MS_SLAVE
}
stat, err := os.Stat(m.Source)
if err != nil {
return err
}
// TODO: (crosbymichael) This does not belong here and should be done a layer above
dest, err = symlink.FollowSymlinkInScope(dest, rootfs)
if err != nil {
return err
}
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
return fmt.Errorf("creating new bind mount target %s", err)
}
if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil {
return err
}
if !m.Writable {
if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil {
return err
}
}
if m.Relabel != "" {
if err := label.Relabel(m.Source, mountLabel, m.Relabel); err != nil {
return err
}
}
if m.Private {
if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
return err
}
}
return nil
}
func tmpfsMount(m *configs.Mount, rootfs, mountLabel string) error {
var (
err error
l = label.FormatMountLabel("", mountLabel)
dest = filepath.Join(rootfs, m.Destination)
)
// TODO: (crosbymichael) This does not belong here and should be done a layer above
if dest, err = symlink.FollowSymlinkInScope(dest, rootfs); err != nil {
return err
}
if err := createIfNotExists(dest, true); err != nil {
return err
}
return syscall.Mount("tmpfs", dest, "tmpfs", uintptr(defaultMountFlags), l)
}
func createIfNotExists(path string, isDir bool) error {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
if isDir {
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
} else {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
f, err := os.OpenFile(path, os.O_CREATE, 0755)
if err != nil {
return err
}
f.Close()
}
}
}
return nil
}