driver.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package graphdriver
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "github.com/Sirupsen/logrus"
  9. "github.com/vbatts/tar-split/tar/storage"
  10. "github.com/docker/docker/pkg/archive"
  11. "github.com/docker/docker/pkg/idtools"
  12. )
  13. // FsMagic unsigned id of the filesystem in use.
  14. type FsMagic uint32
  15. const (
  16. // FsMagicUnsupported is a predefined constant value other than a valid filesystem id.
  17. FsMagicUnsupported = FsMagic(0x00000000)
  18. )
  19. var (
  20. // All registered drivers
  21. drivers map[string]InitFunc
  22. // ErrNotSupported returned when driver is not supported.
  23. ErrNotSupported = errors.New("driver not supported")
  24. // ErrPrerequisites retuned when driver does not meet prerequisites.
  25. ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)")
  26. // ErrIncompatibleFS returned when file system is not supported.
  27. ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver")
  28. )
  29. // InitFunc initializes the storage driver.
  30. type InitFunc func(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error)
  31. // ProtoDriver defines the basic capabilities of a driver.
  32. // This interface exists solely to be a minimum set of methods
  33. // for client code which choose not to implement the entire Driver
  34. // interface and use the NaiveDiffDriver wrapper constructor.
  35. //
  36. // Use of ProtoDriver directly by client code is not recommended.
  37. type ProtoDriver interface {
  38. // String returns a string representation of this driver.
  39. String() string
  40. // CreateReadWrite creates a new, empty filesystem layer that is ready
  41. // to be used as the storage for a container.
  42. CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error
  43. // Create creates a new, empty, filesystem layer with the
  44. // specified id and parent and mountLabel. Parent and mountLabel may be "".
  45. Create(id, parent, mountLabel string, storageOpt map[string]string) error
  46. // Remove attempts to remove the filesystem layer with this id.
  47. Remove(id string) error
  48. // Get returns the mountpoint for the layered filesystem referred
  49. // to by this id. You can optionally specify a mountLabel or "".
  50. // Returns the absolute path to the mounted layered filesystem.
  51. Get(id, mountLabel string) (dir string, err error)
  52. // Put releases the system resources for the specified id,
  53. // e.g, unmounting layered filesystem.
  54. Put(id string) error
  55. // Exists returns whether a filesystem layer with the specified
  56. // ID exists on this driver.
  57. Exists(id string) bool
  58. // Status returns a set of key-value pairs which give low
  59. // level diagnostic status about this driver.
  60. Status() [][2]string
  61. // Returns a set of key-value pairs which give low level information
  62. // about the image/container driver is managing.
  63. GetMetadata(id string) (map[string]string, error)
  64. // Cleanup performs necessary tasks to release resources
  65. // held by the driver, e.g., unmounting all layered filesystems
  66. // known to this driver.
  67. Cleanup() error
  68. }
  69. // Driver is the interface for layered/snapshot file system drivers.
  70. type Driver interface {
  71. ProtoDriver
  72. // Diff produces an archive of the changes between the specified
  73. // layer and its parent layer which may be "".
  74. Diff(id, parent string) (archive.Archive, error)
  75. // Changes produces a list of changes between the specified layer
  76. // and its parent layer. If parent is "", then all changes will be ADD changes.
  77. Changes(id, parent string) ([]archive.Change, error)
  78. // ApplyDiff extracts the changeset from the given diff into the
  79. // layer with the specified id and parent, returning the size of the
  80. // new layer in bytes.
  81. // The archive.Reader must be an uncompressed stream.
  82. ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error)
  83. // DiffSize calculates the changes between the specified id
  84. // and its parent and returns the size in bytes of the changes
  85. // relative to its base filesystem directory.
  86. DiffSize(id, parent string) (size int64, err error)
  87. }
  88. // DiffGetterDriver is the interface for layered file system drivers that
  89. // provide a specialized function for getting file contents for tar-split.
  90. type DiffGetterDriver interface {
  91. Driver
  92. // DiffGetter returns an interface to efficiently retrieve the contents
  93. // of files in a layer.
  94. DiffGetter(id string) (FileGetCloser, error)
  95. }
  96. // FileGetCloser extends the storage.FileGetter interface with a Close method
  97. // for cleaning up.
  98. type FileGetCloser interface {
  99. storage.FileGetter
  100. // Close cleans up any resources associated with the FileGetCloser.
  101. Close() error
  102. }
  103. // Checker makes checks on specified filesystems.
  104. type Checker interface {
  105. // IsMounted returns true if the provided path is mounted for the specific checker
  106. IsMounted(path string) bool
  107. }
  108. func init() {
  109. drivers = make(map[string]InitFunc)
  110. }
  111. // Register registers an InitFunc for the driver.
  112. func Register(name string, initFunc InitFunc) error {
  113. if _, exists := drivers[name]; exists {
  114. return fmt.Errorf("Name already registered %s", name)
  115. }
  116. drivers[name] = initFunc
  117. return nil
  118. }
  119. // GetDriver initializes and returns the registered driver
  120. func GetDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) {
  121. if initFunc, exists := drivers[name]; exists {
  122. return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps)
  123. }
  124. if pluginDriver, err := lookupPlugin(name, home, options); err == nil {
  125. return pluginDriver, nil
  126. }
  127. logrus.Errorf("Failed to GetDriver graph %s %s", name, home)
  128. return nil, ErrNotSupported
  129. }
  130. // getBuiltinDriver initializes and returns the registered driver, but does not try to load from plugins
  131. func getBuiltinDriver(name, home string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) {
  132. if initFunc, exists := drivers[name]; exists {
  133. return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps)
  134. }
  135. logrus.Errorf("Failed to built-in GetDriver graph %s %s", name, home)
  136. return nil, ErrNotSupported
  137. }
  138. // New creates the driver and initializes it at the specified root.
  139. func New(root string, name string, options []string, uidMaps, gidMaps []idtools.IDMap) (Driver, error) {
  140. if name != "" {
  141. logrus.Debugf("[graphdriver] trying provided driver: %s", name) // so the logs show specified driver
  142. return GetDriver(name, root, options, uidMaps, gidMaps)
  143. }
  144. // Guess for prior driver
  145. driversMap := scanPriorDrivers(root)
  146. for _, name := range priority {
  147. if name == "vfs" {
  148. // don't use vfs even if there is state present.
  149. continue
  150. }
  151. if _, prior := driversMap[name]; prior {
  152. // of the state found from prior drivers, check in order of our priority
  153. // which we would prefer
  154. driver, err := getBuiltinDriver(name, root, options, uidMaps, gidMaps)
  155. if err != nil {
  156. // unlike below, we will return error here, because there is prior
  157. // state, and now it is no longer supported/prereq/compatible, so
  158. // something changed and needs attention. Otherwise the daemon's
  159. // images would just "disappear".
  160. logrus.Errorf("[graphdriver] prior storage driver %s failed: %s", name, err)
  161. return nil, err
  162. }
  163. // abort starting when there are other prior configured drivers
  164. // to ensure the user explicitly selects the driver to load
  165. if len(driversMap)-1 > 0 {
  166. var driversSlice []string
  167. for name := range driversMap {
  168. driversSlice = append(driversSlice, name)
  169. }
  170. return nil, fmt.Errorf("%s contains several valid graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(driversSlice, ", "))
  171. }
  172. logrus.Infof("[graphdriver] using prior storage driver: %s", name)
  173. return driver, nil
  174. }
  175. }
  176. // Check for priority drivers first
  177. for _, name := range priority {
  178. driver, err := getBuiltinDriver(name, root, options, uidMaps, gidMaps)
  179. if err != nil {
  180. if isDriverNotSupported(err) {
  181. continue
  182. }
  183. return nil, err
  184. }
  185. return driver, nil
  186. }
  187. // Check all registered drivers if no priority driver is found
  188. for name, initFunc := range drivers {
  189. driver, err := initFunc(filepath.Join(root, name), options, uidMaps, gidMaps)
  190. if err != nil {
  191. if isDriverNotSupported(err) {
  192. continue
  193. }
  194. return nil, err
  195. }
  196. return driver, nil
  197. }
  198. return nil, fmt.Errorf("No supported storage backend found")
  199. }
  200. // isDriverNotSupported returns true if the error initializing
  201. // the graph driver is a non-supported error.
  202. func isDriverNotSupported(err error) bool {
  203. return err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS
  204. }
  205. // scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
  206. func scanPriorDrivers(root string) map[string]bool {
  207. driversMap := make(map[string]bool)
  208. for driver := range drivers {
  209. p := filepath.Join(root, driver)
  210. if _, err := os.Stat(p); err == nil && driver != "vfs" {
  211. driversMap[driver] = true
  212. }
  213. }
  214. return driversMap
  215. }