Add runc support
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
847e5bc7ee
commit
a2ab27ad5b
2 changed files with 173 additions and 3 deletions
171
runc/runc.go
Normal file
171
runc/runc.go
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
// +build runc
|
||||||
|
|
||||||
|
package runc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/docker/containerd/runtime"
|
||||||
|
"github.com/opencontainers/specs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRuntime(stateDir string) (runtime.Runtime, error) {
|
||||||
|
return &runcRuntime{
|
||||||
|
stateDir: stateDir,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type runcContainer struct {
|
||||||
|
id string
|
||||||
|
path string
|
||||||
|
stateDir string
|
||||||
|
exitStatus int
|
||||||
|
processes map[int]*runcProcess
|
||||||
|
initProcess *runcProcess
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) ID() string {
|
||||||
|
return c.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) Start() error {
|
||||||
|
return c.initProcess.cmd.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) Path() string {
|
||||||
|
return c.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) Pid() (int, error) {
|
||||||
|
return c.initProcess.cmd.Process.Pid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) SetExited(status int) {
|
||||||
|
c.exitStatus = status
|
||||||
|
}
|
||||||
|
|
||||||
|
// noop for runc
|
||||||
|
func (c *runcContainer) Delete() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) Processes() ([]runtime.Process, error) {
|
||||||
|
procs := []runtime.Process{
|
||||||
|
c.initProcess,
|
||||||
|
}
|
||||||
|
for _, p := range c.processes {
|
||||||
|
procs = append(procs, p)
|
||||||
|
}
|
||||||
|
return procs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) RemoveProcess(pid int) error {
|
||||||
|
if _, ok := c.processes[pid]; !ok {
|
||||||
|
return runtime.ErrNotChildProcess
|
||||||
|
}
|
||||||
|
delete(c.processes, pid)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) State() runtime.State {
|
||||||
|
// TODO: how to do this with runc
|
||||||
|
return runtime.State{
|
||||||
|
Status: runtime.Running,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) Resume() error {
|
||||||
|
return c.newCommand("resume").Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) Pause() error {
|
||||||
|
return c.newCommand("pause").Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *runcContainer) newCommand(args ...string) *exec.Cmd {
|
||||||
|
cmd := exec.Command("runc", append([]string{"--root", c.stateDir, "--id", c.id}, args...)...)
|
||||||
|
cmd.Dir = c.path
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
type runcProcess struct {
|
||||||
|
cmd *exec.Cmd
|
||||||
|
spec specs.Process
|
||||||
|
}
|
||||||
|
|
||||||
|
// pid of the container, not of runc
|
||||||
|
func (p *runcProcess) Pid() (int, error) {
|
||||||
|
return p.cmd.Process.Pid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *runcProcess) Spec() specs.Process {
|
||||||
|
return p.spec
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *runcProcess) Signal(s os.Signal) error {
|
||||||
|
return p.cmd.Process.Signal(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type runcRuntime struct {
|
||||||
|
stateDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *runcRuntime) Create(id, bundlePath string, stdio *runtime.Stdio) (runtime.Container, error) {
|
||||||
|
cmd := exec.Command("runc", "--root", r.stateDir, "--id", id, "start")
|
||||||
|
cmd.Dir = bundlePath
|
||||||
|
// cmd.Stderr = stdio.Stderr
|
||||||
|
// cmd.Stdout = stdio.Stdout
|
||||||
|
var s specs.Spec
|
||||||
|
f, err := os.Open(filepath.Join(bundlePath, "config.json"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := json.NewDecoder(f).Decode(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &runcContainer{
|
||||||
|
id: id,
|
||||||
|
path: bundlePath,
|
||||||
|
stateDir: r.stateDir,
|
||||||
|
initProcess: &runcProcess{
|
||||||
|
cmd: cmd,
|
||||||
|
spec: s.Process,
|
||||||
|
},
|
||||||
|
processes: make(map[int]*runcProcess),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *runcRuntime) StartProcess(ci runtime.Container, p specs.Process, stdio *runtime.Stdio) (runtime.Process, error) {
|
||||||
|
c, ok := ci.(*runcContainer)
|
||||||
|
if !ok {
|
||||||
|
return nil, runtime.ErrInvalidContainerType
|
||||||
|
}
|
||||||
|
f, err := ioutil.TempFile("", "containerd")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := json.NewEncoder(f).Encode(p); err != nil {
|
||||||
|
f.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cmd := c.newCommand("exec", f.Name())
|
||||||
|
f.Close()
|
||||||
|
process := &runcProcess{
|
||||||
|
cmd: cmd,
|
||||||
|
spec: p,
|
||||||
|
}
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pid, err := process.Pid()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.processes[pid] = process
|
||||||
|
return process, nil
|
||||||
|
}
|
|
@ -3,11 +3,10 @@
|
||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"github.com/docker/containerd/runc"
|
||||||
|
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newRuntime(stateDir string) (runtime.Runtime, error) {
|
func newRuntime(stateDir string) (runtime.Runtime, error) {
|
||||||
return nil, errors.New("Unsupported runtime")
|
return runc.NewRuntime(stateDir)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue