Add Checkpoint and Restore methods to Container

Containers support checkpointing and restore via criu(8) for linux
containers.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2015-03-06 11:21:02 -08:00
parent a4a648ce30
commit 6fec5923e3
3 changed files with 63 additions and 0 deletions

View File

@ -108,6 +108,18 @@ type Container interface {
// Systemerror - System error.
Start(process *Process) (err error)
// Checkpoint checkpoints the running container's state to disk using the criu(8) utility.
//
// errors:
// Systemerror - System error.
Checkpoint() error
// Restore restores the checkpointed container to a running state using the criu(8) utiity.
//
// errors:
// Systemerror - System error.
Restore() error
// Destroys the container after killing all running processes.
//
// Any event registrations are removed before the container is destroyed.

View File

@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"sync"
"syscall"
@ -26,6 +27,7 @@ type linuxContainer struct {
initPath string
initArgs []string
initProcess parentProcess
criuPath string
m sync.Mutex
}
@ -254,6 +256,49 @@ func (c *linuxContainer) NotifyOOM() (<-chan struct{}, error) {
return notifyOnOOM(c.cgroupManager.GetPaths())
}
func (c *linuxContainer) Checkpoint() error {
args := []string{
"dump", "-v4",
"-D", filepath.Join(c.root, "checkpoint"),
"-o", "dump.log",
"--root", c.config.Rootfs,
"--manage-cgroups", "--evasive-devices",
"-t", strconv.Itoa(c.initProcess.pid()),
}
for _, m := range c.config.Mounts {
if m.Device == "bind" {
args = append(args,
"--ext-mount-map", fmt.Sprintf("%s:%s", m.Destination, m.Destination))
}
}
return c.execCriu(args)
}
func (c *linuxContainer) Restore() error {
args := []string{
"restore", "-d", "-v4",
"-D", filepath.Join(c.root, "checkpoint"),
"-o", "restore.log",
"--root", c.config.Rootfs,
"--manage-cgroups", "--evasive-devices",
}
for _, m := range c.config.Mounts {
if m.Device == "bind" {
args = append(args, "--ext-mount-map",
fmt.Sprintf("%s:%s", m.Destination, m.Source))
}
}
return c.execCriu(args)
}
func (c *linuxContainer) execCriu(args []string) error {
output, err := exec.Command(c.criuPath, args...).CombinedOutput()
if err != nil {
return fmt.Errorf("%s: %s", err, output)
}
return nil
}
func (c *linuxContainer) updateState(process parentProcess) error {
c.initProcess = process
state, err := c.currentState()

View File

@ -129,6 +129,10 @@ type LinuxFactory struct {
// a container.
InitArgs []string
// CriuPath is the path to the criu binary used for checkpoint and restore of
// containers.
CriuPath string
// Validator provides validation to container configurations.
Validator validate.Validator
@ -161,6 +165,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
config: config,
initPath: l.InitPath,
initArgs: l.InitArgs,
criuPath: l.CriuPath,
cgroupManager: l.NewCgroupsManager(config.Cgroups, nil),
}, nil
}
@ -184,6 +189,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
config: &state.Config,
initPath: l.InitPath,
initArgs: l.InitArgs,
criuPath: l.CriuPath,
cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths),
root: containerRoot,
}, nil