Files
podman/cmd/podman/checkpoint.go
Adrian Reber 03c88a3deb Added tcp-established to checkpoint/restore
CRIU can checkpoint and restore processes/containers with established
TCP connections if the correct option is specified. To implement
checkpoint and restore with support for established TCP connections with
Podman this commit adds the necessary options to runc during checkpoint
and also tells conmon during restore to use 'runc restore' with
'--tcp-established'.

For this Podman feature to work a corresponding conmon change is
required.

Example:

$ podman run --tmpfs /tmp --name podman-criu-test -d docker://docker.io/yovfiatbeb/podman-criu-test
$ nc `podman inspect -l | jq -r '.[0].NetworkSettings.IPAddress'` 8080
GET /examples/servlets/servlet/HelloWorldExample
Connection: keep-alive

1
GET /examples/servlets/servlet/HelloWorldExample
Connection: keep-alive

2
$ # Using HTTP keep-alive multiple requests are send to the server in the container
$ # Different terminal:
$ podman container checkpoint -l
criu failed: type NOTIFY errno 0
$ # Looking at the log file would show errors because of established TCP connections
$ podman container checkpoint -l --tcp-established
$ # This works now and after the restore the same connection as above can be used for requests
$ podman container restore -l --tcp-established

The restore would fail without '--tcp-established' as the checkpoint image
contains established TCP connections.

Signed-off-by: Adrian Reber <areber@redhat.com>
2018-11-28 08:00:38 +01:00

85 lines
2.0 KiB
Go

package main
import (
"context"
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
checkpointDescription = `
podman container checkpoint
Checkpoints one or more running containers. The container name or ID can be used.
`
checkpointFlags = []cli.Flag{
cli.BoolFlag{
Name: "keep, k",
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: "tcp-established",
Usage: "checkpoint a container with established TCP connections",
},
cli.BoolFlag{
Name: "all, a",
Usage: "checkpoint all running containers",
},
LatestFlag,
}
checkpointCommand = cli.Command{
Name: "checkpoint",
Usage: "Checkpoints one or more containers",
Description: checkpointDescription,
Flags: sortFlags(checkpointFlags),
Action: checkpointCmd,
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
)
func checkpointCmd(c *cli.Context) error {
if rootless.IsRootless() {
return errors.New("checkpointing a container requires root")
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
options := libpod.ContainerCheckpointOptions{
Keep: c.Bool("keep"),
KeepRunning: c.Bool("leave-running"),
TCPEstablished: c.Bool("tcp-established"),
}
if err := checkAllAndLatest(c); err != nil {
return err
}
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
for _, ctr := range containers {
if err = ctr.Checkpoint(context.TODO(), options); err != nil {
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
lastError = errors.Wrapf(err, "failed to checkpoint container %v", ctr.ID())
} else {
fmt.Println(ctr.ID())
}
}
return lastError
}