| package graphdriver |
| |
| import ( |
| "errors" |
| "fmt" |
| "os" |
| "path" |
| |
| "github.com/dotcloud/docker/archive" |
| "github.com/dotcloud/docker/pkg/mount" |
| ) |
| |
| type FsMagic uint64 |
| |
| const ( |
| FsMagicBtrfs = FsMagic(0x9123683E) |
| FsMagicAufs = FsMagic(0x61756673) |
| ) |
| |
| type InitFunc func(root string, options []string) (Driver, error) |
| |
| type Driver interface { |
| String() string |
| |
| Create(id, parent string) error |
| Remove(id string) error |
| |
| Get(id, mountLabel string) (dir string, err error) |
| Put(id string) |
| Exists(id string) bool |
| |
| Status() [][2]string |
| |
| Cleanup() error |
| } |
| |
| type Differ interface { |
| Diff(id string) (archive.Archive, error) |
| Changes(id string) ([]archive.Change, error) |
| ApplyDiff(id string, diff archive.ArchiveReader) error |
| DiffSize(id string) (bytes int64, err error) |
| } |
| |
| var ( |
| DefaultDriver string |
| // All registred drivers |
| drivers map[string]InitFunc |
| // Slice of drivers that should be used in an order |
| priority = []string{ |
| "aufs", |
| "btrfs", |
| "devicemapper", |
| "vfs", |
| } |
| |
| ErrNotSupported = errors.New("driver not supported") |
| ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)") |
| ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver") |
| ) |
| |
| func init() { |
| drivers = make(map[string]InitFunc) |
| } |
| |
| 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 GetDriver(name, home string, options []string) (Driver, error) { |
| if initFunc, exists := drivers[name]; exists { |
| return initFunc(path.Join(home, name), options) |
| } |
| return nil, ErrNotSupported |
| } |
| |
| func New(root string, options []string) (driver Driver, err error) { |
| for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} { |
| if name != "" { |
| return GetDriver(name, root, options) |
| } |
| } |
| |
| // Check for priority drivers first |
| for _, name := range priority { |
| driver, err = GetDriver(name, root, options) |
| if err != nil { |
| if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { |
| continue |
| } |
| return nil, err |
| } |
| return driver, nil |
| } |
| |
| // Check all registered drivers if no priority driver is found |
| for _, initFunc := range drivers { |
| if driver, err = initFunc(root, options); err != nil { |
| if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { |
| continue |
| } |
| return nil, err |
| } |
| return driver, nil |
| } |
| return nil, fmt.Errorf("No supported storage backend found") |
| } |
| |
| func MakePrivate(mountPoint string) error { |
| mounted, err := mount.Mounted(mountPoint) |
| if err != nil { |
| return err |
| } |
| |
| if !mounted { |
| if err := mount.Mount(mountPoint, mountPoint, "none", "bind,rw"); err != nil { |
| return err |
| } |
| } |
| |
| return mount.ForceMount("", mountPoint, "none", "private") |
| } |