layer.go 6.6 KB

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