Merge pull request #4415 from TBBle/wcow_commit_layers
Commit writable WCOW layers as read-only parent layers
This commit is contained in:
commit
bbbd851381
@ -23,15 +23,18 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio"
|
||||||
winfs "github.com/Microsoft/go-winio/pkg/fs"
|
winfs "github.com/Microsoft/go-winio/pkg/fs"
|
||||||
"github.com/Microsoft/go-winio/vhd"
|
"github.com/Microsoft/go-winio/vhd"
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
"github.com/Microsoft/hcsshim/computestorage"
|
"github.com/Microsoft/hcsshim/computestorage"
|
||||||
|
"github.com/Microsoft/hcsshim/pkg/ociwclayer"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
@ -185,14 +188,14 @@ func (s *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er
|
|||||||
return s.mounts(snapshot), nil
|
return s.mounts(snapshot), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {
|
func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) (retErr error) {
|
||||||
ctx, t, err := s.ms.TransactionContext(ctx, true)
|
ctx, t, err := s.ms.TransactionContext(ctx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if retErr != nil {
|
||||||
if rerr := t.Rollback(); rerr != nil {
|
if rerr := t.Rollback(); rerr != nil {
|
||||||
log.G(ctx).WithError(rerr).Warn("failed to rollback transaction")
|
log.G(ctx).WithError(rerr).Warn("failed to rollback transaction")
|
||||||
}
|
}
|
||||||
@ -202,15 +205,30 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
|
|||||||
// grab the existing id
|
// grab the existing id
|
||||||
id, _, _, err := storage.GetInfo(ctx, key)
|
id, _, _, err := storage.GetInfo(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrapf(err, "failed to get storage info for %s", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
usage, err := fs.DiskUsage(ctx, s.getSnapshotDir(id))
|
snapshot, err := storage.GetSnapshot(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil {
|
path := s.getSnapshotDir(id)
|
||||||
|
|
||||||
|
// If (windowsDiff).Apply was used to populate this layer, then it's already in the 'committed' state.
|
||||||
|
// See createSnapshot below for more details
|
||||||
|
if !strings.Contains(key, snapshots.UnpackKeyPrefix) {
|
||||||
|
if err := s.convertScratchToReadOnlyLayer(ctx, snapshot, path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usage, err := fs.DiskUsage(ctx, path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to collect disk usage of snapshot storage: %s", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil {
|
||||||
return errors.Wrap(err, "failed to commit snapshot")
|
return errors.Wrap(err, "failed to commit snapshot")
|
||||||
}
|
}
|
||||||
return t.Commit()
|
return t.Commit()
|
||||||
@ -443,6 +461,43 @@ func (s *snapshotter) createScratchLayer(ctx context.Context, snDir string, pare
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convertScratchToReadOnlyLayer reimporst the layer over itself, to transfer the files from the sandbox.vhdx to the on-disk storage.
|
||||||
|
func (s *snapshotter) convertScratchToReadOnlyLayer(ctx context.Context, snapshot storage.Snapshot, path string) (retErr error) {
|
||||||
|
|
||||||
|
// TODO darrenstahlmsft: When this is done isolated, we should disable these.
|
||||||
|
// it currently cannot be disabled, unless we add ref counting. Since this is
|
||||||
|
// temporary, leaving it enabled is OK for now.
|
||||||
|
// https://github.com/containerd/containerd/issues/1681
|
||||||
|
if err := winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to enable necessary privileges")
|
||||||
|
}
|
||||||
|
|
||||||
|
parentLayerPaths := s.parentIDsToParentPaths(snapshot.ParentIDs)
|
||||||
|
reader, writer := io.Pipe()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := ociwclayer.ExportLayerToTar(ctx, writer, path, parentLayerPaths)
|
||||||
|
writer.CloseWithError(err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if _, err := ociwclayer.ImportLayerFromTar(ctx, reader, path, parentLayerPaths); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to reimport snapshot")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(ioutil.Discard, reader); err != nil {
|
||||||
|
return errors.Wrap(err, "failed discarding extra data in import stream")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: We do not delete the sandbox.vhdx here, as that will break later calls to
|
||||||
|
// ociwclayer.ExportLayerToTar for this snapshot.
|
||||||
|
// As a consequence, the data for this layer is held twice, once on-disk and once
|
||||||
|
// in the sandbox.vhdx.
|
||||||
|
// TODO: This is either a bug or misfeature in hcsshim, so will need to be resolved
|
||||||
|
// there first.
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// This handles creating the UVMs scratch layer.
|
// This handles creating the UVMs scratch layer.
|
||||||
func (s *snapshotter) createUVMScratchLayer(ctx context.Context, snDir string, parentLayers []string) error {
|
func (s *snapshotter) createUVMScratchLayer(ctx context.Context, snDir string, parentLayers []string) error {
|
||||||
parentLen := len(parentLayers)
|
parentLen := len(parentLayers)
|
||||||
|
Loading…
Reference in New Issue
Block a user