driver.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package graphdriver
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "github.com/Sirupsen/logrus"
  9. "github.com/docker/docker/pkg/archive"
  10. )
  11. // FsMagic unsigned id of the filesystem in use.
  12. type FsMagic uint32
  13. const (
  14. // FsMagicUnsupported is a predifined contant value other than a valid filesystem id.
  15. FsMagicUnsupported = FsMagic(0x00000000)
  16. )
  17. var (
  18. // DefaultDriver if a storage driver is not specified.
  19. DefaultDriver string
  20. // All registred 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) (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. // Create creates a new, empty, filesystem layer with the
  41. // specified id and parent. Parent may be "".
  42. Create(id, parent string) error
  43. // Remove attempts to remove the filesystem layer with this id.
  44. Remove(id string) error
  45. // Get returns the mountpoint for the layered filesystem referred
  46. // to by this id. You can optionally specify a mountLabel or "".
  47. // Returns the absolute path to the mounted layered filesystem.
  48. Get(id, mountLabel string) (dir string, err error)
  49. // Put releases the system resources for the specified id,
  50. // e.g, unmounting layered filesystem.
  51. Put(id string) error
  52. // Exists returns whether a filesystem layer with the specified
  53. // ID exists on this driver.
  54. Exists(id string) bool
  55. // Status returns a set of key-value pairs which give low
  56. // level diagnostic status about this driver.
  57. Status() [][2]string
  58. // Returns a set of key-value pairs which give low level information
  59. // about the image/container driver is managing.
  60. GetMetadata(id string) (map[string]string, error)
  61. // Cleanup performs necessary tasks to release resources
  62. // held by the driver, e.g., unmounting all layered filesystems
  63. // known to this driver.
  64. Cleanup() error
  65. }
  66. // Driver is the interface for layered/snapshot file system drivers.
  67. type Driver interface {
  68. ProtoDriver
  69. // Diff produces an archive of the changes between the specified
  70. // layer and its parent layer which may be "".
  71. Diff(id, parent string) (archive.Archive, error)
  72. // Changes produces a list of changes between the specified layer
  73. // and its parent layer. If parent is "", then all changes will be ADD changes.
  74. Changes(id, parent string) ([]archive.Change, error)
  75. // ApplyDiff extracts the changeset from the given diff into the
  76. // layer with the specified id and parent, returning the size of the
  77. // new layer in bytes.
  78. // The archive.Reader must be an uncompressed stream.
  79. ApplyDiff(id, parent string, diff archive.Reader) (size int64, err error)
  80. // DiffSize calculates the changes between the specified id
  81. // and its parent and returns the size in bytes of the changes
  82. // relative to its base filesystem directory.
  83. DiffSize(id, parent string) (size int64, err error)
  84. }
  85. func init() {
  86. drivers = make(map[string]InitFunc)
  87. }
  88. // Register registers a InitFunc for the driver.
  89. func Register(name string, initFunc InitFunc) error {
  90. if _, exists := drivers[name]; exists {
  91. return fmt.Errorf("Name already registered %s", name)
  92. }
  93. drivers[name] = initFunc
  94. return nil
  95. }
  96. // GetDriver initializes and returns the registered driver
  97. func GetDriver(name, home string, options []string) (Driver, error) {
  98. if initFunc, exists := drivers[name]; exists {
  99. return initFunc(filepath.Join(home, name), options)
  100. }
  101. if pluginDriver, err := lookupPlugin(name, home, options); err == nil {
  102. return pluginDriver, nil
  103. }
  104. logrus.Errorf("Failed to GetDriver graph %s %s", name, home)
  105. return nil, ErrNotSupported
  106. }
  107. // getBuiltinDriver initalizes and returns the registered driver, but does not try to load from plugins
  108. func getBuiltinDriver(name, home string, options []string) (Driver, error) {
  109. if initFunc, exists := drivers[name]; exists {
  110. return initFunc(filepath.Join(home, name), options)
  111. }
  112. logrus.Errorf("Failed to built-in GetDriver graph %s %s", name, home)
  113. return nil, ErrNotSupported
  114. }
  115. // New creates the driver and initializes it at the specified root.
  116. func New(root string, options []string) (driver Driver, err error) {
  117. for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} {
  118. if name != "" {
  119. logrus.Debugf("[graphdriver] trying provided driver %q", name) // so the logs show specified driver
  120. return GetDriver(name, root, options)
  121. }
  122. }
  123. // Guess for prior driver
  124. priorDrivers := scanPriorDrivers(root)
  125. for _, name := range priority {
  126. if name == "vfs" {
  127. // don't use vfs even if there is state present.
  128. continue
  129. }
  130. for _, prior := range priorDrivers {
  131. // of the state found from prior drivers, check in order of our priority
  132. // which we would prefer
  133. if prior == name {
  134. driver, err = getBuiltinDriver(name, root, options)
  135. if err != nil {
  136. // unlike below, we will return error here, because there is prior
  137. // state, and now it is no longer supported/prereq/compatible, so
  138. // something changed and needs attention. Otherwise the daemon's
  139. // images would just "disappear".
  140. logrus.Errorf("[graphdriver] prior storage driver %q failed: %s", name, err)
  141. return nil, err
  142. }
  143. if err := checkPriorDriver(name, root); err != nil {
  144. return nil, err
  145. }
  146. logrus.Infof("[graphdriver] using prior storage driver %q", name)
  147. return driver, nil
  148. }
  149. }
  150. }
  151. // Check for priority drivers first
  152. for _, name := range priority {
  153. driver, err = getBuiltinDriver(name, root, options)
  154. if err != nil {
  155. if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
  156. continue
  157. }
  158. return nil, err
  159. }
  160. return driver, nil
  161. }
  162. // Check all registered drivers if no priority driver is found
  163. for _, initFunc := range drivers {
  164. if driver, err = initFunc(root, options); err != nil {
  165. if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
  166. continue
  167. }
  168. return nil, err
  169. }
  170. return driver, nil
  171. }
  172. return nil, fmt.Errorf("No supported storage backend found")
  173. }
  174. // scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
  175. func scanPriorDrivers(root string) []string {
  176. priorDrivers := []string{}
  177. for driver := range drivers {
  178. p := filepath.Join(root, driver)
  179. if _, err := os.Stat(p); err == nil && driver != "vfs" {
  180. priorDrivers = append(priorDrivers, driver)
  181. }
  182. }
  183. return priorDrivers
  184. }
  185. func checkPriorDriver(name, root string) error {
  186. priorDrivers := []string{}
  187. for _, prior := range scanPriorDrivers(root) {
  188. if prior != name && prior != "vfs" {
  189. if _, err := os.Stat(filepath.Join(root, prior)); err == nil {
  190. priorDrivers = append(priorDrivers, prior)
  191. }
  192. }
  193. }
  194. if len(priorDrivers) > 0 {
  195. return fmt.Errorf("%q contains other graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(priorDrivers, ","))
  196. }
  197. return nil
  198. }