mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Integrate devmapper and aufs into the common "graphdriver" framework.
aufs is still enabled by default, no mechanism for switching drivers yet.
This commit is contained in:
commit
98c3693acf
10 changed files with 161 additions and 96 deletions
78
aufs/aufs.go
Normal file
78
aufs/aufs.go
Normal file
|
@ -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,4 +1,4 @@
|
|||
package docker
|
||||
package aufs
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,4 +1,4 @@
|
|||
package docker
|
||||
package aufs
|
||||
|
||||
import "errors"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package docker
|
||||
package aufs
|
||||
|
||||
import "syscall"
|
||||
|
22
container.go
22
container.go
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
|
7
graph.go
7
graph.go
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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".
|
||||
|
|
|
@ -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"
|
||||
|
@ -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)
|
||||
}
|
||||
}()
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
16
graphdriver/driver.go
Normal file
16
graphdriver/driver.go
Normal file
|
@ -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
image.go
73
image.go
|
@ -9,9 +9,7 @@ import (
|
|||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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...)
|
||||
|
@ -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")
|
||||
|
|
44
runtime.go
44
runtime.go
|
@ -5,6 +5,7 @@ import (
|
|||
"container/list"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/aufs"
|
||||
"github.com/dotcloud/docker/gograph"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
|
@ -573,12 +574,16 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
|
|||
if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g, err := NewGraph(path.Join(config.Root, "graph"))
|
||||
driver, err := aufs.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumes, err := NewGraph(path.Join(config.Root, "volumes"))
|
||||
|
||||
g, err := NewGraph(path.Join(config.Root, "graph"), driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumes, err := NewGraph(path.Join(config.Root, "volumes"), driver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -636,6 +641,39 @@ func (runtime *Runtime) Close() error {
|
|||
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,
|
||||
// ordered by creation date.
|
||||
type History []*Container
|
||||
|
|
Loading…
Add table
Reference in a new issue