123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- // Package layer is package for managing read-only
- // and read-write mounts on the union file system
- // driver. Read-only mounts are referenced using a
- // content hash and are protected from mutation in
- // the exposed interface. The tar format is used
- // to create read-only layers and export both
- // read-only and writable layers. The exported
- // tar data for a read-only layer should match
- // the tar used to create the layer.
- package layer
- import (
- "errors"
- "io"
- "github.com/Sirupsen/logrus"
- "github.com/docker/distribution"
- "github.com/docker/distribution/digest"
- "github.com/docker/docker/pkg/archive"
- )
- var (
- // ErrLayerDoesNotExist is used when an operation is
- // attempted on a layer which does not exist.
- ErrLayerDoesNotExist = errors.New("layer does not exist")
- // ErrLayerNotRetained is used when a release is
- // attempted on a layer which is not retained.
- ErrLayerNotRetained = errors.New("layer not retained")
- // ErrMountDoesNotExist is used when an operation is
- // attempted on a mount layer which does not exist.
- ErrMountDoesNotExist = errors.New("mount does not exist")
- // ErrMountNameConflict is used when a mount is attempted
- // to be created but there is already a mount with the name
- // used for creation.
- ErrMountNameConflict = errors.New("mount already exists with name")
- // ErrActiveMount is used when an operation on a
- // mount is attempted but the layer is still
- // mounted and the operation cannot be performed.
- ErrActiveMount = errors.New("mount still active")
- // ErrNotMounted is used when requesting an active
- // mount but the layer is not mounted.
- ErrNotMounted = errors.New("not mounted")
- // ErrMaxDepthExceeded is used when a layer is attempted
- // to be created which would result in a layer depth
- // greater than the 125 max.
- ErrMaxDepthExceeded = errors.New("max depth exceeded")
- // ErrNotSupported is used when the action is not supported
- // on the current platform
- ErrNotSupported = errors.New("not support on this platform")
- )
- // ChainID is the content-addressable ID of a layer.
- type ChainID digest.Digest
- // String returns a string rendition of a layer ID
- func (id ChainID) String() string {
- return string(id)
- }
- // DiffID is the hash of an individual layer tar.
- type DiffID digest.Digest
- // String returns a string rendition of a layer DiffID
- func (diffID DiffID) String() string {
- return string(diffID)
- }
- // TarStreamer represents an object which may
- // have its contents exported as a tar stream.
- type TarStreamer interface {
- // TarStream returns a tar archive stream
- // for the contents of a layer.
- TarStream() (io.ReadCloser, error)
- }
- // Layer represents a read-only layer
- type Layer interface {
- TarStreamer
- // ChainID returns the content hash of the entire layer chain. The hash
- // chain is made up of DiffID of top layer and all of its parents.
- ChainID() ChainID
- // DiffID returns the content hash of the layer
- // tar stream used to create this layer.
- DiffID() DiffID
- // Parent returns the next layer in the layer chain.
- Parent() Layer
- // Size returns the size of the entire layer chain. The size
- // is calculated from the total size of all files in the layers.
- Size() (int64, error)
- // DiffSize returns the size difference of the top layer
- // from parent layer.
- DiffSize() (int64, error)
- // Metadata returns the low level storage metadata associated
- // with layer.
- Metadata() (map[string]string, error)
- }
- // RWLayer represents a layer which is
- // read and writable
- type RWLayer interface {
- TarStreamer
- // Name of mounted layer
- Name() string
- // Parent returns the layer which the writable
- // layer was created from.
- Parent() Layer
- // Mount mounts the RWLayer and returns the filesystem path
- // the to the writable layer.
- Mount(mountLabel string) (string, error)
- // Unmount unmounts the RWLayer. This should be called
- // for every mount. If there are multiple mount calls
- // this operation will only decrement the internal mount counter.
- Unmount() error
- // Size represents the size of the writable layer
- // as calculated by the total size of the files
- // changed in the mutable layer.
- Size() (int64, error)
- // Changes returns the set of changes for the mutable layer
- // from the base layer.
- Changes() ([]archive.Change, error)
- // Metadata returns the low level metadata for the mutable layer
- Metadata() (map[string]string, error)
- }
- // Metadata holds information about a
- // read-only layer
- type Metadata struct {
- // ChainID is the content hash of the layer
- ChainID ChainID
- // DiffID is the hash of the tar data used to
- // create the layer
- DiffID DiffID
- // Size is the size of the layer and all parents
- Size int64
- // DiffSize is the size of the top layer
- DiffSize int64
- }
- // MountInit is a function to initialize a
- // writable mount. Changes made here will
- // not be included in the Tar stream of the
- // RWLayer.
- type MountInit func(root string) error
- // Store represents a backend for managing both
- // read-only and read-write layers.
- type Store interface {
- Register(io.Reader, ChainID) (Layer, error)
- Get(ChainID) (Layer, error)
- Release(Layer) ([]Metadata, error)
- CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error)
- GetRWLayer(id string) (RWLayer, error)
- GetMountID(id string) (string, error)
- ReleaseRWLayer(RWLayer) ([]Metadata, error)
- Cleanup() error
- DriverStatus() [][2]string
- DriverName() string
- }
- // DescribableStore represents a layer store capable of storing
- // descriptors for layers.
- type DescribableStore interface {
- RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error)
- }
- // MetadataTransaction represents functions for setting layer metadata
- // with a single transaction.
- type MetadataTransaction interface {
- SetSize(int64) error
- SetParent(parent ChainID) error
- SetDiffID(DiffID) error
- SetCacheID(string) error
- SetDescriptor(distribution.Descriptor) error
- TarSplitWriter(compressInput bool) (io.WriteCloser, error)
- Commit(ChainID) error
- Cancel() error
- String() string
- }
- // MetadataStore represents a backend for persisting
- // metadata about layers and providing the metadata
- // for restoring a Store.
- type MetadataStore interface {
- // StartTransaction starts an update for new metadata
- // which will be used to represent an ID on commit.
- StartTransaction() (MetadataTransaction, error)
- GetSize(ChainID) (int64, error)
- GetParent(ChainID) (ChainID, error)
- GetDiffID(ChainID) (DiffID, error)
- GetCacheID(ChainID) (string, error)
- GetDescriptor(ChainID) (distribution.Descriptor, error)
- TarSplitReader(ChainID) (io.ReadCloser, error)
- SetMountID(string, string) error
- SetInitID(string, string) error
- SetMountParent(string, ChainID) error
- GetMountID(string) (string, error)
- GetInitID(string) (string, error)
- GetMountParent(string) (ChainID, error)
- // List returns the full list of referenced
- // read-only and read-write layers
- List() ([]ChainID, []string, error)
- Remove(ChainID) error
- RemoveMount(string) error
- }
- // CreateChainID returns ID for a layerDigest slice
- func CreateChainID(dgsts []DiffID) ChainID {
- return createChainIDFromParent("", dgsts...)
- }
- func createChainIDFromParent(parent ChainID, dgsts ...DiffID) ChainID {
- if len(dgsts) == 0 {
- return parent
- }
- if parent == "" {
- return createChainIDFromParent(ChainID(dgsts[0]), dgsts[1:]...)
- }
- // H = "H(n-1) SHA256(n)"
- dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0])))
- return createChainIDFromParent(ChainID(dgst), dgsts[1:]...)
- }
- // ReleaseAndLog releases the provided layer from the given layer
- // store, logging any error and release metadata
- func ReleaseAndLog(ls Store, l Layer) {
- metadata, err := ls.Release(l)
- if err != nil {
- logrus.Errorf("Error releasing layer %s: %v", l.ChainID(), err)
- }
- LogReleaseMetadata(metadata)
- }
- // LogReleaseMetadata logs a metadata array, uses this to
- // ensure consistent logging for release metadata
- func LogReleaseMetadata(metadatas []Metadata) {
- for _, metadata := range metadatas {
- logrus.Infof("Layer %s cleaned up", metadata.ChainID)
- }
- }
|