github.com/jingleWang/moby@v1.13.1/layer/layer.go (about)

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