2015-06-30 07:49:13 +08:00
|
|
|
// +build linux
|
|
|
|
|
2015-06-22 10:31:12 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"github.com/codegangsta/cli"
|
|
|
|
"github.com/opencontainers/runc/libcontainer"
|
|
|
|
"github.com/opencontainers/runc/libcontainer/configs"
|
2015-07-03 00:55:24 +08:00
|
|
|
"github.com/opencontainers/specs"
|
2015-06-22 10:31:12 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
const wildcard = -1
|
|
|
|
|
|
|
|
var allowedDevices = []*configs.Device{
|
|
|
|
// allow mknod for any device
|
|
|
|
{
|
|
|
|
Type: 'c',
|
|
|
|
Major: wildcard,
|
|
|
|
Minor: wildcard,
|
|
|
|
Permissions: "m",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Type: 'b',
|
|
|
|
Major: wildcard,
|
|
|
|
Minor: wildcard,
|
|
|
|
Permissions: "m",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Path: "/dev/console",
|
|
|
|
Type: 'c',
|
|
|
|
Major: 5,
|
|
|
|
Minor: 1,
|
|
|
|
Permissions: "rwm",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Path: "/dev/tty0",
|
|
|
|
Type: 'c',
|
|
|
|
Major: 4,
|
|
|
|
Minor: 0,
|
|
|
|
Permissions: "rwm",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Path: "/dev/tty1",
|
|
|
|
Type: 'c',
|
|
|
|
Major: 4,
|
|
|
|
Minor: 1,
|
|
|
|
Permissions: "rwm",
|
|
|
|
},
|
|
|
|
// /dev/pts/ - pts namespaces are "coming soon"
|
|
|
|
{
|
|
|
|
Path: "",
|
|
|
|
Type: 'c',
|
|
|
|
Major: 136,
|
|
|
|
Minor: wildcard,
|
|
|
|
Permissions: "rwm",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Path: "",
|
|
|
|
Type: 'c',
|
|
|
|
Major: 5,
|
|
|
|
Minor: 2,
|
|
|
|
Permissions: "rwm",
|
|
|
|
},
|
|
|
|
// tuntap
|
|
|
|
{
|
|
|
|
Path: "",
|
|
|
|
Type: 'c',
|
|
|
|
Major: 10,
|
|
|
|
Minor: 200,
|
|
|
|
Permissions: "rwm",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var container libcontainer.Container
|
|
|
|
|
|
|
|
func containerPreload(context *cli.Context) error {
|
|
|
|
c, err := getContainer(context)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
container = c
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var factory libcontainer.Factory
|
|
|
|
|
|
|
|
func factoryPreload(context *cli.Context) error {
|
|
|
|
f, err := loadFactory(context)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
factory = f
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// loadFactory returns the configured factory instance for execing containers.
|
|
|
|
func loadFactory(context *cli.Context) (libcontainer.Factory, error) {
|
|
|
|
root := context.GlobalString("root")
|
|
|
|
abs, err := filepath.Abs(root)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return libcontainer.New(abs, libcontainer.Cgroupfs, func(l *libcontainer.LinuxFactory) error {
|
|
|
|
l.CriuPath = context.GlobalString("criu")
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// getContainer returns the specified container instance by loading it from state
|
|
|
|
// with the default factory.
|
|
|
|
func getContainer(context *cli.Context) (libcontainer.Container, error) {
|
|
|
|
factory, err := loadFactory(context)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
container, err := factory.Load(context.GlobalString("id"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return container, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// fatal prints the error's details if it is a libcontainer specific error type
|
2015-07-11 07:19:18 +08:00
|
|
|
// then exits the program with an exit status of 1.
|
2015-06-22 10:31:12 +08:00
|
|
|
func fatal(err error) {
|
|
|
|
if lerr, ok := err.(libcontainer.Error); ok {
|
|
|
|
lerr.Detail(os.Stderr)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// fatalf formats the errror string with the specified template then exits the
|
|
|
|
// program with an exit status of 1.
|
|
|
|
func fatalf(t string, v ...interface{}) {
|
|
|
|
fmt.Fprintf(os.Stderr, t, v...)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getDefaultID returns a string to be used as the container id based on the
|
2015-06-24 11:29:50 +08:00
|
|
|
// current working directory of the runc process. This function panics
|
2015-06-22 10:31:12 +08:00
|
|
|
// if the cwd is unable to be found based on a system error.
|
|
|
|
func getDefaultID() string {
|
|
|
|
cwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return filepath.Base(cwd)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getDefaultImagePath(context *cli.Context) string {
|
|
|
|
cwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return filepath.Join(cwd, "checkpoint")
|
|
|
|
}
|
|
|
|
|
|
|
|
// newProcess returns a new libcontainer Process with the arguments from the
|
|
|
|
// spec and stdio from the current process.
|
2015-07-03 00:55:24 +08:00
|
|
|
func newProcess(p specs.Process) *libcontainer.Process {
|
2015-06-22 10:31:12 +08:00
|
|
|
return &libcontainer.Process{
|
2015-07-03 00:59:30 +08:00
|
|
|
Args: p.Args,
|
|
|
|
Env: p.Env,
|
|
|
|
// TODO: fix libcontainer's API to better support uid/gid in a typesafe way.
|
2015-07-02 00:57:26 +08:00
|
|
|
User: fmt.Sprintf("%d:%d", p.User.Uid, p.User.Gid),
|
2015-06-22 10:31:12 +08:00
|
|
|
Cwd: p.Cwd,
|
|
|
|
Stdin: os.Stdin,
|
|
|
|
Stdout: os.Stdout,
|
|
|
|
Stderr: os.Stderr,
|
|
|
|
}
|
|
|
|
}
|