Ver Fonte

Improve interface by moving to subpkg

Enable builds on OSX
Michael Crosby há 11 anos atrás
pai
commit
7bc96aec7b

+ 50 - 7
container.go

@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/graphdriver"
+	"github.com/dotcloud/docker/mount"
 	"github.com/dotcloud/docker/term"
 	"github.com/dotcloud/docker/utils"
 	"github.com/kr/pty"
@@ -684,13 +685,41 @@ func (container *Container) Start() (err error) {
 		}
 	}
 
-	mounts, err := runtime.getMounts(container)
+	root := container.RootfsPath()
+	envPath, err := container.EnvConfigPath()
 	if err != nil {
 		return err
 	}
 
-	for _, m := range mounts {
-		if err := m.Mount(container.RootfsPath()); err != nil {
+	// Mount docker specific files into the containers root fs
+	if err := mount.Mount(runtime.sysInitPath, path.Join(root, "/.dockerinit"), "none", "bind,ro"); err != nil {
+		return err
+	}
+	if err := mount.Mount(envPath, path.Join(root, "/.dockerenv"), "none", "bind,ro"); err != nil {
+		return err
+	}
+	if err := mount.Mount(container.ResolvConfPath, path.Join(root, "/etc/resolv.conf"), "none", "bind,ro"); err != nil {
+		return err
+	}
+
+	if container.HostnamePath != "" && container.HostsPath != "" {
+		if err := mount.Mount(container.HostnamePath, path.Join(root, "/etc/hostname"), "none", "bind,ro"); err != nil {
+			return err
+		}
+		if err := mount.Mount(container.HostsPath, path.Join(root, "/etc/hosts"), "none", "bind,ro"); err != nil {
+			return err
+		}
+	}
+
+	// Mount user specified volumes
+
+	for r, v := range container.Volumes {
+		mountAs := "ro"
+		if container.VolumesRW[v] {
+			mountAs = "rw"
+		}
+
+		if err := mount.Mount(v, path.Join(root, r), "none", fmt.Sprintf("bind,%s", mountAs)); err != nil {
 			return err
 		}
 	}
@@ -1372,12 +1401,26 @@ func (container *Container) GetImage() (*Image, error) {
 }
 
 func (container *Container) Unmount() error {
-	mounts, err := container.runtime.getMounts(container)
-	if err != nil {
-		return err
+	var (
+		err    error
+		root   = container.RootfsPath()
+		mounts = []string{
+			path.Join(root, "/.dockerinit"),
+			path.Join(root, "/.dockerenv"),
+			path.Join(root, "/etc/resolv.conf"),
+		}
+	)
+
+	if container.HostnamePath != "" && container.HostsPath != "" {
+		mounts = append(mounts, path.Join(root, "/etc/hostname"), path.Join(root, "/etc/hosts"))
 	}
+
+	for r := range container.Volumes {
+		mounts = append(mounts, path.Join(root, r))
+	}
+
 	for _, m := range mounts {
-		if lastError := m.Unmount(container.RootfsPath()); lastError != nil {
+		if lastError := mount.Unmount(m); lastError != nil {
 			err = lastError
 		}
 	}

+ 2 - 1
graphdriver/aufs/aufs.go

@@ -25,6 +25,7 @@ import (
 	"fmt"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/graphdriver"
+	mountpk "github.com/dotcloud/docker/mount"
 	"github.com/dotcloud/docker/utils"
 	"os"
 	"os/exec"
@@ -295,7 +296,7 @@ func (a *Driver) unmount(id string) error {
 
 func (a *Driver) mounted(id string) (bool, error) {
 	target := path.Join(a.rootPath(), "mnt", id)
-	return graphdriver.Mounted(target)
+	return mountpk.Mounted(target)
 }
 
 // During cleanup aufs needs to unmount all mountpoints

+ 0 - 147
graphdriver/driver.go

@@ -1,19 +1,13 @@
 package graphdriver
 
 import (
-	"bufio"
 	"fmt"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/utils"
 	"os"
 	"path"
-	"strings"
-	"syscall"
-	"time"
 )
 
-const mountinfoFormat = "%d %d %d:%d %s %s %s - %s %s %s"
-
 type InitFunc func(root string) (Driver, error)
 
 type Driver interface {
@@ -37,13 +31,6 @@ type Differ interface {
 	DiffSize(id string) (bytes int64, err error)
 }
 
-type Mount struct {
-	Device  string
-	Target  string
-	Type    string
-	Options string
-}
-
 var (
 	DefaultDriver string
 	// All registred drivers
@@ -101,137 +88,3 @@ func New(root string) (driver Driver, err error) {
 	}
 	return nil, err
 }
-
-func (m *Mount) Mount(root string) error {
-	target := path.Join(root, m.Target)
-	if mounted, err := Mounted(target); err != nil || mounted {
-		return err
-	}
-
-	flag, data := parseOptions(m.Options)
-	if err := syscall.Mount(m.Device, target, m.Type, uintptr(flag), data); err != nil {
-		return err
-	}
-	return nil
-}
-
-func parseOptions(options string) (int, string) {
-	var (
-		flag int
-		data []string
-	)
-
-	flags := map[string]struct {
-		clear bool
-		flag  int
-	}{
-		"defaults":      {false, 0},
-		"ro":            {false, syscall.MS_RDONLY},
-		"rw":            {true, syscall.MS_RDONLY},
-		"suid":          {true, syscall.MS_NOSUID},
-		"nosuid":        {false, syscall.MS_NOSUID},
-		"dev":           {true, syscall.MS_NODEV},
-		"nodev":         {false, syscall.MS_NODEV},
-		"exec":          {true, syscall.MS_NOEXEC},
-		"noexec":        {false, syscall.MS_NOEXEC},
-		"sync":          {false, syscall.MS_SYNCHRONOUS},
-		"async":         {true, syscall.MS_SYNCHRONOUS},
-		"dirsync":       {false, syscall.MS_DIRSYNC},
-		"remount":       {false, syscall.MS_REMOUNT},
-		"mand":          {false, syscall.MS_MANDLOCK},
-		"nomand":        {true, syscall.MS_MANDLOCK},
-		"atime":         {true, syscall.MS_NOATIME},
-		"noatime":       {false, syscall.MS_NOATIME},
-		"diratime":      {true, syscall.MS_NODIRATIME},
-		"nodiratime":    {false, syscall.MS_NODIRATIME},
-		"bind":          {false, syscall.MS_BIND},
-		"rbind":         {false, syscall.MS_BIND | syscall.MS_REC},
-		"relatime":      {false, syscall.MS_RELATIME},
-		"norelatime":    {true, syscall.MS_RELATIME},
-		"strictatime":   {false, syscall.MS_STRICTATIME},
-		"nostrictatime": {true, syscall.MS_STRICTATIME},
-	}
-
-	for _, o := range strings.Split(options, ",") {
-		// If the option does not exist in the flags table then it is a
-		// data value for a specific fs type
-		if f, exists := flags[o]; exists {
-			if f.clear {
-				flag &= ^f.flag
-			} else {
-				flag |= f.flag
-			}
-		} else {
-			data = append(data, o)
-		}
-	}
-	return flag, strings.Join(data, ",")
-}
-
-func (m *Mount) Unmount(root string) (err error) {
-	target := path.Join(root, m.Target)
-	if mounted, err := Mounted(target); err != nil || !mounted {
-		return err
-	}
-
-	// Simple retry logic for unmount
-	for i := 0; i < 10; i++ {
-		if err = syscall.Unmount(target, 0); err == nil {
-			return nil
-		}
-		utils.Debugf("[Unmount] %s", err)
-		time.Sleep(100 * time.Millisecond)
-	}
-	return
-}
-
-func Mounted(mountpoint string) (bool, error) {
-	entries, err := parseMountTable()
-	if err != nil {
-		return false, err
-	}
-
-	// Search the table for the mountpoint
-	for _, e := range entries {
-		if e.mountpoint == mountpoint {
-			return true, nil
-		}
-	}
-	return false, nil
-}
-
-// Represents one line from /proc/self/mountinfo
-type procEntry struct {
-	id, parent, major, minor           int
-	source, mountpoint, fstype, device string
-	vfsopts, opts                      string
-}
-
-// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts
-//
-// 180 20 0:2851 / /var/lib/docker/aufs/mnt/a22632d4ed3cb2438246064408f9f07734cbd331f50c81f1ca3dcbd78541ce83 rw,relatime - aufs none rw,si=e9663ac1adbdb4f8
-func parseMountTable() ([]*procEntry, error) {
-	f, err := os.Open("/proc/self/mountinfo")
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-
-	s := bufio.NewScanner(f)
-	out := []*procEntry{}
-	for s.Scan() {
-		if err := s.Err(); err != nil {
-			return nil, err
-		}
-
-		p := &procEntry{}
-		if _, err := fmt.Sscanf(s.Text(), mountinfoFormat,
-			&p.id, &p.parent, &p.major, &p.minor,
-			&p.source, &p.mountpoint, &p.vfsopts, &p.fstype,
-			&p.device, &p.opts); err != nil {
-			return nil, err
-		}
-		out = append(out, p)
-	}
-	return out, nil
-}

+ 1 - 0
mount/MAINTAINERS

@@ -0,0 +1 @@
+Michael Crosby <michael@crosbymichael.com> (@crosbymichael)

+ 5 - 0
mount/flags_darwin.go

@@ -0,0 +1,5 @@
+package mount
+
+func parseOptions(options string) (int, string) {
+	panic("Not implemented")
+}

+ 61 - 0
mount/flags_linux.go

@@ -0,0 +1,61 @@
+package mount
+
+import (
+	"strings"
+	"syscall"
+)
+
+// Parse fstab type mount options into mount() flags
+// and device specific data
+func parseOptions(options string) (int, string) {
+	var (
+		flag int
+		data []string
+	)
+
+	flags := map[string]struct {
+		clear bool
+		flag  int
+	}{
+		"defaults":      {false, 0},
+		"ro":            {false, syscall.MS_RDONLY},
+		"rw":            {true, syscall.MS_RDONLY},
+		"suid":          {true, syscall.MS_NOSUID},
+		"nosuid":        {false, syscall.MS_NOSUID},
+		"dev":           {true, syscall.MS_NODEV},
+		"nodev":         {false, syscall.MS_NODEV},
+		"exec":          {true, syscall.MS_NOEXEC},
+		"noexec":        {false, syscall.MS_NOEXEC},
+		"sync":          {false, syscall.MS_SYNCHRONOUS},
+		"async":         {true, syscall.MS_SYNCHRONOUS},
+		"dirsync":       {false, syscall.MS_DIRSYNC},
+		"remount":       {false, syscall.MS_REMOUNT},
+		"mand":          {false, syscall.MS_MANDLOCK},
+		"nomand":        {true, syscall.MS_MANDLOCK},
+		"atime":         {true, syscall.MS_NOATIME},
+		"noatime":       {false, syscall.MS_NOATIME},
+		"diratime":      {true, syscall.MS_NODIRATIME},
+		"nodiratime":    {false, syscall.MS_NODIRATIME},
+		"bind":          {false, syscall.MS_BIND},
+		"rbind":         {false, syscall.MS_BIND | syscall.MS_REC},
+		"relatime":      {false, syscall.MS_RELATIME},
+		"norelatime":    {true, syscall.MS_RELATIME},
+		"strictatime":   {false, syscall.MS_STRICTATIME},
+		"nostrictatime": {true, syscall.MS_STRICTATIME},
+	}
+
+	for _, o := range strings.Split(options, ",") {
+		// If the option does not exist in the flags table then it is a
+		// data value for a specific fs type
+		if f, exists := flags[o]; exists {
+			if f.clear {
+				flag &= ^f.flag
+			} else {
+				flag |= f.flag
+			}
+		} else {
+			data = append(data, o)
+		}
+	}
+	return flag, strings.Join(data, ",")
+}

+ 53 - 0
mount/mount.go

@@ -0,0 +1,53 @@
+package mount
+
+import (
+	"time"
+)
+
+// Looks at /proc/self/mountinfo to determine of the specified
+// mountpoint has been mounted
+func Mounted(mountpoint string) (bool, error) {
+	entries, err := parseMountTable()
+	if err != nil {
+		return false, err
+	}
+
+	// Search the table for the mountpoint
+	for _, e := range entries {
+		if e.mountpoint == mountpoint {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+// Mount the specified options at the target path
+// Options must be specified as fstab style
+func Mount(device, target, mType, options string) error {
+	if mounted, err := Mounted(target); err != nil || mounted {
+		return err
+	}
+
+	flag, data := parseOptions(options)
+	if err := mount(device, target, mType, uintptr(flag), data); err != nil {
+		return err
+	}
+	return nil
+
+}
+
+// Unmount the target only if it is mounted
+func Unmount(target string) (err error) {
+	if mounted, err := Mounted(target); err != nil || !mounted {
+		return err
+	}
+
+	// Simple retry logic for unmount
+	for i := 0; i < 10; i++ {
+		if err = unmount(target, 0); err == nil {
+			return nil
+		}
+		time.Sleep(100 * time.Millisecond)
+	}
+	return
+}

+ 4 - 11
graphdriver/driver_test.go → mount/mount_test.go

@@ -1,4 +1,4 @@
-package graphdriver
+package mount
 
 import (
 	"os"
@@ -24,7 +24,7 @@ func TestMountOptionsParsing(t *testing.T) {
 }
 
 func TestMounted(t *testing.T) {
-	tmp := path.Join(os.TempDir(), "graphdriver-tests")
+	tmp := path.Join(os.TempDir(), "mount-tests")
 	if err := os.MkdirAll(tmp, 0777); err != nil {
 		t.Fatal(err)
 	}
@@ -48,18 +48,11 @@ func TestMounted(t *testing.T) {
 	}
 	f.Close()
 
-	mount := &Mount{
-		Device:  sourcePath,
-		Target:  targetPath,
-		Type:    "none",
-		Options: "bind,ro",
-	}
-
-	if err := mount.Mount("/"); err != nil {
+	if err := Mount(sourcePath, targetPath, "none", "bind,ro"); err != nil {
 		t.Fatal(err)
 	}
 	defer func() {
-		if err := mount.Unmount("/"); err != nil {
+		if err := Unmount(targetPath); err != nil {
 			t.Fatal(err)
 		}
 	}()

+ 9 - 0
mount/mounter_darwin.go

@@ -0,0 +1,9 @@
+package mount
+
+func mount(device, target, mType string, flag uintptr, data string) error {
+	panic("Not implemented")
+}
+
+func unmount(target string, flag int) error {
+	panic("Not implemented")
+}

+ 13 - 0
mount/mounter_linux.go

@@ -0,0 +1,13 @@
+package mount
+
+import (
+	"syscall"
+)
+
+func mount(device, target, mType string, flag uintptr, data string) error {
+	return syscall.Mount(device, target, mType, flag, data)
+}
+
+func unmount(target string, flag int) error {
+	return syscall.Unmount(target, flag)
+}

+ 45 - 0
mount/mountinfo.go

@@ -0,0 +1,45 @@
+package mount
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+)
+
+const (
+	mountinfoFormat = "%d %d %d:%d %s %s %s - %s %s %s"
+)
+
+// Represents one line from /proc/self/mountinfo
+type procEntry struct {
+	id, parent, major, minor           int
+	source, mountpoint, fstype, device string
+	vfsopts, opts                      string
+}
+
+// Parse /proc/self/mountinfo because comparing Dev and ino does not work from bind mounts
+func parseMountTable() ([]*procEntry, error) {
+	f, err := os.Open("/proc/self/mountinfo")
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	s := bufio.NewScanner(f)
+	out := []*procEntry{}
+	for s.Scan() {
+		if err := s.Err(); err != nil {
+			return nil, err
+		}
+
+		p := &procEntry{}
+		if _, err := fmt.Sscanf(s.Text(), mountinfoFormat,
+			&p.id, &p.parent, &p.major, &p.minor,
+			&p.source, &p.mountpoint, &p.vfsopts, &p.fstype,
+			&p.device, &p.opts); err != nil {
+			return nil, err
+		}
+		out = append(out, p)
+	}
+	return out, nil
+}

+ 0 - 61
runtime.go

@@ -788,67 +788,6 @@ func (runtime *Runtime) Close() error {
 	return nil
 }
 
-func (runtime *Runtime) getMounts(container *Container) ([]*graphdriver.Mount, error) {
-	// Generate additional bind mounts
-	envPath, err := container.EnvConfigPath()
-	if err != nil {
-		return nil, err
-	}
-	mounts := []*graphdriver.Mount{
-		{
-			Device:  runtime.sysInitPath,
-			Target:  "/.dockerinit",
-			Type:    "none",
-			Options: "bind,ro",
-		},
-		{
-			Device:  envPath,
-			Target:  "/.dockerenv",
-			Type:    "none",
-			Options: "bind,ro",
-		},
-		// In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container
-		{
-			Device:  container.ResolvConfPath,
-			Target:  "/etc/resolv.conf",
-			Type:    "none",
-			Options: "bind,ro",
-		},
-	}
-
-	if container.HostnamePath != "" && container.HostsPath != "" {
-		mounts = append(mounts,
-			&graphdriver.Mount{
-				Device:  container.HostnamePath,
-				Target:  "/etc/hostname",
-				Type:    "none",
-				Options: "bind,ro",
-			},
-			&graphdriver.Mount{
-				Device:  container.HostsPath,
-				Target:  "/etc/hosts",
-				Type:    "none",
-				Options: "bind,ro",
-			})
-	}
-
-	for r, v := range container.Volumes {
-		mountAs := "ro"
-		if container.VolumesRW[v] {
-			mountAs = "rw"
-		}
-
-		mounts = append(mounts,
-			&graphdriver.Mount{
-				Device:  v,
-				Target:  r,
-				Type:    "none",
-				Options: fmt.Sprintf("bind,%s", mountAs),
-			})
-	}
-	return mounts, nil
-}
-
 func (runtime *Runtime) Mount(container *Container) error {
 	dir, err := runtime.driver.Get(container.ID)
 	if err != nil {