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