summaryrefslogtreecommitdiff
path: root/libpod/container_internal_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_internal_linux.go')
-rw-r--r--libpod/container_internal_linux.go60
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