浏览代码

Initial work on moving aufs to a subpackage

Michael Crosby 11 年之前
父节点
当前提交
699a1074fb
共有 10 个文件被更改,包括 160 次插入95 次删除
  1. 78 0
      aufs/aufs.go
  2. 1 1
      aufs/mount.go
  3. 1 1
      aufs/mount_darwin.go
  4. 1 1
      aufs/mount_linux.go
  5. 4 18
      container.go
  6. 5 2
      graph.go
  7. 8 3
      graph_test.go
  8. 16 0
      graphbackend/backend.go
  9. 6 67
      image.go
  10. 40 2
      runtime.go

+ 78 - 0
aufs/aufs.go

@@ -0,0 +1,78 @@
+package aufs
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/graphbackend"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+)
+
+type AufsBackend struct {
+}
+
+// Return a new AUFS backend
+// An error is returned if AUFS is not supported
+func NewBackend() (*AufsBackend, error) {
+	return &AufsBackend{}, nil
+}
+
+func (a *AufsBackend) Mount(img graphbackend.Image, root string) error {
+	layers, err := img.Layers()
+	if err != nil {
+		return err
+	}
+
+	target := path.Join(root, "rootfs")
+	rw := path.Join(root, "rw")
+
+	// Create the target directories if they don't exist
+	if err := os.Mkdir(target, 0755); err != nil && !os.IsExist(err) {
+		return err
+	}
+	if err := os.Mkdir(rw, 0755); err != nil && !os.IsExist(err) {
+		return err
+	}
+	if err := a.aufsMount(layers, rw, target); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (a *AufsBackend) Unmount(root string) error {
+	target := path.Join(root, "rootfs")
+	if _, err := os.Stat(target); err != nil {
+		if os.IsNotExist(err) {
+			return nil
+		}
+		return err
+	}
+	return Unmount(target)
+}
+
+func (a *AufsBackend) Mounted(root string) (bool, error) {
+	return Mounted(path.Join(root, "rootfs"))
+}
+
+func (a *AufsBackend) aufsMount(ro []string, rw, target string) error {
+	rwBranch := fmt.Sprintf("%v=rw", rw)
+	roBranches := ""
+	for _, layer := range ro {
+		roBranches += fmt.Sprintf("%v=ro+wh:", layer)
+	}
+	branches := fmt.Sprintf("br:%v:%v,xino=/dev/shm/aufs.xino", rwBranch, roBranches)
+
+	//if error, try to load aufs kernel module
+	if err := mount("none", target, "aufs", 0, branches); err != nil {
+		log.Printf("Kernel does not support AUFS, trying to load the AUFS module with modprobe...")
+		if err := exec.Command("modprobe", "aufs").Run(); err != nil {
+			return fmt.Errorf("Unable to load the AUFS module")
+		}
+		log.Printf("...module loaded.")
+		if err := mount("none", target, "aufs", 0, branches); err != nil {
+			return fmt.Errorf("Unable to mount using aufs")
+		}
+	}
+	return nil
+}

+ 1 - 1
mount.go → aufs/mount.go

@@ -1,4 +1,4 @@
-package docker
+package aufs
 
 
 import (
 import (
 	"fmt"
 	"fmt"

+ 1 - 1
mount_darwin.go → aufs/mount_darwin.go

@@ -1,4 +1,4 @@
-package docker
+package aufs
 
 
 import "errors"
 import "errors"
 
 

+ 1 - 1
mount_linux.go → aufs/mount_linux.go

@@ -1,4 +1,4 @@
-package docker
+package aufs
 
 
 import "syscall"
 import "syscall"
 
 

+ 4 - 18
container.go

@@ -1381,19 +1381,11 @@ func (container *Container) EnsureMounted() error {
 }
 }
 
 
 func (container *Container) Mount() error {
 func (container *Container) Mount() error {
-	image, err := container.GetImage()
-	if err != nil {
-		return err
-	}
-	return image.Mount(container.RootfsPath(), container.rwPath())
+	return container.runtime.Mount(container)
 }
 }
 
 
 func (container *Container) Changes() ([]Change, error) {
 func (container *Container) Changes() ([]Change, error) {
-	image, err := container.GetImage()
-	if err != nil {
-		return nil, err
-	}
-	return image.Changes(container.rwPath())
+	return container.runtime.Changes(container)
 }
 }
 
 
 func (container *Container) GetImage() (*Image, error) {
 func (container *Container) GetImage() (*Image, error) {
@@ -1404,17 +1396,11 @@ func (container *Container) GetImage() (*Image, error) {
 }
 }
 
 
 func (container *Container) Mounted() (bool, error) {
 func (container *Container) Mounted() (bool, error) {
-	return Mounted(container.RootfsPath())
+	return container.runtime.Mounted(container)
 }
 }
 
 
 func (container *Container) Unmount() error {
 func (container *Container) Unmount() error {
-	if _, err := os.Stat(container.RootfsPath()); err != nil {
-		if os.IsNotExist(err) {
-			return nil
-		}
-		return err
-	}
-	return Unmount(container.RootfsPath())
+	return container.runtime.Unmount(container)
 }
 }
 
 
 // ShortID returns a shorthand version of the container's id for convenience.
 // ShortID returns a shorthand version of the container's id for convenience.

+ 5 - 2
graph.go

@@ -2,6 +2,7 @@ package docker
 
 
 import (
 import (
 	"fmt"
 	"fmt"
+	"github.com/dotcloud/docker/graphbackend"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
@@ -16,11 +17,12 @@ import (
 type Graph struct {
 type Graph struct {
 	Root    string
 	Root    string
 	idIndex *utils.TruncIndex
 	idIndex *utils.TruncIndex
+	backend graphbackend.GraphBackend
 }
 }
 
 
 // NewGraph instantiates a new graph at the given root path in the filesystem.
 // NewGraph instantiates a new graph at the given root path in the filesystem.
 // `root` will be created if it doesn't exist.
 // `root` will be created if it doesn't exist.
-func NewGraph(root string) (*Graph, error) {
+func NewGraph(root string, backend graphbackend.GraphBackend) (*Graph, error) {
 	abspath, err := filepath.Abs(root)
 	abspath, err := filepath.Abs(root)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -32,6 +34,7 @@ func NewGraph(root string) (*Graph, error) {
 	graph := &Graph{
 	graph := &Graph{
 		Root:    abspath,
 		Root:    abspath,
 		idIndex: utils.NewTruncIndex(),
 		idIndex: utils.NewTruncIndex(),
+		backend: backend,
 	}
 	}
 	if err := graph.restore(); err != nil {
 	if err := graph.restore(); err != nil {
 		return nil, err
 		return nil, err
@@ -238,7 +241,7 @@ func (graph *Graph) getDockerInitLayer() (string, error) {
 
 
 func (graph *Graph) tmp() (*Graph, error) {
 func (graph *Graph) tmp() (*Graph, error) {
 	// Changed to _tmp from :tmp:, because it messed with ":" separators in aufs branch syntax...
 	// Changed to _tmp from :tmp:, because it messed with ":" separators in aufs branch syntax...
-	return NewGraph(path.Join(graph.Root, "_tmp"))
+	return NewGraph(path.Join(graph.Root, "_tmp"), graph.backend)
 }
 }
 
 
 // Check if given error is "not empty".
 // Check if given error is "not empty".

+ 8 - 3
graph_test.go

@@ -4,6 +4,7 @@ import (
 	"archive/tar"
 	"archive/tar"
 	"bytes"
 	"bytes"
 	"errors"
 	"errors"
+	"github.com/dotcloud/docker/aufs"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
@@ -144,12 +145,12 @@ func TestMount(t *testing.T) {
 	if err := os.MkdirAll(rw, 0700); err != nil {
 	if err := os.MkdirAll(rw, 0700); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if err := image.Mount(rootfs, rw); err != nil {
+	if err := graph.backend.Mount(image, tmp); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 	// FIXME: test for mount contents
 	// FIXME: test for mount contents
 	defer func() {
 	defer func() {
-		if err := Unmount(rootfs); err != nil {
+		if err := graph.backend.Unmount(tmp); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	}()
 	}()
@@ -294,7 +295,11 @@ func tempGraph(t *testing.T) *Graph {
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	graph, err := NewGraph(tmp)
+	backend, err := aufs.NewBackend()
+	if err != nil {
+		t.Fatal(err)
+	}
+	graph, err := NewGraph(tmp, backend)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

+ 16 - 0
graphbackend/backend.go

@@ -0,0 +1,16 @@
+package graphbackend
+
+type Image interface {
+	Layers() ([]string, error)
+}
+
+type GraphBackend interface {
+	//	Create(img *Image) error
+	//	Delete(img *Image) error
+	Mount(img Image, root string) error
+	Unmount(root string) error
+	Mounted(root string) (bool, error)
+	//	UnmountAll(img *Image) error
+	//	Changes(img *Image, dest string) ([]Change, error)
+	//	Layer(img *Image, dest string) (Archive, error)
+}

+ 6 - 67
image.go

@@ -8,9 +8,7 @@ import (
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
-	"log"
 	"os"
 	"os"
-	"os/exec"
 	"path"
 	"path"
 	"path/filepath"
 	"path/filepath"
 	"strconv"
 	"strconv"
@@ -136,31 +134,6 @@ func jsonPath(root string) string {
 	return path.Join(root, "json")
 	return path.Join(root, "json")
 }
 }
 
 
-func MountAUFS(ro []string, rw string, target string) error {
-	// FIXME: Now mount the layers
-	rwBranch := fmt.Sprintf("%v=rw", rw)
-	roBranches := ""
-	for _, layer := range ro {
-		roBranches += fmt.Sprintf("%v=ro+wh:", layer)
-	}
-	branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
-
-	branches += ",xino=/dev/shm/aufs.xino"
-
-	//if error, try to load aufs kernel module
-	if err := mount("none", target, "aufs", 0, branches); err != nil {
-		log.Printf("Kernel does not support AUFS, trying to load the AUFS module with modprobe...")
-		if err := exec.Command("modprobe", "aufs").Run(); err != nil {
-			return fmt.Errorf("Unable to load the AUFS module")
-		}
-		log.Printf("...module loaded.")
-		if err := mount("none", target, "aufs", 0, branches); err != nil {
-			return fmt.Errorf("Unable to mount using aufs")
-		}
-	}
-	return nil
-}
-
 // TarLayer returns a tar archive of the image's filesystem layer.
 // TarLayer returns a tar archive of the image's filesystem layer.
 func (image *Image) TarLayer(compression Compression) (Archive, error) {
 func (image *Image) TarLayer(compression Compression) (Archive, error) {
 	layerPath, err := image.layer()
 	layerPath, err := image.layer()
@@ -170,37 +143,6 @@ func (image *Image) TarLayer(compression Compression) (Archive, error) {
 	return Tar(layerPath, compression)
 	return Tar(layerPath, compression)
 }
 }
 
 
-func (image *Image) Mount(root, rw string) error {
-	if mounted, err := Mounted(root); err != nil {
-		return err
-	} else if mounted {
-		return fmt.Errorf("%s is already mounted", root)
-	}
-	layers, err := image.layers()
-	if err != nil {
-		return err
-	}
-	// Create the target directories if they don't exist
-	if err := os.Mkdir(root, 0755); err != nil && !os.IsExist(err) {
-		return err
-	}
-	if err := os.Mkdir(rw, 0755); err != nil && !os.IsExist(err) {
-		return err
-	}
-	if err := MountAUFS(layers, rw, root); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (image *Image) Changes(rw string) ([]Change, error) {
-	layers, err := image.layers()
-	if err != nil {
-		return nil, err
-	}
-	return Changes(layers, rw)
-}
-
 func (image *Image) ShortID() string {
 func (image *Image) ShortID() string {
 	return utils.TruncateID(image.ID)
 	return utils.TruncateID(image.ID)
 }
 }
@@ -243,7 +185,11 @@ func (img *Image) History() ([]*Image, error) {
 // layers returns all the filesystem layers needed to mount an image
 // layers returns all the filesystem layers needed to mount an image
 // FIXME: @shykes refactor this function with the new error handling
 // FIXME: @shykes refactor this function with the new error handling
 //        (I'll do it if I have time tonight, I focus on the rest)
 //        (I'll do it if I have time tonight, I focus on the rest)
-func (img *Image) layers() ([]string, error) {
+func (img *Image) Layers() ([]string, error) {
+	if img.graph == nil {
+
+		return nil, fmt.Errorf("Can't lookup dockerinit layer of unregistered image")
+	}
 	var list []string
 	var list []string
 	var e error
 	var e error
 	if err := img.WalkHistory(
 	if err := img.WalkHistory(
@@ -265,7 +211,7 @@ func (img *Image) layers() ([]string, error) {
 	}
 	}
 
 
 	// Inject the dockerinit layer (empty place-holder for mount-binding dockerinit)
 	// Inject the dockerinit layer (empty place-holder for mount-binding dockerinit)
-	if dockerinitLayer, err := img.getDockerInitLayer(); err != nil {
+	if dockerinitLayer, err := img.graph.getDockerInitLayer(); err != nil {
 		return nil, err
 		return nil, err
 	} else {
 	} else {
 		list = append([]string{dockerinitLayer}, list...)
 		list = append([]string{dockerinitLayer}, list...)
@@ -299,13 +245,6 @@ func (img *Image) GetParent() (*Image, error) {
 	return img.graph.Get(img.Parent)
 	return img.graph.Get(img.Parent)
 }
 }
 
 
-func (img *Image) getDockerInitLayer() (string, error) {
-	if img.graph == nil {
-		return "", fmt.Errorf("Can't lookup dockerinit layer of unregistered image")
-	}
-	return img.graph.getDockerInitLayer()
-}
-
 func (img *Image) root() (string, error) {
 func (img *Image) root() (string, error) {
 	if img.graph == nil {
 	if img.graph == nil {
 		return "", fmt.Errorf("Can't lookup root of unregistered image")
 		return "", fmt.Errorf("Can't lookup root of unregistered image")

+ 40 - 2
runtime.go

@@ -5,6 +5,7 @@ import (
 	"container/list"
 	"container/list"
 	"database/sql"
 	"database/sql"
 	"fmt"
 	"fmt"
+	"github.com/dotcloud/docker/aufs"
 	"github.com/dotcloud/docker/gograph"
 	"github.com/dotcloud/docker/gograph"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
@@ -581,12 +582,16 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
 	if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) {
 	if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) {
 		return nil, err
 		return nil, err
 	}
 	}
+	backend, err := aufs.NewBackend()
+	if err != nil {
+		return nil, err
+	}
 
 
-	g, err := NewGraph(path.Join(config.GraphPath, "graph"))
+	g, err := NewGraph(path.Join(config.GraphPath, "graph"), backend)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	volumes, err := NewGraph(path.Join(config.GraphPath, "volumes"))
+	volumes, err := NewGraph(path.Join(config.GraphPath, "volumes"), backend)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -644,6 +649,39 @@ func (runtime *Runtime) Close() error {
 	return runtime.containerGraph.Close()
 	return runtime.containerGraph.Close()
 }
 }
 
 
+func (runtime *Runtime) Mount(container *Container) error {
+	if mounted, err := runtime.Mounted(container); err != nil {
+		return err
+	} else if mounted {
+		return fmt.Errorf("%s is already mounted", container.RootfsPath())
+	}
+	img, err := container.GetImage()
+	if err != nil {
+		return err
+	}
+	return runtime.graph.backend.Mount(img, container.root)
+}
+
+func (runtime *Runtime) Unmount(container *Container) error {
+	return runtime.graph.backend.Unmount(container.root)
+}
+
+func (runtime *Runtime) Mounted(container *Container) (bool, error) {
+	return runtime.graph.backend.Mounted(container.root)
+}
+
+func (runtime *Runtime) Changes(container *Container) ([]Change, error) {
+	img, err := container.GetImage()
+	if err != nil {
+		return nil, err
+	}
+	layers, err := img.Layers()
+	if err != nil {
+		return nil, err
+	}
+	return Changes(layers, container.rwPath())
+}
+
 // History is a convenience type for storing a list of containers,
 // History is a convenience type for storing a list of containers,
 // ordered by creation date.
 // ordered by creation date.
 type History []*Container
 type History []*Container