diff --git a/aufs/aufs.go b/aufs/aufs.go index 528a77f59feae..9ee68482104a2 100644 --- a/aufs/aufs.go +++ b/aufs/aufs.go @@ -9,12 +9,20 @@ import ( "path" ) +func init() { + graphdriver.Register("aufs", Init) +} + type AufsDriver struct { } // New returns a new AUFS driver. // An error is returned if AUFS is not supported. -func New() (*AufsDriver, error) { +func Init(root string) (graphdriver.Driver, error) { + // Try to load the aufs kernel module + if err := exec.Command("modprobe", "aufs").Run(); err != nil { + return nil, err + } return &AufsDriver{}, nil } diff --git a/devmapper/driver.go b/devmapper/driver.go index d52d52b78417f..1eaa0ab76f24d 100644 --- a/devmapper/driver.go +++ b/devmapper/driver.go @@ -2,11 +2,16 @@ package devmapper import ( "fmt" + "github.com/dotcloud/docker/archive" + "github.com/dotcloud/docker/graphdriver" "os" "path" - "github.com/dotcloud/docker/archive" ) +func init() { + graphdriver.Register("devicemapper", Init) +} + // Placeholder interfaces, to be replaced // at integration. @@ -17,22 +22,19 @@ type Image interface { } type Change interface { - } // End of placeholder interfaces. - - type Driver struct { *DeviceSet home string } -func Init(home string) (*Driver, error) { +func Init(home string) (graphdriver.Driver, error) { d := &Driver{ DeviceSet: NewDeviceSet(home), - home: home, + home: home, } if err := d.DeviceSet.ensureInit(); err != nil { return nil, err @@ -64,7 +66,7 @@ func (d *Driver) OnCreate(img Image, layer archive.Archive) error { if err := d.DeviceSet.MountDevice(img.ID(), mp, false); err != nil { return err } - // Apply the layer as a diff + // Apply the layer as a diff if layer != nil { if err := archive.ApplyLayer(mp, layer); err != nil { return err diff --git a/graph.go b/graph.go index 449c3871e8306..660352b60cee2 100644 --- a/graph.go +++ b/graph.go @@ -3,6 +3,8 @@ package docker import ( "fmt" "github.com/dotcloud/docker/archive" + _ "github.com/dotcloud/docker/aufs" + _ "github.com/dotcloud/docker/devmapper" "github.com/dotcloud/docker/graphdriver" "github.com/dotcloud/docker/utils" "io" @@ -18,12 +20,12 @@ import ( type Graph struct { Root string idIndex *utils.TruncIndex - driver graphdriver.Driver + 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, driver graphdriver.Driver) (*Graph, error) { +func NewGraph(root string) (*Graph, error) { abspath, err := filepath.Abs(root) if err != nil { return nil, err @@ -32,10 +34,16 @@ func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) { if err := os.MkdirAll(root, 0700); err != nil && !os.IsExist(err) { return nil, err } + + driver, err := graphdriver.New(root) + if err != nil { + return nil, err + } + graph := &Graph{ Root: abspath, idIndex: utils.NewTruncIndex(), - driver: driver, + driver: driver, } if err := graph.restore(); err != nil { return nil, err @@ -242,7 +250,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"), graph.driver) + return NewGraph(path.Join(graph.Root, "_tmp")) } // Check if given error is "not empty". diff --git a/graphdriver/driver.go b/graphdriver/driver.go index 5570865e84611..fe6fc562020c8 100644 --- a/graphdriver/driver.go +++ b/graphdriver/driver.go @@ -1,5 +1,55 @@ package graphdriver +import ( + "fmt" +) + +type InitFunc func(root string) (Driver, error) + +var ( + // All registred drivers + drivers map[string]InitFunc + // Slice of drivers that should be used in an order + priority = []string{ + "aufs", + "devicemapper", + } +) + +func Register(name string, initFunc InitFunc) error { + if _, exists := drivers[name]; exists { + return fmt.Errorf("Name already registered %s", name) + } + drivers[name] = initFunc + + return nil +} + +func New(root string) (Driver, error) { + var driver Driver + var lastError error + // Check for priority drivers first + for _, name := range priority { + if initFunc, exists := drivers[name]; exists { + driver, lastError = initFunc(root) + if lastError != nil { + continue + } + return driver, nil + } + } + + // Check all registered drivers if no priority driver is found + for _, initFunc := range drivers { + driver, lastError = initFunc(root) + if lastError != nil { + continue + } + return driver, nil + } + return nil, lastError +} + type Image interface { Layers() ([]string, error) } diff --git a/runtime.go b/runtime.go index a040b5aa536c2..6acea49ad313b 100644 --- a/runtime.go +++ b/runtime.go @@ -5,7 +5,6 @@ import ( "container/list" "database/sql" "fmt" - "github.com/dotcloud/docker/aufs" "github.com/dotcloud/docker/gograph" "github.com/dotcloud/docker/utils" "io" @@ -574,16 +573,12 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) { return nil, err } - driver, err := aufs.New() - if err != nil { - return nil, err - } - g, err := NewGraph(path.Join(config.Root, "graph"), driver) + g, err := NewGraph(path.Join(config.Root, "graph")) if err != nil { return nil, err } - volumes, err := NewGraph(path.Join(config.Root, "volumes"), driver) + volumes, err := NewGraph(path.Join(config.Root, "volumes")) if err != nil { return nil, err }