aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Reber <areber@redhat.com>2018-11-20 15:34:15 +0000
committerAdrian Reber <adrian@lisas.de>2018-11-20 17:25:44 +0100
commitb0572d622974837c2221ed1f01a2ab982f078370 (patch)
tree1c4ad4bb26973210546639cbd4f86b12d8754270
parentff47a4c2d5485fc49f937f3ce0c4e2fd6bdb1956 (diff)
downloadpodman-b0572d622974837c2221ed1f01a2ab982f078370.tar.gz
podman-b0572d622974837c2221ed1f01a2ab982f078370.tar.bz2
podman-b0572d622974837c2221ed1f01a2ab982f078370.zip
Added option to keep containers running after checkpointing
CRIU supports to leave processes running after checkpointing: -R|--leave-running leave tasks in running state after checkpoint runc also support to leave containers running after checkpointing: --leave-running leave the process running after checkpointing With this commit the support to leave a container running after checkpointing is brought to Podman: --leave-running, -R leave the container running after writing checkpoint to disk Now it is possible to checkpoint a container at some point in time without stopping the container. This can be used to rollback the container to an early state: $ podman run --tmpfs /tmp --name podman-criu-test -d docker://docker.io/yovfiatbeb/podman-criu-test $ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample 3 $ podman container checkpoint -R -l $ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample 4 $ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample 5 $ podman stop -l $ podman container restore -l $ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample 4 So after checkpointing the container kept running and was stopped after some time. Restoring this container will restore the state right at the checkpoint. Signed-off-by: Adrian Reber <areber@redhat.com>
-rw-r--r--cmd/podman/checkpoint.go7
-rw-r--r--libpod/container_api.go3
-rw-r--r--libpod/container_internal_linux.go12
-rw-r--r--libpod/oci.go15
4 files changed, 27 insertions, 10 deletions
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go
index 49e2aec63..ddfd12bc3 100644
--- a/cmd/podman/checkpoint.go
+++ b/cmd/podman/checkpoint.go
@@ -24,6 +24,10 @@ var (
Usage: "keep all temporary checkpoint files",
},
cli.BoolFlag{
+ Name: "leave-running, R",
+ Usage: "leave the container running after writing checkpoint to disk",
+ },
+ cli.BoolFlag{
Name: "all, a",
Usage: "checkpoint all running containers",
},
@@ -51,7 +55,8 @@ func checkpointCmd(c *cli.Context) error {
defer runtime.Shutdown(false)
options := libpod.ContainerCheckpointOptions{
- Keep: c.Bool("keep"),
+ Keep: c.Bool("keep"),
+ KeepRunning: c.Bool("leave-running"),
}
if err := checkAllAndLatest(c); err != nil {
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 9f5436b14..df6b6e962 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -833,7 +833,8 @@ func (c *Container) Refresh(ctx context.Context) error {
// ContainerCheckpointOptions is a struct used to pass the parameters
// for checkpointing to corresponding functions
type ContainerCheckpointOptions struct {
- Keep bool
+ Keep bool
+ KeepRunning bool
}
// Checkpoint checkpoints a container
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 003e8284a..e6071945d 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -440,7 +440,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
if c.state.State != ContainerStateRunning {
return errors.Wrapf(ErrCtrStateInvalid, "%q is not running, cannot checkpoint", c.state.State)
}
- if err := c.runtime.ociRuntime.checkpointContainer(c); err != nil {
+ if err := c.runtime.ociRuntime.checkpointContainer(c, options); err != nil {
return err
}
@@ -457,11 +457,13 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
logrus.Debugf("Checkpointed container %s", c.ID())
- c.state.State = ContainerStateStopped
+ if !options.KeepRunning {
+ c.state.State = ContainerStateStopped
- // Cleanup Storage and Network
- if err := c.cleanup(ctx); err != nil {
- return err
+ // Cleanup Storage and Network
+ if err := c.cleanup(ctx); err != nil {
+ return err
+ }
}
if !options.Keep {
diff --git a/libpod/oci.go b/libpod/oci.go
index 71da830b5..8ee2c948f 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -844,13 +844,22 @@ func (r *OCIRuntime) execStopContainer(ctr *Container, timeout uint) error {
}
// checkpointContainer checkpoints the given container
-func (r *OCIRuntime) checkpointContainer(ctr *Container) error {
+func (r *OCIRuntime) checkpointContainer(ctr *Container, options ContainerCheckpointOptions) error {
// imagePath is used by CRIU to store the actual checkpoint files
imagePath := ctr.CheckpointPath()
// workPath will be used to store dump.log and stats-dump
workPath := ctr.bundlePath()
logrus.Debugf("Writing checkpoint to %s", imagePath)
logrus.Debugf("Writing checkpoint logs to %s", workPath)
- return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "checkpoint",
- "--image-path", imagePath, "--work-path", workPath, ctr.ID())
+ args := []string{}
+ args = append(args, "checkpoint")
+ args = append(args, "--image-path")
+ args = append(args, imagePath)
+ args = append(args, "--work-path")
+ args = append(args, workPath)
+ if options.KeepRunning {
+ args = append(args, "--leave-running")
+ }
+ args = append(args, ctr.ID())
+ return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...)
}