From 8a16674722ab4a33ce66e57d151b09ac348e8e6d Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Fri, 27 Mar 2020 08:20:13 -0500 Subject: podmanv2 checkpoint and restore add the ability to checkpoint and restore containers on v2podman Signed-off-by: Brent Baude --- pkg/adapter/checkpoint_restore.go | 153 -------------------------------------- pkg/adapter/containers.go | 3 +- 2 files changed, 2 insertions(+), 154 deletions(-) delete mode 100644 pkg/adapter/checkpoint_restore.go (limited to 'pkg/adapter') diff --git a/pkg/adapter/checkpoint_restore.go b/pkg/adapter/checkpoint_restore.go deleted file mode 100644 index a5b74013b..000000000 --- a/pkg/adapter/checkpoint_restore.go +++ /dev/null @@ -1,153 +0,0 @@ -// +build !remoteclient - -package adapter - -import ( - "context" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/image" - "github.com/containers/libpod/pkg/errorhandling" - "github.com/containers/libpod/pkg/util" - "github.com/containers/storage/pkg/archive" - jsoniter "github.com/json-iterator/go" - spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// Prefixing the checkpoint/restore related functions with 'cr' - -// crImportFromJSON imports the JSON files stored in the exported -// checkpoint tarball -func crImportFromJSON(filePath string, v interface{}) error { - jsonFile, err := os.Open(filePath) - if err != nil { - return errors.Wrapf(err, "Failed to open container definition %s for restore", filePath) - } - defer errorhandling.CloseQuiet(jsonFile) - - content, err := ioutil.ReadAll(jsonFile) - if err != nil { - return errors.Wrapf(err, "Failed to read container definition %s for restore", filePath) - } - json := jsoniter.ConfigCompatibleWithStandardLibrary - if err = json.Unmarshal(content, v); err != nil { - return errors.Wrapf(err, "Failed to unmarshal container definition %s for restore", filePath) - } - - return nil -} - -// crImportCheckpoint it the function which imports the information -// from checkpoint tarball and re-creates the container from that information -func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input string, name string) ([]*libpod.Container, error) { - // First get the container definition from the - // tarball to a temporary directory - archiveFile, err := os.Open(input) - if err != nil { - return nil, errors.Wrapf(err, "Failed to open checkpoint archive %s for import", input) - } - defer errorhandling.CloseQuiet(archiveFile) - options := &archive.TarOptions{ - // Here we only need the files config.dump and spec.dump - ExcludePatterns: []string{ - "checkpoint", - "artifacts", - "ctr.log", - "rootfs-diff.tar", - "network.status", - "deleted.files", - }, - } - dir, err := ioutil.TempDir("", "checkpoint") - if err != nil { - return nil, err - } - defer func() { - if err := os.RemoveAll(dir); err != nil { - logrus.Errorf("could not recursively remove %s: %q", dir, err) - } - }() - err = archive.Untar(archiveFile, dir, options) - if err != nil { - return nil, errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input) - } - - // Load spec.dump from temporary directory - dumpSpec := new(spec.Spec) - if err := crImportFromJSON(filepath.Join(dir, "spec.dump"), dumpSpec); err != nil { - return nil, err - } - - // Load config.dump from temporary directory - config := new(libpod.ContainerConfig) - if err = crImportFromJSON(filepath.Join(dir, "config.dump"), config); err != nil { - return nil, err - } - - // This should not happen as checkpoints with these options are not exported. - if (len(config.Dependencies) > 0) || (len(config.NamedVolumes) > 0) { - return nil, errors.Errorf("Cannot import checkpoints of containers with named volumes or dependencies") - } - - ctrID := config.ID - newName := false - - // Check if the restored container gets a new name - if name != "" { - config.ID = "" - config.Name = name - newName = true - } - - ctrName := config.Name - - // The code to load the images is copied from create.go - // In create.go this only set if '--quiet' does not exist. - writer := os.Stderr - rtc, err := runtime.GetConfig() - if err != nil { - return nil, err - } - - _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.Engine.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, nil, util.PullImageMissing) - if err != nil { - return nil, err - } - - // Now create a new container from the just loaded information - container, err := runtime.RestoreContainer(ctx, dumpSpec, config) - if err != nil { - return nil, err - } - - var containers []*libpod.Container - if container == nil { - return nil, nil - } - - containerConfig := container.Config() - if containerConfig.Name != ctrName { - return nil, errors.Errorf("Name of restored container (%s) does not match requested name (%s)", containerConfig.Name, ctrName) - } - - if !newName { - // Only check ID for a restore with the same name. - // Using -n to request a new name for the restored container, will also create a new ID - if containerConfig.ID != ctrID { - return nil, errors.Errorf("ID of restored container (%s) does not match requested ID (%s)", containerConfig.ID, ctrID) - } - } - - // Check if the ExitCommand points to the correct container ID - if containerConfig.ExitCommand[len(containerConfig.ExitCommand)-1] != containerConfig.ID { - return nil, errors.Errorf("'ExitCommandID' uses ID %s instead of container ID %s", containerConfig.ExitCommand[len(containerConfig.ExitCommand)-1], containerConfig.ID) - } - - containers = append(containers, container) - return containers, nil -} diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index c395ffc7f..b4ebeb944 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -26,6 +26,7 @@ import ( "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/logs" "github.com/containers/libpod/pkg/adapter/shortcuts" + "github.com/containers/libpod/pkg/checkpoint" envLib "github.com/containers/libpod/pkg/env" "github.com/containers/libpod/pkg/systemd/generate" "github.com/containers/storage" @@ -625,7 +626,7 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues) switch { case c.Import != "": - containers, err = crImportCheckpoint(ctx, r.Runtime, c.Import, c.Name) + containers, err = checkpoint.CRImportCheckpoint(ctx, r.Runtime, c.Import, c.Name) case c.All: containers, err = r.GetContainers(filterFuncs...) default: -- cgit v1.2.3-54-g00ecf