remove GetLayerByID from ImageService interface
Co-authored-by: Nicolas De Loof <nicolas.deloof@gmail.com> Co-authored-by: Paweł Gronowski <pawel.gronowski@docker.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
a1f6a70522
commit
06619763a2
9 changed files with 68 additions and 50 deletions
|
@ -25,7 +25,7 @@ type execBackend interface {
|
|||
type copyBackend interface {
|
||||
ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error)
|
||||
ContainerCopy(name string, res string) (io.ReadCloser, error)
|
||||
ContainerExport(name string, out io.Writer) error
|
||||
ContainerExport(ctx context.Context, name string, out io.Writer) error
|
||||
ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error
|
||||
ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error)
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response
|
|||
}
|
||||
|
||||
func (s *containerRouter) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
return s.backend.ContainerExport(vars["name"], w)
|
||||
return s.backend.ContainerExport(ctx, vars["name"], w)
|
||||
}
|
||||
|
||||
type bodyOnStartError struct{}
|
||||
|
|
|
@ -9,8 +9,10 @@ import (
|
|||
cerrdefs "github.com/containerd/containerd/errdefs"
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
"github.com/containerd/containerd/mount"
|
||||
cplatforms "github.com/containerd/containerd/platforms"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/platforms"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
|
@ -19,6 +21,15 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (i *ImageService) PerformWithBaseFS(ctx context.Context, c *container.Container, fn func(root string) error) error {
|
||||
snapshotter := i.client.SnapshotService(i.snapshotter)
|
||||
mounts, err := snapshotter.Mounts(ctx, c.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mount.WithTempMount(ctx, mounts, fn)
|
||||
}
|
||||
|
||||
// ExportImage exports a list of images to the given output stream. The
|
||||
// exported images are archived into a tar when written to the output
|
||||
// stream. All images with the given tag and all versions containing
|
||||
|
|
|
@ -75,12 +75,6 @@ func (i *ImageService) CreateLayer(container *container.Container, initFunc laye
|
|||
return nil, errdefs.NotImplemented(errdefs.NotImplemented(errors.New("not implemented")))
|
||||
}
|
||||
|
||||
// GetLayerByID returns a layer by ID
|
||||
// called from daemon.go Daemon.restore(), and Daemon.containerExport().
|
||||
func (i *ImageService) GetLayerByID(cid string) (layer.RWLayer, error) {
|
||||
return nil, errdefs.NotImplemented(errors.New("not implemented"))
|
||||
}
|
||||
|
||||
// LayerStoreStatus returns the status for each layer store
|
||||
// called from info.go
|
||||
func (i *ImageService) LayerStoreStatus() [][2]string {
|
||||
|
|
|
@ -218,6 +218,11 @@ func (daemon *Daemon) RegistryHosts() docker.RegistryHosts {
|
|||
return resolver.NewRegistryConfig(m)
|
||||
}
|
||||
|
||||
// layerAccessor may be implemented by ImageService
|
||||
type layerAccessor interface {
|
||||
GetLayerByID(cid string) (layer.RWLayer, error)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) restore() error {
|
||||
var mapLock sync.Mutex
|
||||
containers := make(map[string]*container.Container)
|
||||
|
@ -259,12 +264,14 @@ func (daemon *Daemon) restore() error {
|
|||
log.Debugf("not restoring container because it was created with another storage driver (%s)", c.Driver)
|
||||
return
|
||||
}
|
||||
rwlayer, err := daemon.imageService.GetLayerByID(c.ID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to load container mount")
|
||||
return
|
||||
if accessor, ok := daemon.imageService.(layerAccessor); ok {
|
||||
rwlayer, err := accessor.GetLayerByID(c.ID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to load container mount")
|
||||
return
|
||||
}
|
||||
c.RWLayer = rwlayer
|
||||
}
|
||||
c.RWLayer = rwlayer
|
||||
log.WithFields(logrus.Fields{
|
||||
"running": c.IsRunning(),
|
||||
"paused": c.IsPaused(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
|
@ -8,12 +9,11 @@ import (
|
|||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
)
|
||||
|
||||
// ContainerExport writes the contents of the container to the given
|
||||
// writer. An error is returned if the container cannot be found.
|
||||
func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
|
||||
func (daemon *Daemon) ContainerExport(ctx context.Context, name string, out io.Writer) error {
|
||||
ctr, err := daemon.GetContainer(name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -33,49 +33,31 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
|
|||
return errdefs.Conflict(err)
|
||||
}
|
||||
|
||||
data, err := daemon.containerExport(ctr)
|
||||
err = daemon.containerExport(ctx, ctr, out)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error exporting container %s: %v", name, err)
|
||||
}
|
||||
defer data.Close()
|
||||
|
||||
// Stream the entire contents of the container (basically a volatile snapshot)
|
||||
if _, err := io.Copy(out, data); err != nil {
|
||||
return fmt.Errorf("Error exporting container %s: %v", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) containerExport(container *container.Container) (arch io.ReadCloser, err error) {
|
||||
rwlayer, err := daemon.imageService.GetLayerByID(container.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
func (daemon *Daemon) containerExport(ctx context.Context, container *container.Container, out io.Writer) error {
|
||||
err := daemon.imageService.PerformWithBaseFS(ctx, container, func(basefs string) error {
|
||||
archv, err := chrootarchive.Tar(basefs, &archive.TarOptions{
|
||||
Compression: archive.Uncompressed,
|
||||
IDMap: daemon.idMapping,
|
||||
}, basefs)
|
||||
if err != nil {
|
||||
daemon.imageService.ReleaseLayer(rwlayer)
|
||||
return err
|
||||
}
|
||||
}()
|
||||
|
||||
basefs, err := rwlayer.Mount(container.GetMountLabel())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
archv, err := chrootarchive.Tar(basefs, &archive.TarOptions{
|
||||
Compression: archive.Uncompressed,
|
||||
IDMap: daemon.idMapping,
|
||||
}, basefs)
|
||||
if err != nil {
|
||||
rwlayer.Unmount()
|
||||
return nil, err
|
||||
}
|
||||
arch = ioutils.NewReadCloserWrapper(archv, func() error {
|
||||
err := archv.Close()
|
||||
rwlayer.Unmount()
|
||||
daemon.imageService.ReleaseLayer(rwlayer)
|
||||
// Stream the entire contents of the container (basically a volatile snapshot)
|
||||
_, err = io.Copy(out, archv)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
daemon.LogContainerEvent(container, "export")
|
||||
return arch, err
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ type ImageService interface {
|
|||
CreateImage(config []byte, parent string) (builder.Image, error)
|
||||
ImageDelete(ctx context.Context, imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
|
||||
ExportImage(ctx context.Context, names []string, outStream io.Writer) error
|
||||
PerformWithBaseFS(ctx context.Context, c *container.Container, fn func(string) error) error
|
||||
LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
||||
Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error)
|
||||
LogImageEvent(imageID, refName, action string)
|
||||
|
@ -52,7 +53,6 @@ type ImageService interface {
|
|||
|
||||
GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error)
|
||||
CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error)
|
||||
GetLayerByID(cid string) (layer.RWLayer, error)
|
||||
LayerStoreStatus() [][2]string
|
||||
GetLayerMountID(cid string) (string, error)
|
||||
ReleaseLayer(rwlayer layer.RWLayer) error
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/image/tarexport"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ExportImage exports a list of images to the given output stream. The
|
||||
|
@ -17,6 +19,28 @@ func (i *ImageService) ExportImage(ctx context.Context, names []string, outStrea
|
|||
return imageExporter.Save(names, outStream)
|
||||
}
|
||||
|
||||
func (i *ImageService) PerformWithBaseFS(ctx context.Context, c *container.Container, fn func(root string) error) error {
|
||||
rwlayer, err := i.layerStore.GetRWLayer(c.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err2 := i.ReleaseLayer(rwlayer)
|
||||
if err2 != nil {
|
||||
logrus.WithError(err2).WithField("container", c.ID).Warn("Failed to release layer")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
basefs, err := rwlayer.Mount(c.GetMountLabel())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fn(basefs)
|
||||
}
|
||||
|
||||
// LoadImage uploads a set of images into the repository. This is the
|
||||
// complement of ExportImage. The input stream is an uncompressed tar
|
||||
// ball containing images and metadata.
|
||||
|
|
|
@ -136,7 +136,7 @@ func (i *ImageService) CreateLayer(container *container.Container, initFunc laye
|
|||
}
|
||||
|
||||
// GetLayerByID returns a layer by ID
|
||||
// called from daemon.go Daemon.restore(), and Daemon.containerExport().
|
||||
// called from daemon.go Daemon.restore().
|
||||
func (i *ImageService) GetLayerByID(cid string) (layer.RWLayer, error) {
|
||||
return i.layerStore.GetRWLayer(cid)
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ func (i *ImageService) StorageDriver() string {
|
|||
}
|
||||
|
||||
// ReleaseLayer releases a layer allowing it to be removed
|
||||
// called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
|
||||
// called from delete.go Daemon.cleanupContainer().
|
||||
func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
|
||||
metaData, err := i.layerStore.ReleaseRWLayer(rwlayer)
|
||||
layer.LogReleaseMetadata(metaData)
|
||||
|
|
Loading…
Add table
Reference in a new issue