runc/linux_container.go

175 lines
3.5 KiB
Go

// +build linux
package libcontainer
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"syscall"
"github.com/docker/libcontainer/network"
"github.com/golang/glog"
)
type linuxContainer struct {
id string
root string
config *Config
state *State
cgroupManager CgroupManager
initArgs []string
}
func (c *linuxContainer) ID() string {
return c.id
}
func (c *linuxContainer) Config() *Config {
return c.config
}
func (c *linuxContainer) RunState() (RunState, error) {
return Destroyed, nil // FIXME return a real state
}
func (c *linuxContainer) Processes() ([]int, error) {
glog.Info("fetch container processes")
pids, err := c.cgroupManager.GetPids()
if err != nil {
return nil, newGenericError(err, SystemError)
}
return pids, nil
}
func (c *linuxContainer) Stats() (*ContainerStats, error) {
glog.Info("fetch container stats")
var (
err error
stats = &ContainerStats{}
)
if stats.CgroupStats, err = c.cgroupManager.GetStats(); err != nil {
return stats, newGenericError(err, SystemError)
}
if stats.NetworkStats, err = network.GetStats(&c.state.NetworkState); err != nil {
return stats, newGenericError(err, SystemError)
}
return stats, nil
}
func (c *linuxContainer) StartProcess(config *ProcessConfig) (int, error) {
state, err := c.RunState()
if err != nil {
return -1, err
}
if state != Destroyed {
glog.Info("start new container process")
panic("not implemented")
}
if err := c.startInitProcess(config); err != nil {
return -1, err
}
return c.state.InitPid, nil
}
func (c *linuxContainer) updateStateFile() error {
data, err := json.MarshalIndent(c.state, "", "\t")
if err != nil {
return newGenericError(err, SystemError)
}
fnew := filepath.Join(c.root, fmt.Sprintf("%s.new", stateFilename))
f, err := os.Create(fnew)
if err != nil {
return newGenericError(err, SystemError)
}
_, err = f.Write(data)
if err != nil {
f.Close()
return newGenericError(err, SystemError)
}
f.Close()
fname := filepath.Join(c.root, stateFilename)
if err := os.Rename(fnew, fname); err != nil {
return newGenericError(err, SystemError)
}
return nil
}
func (c *linuxContainer) startInitProcess(config *ProcessConfig) error {
cmd := exec.Command(c.initArgs[0], append(c.initArgs[1:], config.Args...)...)
cmd.Stdin = config.Stdin
cmd.Stdout = config.Stdout
cmd.Stderr = config.Stderr
cmd.Env = config.Env
cmd.Dir = c.config.RootFs
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
//FIXME call namespaces.Exec()
if err := cmd.Start(); err != nil {
return err
}
c.state.InitPid = cmd.Process.Pid
err := c.updateStateFile()
if err != nil {
return err
}
return nil
}
func (c *linuxContainer) Destroy() error {
state, err := c.RunState()
if err != nil {
return err
}
if state != Destroyed {
return newGenericError(nil, ContainerNotStopped)
}
os.RemoveAll(c.root)
return nil
}
func (c *linuxContainer) Pause() error {
glog.Info("pause container")
panic("not implemented")
}
func (c *linuxContainer) Resume() error {
glog.Info("resume container")
panic("not implemented")
}
func (c *linuxContainer) Signal(pid, signal int) error {
glog.Infof("sending signal %d to pid %d", signal, pid)
panic("not implemented")
}
func (c *linuxContainer) Wait() (int, error) {
glog.Info("wait container")
panic("not implemented")
}
func (c *linuxContainer) WaitProcess(pid int) (int, error) {
glog.Infof("wait process %d", pid)
panic("not implemented")
}