github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/daemon/graphdriver/driver.go (about) 1 package graphdriver 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path" 8 "strings" 9 10 log "github.com/Sirupsen/logrus" 11 "github.com/docker/docker/pkg/archive" 12 ) 13 14 type FsMagic uint64 15 16 const ( 17 FsMagicBtrfs = FsMagic(0x9123683E) 18 FsMagicAufs = FsMagic(0x61756673) 19 ) 20 21 type InitFunc func(root string, options []string) (Driver, error) 22 23 // ProtoDriver defines the basic capabilities of a driver. 24 // This interface exists solely to be a minimum set of methods 25 // for client code which choose not to implement the entire Driver 26 // interface and use the NaiveDiffDriver wrapper constructor. 27 // 28 // Use of ProtoDriver directly by client code is not recommended. 29 type ProtoDriver interface { 30 // String returns a string representation of this driver. 31 String() string 32 // Create creates a new, empty, filesystem layer with the 33 // specified id and parent. Parent may be "". 34 Create(id, parent string) error 35 // Remove attempts to remove the filesystem layer with this id. 36 Remove(id string) error 37 // Get returns the mountpoint for the layered filesystem referred 38 // to by this id. You can optionally specify a mountLabel or "". 39 // Returns the absolute path to the mounted layered filesystem. 40 Get(id, mountLabel string) (dir string, err error) 41 // Put releases the system resources for the specified id, 42 // e.g, unmounting layered filesystem. 43 Put(id string) 44 // Exists returns whether a filesystem layer with the specified 45 // ID exists on this driver. 46 Exists(id string) bool 47 // Status returns a set of key-value pairs which give low 48 // level diagnostic status about this driver. 49 Status() [][2]string 50 // Cleanup performs necessary tasks to release resources 51 // held by the driver, e.g., unmounting all layered filesystems 52 // known to this driver. 53 Cleanup() error 54 } 55 56 // Driver is the interface for layered/snapshot file system drivers. 57 type Driver interface { 58 ProtoDriver 59 // Diff produces an archive of the changes between the specified 60 // layer and its parent layer which may be "". 61 Diff(id, parent string) (archive.Archive, error) 62 // Changes produces a list of changes between the specified layer 63 // and its parent layer. If parent is "", then all changes will be ADD changes. 64 Changes(id, parent string) ([]archive.Change, error) 65 // ApplyDiff extracts the changeset from the given diff into the 66 // layer with the specified id and parent, returning the size of the 67 // new layer in bytes. 68 ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error) 69 // DiffSize calculates the changes between the specified id 70 // and its parent and returns the size in bytes of the changes 71 // relative to its base filesystem directory. 72 DiffSize(id, parent string) (size int64, err error) 73 } 74 75 var ( 76 DefaultDriver string 77 // All registred drivers 78 drivers map[string]InitFunc 79 // Slice of drivers that should be used in an order 80 priority = []string{ 81 "aufs", 82 "btrfs", 83 "devicemapper", 84 "vfs", 85 // experimental, has to be enabled manually for now 86 "overlay", 87 } 88 89 ErrNotSupported = errors.New("driver not supported") 90 ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)") 91 ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver") 92 ) 93 94 func init() { 95 drivers = make(map[string]InitFunc) 96 } 97 98 func Register(name string, initFunc InitFunc) error { 99 if _, exists := drivers[name]; exists { 100 return fmt.Errorf("Name already registered %s", name) 101 } 102 drivers[name] = initFunc 103 104 return nil 105 } 106 107 func GetDriver(name, home string, options []string) (Driver, error) { 108 if initFunc, exists := drivers[name]; exists { 109 return initFunc(path.Join(home, name), options) 110 } 111 return nil, ErrNotSupported 112 } 113 114 func New(root string, options []string) (driver Driver, err error) { 115 for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} { 116 if name != "" { 117 return GetDriver(name, root, options) 118 } 119 } 120 121 // Check for priority drivers first 122 for _, name := range priority { 123 driver, err = GetDriver(name, root, options) 124 if err != nil { 125 if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { 126 continue 127 } 128 return nil, err 129 } 130 checkPriorDriver(name, root) 131 return driver, nil 132 } 133 134 // Check all registered drivers if no priority driver is found 135 for name, initFunc := range drivers { 136 if driver, err = initFunc(root, options); err != nil { 137 if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { 138 continue 139 } 140 return nil, err 141 } 142 checkPriorDriver(name, root) 143 return driver, nil 144 } 145 return nil, fmt.Errorf("No supported storage backend found") 146 } 147 148 func checkPriorDriver(name, root string) { 149 priorDrivers := []string{} 150 for prior := range drivers { 151 if prior != name { 152 if _, err := os.Stat(path.Join(root, prior)); err == nil { 153 priorDrivers = append(priorDrivers, prior) 154 } 155 } 156 } 157 if len(priorDrivers) > 0 { 158 log.Warnf("graphdriver %s selected. Warning: your graphdriver directory %s already contains data managed by other graphdrivers: %s", name, root, strings.Join(priorDrivers, ",")) 159 } 160 }