summaryrefslogtreecommitdiffhomepage
path: root/runsc/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/cmd')
-rw-r--r--runsc/cmd/checkpoint.go57
1 files changed, 52 insertions, 5 deletions
diff --git a/runsc/cmd/checkpoint.go b/runsc/cmd/checkpoint.go
index a28eb0f02..9348289ca 100644
--- a/runsc/cmd/checkpoint.go
+++ b/runsc/cmd/checkpoint.go
@@ -17,12 +17,15 @@ package cmd
import (
"os"
"path/filepath"
+ "syscall"
"context"
"flag"
"github.com/google/subcommands"
+ "gvisor.googlesource.com/gvisor/pkg/log"
"gvisor.googlesource.com/gvisor/runsc/boot"
"gvisor.googlesource.com/gvisor/runsc/container"
+ "gvisor.googlesource.com/gvisor/runsc/specutils"
)
// File containing the container's saved image/state within the given image-path's directory.
@@ -30,7 +33,8 @@ const checkpointFileName = "checkpoint.img"
// Checkpoint implements subcommands.Command for the "checkpoint" command.
type Checkpoint struct {
- imagePath string
+ imagePath string
+ leaveRunning bool
}
// Name implements subcommands.Command.Name.
@@ -51,14 +55,12 @@ func (*Checkpoint) Usage() string {
// SetFlags implements subcommands.Command.SetFlags.
func (c *Checkpoint) SetFlags(f *flag.FlagSet) {
- f.StringVar(&c.imagePath, "image-path", "", "path to saved container image")
+ f.StringVar(&c.imagePath, "image-path", "", "directory path to saved container image")
+ f.BoolVar(&c.leaveRunning, "leave-running", false, "restart the container after checkpointing")
// Unimplemented flags necessary for compatibility with docker.
var wp string
f.StringVar(&wp, "work-path", "", "ignored")
-
- var lr bool
- f.BoolVar(&lr, "leave-running", false, "ignored")
}
// Execute implements subcommands.Command.Execute.
@@ -71,6 +73,7 @@ func (c *Checkpoint) Execute(_ context.Context, f *flag.FlagSet, args ...interfa
id := f.Arg(0)
conf := args[0].(*boot.Config)
+ waitStatus := args[1].(*syscall.WaitStatus)
cont, err := container.Load(conf.RootDir, id)
if err != nil {
@@ -98,5 +101,49 @@ func (c *Checkpoint) Execute(_ context.Context, f *flag.FlagSet, args ...interfa
Fatalf("checkpoint failed: %v", err)
}
+ if !c.leaveRunning {
+ return subcommands.ExitSuccess
+ }
+
+ // TODO: Make it possible to restore into same container.
+ // For now, we can fake it by destroying the container and making a
+ // new container with the same ID. This hack does not work with docker
+ // which uses the container pid to ensure that the restore-container is
+ // actually the same as the checkpoint-container. By restoring into
+ // the same container, we will solve the docker incompatibility.
+
+ // Restore into new container with same ID.
+ bundleDir := cont.BundleDir
+ if bundleDir == "" {
+ Fatalf("error setting bundleDir")
+ }
+
+ spec, err := specutils.ReadSpec(bundleDir)
+ if err != nil {
+ Fatalf("error reading spec: %v", err)
+ }
+
+ specutils.LogSpec(spec)
+
+ if cont.ConsoleSocket != "" {
+ log.Warningf("ignoring console socket since it cannot be restored")
+ }
+
+ if err := cont.DestroyAndWait(); err != nil {
+ Fatalf("error destroying container: %v", err)
+ }
+
+ cont, err = container.Create(id, spec, conf, bundleDir, "", "", fullImagePath)
+ if err != nil {
+ Fatalf("error restoring container: %v", err)
+ }
+
+ if err := cont.Start(conf); err != nil {
+ Fatalf("error starting container: %v", err)
+ }
+
+ ws, err := cont.Wait()
+ *waitStatus = ws
+
return subcommands.ExitSuccess
}