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 }