// +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 exists 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) } // 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 // 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, Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr, } }