github.com/devdivbcp/moby@v17.12.0-ce-rc1.0.20200726071732-2d4bfdc789ad+incompatible/daemon/images/service.go (about) 1 package images // import "github.com/docker/docker/daemon/images" 2 3 import ( 4 "context" 5 "os" 6 "runtime" 7 8 "github.com/docker/docker/container" 9 daemonevents "github.com/docker/docker/daemon/events" 10 "github.com/docker/docker/distribution" 11 "github.com/docker/docker/distribution/metadata" 12 "github.com/docker/docker/distribution/xfer" 13 "github.com/docker/docker/image" 14 "github.com/docker/docker/layer" 15 dockerreference "github.com/docker/docker/reference" 16 "github.com/docker/docker/registry" 17 "github.com/docker/libtrust" 18 "github.com/opencontainers/go-digest" 19 "github.com/pkg/errors" 20 "github.com/sirupsen/logrus" 21 ) 22 23 type containerStore interface { 24 // used by image delete 25 First(container.StoreFilter) *container.Container 26 // used by image prune, and image list 27 List() []*container.Container 28 // TODO: remove, only used for CommitBuildStep 29 Get(string) *container.Container 30 } 31 32 // ImageServiceConfig is the configuration used to create a new ImageService 33 type ImageServiceConfig struct { 34 ContainerStore containerStore 35 DistributionMetadataStore metadata.Store 36 EventsService *daemonevents.Events 37 ImageStore image.Store 38 LayerStores map[string]layer.Store 39 MaxConcurrentDownloads int 40 MaxConcurrentUploads int 41 ReferenceStore dockerreference.Store 42 RegistryService registry.Service 43 TrustKey libtrust.PrivateKey 44 } 45 46 // NewImageService returns a new ImageService from a configuration 47 func NewImageService(config ImageServiceConfig) *ImageService { 48 logrus.Debugf("Max Concurrent Downloads: %d", config.MaxConcurrentDownloads) 49 logrus.Debugf("Max Concurrent Uploads: %d", config.MaxConcurrentUploads) 50 return &ImageService{ 51 containers: config.ContainerStore, 52 distributionMetadataStore: config.DistributionMetadataStore, 53 downloadManager: xfer.NewLayerDownloadManager(config.LayerStores, config.MaxConcurrentDownloads), 54 eventsService: config.EventsService, 55 imageStore: config.ImageStore, 56 layerStores: config.LayerStores, 57 referenceStore: config.ReferenceStore, 58 registryService: config.RegistryService, 59 trustKey: config.TrustKey, 60 uploadManager: xfer.NewLayerUploadManager(config.MaxConcurrentUploads), 61 } 62 } 63 64 // ImageService provides a backend for image management 65 type ImageService struct { 66 containers containerStore 67 distributionMetadataStore metadata.Store 68 downloadManager *xfer.LayerDownloadManager 69 eventsService *daemonevents.Events 70 imageStore image.Store 71 layerStores map[string]layer.Store // By operating system 72 pruneRunning int32 73 referenceStore dockerreference.Store 74 registryService registry.Service 75 trustKey libtrust.PrivateKey 76 uploadManager *xfer.LayerUploadManager 77 } 78 79 // DistributionServices provides daemon image storage services 80 type DistributionServices struct { 81 DownloadManager distribution.RootFSDownloadManager 82 V2MetadataService metadata.V2MetadataService 83 LayerStore layer.Store // TODO: lcow 84 ImageStore image.Store 85 ReferenceStore dockerreference.Store 86 } 87 88 // DistributionServices return services controlling daemon image storage 89 func (i *ImageService) DistributionServices() DistributionServices { 90 return DistributionServices{ 91 DownloadManager: i.downloadManager, 92 V2MetadataService: metadata.NewV2MetadataService(i.distributionMetadataStore), 93 LayerStore: i.layerStores[runtime.GOOS], 94 ImageStore: i.imageStore, 95 ReferenceStore: i.referenceStore, 96 } 97 } 98 99 // CountImages returns the number of images stored by ImageService 100 // called from info.go 101 func (i *ImageService) CountImages() int { 102 return i.imageStore.Len() 103 } 104 105 // Children returns the children image.IDs for a parent image. 106 // called from list.go to filter containers 107 // TODO: refactor to expose an ancestry for image.ID? 108 func (i *ImageService) Children(id image.ID) []image.ID { 109 return i.imageStore.Children(id) 110 } 111 112 // CreateLayer creates a filesystem layer for a container. 113 // called from create.go 114 // TODO: accept an opt struct instead of container? 115 func (i *ImageService) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) { 116 var layerID layer.ChainID 117 if container.ImageID != "" { 118 img, err := i.imageStore.Get(container.ImageID) 119 if err != nil { 120 return nil, err 121 } 122 layerID = img.RootFS.ChainID() 123 } 124 125 rwLayerOpts := &layer.CreateRWLayerOpts{ 126 MountLabel: container.MountLabel, 127 InitFunc: initFunc, 128 StorageOpt: container.HostConfig.StorageOpt, 129 } 130 131 // Indexing by OS is safe here as validation of OS has already been performed in create() (the only 132 // caller), and guaranteed non-nil 133 return i.layerStores[container.OS].CreateRWLayer(container.ID, layerID, rwLayerOpts) 134 } 135 136 // GetLayerByID returns a layer by ID and operating system 137 // called from daemon.go Daemon.restore(), and Daemon.containerExport() 138 func (i *ImageService) GetLayerByID(cid string, os string) (layer.RWLayer, error) { 139 return i.layerStores[os].GetRWLayer(cid) 140 } 141 142 // LayerStoreStatus returns the status for each layer store 143 // called from info.go 144 func (i *ImageService) LayerStoreStatus() map[string][][2]string { 145 result := make(map[string][][2]string) 146 for os, store := range i.layerStores { 147 result[os] = store.DriverStatus() 148 } 149 return result 150 } 151 152 // GetLayerMountID returns the mount ID for a layer 153 // called from daemon.go Daemon.Shutdown(), and Daemon.Cleanup() (cleanup is actually continerCleanup) 154 // TODO: needs to be refactored to Unmount (see callers), or removed and replaced 155 // with GetLayerByID 156 func (i *ImageService) GetLayerMountID(cid string, os string) (string, error) { 157 return i.layerStores[os].GetMountID(cid) 158 } 159 160 // Cleanup resources before the process is shutdown. 161 // called from daemon.go Daemon.Shutdown() 162 func (i *ImageService) Cleanup() { 163 for os, ls := range i.layerStores { 164 if ls != nil { 165 if err := ls.Cleanup(); err != nil { 166 logrus.Errorf("Error during layer Store.Cleanup(): %v %s", err, os) 167 } 168 } 169 } 170 } 171 172 // GraphDriverForOS returns the name of the graph drvier 173 // moved from Daemon.GraphDriverName, used by: 174 // - newContainer 175 // - to report an error in Daemon.Mount(container) 176 func (i *ImageService) GraphDriverForOS(os string) string { 177 return i.layerStores[os].DriverName() 178 } 179 180 // ReleaseLayer releases a layer allowing it to be removed 181 // called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport() 182 func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer, containerOS string) error { 183 metadata, err := i.layerStores[containerOS].ReleaseRWLayer(rwlayer) 184 layer.LogReleaseMetadata(metadata) 185 if err != nil && err != layer.ErrMountDoesNotExist && !os.IsNotExist(errors.Cause(err)) { 186 return errors.Wrapf(err, "driver %q failed to remove root filesystem", 187 i.layerStores[containerOS].DriverName()) 188 } 189 return nil 190 } 191 192 // LayerDiskUsage returns the number of bytes used by layer stores 193 // called from disk_usage.go 194 func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) { 195 var allLayersSize int64 196 layerRefs := i.getLayerRefs() 197 for _, ls := range i.layerStores { 198 allLayers := ls.Map() 199 for _, l := range allLayers { 200 select { 201 case <-ctx.Done(): 202 return allLayersSize, ctx.Err() 203 default: 204 size, err := l.DiffSize() 205 if err == nil { 206 if _, ok := layerRefs[l.ChainID()]; ok { 207 allLayersSize += size 208 } 209 } else { 210 logrus.Warnf("failed to get diff size for layer %v", l.ChainID()) 211 } 212 } 213 } 214 } 215 return allLayersSize, nil 216 } 217 218 func (i *ImageService) getLayerRefs() map[layer.ChainID]int { 219 tmpImages := i.imageStore.Map() 220 layerRefs := map[layer.ChainID]int{} 221 for id, img := range tmpImages { 222 dgst := digest.Digest(id) 223 if len(i.referenceStore.References(dgst)) == 0 && len(i.imageStore.Children(id)) != 0 { 224 continue 225 } 226 227 rootFS := *img.RootFS 228 rootFS.DiffIDs = nil 229 for _, id := range img.RootFS.DiffIDs { 230 rootFS.Append(id) 231 chid := rootFS.ChainID() 232 layerRefs[chid]++ 233 } 234 } 235 236 return layerRefs 237 } 238 239 // UpdateConfig values 240 // 241 // called from reload.go 242 func (i *ImageService) UpdateConfig(maxDownloads, maxUploads *int) { 243 if i.downloadManager != nil && maxDownloads != nil { 244 i.downloadManager.SetConcurrency(*maxDownloads) 245 } 246 if i.uploadManager != nil && maxUploads != nil { 247 i.uploadManager.SetConcurrency(*maxUploads) 248 } 249 }