Browse code

Add graph driver registration

Michael Crosby authored on 2013/11/05 08:22:34
Showing 5 changed files
... ...
@@ -9,12 +9,20 @@ import (
9 9
 	"path"
10 10
 )
11 11
 
12
+func init() {
13
+	graphdriver.Register("aufs", Init)
14
+}
15
+
12 16
 type AufsDriver struct {
13 17
 }
14 18
 
15 19
 // New returns a new AUFS driver.
16 20
 // An error is returned if AUFS is not supported.
17
-func New() (*AufsDriver, error) {
21
+func Init(root string) (graphdriver.Driver, error) {
22
+	// Try to load the aufs kernel module
23
+	if err := exec.Command("modprobe", "aufs").Run(); err != nil {
24
+		return nil, err
25
+	}
18 26
 	return &AufsDriver{}, nil
19 27
 }
20 28
 
... ...
@@ -2,11 +2,16 @@ package devmapper
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"github.com/dotcloud/docker/archive"
6
+	"github.com/dotcloud/docker/graphdriver"
5 7
 	"os"
6 8
 	"path"
7
-	"github.com/dotcloud/docker/archive"
8 9
 )
9 10
 
11
+func init() {
12
+	graphdriver.Register("devicemapper", Init)
13
+}
14
+
10 15
 // Placeholder interfaces, to be replaced
11 16
 // at integration.
12 17
 
... ...
@@ -17,22 +22,19 @@ type Image interface {
17 17
 }
18 18
 
19 19
 type Change interface {
20
-
21 20
 }
22 21
 
23 22
 // End of placeholder interfaces.
24 23
 
25
-
26
-
27 24
 type Driver struct {
28 25
 	*DeviceSet
29 26
 	home string
30 27
 }
31 28
 
32
-func Init(home string) (*Driver, error) {
29
+func Init(home string) (graphdriver.Driver, error) {
33 30
 	d := &Driver{
34 31
 		DeviceSet: NewDeviceSet(home),
35
-		home: home,
32
+		home:      home,
36 33
 	}
37 34
 	if err := d.DeviceSet.ensureInit(); err != nil {
38 35
 		return nil, err
... ...
@@ -64,7 +66,7 @@ func (d *Driver) OnCreate(img Image, layer archive.Archive) error {
64 64
 	if err := d.DeviceSet.MountDevice(img.ID(), mp, false); err != nil {
65 65
 		return err
66 66
 	}
67
-	// Apply the layer as a diff 
67
+	// Apply the layer as a diff
68 68
 	if layer != nil {
69 69
 		if err := archive.ApplyLayer(mp, layer); err != nil {
70 70
 			return err
... ...
@@ -3,6 +3,8 @@ package docker
3 3
 import (
4 4
 	"fmt"
5 5
 	"github.com/dotcloud/docker/archive"
6
+	_ "github.com/dotcloud/docker/aufs"
7
+	_ "github.com/dotcloud/docker/devmapper"
6 8
 	"github.com/dotcloud/docker/graphdriver"
7 9
 	"github.com/dotcloud/docker/utils"
8 10
 	"io"
... ...
@@ -18,12 +20,12 @@ import (
18 18
 type Graph struct {
19 19
 	Root    string
20 20
 	idIndex *utils.TruncIndex
21
-	driver graphdriver.Driver
21
+	driver  graphdriver.Driver
22 22
 }
23 23
 
24 24
 // NewGraph instantiates a new graph at the given root path in the filesystem.
25 25
 // `root` will be created if it doesn't exist.
26
-func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) {
26
+func NewGraph(root string) (*Graph, error) {
27 27
 	abspath, err := filepath.Abs(root)
28 28
 	if err != nil {
29 29
 		return nil, err
... ...
@@ -32,10 +34,16 @@ func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) {
32 32
 	if err := os.MkdirAll(root, 0700); err != nil && !os.IsExist(err) {
33 33
 		return nil, err
34 34
 	}
35
+
36
+	driver, err := graphdriver.New(root)
37
+	if err != nil {
38
+		return nil, err
39
+	}
40
+
35 41
 	graph := &Graph{
36 42
 		Root:    abspath,
37 43
 		idIndex: utils.NewTruncIndex(),
38
-		driver: driver,
44
+		driver:  driver,
39 45
 	}
40 46
 	if err := graph.restore(); err != nil {
41 47
 		return nil, err
... ...
@@ -242,7 +250,7 @@ func (graph *Graph) getDockerInitLayer() (string, error) {
242 242
 
243 243
 func (graph *Graph) tmp() (*Graph, error) {
244 244
 	// Changed to _tmp from :tmp:, because it messed with ":" separators in aufs branch syntax...
245
-	return NewGraph(path.Join(graph.Root, "_tmp"), graph.driver)
245
+	return NewGraph(path.Join(graph.Root, "_tmp"))
246 246
 }
247 247
 
248 248
 // Check if given error is "not empty".
... ...
@@ -1,5 +1,55 @@
1 1
 package graphdriver
2 2
 
3
+import (
4
+	"fmt"
5
+)
6
+
7
+type InitFunc func(root string) (Driver, error)
8
+
9
+var (
10
+	// All registred drivers
11
+	drivers map[string]InitFunc
12
+	// Slice of drivers that should be used in an order
13
+	priority = []string{
14
+		"aufs",
15
+		"devicemapper",
16
+	}
17
+)
18
+
19
+func Register(name string, initFunc InitFunc) error {
20
+	if _, exists := drivers[name]; exists {
21
+		return fmt.Errorf("Name already registered %s", name)
22
+	}
23
+	drivers[name] = initFunc
24
+
25
+	return nil
26
+}
27
+
28
+func New(root string) (Driver, error) {
29
+	var driver Driver
30
+	var lastError error
31
+	// Check for priority drivers first
32
+	for _, name := range priority {
33
+		if initFunc, exists := drivers[name]; exists {
34
+			driver, lastError = initFunc(root)
35
+			if lastError != nil {
36
+				continue
37
+			}
38
+			return driver, nil
39
+		}
40
+	}
41
+
42
+	// Check all registered drivers if no priority driver is found
43
+	for _, initFunc := range drivers {
44
+		driver, lastError = initFunc(root)
45
+		if lastError != nil {
46
+			continue
47
+		}
48
+		return driver, nil
49
+	}
50
+	return nil, lastError
51
+}
52
+
3 53
 type Image interface {
4 54
 	Layers() ([]string, error)
5 55
 }
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"container/list"
6 6
 	"database/sql"
7 7
 	"fmt"
8
-	"github.com/dotcloud/docker/aufs"
9 8
 	"github.com/dotcloud/docker/gograph"
10 9
 	"github.com/dotcloud/docker/utils"
11 10
 	"io"
... ...
@@ -574,16 +573,12 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
574 574
 	if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) {
575 575
 		return nil, err
576 576
 	}
577
-	driver, err := aufs.New()
578
-	if err != nil {
579
-		return nil, err
580
-	}
581 577
 
582
-	g, err := NewGraph(path.Join(config.Root, "graph"), driver)
578
+	g, err := NewGraph(path.Join(config.Root, "graph"))
583 579
 	if err != nil {
584 580
 		return nil, err
585 581
 	}
586
-	volumes, err := NewGraph(path.Join(config.Root, "volumes"), driver)
582
+	volumes, err := NewGraph(path.Join(config.Root, "volumes"))
587 583
 	if err != nil {
588 584
 		return nil, err
589 585
 	}