bbeb859b |
// Package layer is package for managing read-only |
500e77ba |
// and read-write mounts on the union file system |
927b334e |
// driver. Read-only mounts are referenced using a |
500e77ba |
// content hash and are protected from mutation in
// the exposed interface. The tar format is used |
bbeb859b |
// to create read-only layers and export both
// read-only and writable layers. The exported
// tar data for a read-only layer should match |
500e77ba |
// the tar used to create the layer.
package layer
import (
"errors"
"io"
|
05bd0435 |
"github.com/docker/distribution" |
500e77ba |
"github.com/docker/docker/pkg/archive" |
7a7357da |
"github.com/docker/docker/pkg/containerfs" |
7a855799 |
"github.com/opencontainers/go-digest" |
1009e6a4 |
"github.com/sirupsen/logrus" |
500e77ba |
)
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")
|
d04fa49a |
// 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")
|
500e77ba |
// 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") |
65d79e3e |
|
950073aa |
// ErrNotSupported is used when the action is not supported |
0380fbff |
// on the current host operating system.
ErrNotSupported = errors.New("not support on this host operating system") |
500e77ba |
)
// 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. |
21278efa |
TarStream() (io.ReadCloser, error) |
500e77ba |
}
|
bbeb859b |
// Layer represents a read-only layer |
500e77ba |
type Layer interface {
TarStreamer
|
8625d253 |
// TarStreamFrom returns a tar archive stream for all the layer chain with
// arbitrary depth.
TarStreamFrom(ChainID) (io.ReadCloser, error)
|
500e77ba |
// 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
|
d04fa49a |
// Name of mounted layer
Name() string |
500e77ba |
// Parent returns the layer which the writable
// layer was created from.
Parent() Layer
|
d04fa49a |
// Mount mounts the RWLayer and returns the filesystem path
// the to the writable layer. |
7a7357da |
Mount(mountLabel string) (containerfs.ContainerFS, error) |
d04fa49a |
// 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
|
500e77ba |
// 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) |
d04fa49a |
// 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) |
500e77ba |
}
// Metadata holds information about a |
bbeb859b |
// read-only layer |
500e77ba |
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. |
7a7357da |
type MountInit func(root containerfs.ContainerFS) error |
500e77ba |
|
f7f3d342 |
// CreateRWLayerOpts contains optional arguments to be passed to CreateRWLayer
type CreateRWLayerOpts struct {
MountLabel string
InitFunc MountInit
StorageOpt map[string]string
}
|
500e77ba |
// Store represents a backend for managing both
// read-only and read-write layers.
type Store interface { |
afd305c4 |
Register(io.Reader, ChainID) (Layer, error) |
500e77ba |
Get(ChainID) (Layer, error) |
148aef91 |
Map() map[ChainID]Layer |
500e77ba |
Release(Layer) ([]Metadata, error)
|
afd305c4 |
CreateRWLayer(id string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error) |
d04fa49a |
GetRWLayer(id string) (RWLayer, error) |
9c4570a9 |
GetMountID(id string) (string, error) |
d04fa49a |
ReleaseRWLayer(RWLayer) ([]Metadata, error) |
f5916b10 |
Cleanup() error |
afd305c4 |
DriverStatus() [][2]string
DriverName() string |
500e77ba |
}
|
2c60430a |
// DescribableStore represents a layer store capable of storing
// descriptors for layers.
type DescribableStore interface { |
afd305c4 |
RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error) |
2c60430a |
}
|
500e77ba |
// 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 |
2c60430a |
SetDescriptor(distribution.Descriptor) error |
0cba7740 |
setOS(string) error |
a8f88ef4 |
TarSplitWriter(compressInput bool) (io.WriteCloser, error) |
500e77ba |
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) |
2c60430a |
GetDescriptor(ChainID) (distribution.Descriptor, error) |
0cba7740 |
getOS(ChainID) (string, error) |
500e77ba |
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)
|
927b334e |
// List returns the full list of referenced |
500e77ba |
// 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)" |
c168a005 |
dgst := digest.FromBytes([]byte(string(parent) + " " + string(dgsts[0]))) |
500e77ba |
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)
}
|
bbeb859b |
// LogReleaseMetadata logs a metadata array, uses this to |
500e77ba |
// ensure consistent logging for release metadata
func LogReleaseMetadata(metadatas []Metadata) {
for _, metadata := range metadatas {
logrus.Infof("Layer %s cleaned up", metadata.ChainID)
}
} |