diff --git a/containerd-shim/process.go b/containerd-shim/process.go index a08fcb6..61f82e7 100644 --- a/containerd-shim/process.go +++ b/containerd-shim/process.go @@ -91,10 +91,10 @@ func (p *process) start() error { return err } logPath := filepath.Join(cwd, "log.json") - args := []string{ + args := append([]string{ "--log", logPath, "--log-format", "json", - } + }, p.state.RuntimeArgs...) if p.state.Exec { args = append(args, "exec", "--process", filepath.Join(cwd, "process.json"), diff --git a/containerd/main.go b/containerd/main.go index 1c9ec14..96960ac 100644 --- a/containerd/main.go +++ b/containerd/main.go @@ -50,6 +50,11 @@ var daemonFlags = []cli.Flag{ Value: "runc", Usage: "name of the OCI compliant runtime to use when executing containers", }, + cli.StringSliceFlag{ + Name: "runtime-args", + Value: &cli.StringSlice{}, + Usage: "specify additional runtime args", + }, } func main() { @@ -71,6 +76,7 @@ func main() { context.String("state-dir"), 10, context.String("runtime"), + context.StringSlice("runtime-args"), ); err != nil { logrus.Fatal(err) } @@ -80,7 +86,7 @@ func main() { } } -func daemon(address, stateDir string, concurrency int, runtimeName string) error { +func daemon(address, stateDir string, concurrency int, runtimeName string, runtimeArgs []string) error { // setup a standard reaper so that we don't leave any zombies if we are still alive // this is just good practice because we are spawning new processes s := make(chan os.Signal, 2048) @@ -88,7 +94,7 @@ func daemon(address, stateDir string, concurrency int, runtimeName string) error if err := osutils.SetSubreaper(1); err != nil { logrus.WithField("error", err).Error("containerd: set subpreaper") } - sv, err := supervisor.New(stateDir, runtimeName) + sv, err := supervisor.New(stateDir, runtimeName, runtimeArgs) if err != nil { return err } diff --git a/runtime/container.go b/runtime/container.go index 72040d8..db6cf21 100644 --- a/runtime/container.go +++ b/runtime/container.go @@ -83,14 +83,15 @@ func NewStdio(stdin, stdout, stderr string) Stdio { } // New returns a new container -func New(root, id, bundle, runtimeName string, labels []string) (Container, error) { +func New(root, id, bundle, runtimeName string, runtimeArgs, labels []string) (Container, error) { c := &container{ - root: root, - id: id, - bundle: bundle, - labels: labels, - processes: make(map[string]*process), - runtime: runtimeName, + root: root, + id: id, + bundle: bundle, + labels: labels, + processes: make(map[string]*process), + runtime: runtimeName, + runtimeArgs: runtimeArgs, } if err := os.Mkdir(filepath.Join(root, id), 0755); err != nil { return nil, err @@ -101,9 +102,10 @@ func New(root, id, bundle, runtimeName string, labels []string) (Container, erro } defer f.Close() if err := json.NewEncoder(f).Encode(state{ - Bundle: bundle, - Labels: labels, - Runtime: runtimeName, + Bundle: bundle, + Labels: labels, + Runtime: runtimeName, + RuntimeArgs: runtimeArgs, }); err != nil { return nil, err } @@ -121,12 +123,13 @@ func Load(root, id string) (Container, error) { return nil, err } c := &container{ - root: root, - id: id, - bundle: s.Bundle, - labels: s.Labels, - runtime: s.Runtime, - processes: make(map[string]*process), + root: root, + id: id, + bundle: s.Bundle, + labels: s.Labels, + runtime: s.Runtime, + runtimeArgs: s.RuntimeArgs, + processes: make(map[string]*process), } dirs, err := ioutil.ReadDir(filepath.Join(root, id)) if err != nil { @@ -166,13 +169,14 @@ func readProcessState(dir string) (*ProcessState, error) { type container struct { // path to store runtime state information - root string - id string - bundle string - runtime string - processes map[string]*process - labels []string - oomFds []int + root string + id string + bundle string + runtime string + runtimeArgs []string + processes map[string]*process + labels []string + oomFds []int } func (c *container) ID() string { diff --git a/runtime/process_linux.go b/runtime/process_linux.go index 0295ee4..3dc4785 100644 --- a/runtime/process_linux.go +++ b/runtime/process_linux.go @@ -35,8 +35,9 @@ func populateProcessStateForEncoding(config *processConfig, uid int, gid int) Pr RootUID: uid, RootGID: gid, }, - Stdin: config.stdio.Stdin, - Stdout: config.stdio.Stdout, - Stderr: config.stdio.Stderr, + Stdin: config.stdio.Stdin, + Stdout: config.stdio.Stdout, + Stderr: config.stdio.Stderr, + RuntimeArgs: config.c.runtimeArgs, } } diff --git a/runtime/runtime.go b/runtime/runtime.go index 1423c76..c20edeb 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -53,20 +53,22 @@ const ( ) type state struct { - Bundle string `json:"bundle"` - Labels []string `json:"labels"` - Stdin string `json:"stdin"` - Stdout string `json:"stdout"` - Stderr string `json:"stderr"` - Runtime string `json:"runtime"` + Bundle string `json:"bundle"` + Labels []string `json:"labels"` + Stdin string `json:"stdin"` + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` + Runtime string `json:"runtime"` + RuntimeArgs []string `json:"runtimeArgs"` } type ProcessState struct { specs.ProcessSpec - Exec bool `json:"exec"` - Stdin string `json:"containerdStdin"` - Stdout string `json:"containerdStdout"` - Stderr string `json:"containerdStderr"` + Exec bool `json:"exec"` + Stdin string `json:"containerdStdin"` + Stdout string `json:"containerdStdout"` + Stderr string `json:"containerdStderr"` + RuntimeArgs []string `json:"runtimeArgs"` PlatformProcessState } diff --git a/supervisor/create.go b/supervisor/create.go index 16ad36e..8f8e5d9 100644 --- a/supervisor/create.go +++ b/supervisor/create.go @@ -20,7 +20,7 @@ type StartTask struct { func (s *Supervisor) start(t *StartTask) error { start := time.Now() - container, err := runtime.New(s.stateDir, t.ID, t.BundlePath, s.runtime, t.Labels) + container, err := runtime.New(s.stateDir, t.ID, t.BundlePath, s.runtime, s.runtimeArgs, t.Labels) if err != nil { return err } diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go index 6b1ee4a..c4e3dcc 100644 --- a/supervisor/supervisor.go +++ b/supervisor/supervisor.go @@ -18,7 +18,7 @@ const ( ) // New returns an initialized Process supervisor. -func New(stateDir string, runtimeName string) (*Supervisor, error) { +func New(stateDir string, runtimeName string, runtimeArgs []string) (*Supervisor, error) { startTasks := make(chan *startTask, 10) if err := os.MkdirAll(stateDir, 0755); err != nil { return nil, err @@ -40,6 +40,7 @@ func New(stateDir string, runtimeName string) (*Supervisor, error) { tasks: make(chan Task, defaultBufferSize), monitor: monitor, runtime: runtimeName, + runtimeArgs: runtimeArgs, } if err := setupEventLog(s); err != nil { return nil, err @@ -105,9 +106,10 @@ type Supervisor struct { // stateDir is the directory on the system to store container runtime state information. stateDir string // name of the OCI compatible runtime used to execute containers - runtime string - containers map[string]*containerInfo - startTasks chan *startTask + runtime string + runtimeArgs []string + containers map[string]*containerInfo + startTasks chan *startTask // we need a lock around the subscribers map only because additions and deletions from // the map are via the API so we cannot really control the concurrency subscriberLock sync.RWMutex @@ -196,10 +198,11 @@ func (s *Supervisor) notifySubscribers(e Event) { // state of the Supervisor func (s *Supervisor) Start() error { logrus.WithFields(logrus.Fields{ - "stateDir": s.stateDir, - "runtime": s.runtime, - "memory": s.machine.Memory, - "cpus": s.machine.Cpus, + "stateDir": s.stateDir, + "runtime": s.runtime, + "runtimeArgs": s.runtimeArgs, + "memory": s.machine.Memory, + "cpus": s.machine.Cpus, }).Debug("containerd: supervisor running") go func() { for i := range s.tasks {