gitee.com/bomy/docker.git@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 }