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