Merge pull request #10910 from adrianreber/2021-07-12-checkpoint-restore-into-pod
Add support for checkpoint/restore into and out of pods
This commit is contained in:
commit
6c5966cf3c
|
|
@ -71,6 +71,9 @@ func init() {
|
||||||
)
|
)
|
||||||
_ = restoreCommand.RegisterFlagCompletionFunc("publish", completion.AutocompleteNone)
|
_ = restoreCommand.RegisterFlagCompletionFunc("publish", completion.AutocompleteNone)
|
||||||
|
|
||||||
|
flags.StringVar(&restoreOptions.Pod, "pod", "", "Restore container into existing Pod (only works with --import)")
|
||||||
|
_ = restoreCommand.RegisterFlagCompletionFunc("pod", common.AutocompletePodsRunning)
|
||||||
|
|
||||||
validate.AddLatestFlag(restoreCommand, &restoreOptions.Latest)
|
validate.AddLatestFlag(restoreCommand, &restoreOptions.Latest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,6 +94,9 @@ func restore(cmd *cobra.Command, args []string) error {
|
||||||
if restoreOptions.Import == "" && restoreOptions.Name != "" {
|
if restoreOptions.Import == "" && restoreOptions.Name != "" {
|
||||||
return errors.Errorf("--name can only be used with --import")
|
return errors.Errorf("--name can only be used with --import")
|
||||||
}
|
}
|
||||||
|
if restoreOptions.Import == "" && restoreOptions.Pod != "" {
|
||||||
|
return errors.Errorf("--pod can only be used with --import")
|
||||||
|
}
|
||||||
if restoreOptions.Name != "" && restoreOptions.TCPEstablished {
|
if restoreOptions.Name != "" && restoreOptions.TCPEstablished {
|
||||||
return errors.Errorf("--tcp-established cannot be used with --name")
|
return errors.Errorf("--tcp-established cannot be used with --name")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,15 @@ be used once and the restored *container* will have another IP address. This als
|
||||||
that **--name, -n** cannot be used in combination with **--tcp-established**.\
|
that **--name, -n** cannot be used in combination with **--tcp-established**.\
|
||||||
*IMPORTANT: This OPTION is only available in combination with **--import, -i**.*
|
*IMPORTANT: This OPTION is only available in combination with **--import, -i**.*
|
||||||
|
|
||||||
|
#### **--pod**=*name*
|
||||||
|
|
||||||
|
Restore a container into the pod *name*. The destination pod for this restore
|
||||||
|
has to have the same namespaces shared as the pod this container was checkpointed
|
||||||
|
from (see **[podman pod create --share](podman-pod-create.1.md#--share)**).
|
||||||
|
*IMPORTANT: This OPTION is only available in combination with **--import, -i**.*
|
||||||
|
|
||||||
|
This option requires at least CRIU 3.16.
|
||||||
|
|
||||||
#### **--publish**, **-p**=*port*
|
#### **--publish**, **-p**=*port*
|
||||||
|
|
||||||
Replaces the ports that the *container* publishes, as configured during the
|
Replaces the ports that the *container* publishes, as configured during the
|
||||||
|
|
@ -128,7 +137,7 @@ $ podman run --rm -p 2345:80 -d webserver
|
||||||
```
|
```
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
**[podman(1)](podman.1.md)**, **[podman-container-checkpoint(1)](podman-container-checkpoint.1.md)**, **[podman-run(1)](podman-run.1.md)**
|
**[podman(1)](podman.1.md)**, **[podman-container-checkpoint(1)](podman-container-checkpoint.1.md)**, **[podman-run(1)](podman-run.1.md)**, **[podman-pod-create(1)](podman-pod-create.1.md)**
|
||||||
|
|
||||||
## HISTORY
|
## HISTORY
|
||||||
September 2018, Originally compiled by Adrian Reber <areber@redhat.com>
|
September 2018, Originally compiled by Adrian Reber <areber@redhat.com>
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -7,7 +7,7 @@ require (
|
||||||
github.com/blang/semver v3.5.1+incompatible
|
github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
|
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
|
||||||
github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
|
github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
|
||||||
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b
|
github.com/checkpoint-restore/go-criu/v5 v5.1.0
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9
|
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9
|
||||||
github.com/containernetworking/cni v0.8.1
|
github.com/containernetworking/cni v0.8.1
|
||||||
github.com/containernetworking/plugins v0.9.1
|
github.com/containernetworking/plugins v0.9.1
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -128,11 +128,11 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7 h1:ZmSAEFFtv3mepC4/Ze6E/hi6vGZlhRvywqp1l+w+qqw=
|
github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7 h1:ZmSAEFFtv3mepC4/Ze6E/hi6vGZlhRvywqp1l+w+qqw=
|
||||||
github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7/go.mod h1:Kp3ezoDVdhfYxZUtgs4OL8sVvgOLz3txk0sbQD0opvw=
|
github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7/go.mod h1:Kp3ezoDVdhfYxZUtgs4OL8sVvgOLz3txk0sbQD0opvw=
|
||||||
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b h1:T4nWG1TXIxeor8mAu5bFguPJgSIGhZqv/f0z55KCrJM=
|
|
||||||
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho=
|
|
||||||
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||||
|
github.com/checkpoint-restore/go-criu/v5 v5.1.0 h1:BkVH17kcwgmKMnFArsvLrxuBbMwfvPNYRB7mfJ0lzyI=
|
||||||
|
github.com/checkpoint-restore/go-criu/v5 v5.1.0/go.mod h1:iaS8bb7p6zKJanp1Qe8mpl7+bnkYBR500psJR6mwma0=
|
||||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||||
|
|
|
||||||
|
|
@ -780,6 +780,16 @@ type ContainerCheckpointOptions struct {
|
||||||
// Compression tells the API which compression to use for
|
// Compression tells the API which compression to use for
|
||||||
// the exported checkpoint archive.
|
// the exported checkpoint archive.
|
||||||
Compression archive.Compression
|
Compression archive.Compression
|
||||||
|
// If Pod is set the container should be restored into the
|
||||||
|
// given Pod. If Pod is empty it is a restore without a Pod.
|
||||||
|
// Restoring a non Pod container into a Pod or a Pod container
|
||||||
|
// without a Pod is theoretically possible, but will
|
||||||
|
// probably not work if a PID namespace is shared.
|
||||||
|
// A shared PID namespace means that a Pod container has PID 1
|
||||||
|
// in the infrastructure container, but without the infrastructure
|
||||||
|
// container no PID 1 will be in the namespace and that is not
|
||||||
|
// possible.
|
||||||
|
Pod string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkpoint checkpoints a container
|
// Checkpoint checkpoints a container
|
||||||
|
|
@ -811,7 +821,11 @@ func (c *Container) Checkpoint(ctx context.Context, options ContainerCheckpointO
|
||||||
|
|
||||||
// Restore restores a container
|
// Restore restores a container
|
||||||
func (c *Container) Restore(ctx context.Context, options ContainerCheckpointOptions) error {
|
func (c *Container) Restore(ctx context.Context, options ContainerCheckpointOptions) error {
|
||||||
logrus.Debugf("Trying to restore container %s", c.ID())
|
if options.Pod == "" {
|
||||||
|
logrus.Debugf("Trying to restore container %s", c.ID())
|
||||||
|
} else {
|
||||||
|
logrus.Debugf("Trying to restore container %s into pod %s", c.ID(), options.Pod)
|
||||||
|
}
|
||||||
if !c.batched {
|
if !c.batched {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -901,8 +901,27 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
|
func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
|
||||||
if len(c.Dependencies()) > 0 {
|
if len(c.Dependencies()) == 1 {
|
||||||
return errors.Errorf("Cannot export checkpoints of containers with dependencies")
|
// Check if the dependency is an infra container. If it is we can checkpoint
|
||||||
|
// the container out of the Pod.
|
||||||
|
if c.config.Pod == "" {
|
||||||
|
return errors.Errorf("cannot export checkpoints of containers with dependencies")
|
||||||
|
}
|
||||||
|
|
||||||
|
pod, err := c.runtime.state.Pod(c.config.Pod)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", c.ID(), c.config.Pod)
|
||||||
|
}
|
||||||
|
infraID, err := pod.InfraContainerID()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieve infra container ID for pod %s", c.config.Pod)
|
||||||
|
}
|
||||||
|
if c.Dependencies()[0] != infraID {
|
||||||
|
return errors.Errorf("cannot export checkpoints of containers with dependencies")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(c.Dependencies()) > 1 {
|
||||||
|
return errors.Errorf("cannot export checkpoints of containers with dependencies")
|
||||||
}
|
}
|
||||||
logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), options.TargetFile)
|
logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), options.TargetFile)
|
||||||
|
|
||||||
|
|
@ -1021,9 +1040,9 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) checkpointRestoreSupported() error {
|
func (c *Container) checkpointRestoreSupported(version int) error {
|
||||||
if !criu.CheckForCriu() {
|
if !criu.CheckForCriu(version) {
|
||||||
return errors.Errorf("checkpoint/restore requires at least CRIU %d", criu.MinCriuVersion)
|
return errors.Errorf("checkpoint/restore requires at least CRIU %d", version)
|
||||||
}
|
}
|
||||||
if !c.ociRuntime.SupportsCheckpoint() {
|
if !c.ociRuntime.SupportsCheckpoint() {
|
||||||
return errors.Errorf("configured runtime does not support checkpoint/restore")
|
return errors.Errorf("configured runtime does not support checkpoint/restore")
|
||||||
|
|
@ -1032,7 +1051,7 @@ func (c *Container) checkpointRestoreSupported() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) error {
|
func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) error {
|
||||||
if err := c.checkpointRestoreSupported(); err != nil {
|
if err := c.checkpointRestoreSupported(criu.MinCriuVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1136,10 +1155,20 @@ func (c *Container) importPreCheckpoint(input string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (retErr error) {
|
func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (retErr error) {
|
||||||
if err := c.checkpointRestoreSupported(); err != nil {
|
minCriuVersion := func() int {
|
||||||
|
if options.Pod == "" {
|
||||||
|
return criu.MinCriuVersion
|
||||||
|
}
|
||||||
|
return criu.PodCriuVersion
|
||||||
|
}()
|
||||||
|
if err := c.checkpointRestoreSupported(minCriuVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.Pod != "" && !crutils.CRRuntimeSupportsPodCheckpointRestore(c.ociRuntime.Path()) {
|
||||||
|
return errors.Errorf("runtime %s does not support pod restore", c.ociRuntime.Path())
|
||||||
|
}
|
||||||
|
|
||||||
if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) {
|
if !c.ensureState(define.ContainerStateConfigured, define.ContainerStateExited) {
|
||||||
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID())
|
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID())
|
||||||
}
|
}
|
||||||
|
|
@ -1247,6 +1276,83 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.Pod != "" {
|
||||||
|
// Running in a Pod means that we have to change all namespace settings to
|
||||||
|
// the ones from the infrastructure container.
|
||||||
|
pod, err := c.runtime.LookupPod(options.Pod)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "pod %q cannot be retrieved", options.Pod)
|
||||||
|
}
|
||||||
|
|
||||||
|
infraContainer, err := pod.InfraContainer()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieved infra container from pod %q", options.Pod)
|
||||||
|
}
|
||||||
|
|
||||||
|
infraContainer.lock.Lock()
|
||||||
|
if err := infraContainer.syncContainer(); err != nil {
|
||||||
|
infraContainer.lock.Unlock()
|
||||||
|
return errors.Wrapf(err, "Error syncing infrastructure container %s status", infraContainer.ID())
|
||||||
|
}
|
||||||
|
if infraContainer.state.State != define.ContainerStateRunning {
|
||||||
|
if err := infraContainer.initAndStart(ctx); err != nil {
|
||||||
|
infraContainer.lock.Unlock()
|
||||||
|
return errors.Wrapf(err, "Error starting infrastructure container %s status", infraContainer.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
infraContainer.lock.Unlock()
|
||||||
|
|
||||||
|
if c.config.IPCNsCtr != "" {
|
||||||
|
nsPath, err := infraContainer.namespacePath(IPCNS)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieve IPC namespace path for Pod %q", options.Pod)
|
||||||
|
}
|
||||||
|
if err := g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), nsPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.NetNsCtr != "" {
|
||||||
|
nsPath, err := infraContainer.namespacePath(NetNS)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieve network namespace path for Pod %q", options.Pod)
|
||||||
|
}
|
||||||
|
if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), nsPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.PIDNsCtr != "" {
|
||||||
|
nsPath, err := infraContainer.namespacePath(PIDNS)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieve PID namespace path for Pod %q", options.Pod)
|
||||||
|
}
|
||||||
|
if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), nsPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.UTSNsCtr != "" {
|
||||||
|
nsPath, err := infraContainer.namespacePath(UTSNS)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieve UTS namespace path for Pod %q", options.Pod)
|
||||||
|
}
|
||||||
|
if err := g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), nsPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.CgroupNsCtr != "" {
|
||||||
|
nsPath, err := infraContainer.namespacePath(CgroupNS)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "cannot retrieve Cgroup namespace path for Pod %q", options.Pod)
|
||||||
|
}
|
||||||
|
if err := g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), nsPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := c.makeBindMounts(); err != nil {
|
if err := c.makeBindMounts(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1064,6 +1064,30 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
|
||||||
if restoreOptions.TCPEstablished {
|
if restoreOptions.TCPEstablished {
|
||||||
args = append(args, "--runtime-opt", "--tcp-established")
|
args = append(args, "--runtime-opt", "--tcp-established")
|
||||||
}
|
}
|
||||||
|
if restoreOptions.Pod != "" {
|
||||||
|
mountLabel := ctr.config.MountLabel
|
||||||
|
processLabel := ctr.config.ProcessLabel
|
||||||
|
if mountLabel != "" {
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"--runtime-opt",
|
||||||
|
fmt.Sprintf(
|
||||||
|
"--lsm-mount-context=%s",
|
||||||
|
mountLabel,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if processLabel != "" {
|
||||||
|
args = append(
|
||||||
|
args,
|
||||||
|
"--runtime-opt",
|
||||||
|
fmt.Sprintf(
|
||||||
|
"--lsm-profile=selinux:%s",
|
||||||
|
processLabel,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ type RestoreOptions struct {
|
||||||
Keep *bool
|
Keep *bool
|
||||||
Name *string
|
Name *string
|
||||||
TCPEstablished *bool
|
TCPEstablished *bool
|
||||||
|
Pod *string
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run ../generator/generator.go CreateOptions
|
//go:generate go run ../generator/generator.go CreateOptions
|
||||||
|
|
|
||||||
|
|
@ -131,3 +131,19 @@ func (o *RestoreOptions) GetTCPEstablished() bool {
|
||||||
}
|
}
|
||||||
return *o.TCPEstablished
|
return *o.TCPEstablished
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithPod
|
||||||
|
func (o *RestoreOptions) WithPod(value string) *RestoreOptions {
|
||||||
|
v := &value
|
||||||
|
o.Pod = v
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPod
|
||||||
|
func (o *RestoreOptions) GetPod() string {
|
||||||
|
var pod string
|
||||||
|
if o.Pod == nil {
|
||||||
|
return pod
|
||||||
|
}
|
||||||
|
return *o.Pod
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ import (
|
||||||
"github.com/containers/common/libimage"
|
"github.com/containers/common/libimage"
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
"github.com/containers/podman/v3/libpod"
|
"github.com/containers/podman/v3/libpod"
|
||||||
|
ann "github.com/containers/podman/v3/pkg/annotations"
|
||||||
|
"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/domain/entities"
|
||||||
"github.com/containers/podman/v3/pkg/errorhandling"
|
"github.com/containers/podman/v3/pkg/errorhandling"
|
||||||
"github.com/containers/podman/v3/pkg/specgen/generate"
|
"github.com/containers/podman/v3/pkg/specgen/generate"
|
||||||
|
|
@ -68,6 +71,14 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctrConfig.Pod != "" && restoreOptions.Pod == "" {
|
||||||
|
return nil, errors.New("cannot restore pod container without --pod")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrConfig.Pod == "" && restoreOptions.Pod != "" {
|
||||||
|
return nil, errors.New("cannot restore non pod container into pod")
|
||||||
|
}
|
||||||
|
|
||||||
// This should not happen as checkpoints with these options are not exported.
|
// This should not happen as checkpoints with these options are not exported.
|
||||||
if len(ctrConfig.Dependencies) > 0 {
|
if len(ctrConfig.Dependencies) > 0 {
|
||||||
return nil, errors.Errorf("Cannot import checkpoints of containers with dependencies")
|
return nil, errors.Errorf("Cannot import checkpoints of containers with dependencies")
|
||||||
|
|
@ -96,6 +107,91 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
|
||||||
newName = true
|
newName = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if restoreOptions.Pod != "" {
|
||||||
|
// Restoring into a Pod requires much newer versions of CRIU
|
||||||
|
if !criu.CheckForCriu(criu.PodCriuVersion) {
|
||||||
|
return nil, errors.Errorf("restoring containers into pods requires at least CRIU %d", criu.PodCriuVersion)
|
||||||
|
}
|
||||||
|
// The runtime also has to support it
|
||||||
|
if !crutils.CRRuntimeSupportsPodCheckpointRestore(runtime.GetOCIRuntimePath()) {
|
||||||
|
return nil, errors.Errorf("runtime %s does not support pod restore", runtime.GetOCIRuntimePath())
|
||||||
|
}
|
||||||
|
// Restoring into an existing Pod
|
||||||
|
ctrConfig.Pod = restoreOptions.Pod
|
||||||
|
|
||||||
|
// According to podman pod create a pod can share the following namespaces:
|
||||||
|
// cgroup, ipc, net, pid, uts
|
||||||
|
// Let's make sure we a restoring into a pod with the same shared namespaces.
|
||||||
|
pod, err := runtime.LookupPod(ctrConfig.Pod)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "pod %q cannot be retrieved", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
|
||||||
|
infraContainer, err := pod.InfraContainer()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "cannot retrieve infra container from pod %q", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a namespaces was shared (!= "") it needs to be set to the new infrastructure container
|
||||||
|
// If the infrastructure container does not share the same namespaces as the to be restored
|
||||||
|
// container we abort.
|
||||||
|
if ctrConfig.IPCNsCtr != "" {
|
||||||
|
if !pod.SharesIPC() {
|
||||||
|
return nil, errors.Errorf("pod %s does not share the IPC namespace", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
ctrConfig.IPCNsCtr = infraContainer.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrConfig.NetNsCtr != "" {
|
||||||
|
if !pod.SharesNet() {
|
||||||
|
return nil, errors.Errorf("pod %s does not share the network namespace", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
ctrConfig.NetNsCtr = infraContainer.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrConfig.PIDNsCtr != "" {
|
||||||
|
if !pod.SharesPID() {
|
||||||
|
return nil, errors.Errorf("pod %s does not share the PID namespace", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
ctrConfig.PIDNsCtr = infraContainer.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrConfig.UTSNsCtr != "" {
|
||||||
|
if !pod.SharesUTS() {
|
||||||
|
return nil, errors.Errorf("pod %s does not share the UTS namespace", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
ctrConfig.UTSNsCtr = infraContainer.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrConfig.CgroupNsCtr != "" {
|
||||||
|
if !pod.SharesCgroup() {
|
||||||
|
return nil, errors.Errorf("pod %s does not share the cgroup namespace", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
ctrConfig.CgroupNsCtr = infraContainer.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change SELinux labels to infrastructure container labels
|
||||||
|
ctrConfig.MountLabel = infraContainer.MountLabel()
|
||||||
|
ctrConfig.ProcessLabel = infraContainer.ProcessLabel()
|
||||||
|
|
||||||
|
// Fix parent cgroup
|
||||||
|
cgroupPath, err := pod.CgroupPath()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "cannot retrieve cgroup path from pod %q", ctrConfig.Pod)
|
||||||
|
}
|
||||||
|
ctrConfig.CgroupParent = cgroupPath
|
||||||
|
|
||||||
|
oldPodID := dumpSpec.Annotations[ann.SandboxID]
|
||||||
|
// Fix up SandboxID in the annotations
|
||||||
|
dumpSpec.Annotations[ann.SandboxID] = ctrConfig.Pod
|
||||||
|
// Fix up CreateCommand
|
||||||
|
for i, c := range ctrConfig.CreateCommand {
|
||||||
|
if c == oldPodID {
|
||||||
|
ctrConfig.CreateCommand[i] = ctrConfig.Pod
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(restoreOptions.PublishPorts) > 0 {
|
if len(restoreOptions.PublishPorts) > 0 {
|
||||||
ports, _, _, err := generate.ParsePortMapping(restoreOptions.PublishPorts)
|
ports, _, _, err := generate.ParsePortMapping(restoreOptions.PublishPorts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package crutils
|
package crutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -189,3 +190,13 @@ func CRRuntimeSupportsCheckpointRestore(runtimePath string) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CRRuntimeSupportsCheckpointRestore tests if the runtime at 'runtimePath'
|
||||||
|
// supports restoring into existing Pods. The runtime needs to support
|
||||||
|
// the CRIU option --lsm-mount-context and the existence of this is checked
|
||||||
|
// by this function. In addition it is necessary to at least have CRIU 3.16.
|
||||||
|
func CRRuntimeSupportsPodCheckpointRestore(runtimePath string) bool {
|
||||||
|
cmd := exec.Command(runtimePath, "restore", "--lsm-mount-context")
|
||||||
|
out, _ := cmd.CombinedOutput()
|
||||||
|
return bytes.Contains(out, []byte("flag needs an argument"))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
package criu
|
package criu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/checkpoint-restore/go-criu"
|
"github.com/checkpoint-restore/go-criu/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MinCriuVersion for Podman at least CRIU 3.11 is required
|
// MinCriuVersion for Podman at least CRIU 3.11 is required
|
||||||
const MinCriuVersion = 31100
|
const MinCriuVersion = 31100
|
||||||
|
|
||||||
|
// PodCriuVersion is the version of CRIU needed for
|
||||||
|
// checkpointing and restoring containers out of and into Pods.
|
||||||
|
const PodCriuVersion = 31600
|
||||||
|
|
||||||
// CheckForCriu uses CRIU's go bindings to check if the CRIU
|
// CheckForCriu uses CRIU's go bindings to check if the CRIU
|
||||||
// binary exists and if it at least the version Podman needs.
|
// binary exists and if it at least the version Podman needs.
|
||||||
func CheckForCriu() bool {
|
func CheckForCriu(version int) bool {
|
||||||
c := criu.MakeCriu()
|
c := criu.MakeCriu()
|
||||||
result, err := c.IsCriuAtLeast(MinCriuVersion)
|
result, err := c.IsCriuAtLeast(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,7 @@ type RestoreOptions struct {
|
||||||
TCPEstablished bool
|
TCPEstablished bool
|
||||||
ImportPrevious string
|
ImportPrevious string
|
||||||
PublishPorts []specgen.PortMapping
|
PublishPorts []specgen.PortMapping
|
||||||
|
Pod string
|
||||||
}
|
}
|
||||||
|
|
||||||
type RestoreReport struct {
|
type RestoreReport struct {
|
||||||
|
|
|
||||||
|
|
@ -529,6 +529,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
|
||||||
IgnoreStaticIP: options.IgnoreStaticIP,
|
IgnoreStaticIP: options.IgnoreStaticIP,
|
||||||
IgnoreStaticMAC: options.IgnoreStaticMAC,
|
IgnoreStaticMAC: options.IgnoreStaticMAC,
|
||||||
ImportPrevious: options.ImportPrevious,
|
ImportPrevious: options.ImportPrevious,
|
||||||
|
Pod: options.Pod,
|
||||||
}
|
}
|
||||||
|
|
||||||
filterFuncs := []libpod.ContainerFilter{
|
filterFuncs := []libpod.ContainerFilter{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v3/pkg/checkpoint/crutils"
|
||||||
"github.com/containers/podman/v3/pkg/criu"
|
"github.com/containers/podman/v3/pkg/criu"
|
||||||
. "github.com/containers/podman/v3/test/utils"
|
. "github.com/containers/podman/v3/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
|
|
@ -46,7 +48,7 @@ var _ = Describe("Podman checkpoint", func() {
|
||||||
Skip("OCI runtime does not support checkpoint/restore")
|
Skip("OCI runtime does not support checkpoint/restore")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !criu.CheckForCriu() {
|
if !criu.CheckForCriu(criu.MinCriuVersion) {
|
||||||
Skip("CRIU is missing or too old.")
|
Skip("CRIU is missing or too old.")
|
||||||
}
|
}
|
||||||
// Only Fedora 29 and newer has a new enough selinux-policy and
|
// Only Fedora 29 and newer has a new enough selinux-policy and
|
||||||
|
|
@ -977,4 +979,164 @@ var _ = Describe("Podman checkpoint", func() {
|
||||||
// Remove exported checkpoint
|
// Remove exported checkpoint
|
||||||
os.Remove(fileName)
|
os.Remove(fileName)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
namespaceCombination := []string{
|
||||||
|
"cgroup,ipc,net,uts,pid",
|
||||||
|
"cgroup,ipc,net,uts",
|
||||||
|
"cgroup,ipc,net",
|
||||||
|
"cgroup,ipc",
|
||||||
|
"ipc,net,uts,pid",
|
||||||
|
"ipc,net,uts",
|
||||||
|
"ipc,net",
|
||||||
|
"net,uts,pid",
|
||||||
|
"net,uts",
|
||||||
|
"uts,pid",
|
||||||
|
}
|
||||||
|
for _, share := range namespaceCombination {
|
||||||
|
testName := fmt.Sprintf(
|
||||||
|
"podman checkpoint and restore container out of and into pod (%s)",
|
||||||
|
share,
|
||||||
|
)
|
||||||
|
It(testName, func() {
|
||||||
|
if !criu.CheckForCriu(criu.PodCriuVersion) {
|
||||||
|
Skip("CRIU is missing or too old.")
|
||||||
|
}
|
||||||
|
if !crutils.CRRuntimeSupportsPodCheckpointRestore(podmanTest.OCIRuntime) {
|
||||||
|
Skip("runtime does not support pod restore")
|
||||||
|
}
|
||||||
|
// Create a pod
|
||||||
|
session := podmanTest.Podman([]string{
|
||||||
|
"pod",
|
||||||
|
"create",
|
||||||
|
"--share",
|
||||||
|
share,
|
||||||
|
})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).To(Exit(0))
|
||||||
|
podID := session.OutputToString()
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{
|
||||||
|
"run",
|
||||||
|
"-d",
|
||||||
|
"--rm",
|
||||||
|
"--pod",
|
||||||
|
podID,
|
||||||
|
ALPINE,
|
||||||
|
"top",
|
||||||
|
})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).To(Exit(0))
|
||||||
|
cid := session.OutputToString()
|
||||||
|
|
||||||
|
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
|
||||||
|
|
||||||
|
// Checkpoint the container
|
||||||
|
result := podmanTest.Podman([]string{
|
||||||
|
"container",
|
||||||
|
"checkpoint",
|
||||||
|
"-e",
|
||||||
|
fileName,
|
||||||
|
cid,
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
|
||||||
|
// As the container has been started with '--rm' it will be completely
|
||||||
|
// cleaned up after checkpointing.
|
||||||
|
Expect(result).To(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||||
|
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
|
||||||
|
|
||||||
|
// Remove the pod and create a new pod
|
||||||
|
result = podmanTest.Podman([]string{
|
||||||
|
"pod",
|
||||||
|
"rm",
|
||||||
|
podID,
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).To(Exit(0))
|
||||||
|
|
||||||
|
// First create a pod with different shared namespaces.
|
||||||
|
// Restore should fail
|
||||||
|
|
||||||
|
wrongShare := share[:strings.LastIndex(share, ",")]
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{
|
||||||
|
"pod",
|
||||||
|
"create",
|
||||||
|
"--share",
|
||||||
|
wrongShare,
|
||||||
|
})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).To(Exit(0))
|
||||||
|
podID = session.OutputToString()
|
||||||
|
|
||||||
|
// Restore container with different port mapping
|
||||||
|
result = podmanTest.Podman([]string{
|
||||||
|
"container",
|
||||||
|
"restore",
|
||||||
|
"--pod",
|
||||||
|
podID,
|
||||||
|
"-i",
|
||||||
|
fileName,
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).To(Exit(125))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("does not share the"))
|
||||||
|
|
||||||
|
// Remove the pod and create a new pod
|
||||||
|
result = podmanTest.Podman([]string{
|
||||||
|
"pod",
|
||||||
|
"rm",
|
||||||
|
podID,
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).To(Exit(0))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{
|
||||||
|
"pod",
|
||||||
|
"create",
|
||||||
|
"--share",
|
||||||
|
share,
|
||||||
|
})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).To(Exit(0))
|
||||||
|
podID = session.OutputToString()
|
||||||
|
|
||||||
|
// Restore container with different port mapping
|
||||||
|
result = podmanTest.Podman([]string{
|
||||||
|
"container",
|
||||||
|
"restore",
|
||||||
|
"--pod",
|
||||||
|
podID,
|
||||||
|
"-i",
|
||||||
|
fileName,
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
|
||||||
|
Expect(result).To(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
|
||||||
|
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
|
||||||
|
|
||||||
|
result = podmanTest.Podman([]string{
|
||||||
|
"rm",
|
||||||
|
"-f",
|
||||||
|
result.OutputToString(),
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).To(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||||
|
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
|
||||||
|
|
||||||
|
result = podmanTest.Podman([]string{
|
||||||
|
"pod",
|
||||||
|
"rm",
|
||||||
|
"-fa",
|
||||||
|
})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).To(Exit(0))
|
||||||
|
|
||||||
|
// Remove exported checkpoint
|
||||||
|
os.Remove(fileName)
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
test/test
|
|
||||||
test/piggie
|
|
||||||
test/phaul
|
|
||||||
image
|
|
||||||
rpc/rpc.proto
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
language: go
|
|
||||||
sudo: required
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
go:
|
|
||||||
- "1.8"
|
|
||||||
- "1.9"
|
|
||||||
- "1.10"
|
|
||||||
env:
|
|
||||||
# Run the tests with CRIU master and criu-dev
|
|
||||||
- CRIU_BRANCH="master"
|
|
||||||
- CRIU_BRANCH="criu-dev"
|
|
||||||
install:
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install -y libprotobuf-dev libprotobuf-c0-dev protobuf-c-compiler protobuf-compiler python-protobuf libnl-3-dev libnet-dev libcap-dev
|
|
||||||
- go get github.com/checkpoint-restore/go-criu
|
|
||||||
- git clone --single-branch -b ${CRIU_BRANCH} https://github.com/checkpoint-restore/criu.git
|
|
||||||
- cd criu; make
|
|
||||||
- sudo install -D -m 755 criu/criu /usr/sbin/
|
|
||||||
- cd ..
|
|
||||||
script:
|
|
||||||
# This builds the code without running the tests.
|
|
||||||
- make build phaul test/test test/phaul test/piggie
|
|
||||||
# Run actual test as root as it uses CRIU.
|
|
||||||
- sudo make test phaul-test
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
GO ?= go
|
|
||||||
CC ?= gcc
|
|
||||||
ifeq ($(GOPATH),)
|
|
||||||
export GOPATH := $(shell $(GO) env GOPATH)
|
|
||||||
endif
|
|
||||||
FIRST_GOPATH := $(firstword $(subst :, ,$(GOPATH)))
|
|
||||||
GOBIN := $(shell $(GO) env GOBIN)
|
|
||||||
ifeq ($(GOBIN),)
|
|
||||||
GOBIN := $(FIRST_GOPATH)/bin
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: build test phaul phaul-test
|
|
||||||
|
|
||||||
lint:
|
|
||||||
@golint . test phaul
|
|
||||||
build:
|
|
||||||
@$(GO) build -v
|
|
||||||
|
|
||||||
test/piggie: test/piggie.c
|
|
||||||
@$(CC) $^ -o $@
|
|
||||||
|
|
||||||
test/test: test/main.go
|
|
||||||
@$(GO) build -v -o test/test test/main.go
|
|
||||||
|
|
||||||
test: test/test test/piggie
|
|
||||||
mkdir -p image
|
|
||||||
test/piggie
|
|
||||||
test/test dump `pidof piggie` image
|
|
||||||
test/test restore image
|
|
||||||
pkill -9 piggie || :
|
|
||||||
|
|
||||||
phaul:
|
|
||||||
@cd phaul; go build -v
|
|
||||||
|
|
||||||
test/phaul: test/phaul-main.go
|
|
||||||
@$(GO) build -v -o test/phaul test/phaul-main.go
|
|
||||||
|
|
||||||
phaul-test: test/phaul test/piggie
|
|
||||||
rm -rf image
|
|
||||||
test/piggie
|
|
||||||
test/phaul `pidof piggie`
|
|
||||||
pkill -9 piggie || :
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@rm -f test/test test/piggie test/phaul
|
|
||||||
@rm -rf image
|
|
||||||
@rm -f rpc/rpc.proto
|
|
||||||
|
|
||||||
install.tools:
|
|
||||||
if [ ! -x "$(GOBIN)/golint" ]; then \
|
|
||||||
$(GO) get -u golang.org/x/lint/golint; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
rpc/rpc.proto:
|
|
||||||
curl -s https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@
|
|
||||||
|
|
||||||
rpc/rpc.pb.go: rpc/rpc.proto
|
|
||||||
protoc --go_out=. $^
|
|
||||||
|
|
||||||
.PHONY: build test clean lint phaul
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,5 @@
|
||||||
|
test/test
|
||||||
|
test/piggie/piggie
|
||||||
|
test/phaul
|
||||||
|
image
|
||||||
|
stats/stats.proto
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
run:
|
||||||
|
skip_dirs:
|
||||||
|
- rpc
|
||||||
|
- stats
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: false
|
||||||
|
presets:
|
||||||
|
- bugs
|
||||||
|
- performance
|
||||||
|
- unused
|
||||||
|
- format
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
GO ?= go
|
||||||
|
CC ?= gcc
|
||||||
|
|
||||||
|
all: build test phaul-test
|
||||||
|
|
||||||
|
lint:
|
||||||
|
golangci-lint run ./...
|
||||||
|
|
||||||
|
build:
|
||||||
|
$(GO) build -v ./...
|
||||||
|
|
||||||
|
TEST_BINARIES := test/test test/piggie/piggie test/phaul/phaul
|
||||||
|
test-bin: $(TEST_BINARIES)
|
||||||
|
|
||||||
|
test/piggie/piggie: test/piggie/piggie.c
|
||||||
|
$(CC) $^ -o $@
|
||||||
|
|
||||||
|
test/test: test/*.go
|
||||||
|
$(GO) build -v -o $@ $^
|
||||||
|
|
||||||
|
test: $(TEST_BINARIES)
|
||||||
|
mkdir -p image
|
||||||
|
PID=$$(test/piggie/piggie) && { \
|
||||||
|
test/test dump $$PID image && \
|
||||||
|
test/test restore image; \
|
||||||
|
pkill -9 piggie; \
|
||||||
|
}
|
||||||
|
rm -rf image
|
||||||
|
|
||||||
|
test/phaul/phaul: test/phaul/*.go
|
||||||
|
$(GO) build -v -o $@ $^
|
||||||
|
|
||||||
|
phaul-test: $(TEST_BINARIES)
|
||||||
|
rm -rf image
|
||||||
|
PID=$$(test/piggie/piggie) && { \
|
||||||
|
test/phaul/phaul $$PID; \
|
||||||
|
pkill -9 piggie; \
|
||||||
|
}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f $(TEST_BINARIES)
|
||||||
|
@rm -rf image
|
||||||
|
@rm -f rpc/rpc.proto stats/stats.proto
|
||||||
|
|
||||||
|
rpc/rpc.proto:
|
||||||
|
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@
|
||||||
|
|
||||||
|
stats/stats.proto:
|
||||||
|
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/stats.proto -o $@
|
||||||
|
|
||||||
|
rpc/rpc.pb.go: rpc/rpc.proto
|
||||||
|
protoc --go_out=. --go_opt=Mrpc/rpc.proto=rpc/ $^
|
||||||
|
|
||||||
|
stats/stats.pb.go: stats/stats.proto
|
||||||
|
protoc --go_out=. $^
|
||||||
|
|
||||||
|
vendor:
|
||||||
|
GO111MODULE=on $(GO) mod tidy
|
||||||
|
GO111MODULE=on $(GO) mod vendor
|
||||||
|
GO111MODULE=on $(GO) mod verify
|
||||||
|
|
||||||
|
.PHONY: build test phaul-test test-bin clean lint vendor
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
[](https://travis-ci.org/checkpoint-restore/go-criu)
|
[](https://github.com/checkpoint-restore/go-criu/actions?query=workflow%3Aci)
|
||||||
|
[](https://github.com/checkpoint-restore/go-criu/actions?query=workflow%3Averify)
|
||||||
|
[](https://pkg.go.dev/github.com/checkpoint-restore/go-criu)
|
||||||
|
|
||||||
## go-criu -- Go bindings for [CRIU](https://criu.org/)
|
## go-criu -- Go bindings for CRIU
|
||||||
|
|
||||||
This repository provides Go bindings for CRIU. The code is based on the Go based PHaul
|
This repository provides Go bindings for [CRIU](https://criu.org/). The code is based on the Go-based PHaul
|
||||||
implementation from the CRIU repository. For easier inclusion into other Go projects the
|
implementation from the CRIU repository. For easier inclusion into other Go projects the
|
||||||
CRIU Go bindings have been moved to this repository.
|
CRIU Go bindings have been moved to this repository.
|
||||||
|
|
||||||
|
|
@ -10,24 +12,46 @@ The Go bindings provide an easy way to use the CRIU RPC calls from Go without th
|
||||||
to set up all the infrastructure to make the actual RPC connection to CRIU.
|
to set up all the infrastructure to make the actual RPC connection to CRIU.
|
||||||
|
|
||||||
The following example would print the version of CRIU:
|
The following example would print the version of CRIU:
|
||||||
```
|
```go
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/checkpoint/restore/go-criu/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
c := criu.MakeCriu()
|
c := criu.MakeCriu()
|
||||||
version, err := c.GetCriuVersion()
|
version, err := c.GetCriuVersion()
|
||||||
fmt.Println(version)
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
log.Println(version)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
or to just check if at least a certain CRIU version is installed:
|
or to just check if at least a certain CRIU version is installed:
|
||||||
```
|
|
||||||
|
```go
|
||||||
c := criu.MakeCriu()
|
c := criu.MakeCriu()
|
||||||
result, err := c.IsCriuAtLeast(31100)
|
result, err := c.IsCriuAtLeast(31100)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
go-criu will carry the same version number as CRIU. This implies that each
|
The first go-criu release was 3.11 based on CRIU 3.11. The initial plan
|
||||||
go-criu release will pull in the necessary changes from CRIU before making a
|
was to follow CRIU so that go-criu would carry the same version number as
|
||||||
release.
|
CRIU.
|
||||||
|
|
||||||
The first go-criu release was 3.11 based on CRIU 3.11.
|
As go-criu is imported in other projects and as Go modules are expected
|
||||||
|
to follow Semantic Versioning go-criu will also follow Semantic Versioning
|
||||||
|
starting with the 4.0.0 release.
|
||||||
|
|
||||||
|
The following table shows the relation between go-criu and criu versions:
|
||||||
|
|
||||||
|
| Major version | Latest release | CRIU version |
|
||||||
|
| -------------- | -------------- | ------------ |
|
||||||
|
| v5 | 5.0.0 | 3.15 |
|
||||||
|
| v4 | 4.1.0 | 3.14 |
|
||||||
|
|
||||||
## How to contribute
|
## How to contribute
|
||||||
|
|
||||||
|
|
@ -61,6 +85,11 @@ by adding a "Signed-off-by" line containing the contributor's name and e-mail
|
||||||
to every commit message. Your signature certifies that you wrote the patch or
|
to every commit message. Your signature certifies that you wrote the patch or
|
||||||
otherwise have the right to pass it on as an open-source patch.
|
otherwise have the right to pass it on as an open-source patch.
|
||||||
|
|
||||||
### License
|
### License and copyright
|
||||||
|
|
||||||
The license of go-criu is the Apache 2.0 license.
|
Unless mentioned otherwise in a specific file's header, all code in
|
||||||
|
this project is released under the Apache 2.0 license.
|
||||||
|
|
||||||
|
The author of a change remains the copyright holder of their code
|
||||||
|
(no copyright assignment). The list of authors and contributors can be
|
||||||
|
retrieved from the git commit history and in some cases, the file headers.
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
module github.com/checkpoint-restore/go-criu/v5
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/golang/protobuf v1.5.2
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||||
|
google.golang.org/protobuf v1.26.0
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||||
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
|
@ -8,19 +8,28 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/checkpoint-restore/go-criu/rpc"
|
"github.com/checkpoint-restore/go-criu/v5/rpc"
|
||||||
"github.com/golang/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Criu struct
|
// Criu struct
|
||||||
type Criu struct {
|
type Criu struct {
|
||||||
swrkCmd *exec.Cmd
|
swrkCmd *exec.Cmd
|
||||||
swrkSk *os.File
|
swrkSk *os.File
|
||||||
|
swrkPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeCriu returns the Criu object required for most operations
|
// MakeCriu returns the Criu object required for most operations
|
||||||
func MakeCriu() *Criu {
|
func MakeCriu() *Criu {
|
||||||
return &Criu{}
|
return &Criu{
|
||||||
|
swrkPath: "criu",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCriuPath allows setting the path to the CRIU binary
|
||||||
|
// if it is in a non standard location
|
||||||
|
func (c *Criu) SetCriuPath(path string) {
|
||||||
|
c.swrkPath = path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare sets up everything for the RPC communication to CRIU
|
// Prepare sets up everything for the RPC communication to CRIU
|
||||||
|
|
@ -36,7 +45,8 @@ func (c *Criu) Prepare() error {
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
args := []string{"swrk", strconv.Itoa(fds[1])}
|
args := []string{"swrk", strconv.Itoa(fds[1])}
|
||||||
cmd := exec.Command("criu", args...)
|
// #nosec G204
|
||||||
|
cmd := exec.Command(c.swrkPath, args...)
|
||||||
|
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -55,7 +65,7 @@ func (c *Criu) Cleanup() {
|
||||||
if c.swrkCmd != nil {
|
if c.swrkCmd != nil {
|
||||||
c.swrkSk.Close()
|
c.swrkSk.Close()
|
||||||
c.swrkSk = nil
|
c.swrkSk = nil
|
||||||
c.swrkCmd.Wait()
|
_ = c.swrkCmd.Wait()
|
||||||
c.swrkCmd = nil
|
c.swrkCmd = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -178,28 +188,28 @@ func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy N
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump dumps a process
|
// Dump dumps a process
|
||||||
func (c *Criu) Dump(opts rpc.CriuOpts, nfy Notify) error {
|
func (c *Criu) Dump(opts *rpc.CriuOpts, nfy Notify) error {
|
||||||
return c.doSwrk(rpc.CriuReqType_DUMP, &opts, nfy)
|
return c.doSwrk(rpc.CriuReqType_DUMP, opts, nfy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores a process
|
// Restore restores a process
|
||||||
func (c *Criu) Restore(opts rpc.CriuOpts, nfy Notify) error {
|
func (c *Criu) Restore(opts *rpc.CriuOpts, nfy Notify) error {
|
||||||
return c.doSwrk(rpc.CriuReqType_RESTORE, &opts, nfy)
|
return c.doSwrk(rpc.CriuReqType_RESTORE, opts, nfy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreDump does a pre-dump
|
// PreDump does a pre-dump
|
||||||
func (c *Criu) PreDump(opts rpc.CriuOpts, nfy Notify) error {
|
func (c *Criu) PreDump(opts *rpc.CriuOpts, nfy Notify) error {
|
||||||
return c.doSwrk(rpc.CriuReqType_PRE_DUMP, &opts, nfy)
|
return c.doSwrk(rpc.CriuReqType_PRE_DUMP, opts, nfy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartPageServer starts the page server
|
// StartPageServer starts the page server
|
||||||
func (c *Criu) StartPageServer(opts rpc.CriuOpts) error {
|
func (c *Criu) StartPageServer(opts *rpc.CriuOpts) error {
|
||||||
return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, &opts, nil)
|
return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, opts, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartPageServerChld starts the page server and returns PID and port
|
// StartPageServerChld starts the page server and returns PID and port
|
||||||
func (c *Criu) StartPageServerChld(opts rpc.CriuOpts) (int, int, error) {
|
func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) {
|
||||||
resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, &opts, nil)
|
resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, opts, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -219,8 +229,8 @@ func (c *Criu) GetCriuVersion() (int, error) {
|
||||||
return 0, fmt.Errorf("Unexpected CRIU RPC response")
|
return 0, fmt.Errorf("Unexpected CRIU RPC response")
|
||||||
}
|
}
|
||||||
|
|
||||||
version := int(*resp.GetVersion().Major) * 10000
|
version := int(*resp.GetVersion().MajorNumber) * 10000
|
||||||
version += int(*resp.GetVersion().Minor) * 100
|
version += int(*resp.GetVersion().MinorNumber) * 100
|
||||||
if resp.GetVersion().Sublevel != nil {
|
if resp.GetVersion().Sublevel != nil {
|
||||||
version += int(*resp.GetVersion().Sublevel)
|
version += int(*resp.GetVersion().Sublevel)
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package criu
|
package criu
|
||||||
|
|
||||||
//Notify interface
|
// Notify interface
|
||||||
type Notify interface {
|
type Notify interface {
|
||||||
PreDump() error
|
PreDump() error
|
||||||
PostDump() error
|
PostDump() error
|
||||||
|
|
@ -14,8 +14,7 @@ type Notify interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoNotify struct
|
// NoNotify struct
|
||||||
type NoNotify struct {
|
type NoNotify struct{}
|
||||||
}
|
|
||||||
|
|
||||||
// PreDump NoNotify
|
// PreDump NoNotify
|
||||||
func (c NoNotify) PreDump() error {
|
func (c NoNotify) PreDump() error {
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,239 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
message criu_page_server_info {
|
||||||
|
optional string address = 1;
|
||||||
|
optional int32 port = 2;
|
||||||
|
optional int32 pid = 3;
|
||||||
|
optional int32 fd = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_veth_pair {
|
||||||
|
required string if_in = 1;
|
||||||
|
required string if_out = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message ext_mount_map {
|
||||||
|
required string key = 1;
|
||||||
|
required string val = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message join_namespace {
|
||||||
|
required string ns = 1;
|
||||||
|
required string ns_file = 2;
|
||||||
|
optional string extra_opt = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message inherit_fd {
|
||||||
|
required string key = 1;
|
||||||
|
required int32 fd = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message cgroup_root {
|
||||||
|
optional string ctrl = 1;
|
||||||
|
required string path = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message unix_sk {
|
||||||
|
required uint32 inode = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum criu_cg_mode {
|
||||||
|
IGNORE = 0;
|
||||||
|
CG_NONE = 1;
|
||||||
|
PROPS = 2;
|
||||||
|
SOFT = 3;
|
||||||
|
FULL = 4;
|
||||||
|
STRICT = 5;
|
||||||
|
DEFAULT = 6;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum criu_pre_dump_mode {
|
||||||
|
SPLICE = 1;
|
||||||
|
VM_READ = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message criu_opts {
|
||||||
|
required int32 images_dir_fd = 1;
|
||||||
|
optional int32 pid = 2; /* if not set on dump, will dump requesting process */
|
||||||
|
|
||||||
|
optional bool leave_running = 3;
|
||||||
|
optional bool ext_unix_sk = 4;
|
||||||
|
optional bool tcp_established = 5;
|
||||||
|
optional bool evasive_devices = 6;
|
||||||
|
optional bool shell_job = 7;
|
||||||
|
optional bool file_locks = 8;
|
||||||
|
optional int32 log_level = 9 [default = 2];
|
||||||
|
optional string log_file = 10; /* No subdirs are allowed. Consider using work-dir */
|
||||||
|
|
||||||
|
optional criu_page_server_info ps = 11;
|
||||||
|
|
||||||
|
optional bool notify_scripts = 12;
|
||||||
|
|
||||||
|
optional string root = 13;
|
||||||
|
optional string parent_img = 14;
|
||||||
|
optional bool track_mem = 15;
|
||||||
|
optional bool auto_dedup = 16;
|
||||||
|
|
||||||
|
optional int32 work_dir_fd = 17;
|
||||||
|
optional bool link_remap = 18;
|
||||||
|
repeated criu_veth_pair veths = 19; /* DEPRECATED, use external instead */
|
||||||
|
|
||||||
|
optional uint32 cpu_cap = 20 [default = 0xffffffff];
|
||||||
|
optional bool force_irmap = 21;
|
||||||
|
repeated string exec_cmd = 22;
|
||||||
|
|
||||||
|
repeated ext_mount_map ext_mnt = 23; /* DEPRECATED, use external instead */
|
||||||
|
optional bool manage_cgroups = 24; /* backward compatibility */
|
||||||
|
repeated cgroup_root cg_root = 25;
|
||||||
|
|
||||||
|
optional bool rst_sibling = 26; /* swrk only */
|
||||||
|
repeated inherit_fd inherit_fd = 27; /* swrk only */
|
||||||
|
|
||||||
|
optional bool auto_ext_mnt = 28;
|
||||||
|
optional bool ext_sharing = 29;
|
||||||
|
optional bool ext_masters = 30;
|
||||||
|
|
||||||
|
repeated string skip_mnt = 31;
|
||||||
|
repeated string enable_fs = 32;
|
||||||
|
|
||||||
|
repeated unix_sk unix_sk_ino = 33; /* DEPRECATED, use external instead */
|
||||||
|
|
||||||
|
optional criu_cg_mode manage_cgroups_mode = 34;
|
||||||
|
optional uint32 ghost_limit = 35 [default = 0x100000];
|
||||||
|
repeated string irmap_scan_paths = 36;
|
||||||
|
repeated string external = 37;
|
||||||
|
optional uint32 empty_ns = 38;
|
||||||
|
repeated join_namespace join_ns = 39;
|
||||||
|
|
||||||
|
optional string cgroup_props = 41;
|
||||||
|
optional string cgroup_props_file = 42;
|
||||||
|
repeated string cgroup_dump_controller = 43;
|
||||||
|
|
||||||
|
optional string freeze_cgroup = 44;
|
||||||
|
optional uint32 timeout = 45;
|
||||||
|
optional bool tcp_skip_in_flight = 46;
|
||||||
|
optional bool weak_sysctls = 47;
|
||||||
|
optional bool lazy_pages = 48;
|
||||||
|
optional int32 status_fd = 49;
|
||||||
|
optional bool orphan_pts_master = 50;
|
||||||
|
optional string config_file = 51;
|
||||||
|
optional bool tcp_close = 52;
|
||||||
|
optional string lsm_profile = 53;
|
||||||
|
optional string tls_cacert = 54;
|
||||||
|
optional string tls_cacrl = 55;
|
||||||
|
optional string tls_cert = 56;
|
||||||
|
optional string tls_key = 57;
|
||||||
|
optional bool tls = 58;
|
||||||
|
optional bool tls_no_cn_verify = 59;
|
||||||
|
optional string cgroup_yard = 60;
|
||||||
|
optional criu_pre_dump_mode pre_dump_mode = 61 [default = SPLICE];
|
||||||
|
optional int32 pidfd_store_sk = 62;
|
||||||
|
optional string lsm_mount_context = 63;
|
||||||
|
/* optional bool check_mounts = 128; */
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_dump_resp {
|
||||||
|
optional bool restored = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_restore_resp {
|
||||||
|
required int32 pid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_notify {
|
||||||
|
optional string script = 1;
|
||||||
|
optional int32 pid = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum criu_req_type {
|
||||||
|
EMPTY = 0;
|
||||||
|
DUMP = 1;
|
||||||
|
RESTORE = 2;
|
||||||
|
CHECK = 3;
|
||||||
|
PRE_DUMP = 4;
|
||||||
|
PAGE_SERVER = 5;
|
||||||
|
|
||||||
|
NOTIFY = 6;
|
||||||
|
|
||||||
|
CPUINFO_DUMP = 7;
|
||||||
|
CPUINFO_CHECK = 8;
|
||||||
|
|
||||||
|
FEATURE_CHECK = 9;
|
||||||
|
|
||||||
|
VERSION = 10;
|
||||||
|
|
||||||
|
WAIT_PID = 11;
|
||||||
|
PAGE_SERVER_CHLD = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of features which can queried via
|
||||||
|
* CRIU_REQ_TYPE__FEATURE_CHECK
|
||||||
|
*/
|
||||||
|
message criu_features {
|
||||||
|
optional bool mem_track = 1;
|
||||||
|
optional bool lazy_pages = 2;
|
||||||
|
optional bool pidfd_store = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request -- each type corresponds to must-be-there
|
||||||
|
* request arguments of respective type
|
||||||
|
*/
|
||||||
|
|
||||||
|
message criu_req {
|
||||||
|
required criu_req_type type = 1;
|
||||||
|
|
||||||
|
optional criu_opts opts = 2;
|
||||||
|
optional bool notify_success = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When set service won't close the connection but
|
||||||
|
* will wait for more req-s to appear. Works not
|
||||||
|
* for all request types.
|
||||||
|
*/
|
||||||
|
optional bool keep_open = 4;
|
||||||
|
/*
|
||||||
|
* 'features' can be used to query which features
|
||||||
|
* are supported by the installed criu/kernel
|
||||||
|
* via RPC.
|
||||||
|
*/
|
||||||
|
optional criu_features features = 5;
|
||||||
|
|
||||||
|
/* 'pid' is used for WAIT_PID */
|
||||||
|
optional uint32 pid = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response -- it states whether the request was served
|
||||||
|
* and additional request-specific information
|
||||||
|
*/
|
||||||
|
|
||||||
|
message criu_resp {
|
||||||
|
required criu_req_type type = 1;
|
||||||
|
required bool success = 2;
|
||||||
|
|
||||||
|
optional criu_dump_resp dump = 3;
|
||||||
|
optional criu_restore_resp restore = 4;
|
||||||
|
optional criu_notify notify = 5;
|
||||||
|
optional criu_page_server_info ps = 6;
|
||||||
|
|
||||||
|
optional int32 cr_errno = 7;
|
||||||
|
optional criu_features features = 8;
|
||||||
|
optional string cr_errmsg = 9;
|
||||||
|
optional criu_version version = 10;
|
||||||
|
|
||||||
|
optional int32 status = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Answer for criu_req_type.VERSION requests */
|
||||||
|
message criu_version {
|
||||||
|
required int32 major_number = 1;
|
||||||
|
required int32 minor_number = 2;
|
||||||
|
optional string gitid = 3;
|
||||||
|
optional int32 sublevel = 4;
|
||||||
|
optional int32 extra = 5;
|
||||||
|
optional string name = 6;
|
||||||
|
}
|
||||||
|
|
@ -46,9 +46,9 @@ github.com/buger/goterm
|
||||||
github.com/cespare/xxhash/v2
|
github.com/cespare/xxhash/v2
|
||||||
# github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
|
# github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
|
||||||
github.com/checkpoint-restore/checkpointctl/lib
|
github.com/checkpoint-restore/checkpointctl/lib
|
||||||
# github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b
|
# github.com/checkpoint-restore/go-criu/v5 v5.1.0
|
||||||
github.com/checkpoint-restore/go-criu
|
github.com/checkpoint-restore/go-criu/v5
|
||||||
github.com/checkpoint-restore/go-criu/rpc
|
github.com/checkpoint-restore/go-criu/v5/rpc
|
||||||
# github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
# github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||||
github.com/chzyer/readline
|
github.com/chzyer/readline
|
||||||
# github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9
|
# github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue