diff options
Diffstat (limited to 'libpod/container_internal_linux.go')
-rw-r--r-- | libpod/container_internal_linux.go | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index ac20e1f25..ce2b52234 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -40,7 +40,6 @@ import ( "github.com/containers/storage/pkg/idtools" securejoin "github.com/cyphar/filepath-securejoin" runcuser "github.com/opencontainers/runc/libcontainer/user" - "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/selinux/go-selinux/label" @@ -284,7 +283,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { return nil, err } - g := generate.NewFromSpec(c.config.Spec) + g := generate.Generator{Config: c.config.Spec} // If network namespace was requested, add it now if c.config.CreateNetNS { @@ -400,7 +399,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { return nil, errors.Wrapf(err, "failed to create TempDir in the %s directory", c.config.StaticDir) } - var overlayMount specs.Mount + var overlayMount spec.Mount if volume.ReadWrite { overlayMount, err = overlay.Mount(contentDir, mountPoint, volume.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions()) } else { @@ -812,6 +811,9 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { "spec.dump", "network.status"} + if options.PreCheckPoint { + includeFiles[0] = "pre-checkpoint" + } // Get root file-system changes included in the checkpoint archive rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar") deleteFilesList := filepath.Join(c.bundlePath(), "deleted.files") @@ -1015,6 +1017,15 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO defer c.newContainerEvent(events.Checkpoint) + // There is a bug from criu: https://github.com/checkpoint-restore/criu/issues/116 + // We have to change the symbolic link from absolute path to relative path + if options.WithPrevious { + os.Remove(path.Join(c.CheckpointPath(), "parent")) + if err := os.Symlink("../pre-checkpoint", path.Join(c.CheckpointPath(), "parent")); err != nil { + return err + } + } + if options.TargetFile != "" { if err = c.exportCheckpoint(options); err != nil { return err @@ -1023,7 +1034,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO logrus.Debugf("Checkpointed container %s", c.ID()) - if !options.KeepRunning { + if !options.KeepRunning && !options.PreCheckPoint { c.state.State = define.ContainerStateStopped // Cleanup Storage and Network @@ -1032,7 +1043,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO } } - if !options.Keep { + if !options.Keep && !options.PreCheckPoint { cleanup := []string{ "dump.log", "stats-dump", @@ -1080,6 +1091,21 @@ func (c *Container) importCheckpoint(input string) error { return nil } +func (c *Container) importPreCheckpoint(input string) error { + archiveFile, err := os.Open(input) + if err != nil { + return errors.Wrap(err, "failed to open pre-checkpoint archive for import") + } + + defer archiveFile.Close() + + err = archive.Untar(archiveFile, c.bundlePath(), nil) + if err != nil { + return errors.Wrapf(err, "Unpacking of pre-checkpoint archive %s failed", input) + } + return nil +} + func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (retErr error) { if err := c.checkpointRestoreSupported(); err != nil { return err @@ -1089,6 +1115,12 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID()) } + if options.ImportPrevious != "" { + if err := c.importPreCheckpoint(options.ImportPrevious); err != nil { + return err + } + } + if options.TargetFile != "" { if err := c.importCheckpoint(options.TargetFile); err != nil { return err @@ -1322,6 +1354,10 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if err != nil { logrus.Debugf("Non-fatal: removal of checkpoint directory (%s) failed: %v", c.CheckpointPath(), err) } + err = os.RemoveAll(c.PreCheckPointPath()) + if err != nil { + logrus.Debugf("Non-fatal: removal of pre-checkpoint directory (%s) failed: %v", c.PreCheckPointPath(), err) + } cleanup := [...]string{"restore.log", "dump.log", "stats-dump", "stats-restore", "network.status", "rootfs-diff.tar", "deleted.files"} for _, del := range cleanup { file := filepath.Join(c.bundlePath(), del) @@ -1482,18 +1518,14 @@ func (c *Container) makeBindMounts() error { } if newPasswd != "" { // Make /etc/passwd - if _, ok := c.state.BindMounts["/etc/passwd"]; ok { - // If it already exists, delete so we can recreate - delete(c.state.BindMounts, "/etc/passwd") - } + // If it already exists, delete so we can recreate + delete(c.state.BindMounts, "/etc/passwd") c.state.BindMounts["/etc/passwd"] = newPasswd } if newGroup != "" { // Make /etc/group - if _, ok := c.state.BindMounts["/etc/group"]; ok { - // If it already exists, delete so we can recreate - delete(c.state.BindMounts, "/etc/group") - } + // If it already exists, delete so we can recreate + delete(c.state.BindMounts, "/etc/group") c.state.BindMounts["/etc/group"] = newGroup } @@ -1710,7 +1742,7 @@ func (c *Container) generateHosts(path string) (string, error) { // FIXME. Path should be used by this function,but I am not sure what is correct; remove //lint // once this is fixed func (c *Container) appendHosts(path string, netCtr *Container) (string, error) { //nolint - return c.appendStringToRundir("hosts", netCtr.getHosts()) + return c.appendStringToRunDir("hosts", netCtr.getHosts()) } // getHosts finds the pertinent information for a container's host file in its config and state |