layer.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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/docker/distribution"
  15. "github.com/docker/docker/pkg/archive"
  16. "github.com/docker/docker/pkg/containerfs"
  17. "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 platform
  47. ErrNotSupported = errors.New("not support on this platform")
  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. // Platform is the platform of a layer
  56. type Platform string
  57. // String returns a string rendition of layers target platform
  58. func (id Platform) String() string {
  59. return string(id)
  60. }
  61. // DiffID is the hash of an individual layer tar.
  62. type DiffID digest.Digest
  63. // String returns a string rendition of a layer DiffID
  64. func (diffID DiffID) String() string {
  65. return string(diffID)
  66. }
  67. // TarStreamer represents an object which may
  68. // have its contents exported as a tar stream.
  69. type TarStreamer interface {
  70. // TarStream returns a tar archive stream
  71. // for the contents of a layer.
  72. TarStream() (io.ReadCloser, error)
  73. }
  74. // Layer represents a read-only layer
  75. type Layer interface {
  76. TarStreamer
  77. // TarStreamFrom returns a tar archive stream for all the layer chain with
  78. // arbitrary depth.
  79. TarStreamFrom(ChainID) (io.ReadCloser, error)
  80. // ChainID returns the content hash of the entire layer chain. The hash
  81. // chain is made up of DiffID of top layer and all of its parents.
  82. ChainID() ChainID
  83. // DiffID returns the content hash of the layer
  84. // tar stream used to create this layer.
  85. DiffID() DiffID
  86. // Parent returns the next layer in the layer chain.
  87. Parent() Layer
  88. // Platform returns the platform of the layer
  89. Platform() Platform
  90. // Size returns the size of the entire layer chain. The size
  91. // is calculated from the total size of all files in the layers.
  92. Size() (int64, error)
  93. // DiffSize returns the size difference of the top layer
  94. // from parent layer.
  95. DiffSize() (int64, error)
  96. // Metadata returns the low level storage metadata associated
  97. // with layer.
  98. Metadata() (map[string]string, error)
  99. }
  100. // RWLayer represents a layer which is
  101. // read and writable
  102. type RWLayer interface {
  103. TarStreamer
  104. // Name of mounted layer
  105. Name() string
  106. // Parent returns the layer which the writable
  107. // layer was created from.
  108. Parent() Layer
  109. // Mount mounts the RWLayer and returns the filesystem path
  110. // the to the writable layer.
  111. Mount(mountLabel string) (containerfs.ContainerFS, error)
  112. // Unmount unmounts the RWLayer. This should be called
  113. // for every mount. If there are multiple mount calls
  114. // this operation will only decrement the internal mount counter.
  115. Unmount() error
  116. // Size represents the size of the writable layer
  117. // as calculated by the total size of the files
  118. // changed in the mutable layer.
  119. Size() (int64, error)
  120. // Changes returns the set of changes for the mutable layer
  121. // from the base layer.
  122. Changes() ([]archive.Change, error)
  123. // Metadata returns the low level metadata for the mutable layer
  124. Metadata() (map[string]string, error)
  125. }
  126. // Metadata holds information about a
  127. // read-only layer
  128. type Metadata struct {
  129. // ChainID is the content hash of the layer
  130. ChainID ChainID
  131. // DiffID is the hash of the tar data used to
  132. // create the layer
  133. DiffID DiffID
  134. // Size is the size of the layer and all parents
  135. Size int64
  136. // DiffSize is the size of the top layer
  137. DiffSize int64
  138. }
  139. // MountInit is a function to initialize a
  140. // writable mount. Changes made here will
  141. // not be included in the Tar stream of the
  142. // RWLayer.
  143. type MountInit func(root containerfs.ContainerFS) error
  144. // CreateRWLayerOpts contains optional arguments to be passed to CreateRWLayer
  145. type CreateRWLayerOpts struct {
  146. MountLabel string
  147. InitFunc MountInit
  148. StorageOpt map[string]string
  149. }
  150. // Store represents a backend for managing both
  151. // read-only and read-write layers.
  152. type Store interface {
  153. Register(io.Reader, ChainID, Platform) (Layer, error)
  154. Get(ChainID) (Layer, error)
  155. Map() map[ChainID]Layer
  156. Release(Layer) ([]Metadata, error)
  157. CreateRWLayer(id string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error)
  158. GetRWLayer(id string) (RWLayer, error)
  159. GetMountID(id string) (string, error)
  160. ReleaseRWLayer(RWLayer) ([]Metadata, error)
  161. Cleanup() error
  162. DriverStatus() [][2]string
  163. DriverName() string
  164. }
  165. // DescribableStore represents a layer store capable of storing
  166. // descriptors for layers.
  167. type DescribableStore interface {
  168. RegisterWithDescriptor(io.Reader, ChainID, Platform, distribution.Descriptor) (Layer, error)
  169. }
  170. // MetadataTransaction represents functions for setting layer metadata
  171. // with a single transaction.
  172. type MetadataTransaction interface {
  173. SetSize(int64) error
  174. SetParent(parent ChainID) error
  175. SetDiffID(DiffID) error
  176. SetCacheID(string) error
  177. SetDescriptor(distribution.Descriptor) error
  178. SetPlatform(Platform) error
  179. TarSplitWriter(compressInput bool) (io.WriteCloser, error)
  180. Commit(ChainID) error
  181. Cancel() error
  182. String() string
  183. }
  184. // MetadataStore represents a backend for persisting
  185. // metadata about layers and providing the metadata
  186. // for restoring a Store.
  187. type MetadataStore interface {
  188. // StartTransaction starts an update for new metadata
  189. // which will be used to represent an ID on commit.
  190. StartTransaction() (MetadataTransaction, error)
  191. GetSize(ChainID) (int64, error)
  192. GetParent(ChainID) (ChainID, error)
  193. GetDiffID(ChainID) (DiffID, error)
  194. GetCacheID(ChainID) (string, error)
  195. GetDescriptor(ChainID) (distribution.Descriptor, error)
  196. GetPlatform(ChainID) (Platform, error)
  197. TarSplitReader(ChainID) (io.ReadCloser, error)
  198. SetMountID(string, string) error
  199. SetInitID(string, string) error
  200. SetMountParent(string, ChainID) error
  201. GetMountID(string) (string, error)
  202. GetInitID(string) (string, error)
  203. GetMountParent(string) (ChainID, error)
  204. // List returns the full list of referenced
  205. // read-only and read-write layers
  206. List() ([]ChainID, []string, error)
  207. Remove(ChainID) error
  208. RemoveMount(string) error
  209. }
  210. // CreateChainID returns ID for a layerDigest slice
  211. func CreateChainID(dgsts []DiffID) ChainID {
  212. return createChainIDFromParent("", dgsts...)
  213. }
  214. func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
  215. if len(dgsts) == 0 {
  216. return parent
  217. }
  218. if parent == "" {
  219. return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
  220. }
  221. // H = "H(n-1) SHA256(n)"
  222. dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
  223. return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
  224. }
  225. // ReleaseAndLog releases the provided layer from the given layer
  226. // store, logging any error and release metadata
  227. func ReleaseAndLog(ls Store, l Layer) {
  228. metadata, err := ls.Release(l)
  229. if err != nil {
  230. logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err)
  231. }
  232. LogReleaseMetadata(metadata)
  233. }
  234. // LogReleaseMetadata logs a metadata array, uses this to
  235. // ensure consistent logging for release metadata
  236. func LogReleaseMetadata(metadatas []Metadata) {
  237. for _, metadata := range metadatas {
  238. logrus.Infof("Layer %s cleaned up", metadata.ChainID)
  239. }
  240. }