diff options
author | Adrian Reber <areber@redhat.com> | 2021-11-17 16:55:43 +0000 |
---|---|---|
committer | Adrian Reber <areber@redhat.com> | 2021-11-19 17:46:06 +0000 |
commit | c76caba367583c5d4f1e8fe3f111383148d4d175 (patch) | |
tree | d53725f3777e678942b902038cfe1fde42ca07f9 /pkg/checkpoint | |
parent | 671e5ee42d4eb71fc0238e8b0b1e4a68b1def156 (diff) | |
download | podman-c76caba367583c5d4f1e8fe3f111383148d4d175.tar.gz podman-c76caba367583c5d4f1e8fe3f111383148d4d175.tar.bz2 podman-c76caba367583c5d4f1e8fe3f111383148d4d175.zip |
Use same runtime to restore a container as during checkpointing
There are at least two runtimes that support checkpoint and restore:
runc and crun. Although the checkpoints created by these are almost
compatible, it is not (yet) possible to restore a checkpoint created
with one runtime with the other runtime. To make checkpoint/restore
usage more comfortable this adds code to look into the checkpoint
archive during restore and to set the runtime to the one used during
checkpointing.
This also adds a check, if the user explicitly sets a runtime during
restore, that the runtime is also the same as used during checkpointing.
If a different runtime is selected than the one used during
checkpointing the restore will fail early.
If runc and crun will create compatible checkpoints in the future the
check can be changed to treat crun and runc as compatible
checkpoint/restore runtimes.
Signed-off-by: Adrian Reber <areber@redhat.com>
Diffstat (limited to 'pkg/checkpoint')
-rw-r--r-- | pkg/checkpoint/checkpoint_restore.go | 26 | ||||
-rw-r--r-- | pkg/checkpoint/crutils/checkpoint_restore_utils.go | 55 |
2 files changed, 57 insertions, 24 deletions
diff --git a/pkg/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go index 85fe6a77e..c371adf5b 100644 --- a/pkg/checkpoint/checkpoint_restore.go +++ b/pkg/checkpoint/checkpoint_restore.go @@ -6,7 +6,6 @@ import ( "os" metadata "github.com/checkpoint-restore/checkpointctl/lib" - "github.com/checkpoint-restore/go-criu/v5/stats" "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod" @@ -14,10 +13,8 @@ import ( "github.com/containers/podman/v3/pkg/checkpoint/crutils" "github.com/containers/podman/v3/pkg/criu" "github.com/containers/podman/v3/pkg/domain/entities" - "github.com/containers/podman/v3/pkg/errorhandling" "github.com/containers/podman/v3/pkg/specgen/generate" "github.com/containers/podman/v3/pkg/specgenutil" - "github.com/containers/storage/pkg/archive" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -30,24 +27,6 @@ import ( func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOptions entities.RestoreOptions) ([]*libpod.Container, error) { // First get the container definition from the // tarball to a temporary directory - archiveFile, err := os.Open(restoreOptions.Import) - if err != nil { - return nil, errors.Wrap(err, "failed to open checkpoint archive for import") - } - defer errorhandling.CloseQuiet(archiveFile) - options := &archive.TarOptions{ - // Here we only need the files config.dump and spec.dump - ExcludePatterns: []string{ - "volumes", - "ctr.log", - "artifacts", - stats.StatsDump, - metadata.RootFsDiffTar, - metadata.DeletedFilesFile, - metadata.NetworkStatusFile, - metadata.CheckpointDirectory, - }, - } dir, err := ioutil.TempDir("", "checkpoint") if err != nil { return nil, err @@ -57,9 +36,8 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt 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", restoreOptions.Import) + if err := crutils.CRImportCheckpointConfigOnly(dir, restoreOptions.Import); err != nil { + return nil, err } // Load spec.dump from temporary directory diff --git a/pkg/checkpoint/crutils/checkpoint_restore_utils.go b/pkg/checkpoint/crutils/checkpoint_restore_utils.go index 3b77368bb..2765d18e8 100644 --- a/pkg/checkpoint/crutils/checkpoint_restore_utils.go +++ b/pkg/checkpoint/crutils/checkpoint_restore_utils.go @@ -3,11 +3,13 @@ package crutils import ( "bytes" "io" + "io/ioutil" "os" "os/exec" "path/filepath" metadata "github.com/checkpoint-restore/checkpointctl/lib" + "github.com/checkpoint-restore/go-criu/v5/stats" "github.com/containers/storage/pkg/archive" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -39,6 +41,36 @@ func CRImportCheckpointWithoutConfig(destination, input string) error { return nil } +// CRImportCheckpointConfigOnly only imports the checkpoint configuration +// from the checkpoint archive (input) into the directory destination. +// Only the files "config.dump" and "spec.dump" are extracted. +func CRImportCheckpointConfigOnly(destination, input string) error { + archiveFile, err := os.Open(input) + if err != nil { + return errors.Wrapf(err, "Failed to open checkpoint archive %s for import", input) + } + + defer archiveFile.Close() + options := &archive.TarOptions{ + // Here we only need the files config.dump and spec.dump + ExcludePatterns: []string{ + "volumes", + "ctr.log", + "artifacts", + stats.StatsDump, + metadata.RootFsDiffTar, + metadata.DeletedFilesFile, + metadata.NetworkStatusFile, + metadata.CheckpointDirectory, + }, + } + if err = archive.Untar(archiveFile, destination, options); err != nil { + return errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input) + } + + return nil +} + // CRRemoveDeletedFiles loads the list of deleted files and if // it exists deletes all files listed. func CRRemoveDeletedFiles(id, baseDirectory, containerRootDirectory string) error { @@ -200,3 +232,26 @@ func CRRuntimeSupportsPodCheckpointRestore(runtimePath string) bool { out, _ := cmd.CombinedOutput() return bytes.Contains(out, []byte("flag needs an argument")) } + +// CRGetRuntimeFromArchive extracts the checkpoint metadata from the +// given checkpoint archive and returns the runtime used to create +// the given checkpoint archive. +func CRGetRuntimeFromArchive(input string) (*string, error) { + dir, err := ioutil.TempDir("", "checkpoint") + if err != nil { + return nil, err + } + defer os.RemoveAll(dir) + + if err := CRImportCheckpointConfigOnly(dir, input); err != nil { + return nil, err + } + + // Load config.dump from temporary directory + ctrConfig := new(metadata.ContainerConfig) + if _, err = metadata.ReadJSONFile(ctrConfig, dir, metadata.ConfigDumpFile); err != nil { + return nil, err + } + + return &ctrConfig.OCIRuntime, nil +} |