github.com/lmars/docker@v1.6.0-rc2/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 uint32 15 16 const ( 17 FsMagicBtrfs = FsMagic(0x9123683E) 18 FsMagicAufs = FsMagic(0x61756673) 19 FsMagicExtfs = FsMagic(0x0000EF53) 20 FsMagicCramfs = FsMagic(0x28cd3d45) 21 FsMagicRamFs = FsMagic(0x858458f6) 22 FsMagicTmpFs = FsMagic(0x01021994) 23 FsMagicSquashFs = FsMagic(0x73717368) 24 FsMagicNfsFs = FsMagic(0x00006969) 25 FsMagicReiserFs = FsMagic(0x52654973) 26 FsMagicSmbFs = FsMagic(0x0000517B) 27 FsMagicJffs2Fs = FsMagic(0x000072b6) 28 FsMagicZfs = FsMagic(0x2fc12fc1) 29 FsMagicXfs = FsMagic(0x58465342) 30 FsMagicUnsupported = FsMagic(0x00000000) 31 ) 32 33 var ( 34 DefaultDriver string 35 // All registred drivers 36 drivers map[string]InitFunc 37 // Slice of drivers that should be used in an order 38 priority = []string{ 39 "aufs", 40 "btrfs", 41 "devicemapper", 42 "vfs", 43 // experimental, has to be enabled manually for now 44 "overlay", 45 } 46 47 ErrNotSupported = errors.New("driver not supported") 48 ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)") 49 ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver") 50 51 FsNames = map[FsMagic]string{ 52 FsMagicAufs: "aufs", 53 FsMagicBtrfs: "btrfs", 54 FsMagicExtfs: "extfs", 55 FsMagicCramfs: "cramfs", 56 FsMagicRamFs: "ramfs", 57 FsMagicTmpFs: "tmpfs", 58 FsMagicSquashFs: "squashfs", 59 FsMagicNfsFs: "nfs", 60 FsMagicReiserFs: "reiserfs", 61 FsMagicSmbFs: "smb", 62 FsMagicJffs2Fs: "jffs2", 63 FsMagicZfs: "zfs", 64 FsMagicXfs: "xfs", 65 FsMagicUnsupported: "unsupported", 66 } 67 ) 68 69 type InitFunc func(root string, options []string) (Driver, error) 70 71 // ProtoDriver defines the basic capabilities of a driver. 72 // This interface exists solely to be a minimum set of methods 73 // for client code which choose not to implement the entire Driver 74 // interface and use the NaiveDiffDriver wrapper constructor. 75 // 76 // Use of ProtoDriver directly by client code is not recommended. 77 type ProtoDriver interface { 78 // String returns a string representation of this driver. 79 String() string 80 // Create creates a new, empty, filesystem layer with the 81 // specified id and parent. Parent may be "". 82 Create(id, parent string) error 83 // Remove attempts to remove the filesystem layer with this id. 84 Remove(id string) error 85 // Get returns the mountpoint for the layered filesystem referred 86 // to by this id. You can optionally specify a mountLabel or "". 87 // Returns the absolute path to the mounted layered filesystem. 88 Get(id, mountLabel string) (dir string, err error) 89 // Put releases the system resources for the specified id, 90 // e.g, unmounting layered filesystem. 91 Put(id string) error 92 // Exists returns whether a filesystem layer with the specified 93 // ID exists on this driver. 94 Exists(id string) bool 95 // Status returns a set of key-value pairs which give low 96 // level diagnostic status about this driver. 97 Status() [][2]string 98 // Cleanup performs necessary tasks to release resources 99 // held by the driver, e.g., unmounting all layered filesystems 100 // known to this driver. 101 Cleanup() error 102 } 103 104 // Driver is the interface for layered/snapshot file system drivers. 105 type Driver interface { 106 ProtoDriver 107 // Diff produces an archive of the changes between the specified 108 // layer and its parent layer which may be "". 109 Diff(id, parent string) (archive.Archive, error) 110 // Changes produces a list of changes between the specified layer 111 // and its parent layer. If parent is "", then all changes will be ADD changes. 112 Changes(id, parent string) ([]archive.Change, error) 113 // ApplyDiff extracts the changeset from the given diff into the 114 // layer with the specified id and parent, returning the size of the 115 // new layer in bytes. 116 ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error) 117 // DiffSize calculates the changes between the specified id 118 // and its parent and returns the size in bytes of the changes 119 // relative to its base filesystem directory. 120 DiffSize(id, parent string) (size int64, err error) 121 } 122 123 func init() { 124 drivers = make(map[string]InitFunc) 125 } 126 127 func Register(name string, initFunc InitFunc) error { 128 if _, exists := drivers[name]; exists { 129 return fmt.Errorf("Name already registered %s", name) 130 } 131 drivers[name] = initFunc 132 133 return nil 134 } 135 136 func GetDriver(name, home string, options []string) (Driver, error) { 137 if initFunc, exists := drivers[name]; exists { 138 return initFunc(path.Join(home, name), options) 139 } 140 return nil, ErrNotSupported 141 } 142 143 func New(root string, options []string) (driver Driver, err error) { 144 for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} { 145 if name != "" { 146 return GetDriver(name, root, options) 147 } 148 } 149 150 // Check for priority drivers first 151 for _, name := range priority { 152 driver, err = GetDriver(name, root, options) 153 if err != nil { 154 if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { 155 continue 156 } 157 return nil, err 158 } 159 checkPriorDriver(name, root) 160 return driver, nil 161 } 162 163 // Check all registered drivers if no priority driver is found 164 for name, initFunc := range drivers { 165 if driver, err = initFunc(root, options); err != nil { 166 if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS { 167 continue 168 } 169 return nil, err 170 } 171 checkPriorDriver(name, root) 172 return driver, nil 173 } 174 return nil, fmt.Errorf("No supported storage backend found") 175 } 176 177 func checkPriorDriver(name, root string) { 178 priorDrivers := []string{} 179 for prior := range drivers { 180 if prior != name && prior != "vfs" { 181 if _, err := os.Stat(path.Join(root, prior)); err == nil { 182 priorDrivers = append(priorDrivers, prior) 183 } 184 } 185 } 186 if len(priorDrivers) > 0 { 187 log.Warnf("Graphdriver %s selected. Your graphdriver directory %s already contains data managed by other graphdrivers: %s", name, root, strings.Join(priorDrivers, ",")) 188 } 189 }