mirror of
https://github.com/containers/podman.git
synced 2025-06-25 12:20:42 +08:00
remote-client checkpoint/restore
add the ability for the remote client to be able to checkpoint and restore containers. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
@ -1,13 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/containers/libpod/pkg/rootless"
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -57,7 +53,7 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error {
|
|||||||
return errors.New("checkpointing a container requires root")
|
return errors.New("checkpointing a container requires root")
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "could not get runtime")
|
return errors.Wrapf(err, "could not get runtime")
|
||||||
}
|
}
|
||||||
@ -68,17 +64,5 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error {
|
|||||||
KeepRunning: c.LeaveRunning,
|
KeepRunning: c.LeaveRunning,
|
||||||
TCPEstablished: c.TcpEstablished,
|
TCPEstablished: c.TcpEstablished,
|
||||||
}
|
}
|
||||||
containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
|
return runtime.Checkpoint(c, options)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/containers/libpod/pkg/rootless"
|
"github.com/containers/libpod/pkg/rootless"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -57,7 +53,7 @@ func restoreCmd(c *cliconfig.RestoreValues) error {
|
|||||||
return errors.New("restoring a container requires root")
|
return errors.New("restoring a container requires root")
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "could not get runtime")
|
return errors.Wrapf(err, "could not get runtime")
|
||||||
}
|
}
|
||||||
@ -67,18 +63,5 @@ func restoreCmd(c *cliconfig.RestoreValues) error {
|
|||||||
Keep: c.Keep,
|
Keep: c.Keep,
|
||||||
TCPEstablished: c.TcpEstablished,
|
TCPEstablished: c.TcpEstablished,
|
||||||
}
|
}
|
||||||
|
return runtime.Restore(c, options)
|
||||||
containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateExited, "checkpointed")
|
|
||||||
|
|
||||||
for _, ctr := range containers {
|
|
||||||
if err = ctr.Restore(context.TODO(), options); err != nil {
|
|
||||||
if lastError != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, lastError)
|
|
||||||
}
|
|
||||||
lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID())
|
|
||||||
} else {
|
|
||||||
fmt.Println(ctr.ID())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lastError
|
|
||||||
}
|
}
|
||||||
|
@ -443,3 +443,67 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checkpoint one or more containers
|
||||||
|
func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error {
|
||||||
|
var (
|
||||||
|
containers []*libpod.Container
|
||||||
|
err, lastError error
|
||||||
|
)
|
||||||
|
|
||||||
|
if c.All {
|
||||||
|
containers, err = r.Runtime.GetRunningContainers()
|
||||||
|
} else {
|
||||||
|
containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore one or more containers
|
||||||
|
func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error {
|
||||||
|
var (
|
||||||
|
containers []*libpod.Container
|
||||||
|
err, lastError error
|
||||||
|
filterFuncs []libpod.ContainerFilter
|
||||||
|
)
|
||||||
|
|
||||||
|
filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
|
||||||
|
state, _ := c.State()
|
||||||
|
return state == libpod.ContainerStateExited
|
||||||
|
})
|
||||||
|
|
||||||
|
if c.All {
|
||||||
|
containers, err = r.GetContainers(filterFuncs...)
|
||||||
|
} else {
|
||||||
|
containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ctr := range containers {
|
||||||
|
if err = ctr.Restore(context.TODO(), options); err != nil {
|
||||||
|
if lastError != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, lastError)
|
||||||
|
}
|
||||||
|
lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID())
|
||||||
|
} else {
|
||||||
|
fmt.Println(ctr.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastError
|
||||||
|
}
|
||||||
|
@ -539,3 +539,75 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
|
|||||||
}
|
}
|
||||||
return <-errChan
|
return <-errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checkpoint one or more containers
|
||||||
|
func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error {
|
||||||
|
var lastError error
|
||||||
|
ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.All {
|
||||||
|
// We dont have a great way to get all the running containers, so need to get all and then
|
||||||
|
// check status on them bc checkpoint considers checkpointing a stopped container an error
|
||||||
|
var runningIds []string
|
||||||
|
for _, id := range ids {
|
||||||
|
ctr, err := r.LookupContainer(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ctr.state.State == libpod.ContainerStateRunning {
|
||||||
|
runningIds = append(runningIds, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ids = runningIds
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range ids {
|
||||||
|
if _, err := iopodman.ContainerCheckpoint().Call(r.Conn, id, options.Keep, options.KeepRunning, options.TCPEstablished); err != nil {
|
||||||
|
if lastError != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, lastError)
|
||||||
|
}
|
||||||
|
lastError = errors.Wrapf(err, "failed to checkpoint container %v", id)
|
||||||
|
} else {
|
||||||
|
fmt.Println(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore one or more containers
|
||||||
|
func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error {
|
||||||
|
var lastError error
|
||||||
|
ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.All {
|
||||||
|
// We dont have a great way to get all the exited containers, so need to get all and then
|
||||||
|
// check status on them bc checkpoint considers restoring a running container an error
|
||||||
|
var exitedIDs []string
|
||||||
|
for _, id := range ids {
|
||||||
|
ctr, err := r.LookupContainer(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ctr.state.State != libpod.ContainerStateRunning {
|
||||||
|
exitedIDs = append(exitedIDs, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ids = exitedIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, id := range ids {
|
||||||
|
if _, err := iopodman.ContainerRestore().Call(r.Conn, id, options.Keep, options.TCPEstablished); err != nil {
|
||||||
|
if lastError != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, lastError)
|
||||||
|
}
|
||||||
|
lastError = errors.Wrapf(err, "failed to restore container %v", id)
|
||||||
|
} else {
|
||||||
|
fmt.Println(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastError
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user