mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
85f40c2bc7
Without this, multiple runc containers can accidentally share the same cgroup(s) (and change each other's limits), when runc is invoked from the same directory (i.e.: same cwd on multiple runc executions). After these changes, each runc container will run on its own cgroup(s). Before, the only workaround was to invoke runc from an unique (temporary?) cwd for each container. Common cgroup configuration (and hierarchical limits) can be set by having multiple runc containers share the same cgroup parent, which is the cgroup of the process executing runc. Signed-off-by: Fabio Kung <fabio.kung@gmail.com>
112 lines
3.1 KiB
Go
112 lines
3.1 KiB
Go
// +build linux
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/codegangsta/cli"
|
|
"github.com/opencontainers/runc/libcontainer"
|
|
"github.com/opencontainers/runc/libcontainer/configs"
|
|
"github.com/opencontainers/specs"
|
|
)
|
|
|
|
var restoreCommand = cli.Command{
|
|
Name: "restore",
|
|
Usage: "restore a container from a previous checkpoint",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{Name: "image-path", Value: "", Usage: "path to criu image files for restoring"},
|
|
cli.StringFlag{Name: "work-path", Value: "", Usage: "path for saving work files and logs"},
|
|
cli.BoolFlag{Name: "tcp-established", Usage: "allow open tcp connections"},
|
|
cli.BoolFlag{Name: "ext-unix-sk", Usage: "allow external unix sockets"},
|
|
cli.BoolFlag{Name: "shell-job", Usage: "allow shell jobs"},
|
|
cli.BoolFlag{Name: "file-locks", Usage: "handle file locks, for safety"},
|
|
},
|
|
Action: func(context *cli.Context) {
|
|
imagePath := context.String("image-path")
|
|
if imagePath == "" {
|
|
imagePath = getDefaultImagePath(context)
|
|
}
|
|
spec, err := loadSpec(context.Args().First())
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
config, err := createLibcontainerConfig(context.GlobalString("id"), spec)
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
status, err := restoreContainer(context, spec, config, imagePath)
|
|
if err != nil {
|
|
fatal(err)
|
|
}
|
|
os.Exit(status)
|
|
},
|
|
}
|
|
|
|
func restoreContainer(context *cli.Context, spec *specs.LinuxSpec, config *configs.Config, imagePath string) (code int, err error) {
|
|
rootuid := 0
|
|
factory, err := loadFactory(context)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
container, err := factory.Load(context.GlobalString("id"))
|
|
if err != nil {
|
|
container, err = factory.Create(context.GlobalString("id"), config)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
}
|
|
options := criuOptions(context)
|
|
// ensure that the container is always removed if we were the process
|
|
// that created it.
|
|
defer func() {
|
|
if err != nil {
|
|
return
|
|
}
|
|
status, err := container.Status()
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
if status != libcontainer.Checkpointed {
|
|
if err := container.Destroy(); err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
if err := os.RemoveAll(options.ImagesDirectory); err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}
|
|
}()
|
|
process := &libcontainer.Process{
|
|
Stdin: os.Stdin,
|
|
Stdout: os.Stdout,
|
|
Stderr: os.Stderr,
|
|
}
|
|
tty, err := newTty(spec.Process.Terminal, process, rootuid)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
handler := newSignalHandler(tty)
|
|
defer handler.Close()
|
|
if err := container.Restore(process, options); err != nil {
|
|
return -1, err
|
|
}
|
|
return handler.forward(process)
|
|
}
|
|
|
|
func criuOptions(context *cli.Context) *libcontainer.CriuOpts {
|
|
imagePath := getCheckpointImagePath(context)
|
|
if err := os.MkdirAll(imagePath, 0655); err != nil {
|
|
fatal(err)
|
|
}
|
|
return &libcontainer.CriuOpts{
|
|
ImagesDirectory: imagePath,
|
|
WorkDirectory: context.String("work-path"),
|
|
LeaveRunning: context.Bool("leave-running"),
|
|
TcpEstablished: true, // context.Bool("tcp-established"),
|
|
ExternalUnixConnections: context.Bool("ext-unix-sk"),
|
|
ShellJob: context.Bool("shell-job"),
|
|
FileLocks: context.Bool("file-locks"),
|
|
}
|
|
}
|