Просмотр исходного кода

Integrate devmapper and aufs into the common "graphdriver" framework.

aufs is still enabled by default, no mechanism for switching drivers
yet.
Solomon Hykes 11 лет назад
Родитель
Сommit
98c3693acf
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
      graphdriver/driver.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/graphdriver"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+)
+
+type AufsDriver struct {
+}
+
+// New returns a new AUFS driver.
+// An error is returned if AUFS is not supported.
+func New() (*AufsDriver, error) {
+	return &AufsDriver{}, nil
+}
+
+func (a *AufsDriver) Mount(img graphdriver.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 *AufsDriver) 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 *AufsDriver) Mounted(root string) (bool, error) {
+	return Mounted(path.Join(root, "rootfs"))
+}
+
+func (a *AufsDriver) 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

@@ -1382,19 +1382,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) {
@@ -1405,17 +1397,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

@@ -3,6 +3,7 @@ package docker
 import (
 import (
 	"fmt"
 	"fmt"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/archive"
+	"github.com/dotcloud/docker/graphdriver"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
@@ -17,11 +18,12 @@ import (
 type Graph struct {
 type Graph struct {
 	Root    string
 	Root    string
 	idIndex *utils.TruncIndex
 	idIndex *utils.TruncIndex
+	driver graphdriver.Driver
 }
 }
 
 
 // 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, driver graphdriver.Driver) (*Graph, error) {
 	abspath, err := filepath.Abs(root)
 	abspath, err := filepath.Abs(root)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -33,6 +35,7 @@ func NewGraph(root string) (*Graph, error) {
 	graph := &Graph{
 	graph := &Graph{
 		Root:    abspath,
 		Root:    abspath,
 		idIndex: utils.NewTruncIndex(),
 		idIndex: utils.NewTruncIndex(),
+		driver: driver,
 	}
 	}
 	if err := graph.restore(); err != nil {
 	if err := graph.restore(); err != nil {
 		return nil, err
 		return nil, err
@@ -239,7 +242,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.driver)
 }
 }
 
 
 // Check if given error is "not empty".
 // Check if given error is "not empty".

+ 8 - 3
graph_test.go

@@ -5,6 +5,7 @@ import (
 	"bytes"
 	"bytes"
 	"errors"
 	"errors"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/archive"
+	"github.com/dotcloud/docker/aufs"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
@@ -145,12 +146,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.driver.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.driver.Unmount(tmp); err != nil {
 			t.Error(err)
 			t.Error(err)
 		}
 		}
 	}()
 	}()
@@ -295,7 +296,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.New()
+	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
graphdriver/driver.go

@@ -0,0 +1,16 @@
+package graphdriver
+
+type Image interface {
+	Layers() ([]string, error)
+}
+
+type Driver 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

@@ -9,9 +9,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"
@@ -137,31 +135,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 archive.Compression) (archive.Archive, error) {
 func (image *Image) TarLayer(compression archive.Compression) (archive.Archive, error) {
 	layerPath, err := image.layer()
 	layerPath, err := image.layer()
@@ -171,37 +144,6 @@ func (image *Image) TarLayer(compression archive.Compression) (archive.Archive,
 	return archive.Tar(layerPath, compression)
 	return archive.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)
 }
 }
@@ -244,7 +186,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(
@@ -266,7 +212,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...)
@@ -300,13 +246,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"
@@ -573,12 +574,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
 	}
 	}
+	driver, err := aufs.New()
+	if err != nil {
+		return nil, err
+	}
 
 
-	g, err := NewGraph(path.Join(config.Root, "graph"))
+	g, err := NewGraph(path.Join(config.Root, "graph"), driver)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	volumes, err := NewGraph(path.Join(config.Root, "volumes"))
+	volumes, err := NewGraph(path.Join(config.Root, "volumes"), driver)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -636,6 +641,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.driver.Mount(img, container.root)
+}
+
+func (runtime *Runtime) Unmount(container *Container) error {
+	return runtime.graph.driver.Unmount(container.root)
+}
+
+func (runtime *Runtime) Mounted(container *Container) (bool, error) {
+	return runtime.graph.driver.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