runc/utils.go

178 lines
3.8 KiB
Go

// +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)
}
// 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,
}
}