Skip to content

Commit

Permalink
Initial work on moving aufs to a subpackage
Browse files Browse the repository at this point in the history
  • Loading branch information
crosbymichael committed Nov 1, 2013
1 parent 3e7b976 commit 699a107
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 95 deletions.
78 changes: 78 additions & 0 deletions 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
}
2 changes: 1 addition & 1 deletion mount.go → aufs/mount.go
@@ -1,4 +1,4 @@
package docker
package aufs

import (
"fmt"
Expand Down
2 changes: 1 addition & 1 deletion mount_darwin.go → aufs/mount_darwin.go
@@ -1,4 +1,4 @@
package docker
package aufs

import "errors"

Expand Down
2 changes: 1 addition & 1 deletion mount_linux.go → aufs/mount_linux.go
@@ -1,4 +1,4 @@
package docker
package aufs

import "syscall"

Expand Down
22 changes: 4 additions & 18 deletions container.go
Expand Up @@ -1381,19 +1381,11 @@ func (container *Container) EnsureMounted() 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) {
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) {
Expand All @@ -1404,17 +1396,11 @@ func (container *Container) GetImage() (*Image, error) {
}

func (container *Container) Mounted() (bool, error) {
return Mounted(container.RootfsPath())
return container.runtime.Mounted(container)
}

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.
Expand Down
7 changes: 5 additions & 2 deletions graph.go
Expand Up @@ -2,6 +2,7 @@ package docker

import (
"fmt"
"github.com/dotcloud/docker/graphbackend"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
Expand All @@ -16,11 +17,12 @@ import (
type Graph struct {
Root string
idIndex *utils.TruncIndex
backend graphbackend.GraphBackend
}

// NewGraph instantiates a new graph at the given root path in the filesystem.
// `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)
if err != nil {
return nil, err
Expand All @@ -32,6 +34,7 @@ func NewGraph(root string) (*Graph, error) {
graph := &Graph{
Root: abspath,
idIndex: utils.NewTruncIndex(),
backend: backend,
}
if err := graph.restore(); err != nil {
return nil, err
Expand Down Expand Up @@ -238,7 +241,7 @@ func (graph *Graph) getDockerInitLayer() (string, error) {

func (graph *Graph) tmp() (*Graph, error) {
// 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".
Expand Down
11 changes: 8 additions & 3 deletions graph_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"archive/tar"
"bytes"
"errors"
"github.com/dotcloud/docker/aufs"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
Expand Down Expand Up @@ -144,12 +145,12 @@ func TestMount(t *testing.T) {
if err := os.MkdirAll(rw, 0700); err != nil {
t.Fatal(err)
}
if err := image.Mount(rootfs, rw); err != nil {
if err := graph.backend.Mount(image, tmp); err != nil {
t.Fatal(err)
}
// FIXME: test for mount contents
defer func() {
if err := Unmount(rootfs); err != nil {
if err := graph.backend.Unmount(tmp); err != nil {
t.Error(err)
}
}()
Expand Down Expand Up @@ -294,7 +295,11 @@ func tempGraph(t *testing.T) *Graph {
if err != nil {
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 {
t.Fatal(err)
}
Expand Down
16 changes: 16 additions & 0 deletions 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)
}
73 changes: 6 additions & 67 deletions image.go
Expand Up @@ -8,9 +8,7 @@ import (
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -136,31 +134,6 @@ func jsonPath(root string) string {
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.
func (image *Image) TarLayer(compression Compression) (Archive, error) {
layerPath, err := image.layer()
Expand All @@ -170,37 +143,6 @@ func (image *Image) TarLayer(compression Compression) (Archive, error) {
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 {
return utils.TruncateID(image.ID)
}
Expand Down Expand Up @@ -243,7 +185,11 @@ func (img *Image) History() ([]*Image, error) {
// layers returns all the filesystem layers needed to mount an image
// FIXME: @shykes refactor this function with the new error handling
// (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 e error
if err := img.WalkHistory(
Expand All @@ -265,7 +211,7 @@ func (img *Image) layers() ([]string, error) {
}

// 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
} else {
list = append([]string{dockerinitLayer}, list...)
Expand Down Expand Up @@ -299,13 +245,6 @@ func (img *Image) GetParent() (*Image, error) {
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) {
if img.graph == nil {
return "", fmt.Errorf("Can't lookup root of unregistered image")
Expand Down

0 comments on commit 699a107

Please sign in to comment.