layer.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Package layer is package for managing read-only
  2. // and read-write mounts on the union file system
  3. // driver. Read-only mounts are referenced using a
  4. // content hash and are protected from mutation in
  5. // the exposed interface. The tar format is used
  6. // to create read-only layers and export both
  7. // read-only and writable layers. The exported
  8. // tar data for a read-only layer should match
  9. // the tar used to create the layer.
  10. package layer // import "github.com/docker/docker/layer"
  11. import (
  12. "errors"
  13. "io"
  14. "github.com/docker/distribution"
  15. "github.com/docker/docker/pkg/archive"
  16. "github.com/docker/docker/pkg/containerfs"
  17. digest "github.com/opencontainers/go-digest"
  18. "github.com/sirupsen/logrus"
  19. )
  20. var (
  21. // ErrLayerDoesNotExist is used when an operation is
  22. // attempted on a layer which does not exist.
  23. ErrLayerDoesNotExist = errors.New("layer does not exist")
  24. // ErrLayerNotRetained is used when a release is
  25. // attempted on a layer which is not retained.
  26. ErrLayerNotRetained = errors.New("layer not retained")
  27. // ErrMountDoesNotExist is used when an operation is
  28. // attempted on a mount layer which does not exist.
  29. ErrMountDoesNotExist = errors.New("mount does not exist")
  30. // ErrMountNameConflict is used when a mount is attempted
  31. // to be created but there is already a mount with the name
  32. // used for creation.
  33. ErrMountNameConflict = errors.New("mount already exists with name")
  34. // ErrActiveMount is used when an operation on a
  35. // mount is attempted but the layer is still
  36. // mounted and the operation cannot be performed.
  37. ErrActiveMount = errors.New("mount still active")
  38. // ErrNotMounted is used when requesting an active
  39. // mount but the layer is not mounted.
  40. ErrNotMounted = errors.New("not mounted")
  41. // ErrMaxDepthExceeded is used when a layer is attempted
  42. // to be created which would result in a layer depth
  43. // greater than the 125 max.
  44. ErrMaxDepthExceeded = errors.New("max depth exceeded")
  45. // ErrNotSupported is used when the action is not supported
  46. // on the current host operating system.
  47. ErrNotSupported = errors.New("not support on this host operating system")
  48. )
  49. // ChainID is the content-addressable ID of a layer.
  50. type ChainID digest.Digest
  51. // String returns a string rendition of a layer ID
  52. func (id ChainID) String() string {
  53. return string(id)
  54. }
  55. // DiffID is the hash of an individual layer tar.
  56. type DiffID digest.Digest
  57. // String returns a string rendition of a layer DiffID
  58. func (diffID DiffID) String() string {
  59. return string(diffID)
  60. }
  61. // TarStreamer represents an object which may
  62. // have its contents exported as a tar stream.
  63. type TarStreamer interface {
  64. // TarStream returns a tar archive stream
  65. // for the contents of a layer.
  66. TarStream() (io.ReadCloser, error)
  67. }
  68. // Layer represents a read-only layer
  69. type Layer interface {
  70. TarStreamer
  71. // TarStreamFrom returns a tar archive stream for all the layer chain with
  72. // arbitrary depth.
  73. TarStreamFrom(ChainID) (io.ReadCloser, error)
  74. // ChainID returns the content hash of the entire layer chain. The hash
  75. // chain is made up of DiffID of top layer and all of its parents.
  76. ChainID() ChainID
  77. // DiffID returns the content hash of the layer
  78. // tar stream used to create this layer.
  79. DiffID() DiffID
  80. // Parent returns the next layer in the layer chain.
  81. Parent() Layer
  82. // Size returns the size of the entire layer chain. The size
  83. // is calculated from the total size of all files in the layers.
  84. Size() (int64, error)
  85. // DiffSize returns the size difference of the top layer
  86. // from parent layer.
  87. DiffSize() (int64, error)
  88. // Metadata returns the low level storage metadata associated
  89. // with layer.
  90. Metadata() (map[string]string, error)
  91. }
  92. // RWLayer represents a layer which is
  93. // read and writable
  94. type RWLayer interface {
  95. TarStreamer
  96. // Name of mounted layer
  97. Name() string
  98. // Parent returns the layer which the writable
  99. // layer was created from.
  100. Parent() Layer
  101. // Mount mounts the RWLayer and returns the filesystem path
  102. // to the writable layer.
  103. Mount(mountLabel string) (containerfs.ContainerFS, error)
  104. // Unmount unmounts the RWLayer. This should be called
  105. // for every mount. If there are multiple mount calls
  106. // this operation will only decrement the internal mount counter.
  107. Unmount() error
  108. // Size represents the size of the writable layer
  109. // as calculated by the total size of the files
  110. // changed in the mutable layer.
  111. Size() (int64, error)
  112. // Changes returns the set of changes for the mutable layer
  113. // from the base layer.
  114. Changes() ([]archive.Change, error)
  115. // Metadata returns the low level metadata for the mutable layer
  116. Metadata() (map[string]string, error)
  117. // ApplyDiff applies the diff to the RW layer
  118. ApplyDiff(diff io.Reader) (int64, error)
  119. }
  120. // Metadata holds information about a
  121. // read-only layer
  122. type Metadata struct {
  123. // ChainID is the content hash of the layer
  124. ChainID ChainID
  125. // DiffID is the hash of the tar data used to
  126. // create the layer
  127. DiffID DiffID
  128. // Size is the size of the layer and all parents
  129. Size int64
  130. // DiffSize is the size of the top layer
  131. DiffSize int64
  132. }
  133. // MountInit is a function to initialize a
  134. // writable mount. Changes made here will
  135. // not be included in the Tar stream of the
  136. // RWLayer.
  137. type MountInit func(root containerfs.ContainerFS) error
  138. // CreateRWLayerOpts contains optional arguments to be passed to CreateRWLayer
  139. type CreateRWLayerOpts struct {
  140. MountLabel string
  141. InitFunc MountInit
  142. StorageOpt map[string]string
  143. }
  144. // Store represents a backend for managing both
  145. // read-only and read-write layers.
  146. type Store interface {
  147. Register(io.Reader, ChainID) (Layer, error)
  148. Get(ChainID) (Layer, error)
  149. Map() map[ChainID]Layer
  150. Release(Layer) ([]Metadata, error)
  151. CreateRWLayer(id string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error)
  152. GetRWLayer(id string) (RWLayer, error)
  153. GetMountID(id string) (string, error)
  154. ReleaseRWLayer(RWLayer) ([]Metadata, error)
  155. Cleanup() error
  156. DriverStatus() [][2]string
  157. DriverName() string
  158. }
  159. // DescribableStore represents a layer store capable of storing
  160. // descriptors for layers.
  161. type DescribableStore interface {
  162. RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error)
  163. }
  164. // CreateChainID returns ID for a layerDigest slice
  165. func CreateChainID(dgsts []DiffID) ChainID {
  166. return createChainIDFromParent("", dgsts...)
  167. }
  168. func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
  169. if len(dgsts) == 0 {
  170. return parent
  171. }
  172. if parent == "" {
  173. return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
  174. }
  175. // H = "H(n-1) SHA256(n)"
  176. dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
  177. return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
  178. }
  179. // ReleaseAndLog releases the provided layer from the given layer
  180. // store, logging any error and release metadata
  181. func ReleaseAndLog(ls Store, l Layer) {
  182. metadata, err := ls.Release(l)
  183. if err != nil {
  184. logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err)
  185. }
  186. LogReleaseMetadata(metadata)
  187. }
  188. // LogReleaseMetadata logs a metadata array, uses this to
  189. // ensure consistent logging for release metadata
  190. func LogReleaseMetadata(metadatas []Metadata) {
  191. for _, metadata := range metadatas {
  192. logrus.Infof("Layer %s cleaned up", metadata.ChainID)
  193. }
  194. }