layer.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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
  11. import (
  12. "errors"
  13. "io"
  14. "github.com/Sirupsen/logrus"
  15. "github.com/docker/distribution"
  16. "github.com/docker/distribution/digest"
  17. "github.com/docker/docker/pkg/archive"
  18. )
  19. var (
  20. // ErrLayerDoesNotExist is used when an operation is
  21. // attempted on a layer which does not exist.
  22. ErrLayerDoesNotExist = errors.New("layer does not exist")
  23. // ErrLayerNotRetained is used when a release is
  24. // attempted on a layer which is not retained.
  25. ErrLayerNotRetained = errors.New("layer not retained")
  26. // ErrMountDoesNotExist is used when an operation is
  27. // attempted on a mount layer which does not exist.
  28. ErrMountDoesNotExist = errors.New("mount does not exist")
  29. // ErrMountNameConflict is used when a mount is attempted
  30. // to be created but there is already a mount with the name
  31. // used for creation.
  32. ErrMountNameConflict = errors.New("mount already exists with name")
  33. // ErrActiveMount is used when an operation on a
  34. // mount is attempted but the layer is still
  35. // mounted and the operation cannot be performed.
  36. ErrActiveMount = errors.New("mount still active")
  37. // ErrNotMounted is used when requesting an active
  38. // mount but the layer is not mounted.
  39. ErrNotMounted = errors.New("not mounted")
  40. // ErrMaxDepthExceeded is used when a layer is attempted
  41. // to be created which would result in a layer depth
  42. // greater than the 125 max.
  43. ErrMaxDepthExceeded = errors.New("max depth exceeded")
  44. // ErrNotSupported is used when the action is not supported
  45. // on the current platform
  46. ErrNotSupported = errors.New("not support on this platform")
  47. )
  48. // ChainID is the content-addressable ID of a layer.
  49. type ChainID digest.Digest
  50. // String returns a string rendition of a layer ID
  51. func (id ChainID) String() string {
  52. return string(id)
  53. }
  54. // DiffID is the hash of an individual layer tar.
  55. type DiffID digest.Digest
  56. // String returns a string rendition of a layer DiffID
  57. func (diffID DiffID) String() string {
  58. return string(diffID)
  59. }
  60. // TarStreamer represents an object which may
  61. // have its contents exported as a tar stream.
  62. type TarStreamer interface {
  63. // TarStream returns a tar archive stream
  64. // for the contents of a layer.
  65. TarStream() (io.ReadCloser, error)
  66. }
  67. // Layer represents a read-only layer
  68. type Layer interface {
  69. TarStreamer
  70. // ChainID returns the content hash of the entire layer chain. The hash
  71. // chain is made up of DiffID of top layer and all of its parents.
  72. ChainID() ChainID
  73. // DiffID returns the content hash of the layer
  74. // tar stream used to create this layer.
  75. DiffID() DiffID
  76. // Parent returns the next layer in the layer chain.
  77. Parent() Layer
  78. // Size returns the size of the entire layer chain. The size
  79. // is calculated from the total size of all files in the layers.
  80. Size() (int64, error)
  81. // DiffSize returns the size difference of the top layer
  82. // from parent layer.
  83. DiffSize() (int64, error)
  84. // Metadata returns the low level storage metadata associated
  85. // with layer.
  86. Metadata() (map[string]string, error)
  87. }
  88. // RWLayer represents a layer which is
  89. // read and writable
  90. type RWLayer interface {
  91. TarStreamer
  92. // Name of mounted layer
  93. Name() string
  94. // Parent returns the layer which the writable
  95. // layer was created from.
  96. Parent() Layer
  97. // Mount mounts the RWLayer and returns the filesystem path
  98. // the to the writable layer.
  99. Mount(mountLabel string) (string, error)
  100. // Unmount unmounts the RWLayer. This should be called
  101. // for every mount. If there are multiple mount calls
  102. // this operation will only decrement the internal mount counter.
  103. Unmount() error
  104. // Size represents the size of the writable layer
  105. // as calculated by the total size of the files
  106. // changed in the mutable layer.
  107. Size() (int64, error)
  108. // Changes returns the set of changes for the mutable layer
  109. // from the base layer.
  110. Changes() ([]archive.Change, error)
  111. // Metadata returns the low level metadata for the mutable layer
  112. Metadata() (map[string]string, error)
  113. }
  114. // Metadata holds information about a
  115. // read-only layer
  116. type Metadata struct {
  117. // ChainID is the content hash of the layer
  118. ChainID ChainID
  119. // DiffID is the hash of the tar data used to
  120. // create the layer
  121. DiffID DiffID
  122. // Size is the size of the layer and all parents
  123. Size int64
  124. // DiffSize is the size of the top layer
  125. DiffSize int64
  126. }
  127. // MountInit is a function to initialize a
  128. // writable mount. Changes made here will
  129. // not be included in the Tar stream of the
  130. // RWLayer.
  131. type MountInit func(root string) error
  132. // Store represents a backend for managing both
  133. // read-only and read-write layers.
  134. type Store interface {
  135. Register(io.Reader, ChainID) (Layer, error)
  136. Get(ChainID) (Layer, error)
  137. Release(Layer) ([]Metadata, error)
  138. CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error)
  139. GetRWLayer(id string) (RWLayer, error)
  140. GetMountID(id string) (string, error)
  141. ReleaseRWLayer(RWLayer) ([]Metadata, error)
  142. Cleanup() error
  143. DriverStatus() [][2]string
  144. DriverName() string
  145. }
  146. // DescribableStore represents a layer store capable of storing
  147. // descriptors for layers.
  148. type DescribableStore interface {
  149. RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error)
  150. }
  151. // MetadataTransaction represents functions for setting layer metadata
  152. // with a single transaction.
  153. type MetadataTransaction interface {
  154. SetSize(int64) error
  155. SetParent(parent ChainID) error
  156. SetDiffID(DiffID) error
  157. SetCacheID(string) error
  158. SetDescriptor(distribution.Descriptor) error
  159. TarSplitWriter(compressInput bool) (io.WriteCloser, error)
  160. Commit(ChainID) error
  161. Cancel() error
  162. String() string
  163. }
  164. // MetadataStore represents a backend for persisting
  165. // metadata about layers and providing the metadata
  166. // for restoring a Store.
  167. type MetadataStore interface {
  168. // StartTransaction starts an update for new metadata
  169. // which will be used to represent an ID on commit.
  170. StartTransaction() (MetadataTransaction, error)
  171. GetSize(ChainID) (int64, error)
  172. GetParent(ChainID) (ChainID, error)
  173. GetDiffID(ChainID) (DiffID, error)
  174. GetCacheID(ChainID) (string, error)
  175. GetDescriptor(ChainID) (distribution.Descriptor, error)
  176. TarSplitReader(ChainID) (io.ReadCloser, error)
  177. SetMountID(string, string) error
  178. SetInitID(string, string) error
  179. SetMountParent(string, ChainID) error
  180. GetMountID(string) (string, error)
  181. GetInitID(string) (string, error)
  182. GetMountParent(string) (ChainID, error)
  183. // List returns the full list of referenced
  184. // read-only and read-write layers
  185. List() ([]ChainID, []string, error)
  186. Remove(ChainID) error
  187. RemoveMount(string) error
  188. }
  189. // CreateChainID returns ID for a layerDigest slice
  190. func CreateChainID(dgsts []DiffID) ChainID {
  191. return createChainIDFromParent("", dgsts...)
  192. }
  193. func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
  194. if len(dgsts) == 0 {
  195. return parent
  196. }
  197. if parent == "" {
  198. return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
  199. }
  200. // H = "H(n-1) SHA256(n)"
  201. dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
  202. return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
  203. }
  204. // ReleaseAndLog releases the provided layer from the given layer
  205. // store, logging any error and release metadata
  206. func ReleaseAndLog(ls Store, l Layer) {
  207. metadata, err := ls.Release(l)
  208. if err != nil {
  209. logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err)
  210. }
  211. LogReleaseMetadata(metadata)
  212. }
  213. // LogReleaseMetadata logs a metadata array, uses this to
  214. // ensure consistent logging for release metadata
  215. func LogReleaseMetadata(metadatas []Metadata) {
  216. for _, metadata := range metadatas {
  217. logrus.Infof("Layer %s cleaned up", metadata.ChainID)
  218. }
  219. }