Skip to content

Commit

Permalink
Integrate devmapper and aufs into the common "graphdriver" framework.
Browse files Browse the repository at this point in the history
aufs is still enabled by default, no mechanism for switching drivers
yet.
  • Loading branch information
Solomon Hykes committed Nov 4, 2013
2 parents 6c77f2c + 3cd4232 commit 98c3693
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
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 1 addition & 1 deletion mount.go → aufs/mount.go
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package docker
package aufs

import "syscall"

Expand Down
22 changes: 4 additions & 18 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -1382,19 +1382,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 @@ -1405,17 +1397,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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package docker
import (
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/graphdriver"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
Expand All @@ -17,11 +18,12 @@ import (
type Graph struct {
Root string
idIndex *utils.TruncIndex
driver graphdriver.Driver
}

// 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, driver graphdriver.Driver) (*Graph, error) {
abspath, err := filepath.Abs(root)
if err != nil {
return nil, err
Expand All @@ -33,6 +35,7 @@ func NewGraph(root string) (*Graph, error) {
graph := &Graph{
Root: abspath,
idIndex: utils.NewTruncIndex(),
driver: driver,
}
if err := graph.restore(); err != nil {
return nil, err
Expand Down Expand Up @@ -239,7 +242,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.driver)
}

// Check if given error is "not empty".
Expand Down
11 changes: 8 additions & 3 deletions graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"errors"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/aufs"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
Expand Down Expand Up @@ -145,12 +146,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.driver.Mount(image, tmp); err != nil {
t.Fatal(err)
}
// FIXME: test for mount contents
defer func() {
if err := Unmount(rootfs); err != nil {
if err := graph.driver.Unmount(tmp); err != nil {
t.Error(err)
}
}()
Expand Down Expand Up @@ -295,7 +296,11 @@ func tempGraph(t *testing.T) *Graph {
if err != nil {
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 {
t.Fatal(err)
}
Expand Down
16 changes: 16 additions & 0 deletions graphdriver/driver.go
Original file line number Diff line number Diff line change
@@ -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)
}
73 changes: 6 additions & 67 deletions image.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -137,31 +135,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 archive.Compression) (archive.Archive, error) {
layerPath, err := image.layer()
Expand All @@ -171,37 +144,6 @@ func (image *Image) TarLayer(compression archive.Compression) (archive.Archive,
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 {
return utils.TruncateID(image.ID)
}
Expand Down Expand Up @@ -244,7 +186,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 @@ -266,7 +212,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 @@ -300,13 +246,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 98c3693

Please sign in to comment.