소스 검색

Implement GetLayerFolders for the containerd image store

The existing API ImageService.GetLayerFolders didn't have access to the
ID of the container, and once we have that, the snapshotter Mounts API
provides all the information we need here.

Signed-off-by: Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paul "TBBle" Hampson 1 년 전
부모
커밋
66325f7271

+ 0 - 6
daemon/containerd/service.go

@@ -19,7 +19,6 @@ import (
 	dimages "github.com/docker/docker/daemon/images"
 	"github.com/docker/docker/daemon/snapshotter"
 	"github.com/docker/docker/errdefs"
-	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/registry"
@@ -156,11 +155,6 @@ func (i *ImageService) UpdateConfig(maxDownloads, maxUploads int) {
 	log.G(context.TODO()).Warn("max downloads and uploads is not yet implemented with the containerd store")
 }
 
-// GetLayerFolders returns the layer folders from an image RootFS.
-func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
-	return nil, errdefs.NotImplemented(errors.New("not implemented"))
-}
-
 // GetContainerLayerSize returns the real size & virtual size of the container.
 func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error) {
 	ctr := i.containers.Get(containerID)

+ 15 - 0
daemon/containerd/service_unix.go

@@ -0,0 +1,15 @@
+//go:build linux || freebsd
+
+package containerd
+
+import (
+	"github.com/docker/docker/errdefs"
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
+	"github.com/pkg/errors"
+)
+
+// GetLayerFolders returns the layer folders from an image RootFS.
+func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer, containerID string) ([]string, error) {
+	return nil, errdefs.NotImplemented(errors.New("not implemented"))
+}

+ 31 - 0
daemon/containerd/service_windows.go

@@ -0,0 +1,31 @@
+package containerd
+
+import (
+	"context"
+
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
+	"github.com/pkg/errors"
+)
+
+// GetLayerFolders returns the layer folders from an image RootFS.
+func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer, containerID string) ([]string, error) {
+	if rwLayer != nil {
+		return nil, errors.New("RWLayer is unexpectedly not nil")
+	}
+
+	snapshotter := i.client.SnapshotService(i.StorageDriver())
+	mounts, err := snapshotter.Mounts(context.TODO(), containerID)
+	if err != nil {
+		return nil, errors.Wrapf(err, "snapshotter.Mounts failed: container %s", containerID)
+	}
+
+	// This is the same logic used by the hcsshim containerd runtime shim's createInternal
+	// to convert an array of Mounts into windows layers.
+	// See https://github.com/microsoft/hcsshim/blob/release/0.11/cmd/containerd-shim-runhcs-v1/service_internal.go
+	parentPaths, err := mounts[0].GetParentPaths()
+	if err != nil {
+		return nil, errors.Wrapf(err, "GetParentPaths failed: container %s", containerID)
+	}
+	return append(parentPaths, mounts[0].Source), nil
+}

+ 1 - 1
daemon/image_service.go

@@ -65,7 +65,7 @@ type ImageService interface {
 
 	// Windows specific
 
-	GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error)
+	GetLayerFolders(img *image.Image, rwLayer layer.RWLayer, containerID string) ([]string, error)
 
 	// Build
 

+ 1 - 1
daemon/images/image_unix.go

@@ -11,7 +11,7 @@ import (
 )
 
 // GetLayerFolders returns the layer folders from an image RootFS
-func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
+func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer, containerID string) ([]string, error) {
 	// Windows specific
 	panic("not implemented")
 }

+ 1 - 1
daemon/images/image_windows.go

@@ -15,7 +15,7 @@ func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID st
 }
 
 // GetLayerFolders returns the layer folders from an image RootFS
-func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
+func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer, containerID string) ([]string, error) {
 	folders := []string{}
 	rd := len(img.RootFS.DiffIDs)
 	for index := 1; index <= rd; index++ {

+ 2 - 2
daemon/oci_windows.go

@@ -138,9 +138,9 @@ func (daemon *Daemon) createSpec(ctx context.Context, daemonCfg *configStore, c
 		}
 	}
 	s.Process.User.Username = c.Config.User
-	s.Windows.LayerFolders, err = daemon.imageService.GetLayerFolders(img, c.RWLayer)
+	s.Windows.LayerFolders, err = daemon.imageService.GetLayerFolders(img, c.RWLayer, c.ID)
 	if err != nil {
-		return nil, errors.Wrapf(err, "container %s", c.ID)
+		return nil, errors.Wrapf(err, "GetLayerFolders failed: container %s", c.ID)
 	}
 
 	// Get endpoints for the libnetwork allocated networks to the container