| // +build linux |
| |
| package main |
| |
| import ( |
| "fmt" |
| "os" |
| "path/filepath" |
| |
| "github.com/codegangsta/cli" |
| "github.com/opencontainers/runc/libcontainer" |
| "github.com/opencontainers/runc/libcontainer/configs" |
| "github.com/opencontainers/specs" |
| ) |
| |
| 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 |
| // then exits the program with an exit status of 1. |
| 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) |
| } |
| |
| // getDefaultID returns a string to be used as the container id based on the |
| // current working directory of the runc process. This function panics |
| // 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. |
| func newProcess(p specs.Process) *libcontainer.Process { |
| return &libcontainer.Process{ |
| Args: p.Args, |
| Env: p.Env, |
| // TODO: fix libcontainer's API to better support uid/gid in a typesafe way. |
| User: fmt.Sprintf("%d:%d", p.User.UID, p.User.GID), |
| Cwd: p.Cwd, |
| } |
| } |