github.com/rish1988/moby@v25.0.2+incompatible/daemon/containerd/service.go (about)

     1  package containerd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync/atomic"
     7  
     8  	"github.com/containerd/containerd"
     9  	"github.com/containerd/containerd/content"
    10  	cerrdefs "github.com/containerd/containerd/errdefs"
    11  	"github.com/containerd/containerd/images"
    12  	"github.com/containerd/containerd/plugin"
    13  	"github.com/containerd/containerd/remotes/docker"
    14  	"github.com/containerd/containerd/snapshots"
    15  	"github.com/containerd/log"
    16  	"github.com/distribution/reference"
    17  	"github.com/docker/docker/container"
    18  	daemonevents "github.com/docker/docker/daemon/events"
    19  	dimages "github.com/docker/docker/daemon/images"
    20  	"github.com/docker/docker/daemon/snapshotter"
    21  	"github.com/docker/docker/errdefs"
    22  	"github.com/docker/docker/layer"
    23  	"github.com/docker/docker/pkg/idtools"
    24  	"github.com/docker/docker/registry"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  // ImageService implements daemon.ImageService
    29  type ImageService struct {
    30  	client          *containerd.Client
    31  	images          images.Store
    32  	content         content.Store
    33  	containers      container.Store
    34  	snapshotter     string
    35  	registryHosts   docker.RegistryHosts
    36  	registryService registryResolver
    37  	eventsService   *daemonevents.Events
    38  	pruneRunning    atomic.Bool
    39  	refCountMounter snapshotter.Mounter
    40  	idMapping       idtools.IdentityMapping
    41  }
    42  
    43  type registryResolver interface {
    44  	IsInsecureRegistry(host string) bool
    45  	ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error)
    46  	LookupPullEndpoints(hostname string) ([]registry.APIEndpoint, error)
    47  	LookupPushEndpoints(hostname string) ([]registry.APIEndpoint, error)
    48  }
    49  
    50  type ImageServiceConfig struct {
    51  	Client          *containerd.Client
    52  	Containers      container.Store
    53  	Snapshotter     string
    54  	RegistryHosts   docker.RegistryHosts
    55  	Registry        registryResolver
    56  	EventsService   *daemonevents.Events
    57  	RefCountMounter snapshotter.Mounter
    58  	IDMapping       idtools.IdentityMapping
    59  }
    60  
    61  // NewService creates a new ImageService.
    62  func NewService(config ImageServiceConfig) *ImageService {
    63  	return &ImageService{
    64  		client:          config.Client,
    65  		images:          config.Client.ImageService(),
    66  		content:         config.Client.ContentStore(),
    67  		containers:      config.Containers,
    68  		snapshotter:     config.Snapshotter,
    69  		registryHosts:   config.RegistryHosts,
    70  		registryService: config.Registry,
    71  		eventsService:   config.EventsService,
    72  		refCountMounter: config.RefCountMounter,
    73  		idMapping:       config.IDMapping,
    74  	}
    75  }
    76  
    77  // DistributionServices return services controlling daemon image storage.
    78  func (i *ImageService) DistributionServices() dimages.DistributionServices {
    79  	return dimages.DistributionServices{}
    80  }
    81  
    82  // CountImages returns the number of images stored by ImageService
    83  // called from info.go
    84  func (i *ImageService) CountImages(ctx context.Context) int {
    85  	imgs, err := i.client.ListImages(ctx)
    86  	if err != nil {
    87  		return 0
    88  	}
    89  
    90  	return len(imgs)
    91  }
    92  
    93  // CreateLayer creates a filesystem layer for a container.
    94  // called from create.go
    95  // TODO: accept an opt struct instead of container?
    96  func (i *ImageService) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) {
    97  	return nil, errdefs.NotImplemented(errdefs.NotImplemented(errors.New("not implemented")))
    98  }
    99  
   100  // LayerStoreStatus returns the status for each layer store
   101  // called from info.go
   102  func (i *ImageService) LayerStoreStatus() [][2]string {
   103  	// TODO(thaJeztah) do we want to add more details about the driver here?
   104  	return [][2]string{
   105  		{"driver-type", string(plugin.SnapshotPlugin)},
   106  	}
   107  }
   108  
   109  // GetLayerMountID returns the mount ID for a layer
   110  // called from daemon.go Daemon.Shutdown(), and Daemon.Cleanup() (cleanup is actually continerCleanup)
   111  // TODO: needs to be refactored to Unmount (see callers), or removed and replaced with GetLayerByID
   112  func (i *ImageService) GetLayerMountID(cid string) (string, error) {
   113  	return "", errdefs.NotImplemented(errors.New("not implemented"))
   114  }
   115  
   116  // Cleanup resources before the process is shutdown.
   117  // called from daemon.go Daemon.Shutdown()
   118  func (i *ImageService) Cleanup() error {
   119  	return nil
   120  }
   121  
   122  // StorageDriver returns the name of the default storage-driver (snapshotter)
   123  // used by the ImageService.
   124  func (i *ImageService) StorageDriver() string {
   125  	return i.snapshotter
   126  }
   127  
   128  // ReleaseLayer releases a layer allowing it to be removed
   129  // called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
   130  func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
   131  	return errdefs.NotImplemented(errors.New("not implemented"))
   132  }
   133  
   134  // LayerDiskUsage returns the number of bytes used by layer stores
   135  // called from disk_usage.go
   136  func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) {
   137  	var allLayersSize int64
   138  	// TODO(thaJeztah): do we need to take multiple snapshotters into account? See https://github.com/moby/moby/issues/45273
   139  	snapshotter := i.client.SnapshotService(i.snapshotter)
   140  	snapshotter.Walk(ctx, func(ctx context.Context, info snapshots.Info) error {
   141  		usage, err := snapshotter.Usage(ctx, info.Name)
   142  		if err != nil {
   143  			return err
   144  		}
   145  		allLayersSize += usage.Size
   146  		return nil
   147  	})
   148  	return allLayersSize, nil
   149  }
   150  
   151  // UpdateConfig values
   152  //
   153  // called from reload.go
   154  func (i *ImageService) UpdateConfig(maxDownloads, maxUploads int) {
   155  	log.G(context.TODO()).Warn("max downloads and uploads is not yet implemented with the containerd store")
   156  }
   157  
   158  // GetContainerLayerSize returns the real size & virtual size of the container.
   159  func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error) {
   160  	ctr := i.containers.Get(containerID)
   161  	if ctr == nil {
   162  		return 0, 0, nil
   163  	}
   164  
   165  	snapshotter := i.client.SnapshotService(ctr.Driver)
   166  	rwLayerUsage, err := snapshotter.Usage(ctx, containerID)
   167  	if err != nil {
   168  		if cerrdefs.IsNotFound(err) {
   169  			return 0, 0, errdefs.NotFound(fmt.Errorf("rw layer snapshot not found for container %s", containerID))
   170  		}
   171  		return 0, 0, errdefs.System(errors.Wrapf(err, "snapshotter.Usage failed for %s", containerID))
   172  	}
   173  
   174  	unpackedUsage, err := calculateSnapshotParentUsage(ctx, snapshotter, containerID)
   175  	if err != nil {
   176  		if cerrdefs.IsNotFound(err) {
   177  			log.G(ctx).WithField("ctr", containerID).Warn("parent of container snapshot no longer present")
   178  		} else {
   179  			log.G(ctx).WithError(err).WithField("ctr", containerID).Warn("unexpected error when calculating usage of the parent snapshots")
   180  		}
   181  	}
   182  	log.G(ctx).WithFields(log.Fields{
   183  		"rwLayerUsage": rwLayerUsage.Size,
   184  		"unpacked":     unpackedUsage.Size,
   185  	}).Debug("GetContainerLayerSize")
   186  
   187  	// TODO(thaJeztah): include content-store size for the image (similar to "GET /images/json")
   188  	return rwLayerUsage.Size, rwLayerUsage.Size + unpackedUsage.Size, nil
   189  }