Update shim for exec

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-02-01 11:02:41 -08:00
parent 6808dbc02f
commit 835f3b6a97
37 changed files with 786 additions and 709 deletions

165
containerd-shim/process.go Normal file
View file

@ -0,0 +1,165 @@
package main
import (
"encoding/json"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"syscall"
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/specs"
)
type process struct {
id string
bundle string
stdio *stdio
s specs.Process
exec bool
containerPid int
}
func newProcess(id, bundle string, exec bool) (*process, error) {
f, err := os.Open("process.json")
if err != nil {
return nil, err
}
defer f.Close()
p := &process{
id: id,
bundle: bundle,
exec: exec,
}
if err := json.NewDecoder(f).Decode(&p.s); err != nil {
return nil, err
}
if err := p.openIO(); err != nil {
return nil, err
}
return p, nil
}
func (p *process) start() error {
cwd, err := os.Getwd()
if err != nil {
return err
}
args := []string{
"--id", p.id,
}
if p.exec {
args = append(args, "exec",
"--process", filepath.Join(cwd, "process.json"))
} else {
args = append(args, "start",
"--bundle", p.bundle)
}
args = append(args,
"-d",
"--console", p.stdio.console,
"--pid-file", filepath.Join(cwd, "pid"),
)
cmd := exec.Command("runc", args...)
cmd.Stdin = p.stdio.stdin
cmd.Stdout = p.stdio.stdout
cmd.Stderr = p.stdio.stderr
// set the parent death signal to SIGKILL so that if the shim dies the container
// process also dies
cmd.SysProcAttr = &syscall.SysProcAttr{
Pdeathsig: syscall.SIGKILL,
}
if err := cmd.Run(); err != nil {
return err
}
data, err := ioutil.ReadFile("pid")
if err != nil {
return err
}
pid, err := strconv.Atoi(string(data))
if err != nil {
return err
}
p.containerPid = pid
return nil
}
func (p *process) pid() int {
return p.containerPid
}
func (p *process) delete() error {
if !p.exec {
return exec.Command("runc", "--id", p.id, "delete").Run()
}
return nil
}
// openIO opens the pre-created fifo's for use with the container
// in RDWR so that they remain open if the other side stops listening
func (p *process) openIO() error {
p.stdio = &stdio{}
if p.s.Terminal {
// FIXME: this is wrong for user namespaces and will need to be translated
console, err := libcontainer.NewConsole(int(p.s.User.UID), int(p.s.User.GID))
if err != nil {
return err
}
p.stdio.console = console.Path()
stdin, err := os.OpenFile("stdin", syscall.O_RDWR, 0)
if err != nil {
return err
}
go func() {
io.Copy(console, stdin)
}()
stdout, err := os.OpenFile("stdout", syscall.O_RDWR, 0)
if err != nil {
return err
}
go func() {
io.Copy(stdout, console)
console.Close()
}()
return nil
}
// non-tty
for name, dest := range map[string]**os.File{
"stdin": &p.stdio.stdin,
"stdout": &p.stdio.stdout,
"stderr": &p.stdio.stderr,
} {
f, err := os.OpenFile(name, syscall.O_RDWR, 0)
if err != nil {
return err
}
*dest = f
}
return nil
}
func (p *process) Close() error {
return p.stdio.Close()
}
type stdio struct {
stdin *os.File
stdout *os.File
stderr *os.File
console string
}
func (s *stdio) Close() error {
err := s.stdin.Close()
if oerr := s.stdout.Close(); err == nil {
err = oerr
}
if oerr := s.stderr.Close(); err == nil {
err = oerr
}
return err
}