1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Fix golint warnings for daemon/execdriver/*

Addresses: #14756

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
This commit is contained in:
Qiang Huang 2015-07-28 08:43:22 +08:00
parent 4ed3e3a5b2
commit 3d17c3bb66
20 changed files with 231 additions and 99 deletions

View file

@ -272,11 +272,11 @@ func populateCommand(c *Container, env []string) error {
resources := &execdriver.Resources{ resources := &execdriver.Resources{
Memory: c.hostConfig.Memory, Memory: c.hostConfig.Memory,
MemorySwap: c.hostConfig.MemorySwap, MemorySwap: c.hostConfig.MemorySwap,
CpuShares: c.hostConfig.CPUShares, CPUShares: c.hostConfig.CPUShares,
CpusetCpus: c.hostConfig.CpusetCpus, CpusetCpus: c.hostConfig.CpusetCpus,
CpusetMems: c.hostConfig.CpusetMems, CpusetMems: c.hostConfig.CpusetMems,
CpuPeriod: c.hostConfig.CPUPeriod, CPUPeriod: c.hostConfig.CPUPeriod,
CpuQuota: c.hostConfig.CPUQuota, CPUQuota: c.hostConfig.CPUQuota,
BlkioWeight: c.hostConfig.BlkioWeight, BlkioWeight: c.hostConfig.BlkioWeight,
Rlimits: rlimits, Rlimits: rlimits,
OomKillDisable: c.hostConfig.OomKillDisable, OomKillDisable: c.hostConfig.OomKillDisable,

View file

@ -16,6 +16,7 @@ import (
// arbatrary data to be sent // arbatrary data to be sent
type Context map[string]string type Context map[string]string
// Define error messages
var ( var (
ErrNotRunning = errors.New("Container is not running") ErrNotRunning = errors.New("Container is not running")
ErrWaitTimeoutReached = errors.New("Wait timeout reached") ErrWaitTimeoutReached = errors.New("Wait timeout reached")
@ -23,17 +24,19 @@ var (
ErrDriverNotFound = errors.New("The requested docker init has not been found") ErrDriverNotFound = errors.New("The requested docker init has not been found")
) )
// StartCallback defines a callback function.
// It's used by 'Run' and 'Exec', does some work in parent process
// after child process is started.
type StartCallback func(*ProcessConfig, int) type StartCallback func(*ProcessConfig, int)
// Driver specific information based on // Info is driver specific information based on
// processes registered with the driver // processes registered with the driver
type Info interface { type Info interface {
IsRunning() bool IsRunning() bool
} }
// Terminal in an interface for drivers to implement // Terminal represents a pseudo TTY, it is for when
// if they want to support Close and Resize calls from // using a container interactively.
// the core
type Terminal interface { type Terminal interface {
io.Closer io.Closer
Resize(height, width int) error Resize(height, width int) error
@ -48,19 +51,44 @@ type ExitStatus struct {
OOMKilled bool OOMKilled bool
} }
// Driver is an interface for drivers to implement
// including all basic functions a driver should have
type Driver interface { type Driver interface {
Run(c *Command, pipes *Pipes, startCallback StartCallback) (ExitStatus, error) // Run executes the process and blocks until the process exits and returns the exit code // Run executes the process, blocks until the process exits and returns
// Exec executes the process in an existing container, blocks until the process exits and returns the exit code // the exit code. It's the last stage on Docker side for running a container.
Run(c *Command, pipes *Pipes, startCallback StartCallback) (ExitStatus, error)
// Exec executes the process in an existing container, blocks until the
// process exits and returns the exit code.
Exec(c *Command, processConfig *ProcessConfig, pipes *Pipes, startCallback StartCallback) (int, error) Exec(c *Command, processConfig *ProcessConfig, pipes *Pipes, startCallback StartCallback) (int, error)
// Kill sends signals to process in container.
Kill(c *Command, sig int) error Kill(c *Command, sig int) error
// Pause pauses a container.
Pause(c *Command) error Pause(c *Command) error
// Unpause unpauses a container.
Unpause(c *Command) error Unpause(c *Command) error
Name() string // Driver name
Info(id string) Info // "temporary" hack (until we move state from core to plugins) // Name returns the name of the driver.
GetPidsForContainer(id string) ([]int, error) // Returns a list of pids for the given container. Name() string
Terminate(c *Command) error // kill it with fire
Clean(id string) error // clean all traces of container exec // Info returns the configuration stored in the driver struct,
Stats(id string) (*ResourceStats, error) // Get resource stats for a running container // "temporary" hack (until we move state from core to plugins).
Info(id string) Info
// GetPidsForContainer returns a list of pid for the processes running in a container.
GetPidsForContainer(id string) ([]int, error)
// Terminate kills a container by sending signal SIGKILL.
Terminate(c *Command) error
// Clean removes all traces of container exec.
Clean(id string) error
// Stats returns resource stats for a running container
Stats(id string) (*ResourceStats, error)
} }
// Network settings of the container // Network settings of the container
@ -72,22 +100,37 @@ type Network struct {
HostNetworking bool `json:"host_networking"` HostNetworking bool `json:"host_networking"`
} }
// IPC settings of the container // Ipc settings of the container
// It is for IPC namespace setting. Usually different containers
// have their own IPC namespace, however this specifies to use
// an existing IPC namespace.
// You can join the host's or a container's IPC namespace.
type Ipc struct { type Ipc struct {
ContainerID string `json:"container_id"` // id of the container to join ipc. ContainerID string `json:"container_id"` // id of the container to join ipc.
HostIpc bool `json:"host_ipc"` HostIpc bool `json:"host_ipc"`
} }
// PID settings of the container // Pid settings of the container
// It is for PID namespace setting. Usually different containers
// have their own PID namespace, however this specifies to use
// an existing PID namespace.
// Joining the host's PID namespace is currently the only supported
// option.
type Pid struct { type Pid struct {
HostPid bool `json:"host_pid"` HostPid bool `json:"host_pid"`
} }
// UTS settings of the container // UTS settings of the container
// It is for UTS namespace setting. Usually different containers
// have their own UTS namespace, however this specifies to use
// an existing UTS namespace.
// Joining the host's UTS namespace is currently the only supported
// option.
type UTS struct { type UTS struct {
HostUTS bool `json:"host_uts"` HostUTS bool `json:"host_uts"`
} }
// NetworkInterface contains all network configs for a driver
type NetworkInterface struct { type NetworkInterface struct {
Gateway string `json:"gateway"` Gateway string `json:"gateway"`
IPAddress string `json:"ip"` IPAddress string `json:"ip"`
@ -101,21 +144,24 @@ type NetworkInterface struct {
HairpinMode bool `json:"hairpin_mode"` HairpinMode bool `json:"hairpin_mode"`
} }
// Resources contains all resource configs for a driver.
// Currently these are all for cgroup configs.
// TODO Windows: Factor out ulimit.Rlimit // TODO Windows: Factor out ulimit.Rlimit
type Resources struct { type Resources struct {
Memory int64 `json:"memory"` Memory int64 `json:"memory"`
MemorySwap int64 `json:"memory_swap"` MemorySwap int64 `json:"memory_swap"`
CpuShares int64 `json:"cpu_shares"` CPUShares int64 `json:"cpu_shares"`
CpusetCpus string `json:"cpuset_cpus"` CpusetCpus string `json:"cpuset_cpus"`
CpusetMems string `json:"cpuset_mems"` CpusetMems string `json:"cpuset_mems"`
CpuPeriod int64 `json:"cpu_period"` CPUPeriod int64 `json:"cpu_period"`
CpuQuota int64 `json:"cpu_quota"` CPUQuota int64 `json:"cpu_quota"`
BlkioWeight int64 `json:"blkio_weight"` BlkioWeight int64 `json:"blkio_weight"`
Rlimits []*ulimit.Rlimit `json:"rlimits"` Rlimits []*ulimit.Rlimit `json:"rlimits"`
OomKillDisable bool `json:"oom_kill_disable"` OomKillDisable bool `json:"oom_kill_disable"`
MemorySwappiness int64 `json:"memory_swappiness"` MemorySwappiness int64 `json:"memory_swappiness"`
} }
// ResourceStats contains information about resource usage by a container.
type ResourceStats struct { type ResourceStats struct {
*libcontainer.Stats *libcontainer.Stats
Read time.Time `json:"read"` Read time.Time `json:"read"`
@ -123,6 +169,7 @@ type ResourceStats struct {
SystemUsage uint64 `json:"system_usage"` SystemUsage uint64 `json:"system_usage"`
} }
// Mount contains information for a mount operation.
type Mount struct { type Mount struct {
Source string `json:"source"` Source string `json:"source"`
Destination string `json:"destination"` Destination string `json:"destination"`
@ -131,7 +178,7 @@ type Mount struct {
Slave bool `json:"slave"` Slave bool `json:"slave"`
} }
// Describes a process that will be run inside a container. // ProcessConfig describes a process that will be run inside a container.
type ProcessConfig struct { type ProcessConfig struct {
exec.Cmd `json:"-"` exec.Cmd `json:"-"`
@ -145,10 +192,10 @@ type ProcessConfig struct {
ConsoleSize [2]int `json:"-"` // h,w of initial console size ConsoleSize [2]int `json:"-"` // h,w of initial console size
} }
// Command wrapps an os/exec.Cmd to add more metadata
//
// TODO Windows: Factor out unused fields such as LxcConfig, AppArmorProfile, // TODO Windows: Factor out unused fields such as LxcConfig, AppArmorProfile,
// and CgroupParent. // and CgroupParent.
//
// Process wrapps an os/exec.Cmd to add more metadata
type Command struct { type Command struct {
ID string `json:"id"` ID string `json:"id"`
Rootfs string `json:"rootfs"` // root fs of the container Rootfs string `json:"rootfs"` // root fs of the container

View file

@ -15,6 +15,9 @@ import (
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
) )
// InitContainer is the initialization of a container config.
// It returns the initial configs for a container. It's mostly
// defined by the default template.
func InitContainer(c *Command) *configs.Config { func InitContainer(c *Command) *configs.Config {
container := template.New() container := template.New()
@ -46,16 +49,17 @@ func getEnv(key string, env []string) string {
return "" return ""
} }
// SetupCgroups setups cgroup resources for a container.
func SetupCgroups(container *configs.Config, c *Command) error { func SetupCgroups(container *configs.Config, c *Command) error {
if c.Resources != nil { if c.Resources != nil {
container.Cgroups.CpuShares = c.Resources.CpuShares container.Cgroups.CpuShares = c.Resources.CPUShares
container.Cgroups.Memory = c.Resources.Memory container.Cgroups.Memory = c.Resources.Memory
container.Cgroups.MemoryReservation = c.Resources.Memory container.Cgroups.MemoryReservation = c.Resources.Memory
container.Cgroups.MemorySwap = c.Resources.MemorySwap container.Cgroups.MemorySwap = c.Resources.MemorySwap
container.Cgroups.CpusetCpus = c.Resources.CpusetCpus container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
container.Cgroups.CpusetMems = c.Resources.CpusetMems container.Cgroups.CpusetMems = c.Resources.CpusetMems
container.Cgroups.CpuPeriod = c.Resources.CpuPeriod container.Cgroups.CpuPeriod = c.Resources.CPUPeriod
container.Cgroups.CpuQuota = c.Resources.CpuQuota container.Cgroups.CpuQuota = c.Resources.CPUQuota
container.Cgroups.BlkioWeight = c.Resources.BlkioWeight container.Cgroups.BlkioWeight = c.Resources.BlkioWeight
container.Cgroups.OomKillDisable = c.Resources.OomKillDisable container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness
@ -109,6 +113,7 @@ func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) {
return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
} }
// Stats collects all the resource usage information from a container.
func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) { func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) {
f, err := os.Open(filepath.Join(containerDir, "state.json")) f, err := os.Open(filepath.Join(containerDir, "state.json"))
if err != nil { if err != nil {

View file

@ -12,6 +12,7 @@ import (
"github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/pkg/sysinfo"
) )
// NewDriver returns a new execdriver.Driver from the given name configured with the provided options.
func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) { func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) {
switch name { switch name {
case "lxc": case "lxc":

View file

@ -10,6 +10,7 @@ import (
"github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/pkg/sysinfo"
) )
// NewDriver returns a new execdriver.Driver from the given name configured with the provided options.
func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) { func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) {
switch name { switch name {
case "windows": case "windows":

View file

@ -34,11 +34,15 @@ import (
"github.com/vishvananda/netns" "github.com/vishvananda/netns"
) )
// DriverName for lxc driver
const DriverName = "lxc" const DriverName = "lxc"
// ErrExec defines unsupported error message
var ErrExec = errors.New("Unsupported: Exec is not supported by the lxc driver") var ErrExec = errors.New("Unsupported: Exec is not supported by the lxc driver")
type driver struct { // Driver contains all information for lxc driver,
// it implements execdriver.Driver
type Driver struct {
root string // root path for the driver to use root string // root path for the driver to use
libPath string libPath string
initPath string initPath string
@ -54,7 +58,8 @@ type activeContainer struct {
cmd *exec.Cmd cmd *exec.Cmd
} }
func NewDriver(root, libPath, initPath string, apparmor bool) (*driver, error) { // NewDriver returns a new lxc driver, called from NewDriver of execdriver
func NewDriver(root, libPath, initPath string, apparmor bool) (*Driver, error) {
if err := os.MkdirAll(root, 0700); err != nil { if err := os.MkdirAll(root, 0700); err != nil {
return nil, err return nil, err
} }
@ -66,7 +71,7 @@ func NewDriver(root, libPath, initPath string, apparmor bool) (*driver, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &driver{ return &Driver{
apparmor: apparmor, apparmor: apparmor,
root: root, root: root,
libPath: libPath, libPath: libPath,
@ -77,7 +82,8 @@ func NewDriver(root, libPath, initPath string, apparmor bool) (*driver, error) {
}, nil }, nil
} }
func (d *driver) Name() string { // Name implements the exec driver Driver interface.
func (d *Driver) Name() string {
version := d.version() version := d.version()
return fmt.Sprintf("%s-%s", DriverName, version) return fmt.Sprintf("%s-%s", DriverName, version)
} }
@ -117,7 +123,9 @@ func killNetNsProc(proc *os.Process) {
proc.Wait() proc.Wait()
} }
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) { // Run implements the exec driver Driver interface,
// it calls 'exec.Cmd' to launch lxc commands to run a container.
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
var ( var (
term execdriver.Terminal term execdriver.Terminal
err error err error
@ -392,7 +400,7 @@ func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
// createContainer populates and configures the container type with the // createContainer populates and configures the container type with the
// data provided by the execdriver.Command // data provided by the execdriver.Command
func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) { func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
container := execdriver.InitContainer(c) container := execdriver.InitContainer(c)
if err := execdriver.SetupCgroups(container, c); err != nil { if err := execdriver.SetupCgroups(container, c); err != nil {
return nil, err return nil, err
@ -400,8 +408,8 @@ func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error)
return container, nil return container, nil
} }
// Return an map of susbystem -> container cgroup // Return an map of susbystem -> absolute container cgroup path
func cgroupPaths(containerId string) (map[string]string, error) { func cgroupPaths(containerID string) (map[string]string, error) {
subsystems, err := cgroups.GetAllSubsystems() subsystems, err := cgroups.GetAllSubsystems()
if err != nil { if err != nil {
return nil, err return nil, err
@ -415,7 +423,7 @@ func cgroupPaths(containerId string) (map[string]string, error) {
//unsupported subystem //unsupported subystem
continue continue
} }
path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerId) path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerID)
paths[subsystem] = path paths[subsystem] = path
} }
@ -506,8 +514,8 @@ func setupUser(userSpec string) error {
return nil return nil
} }
/// Return the exit code of the process // getExitCode returns the exit code of the process.
// if the process has not exited -1 will be returned // If the process has not exited -1 will be returned.
func getExitCode(c *execdriver.Command) int { func getExitCode(c *execdriver.Command) int {
if c.ProcessConfig.ProcessState == nil { if c.ProcessConfig.ProcessState == nil {
return -1 return -1
@ -515,15 +523,18 @@ func getExitCode(c *execdriver.Command) int {
return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
} }
func (d *driver) Kill(c *execdriver.Command, sig int) error { // Kill implements the exec driver Driver interface.
func (d *Driver) Kill(c *execdriver.Command, sig int) error {
if sig == 9 || c.ProcessConfig.Process == nil { if sig == 9 || c.ProcessConfig.Process == nil {
return KillLxc(c.ID, sig) return killLxc(c.ID, sig)
} }
return c.ProcessConfig.Process.Signal(syscall.Signal(sig)) return c.ProcessConfig.Process.Signal(syscall.Signal(sig))
} }
func (d *driver) Pause(c *execdriver.Command) error { // Pause implements the exec driver Driver interface,
// it executes lxc-freeze to pause a container.
func (d *Driver) Pause(c *execdriver.Command) error {
_, err := exec.LookPath("lxc-freeze") _, err := exec.LookPath("lxc-freeze")
if err == nil { if err == nil {
output, errExec := exec.Command("lxc-freeze", "-n", c.ID).CombinedOutput() output, errExec := exec.Command("lxc-freeze", "-n", c.ID).CombinedOutput()
@ -535,7 +546,9 @@ func (d *driver) Pause(c *execdriver.Command) error {
return err return err
} }
func (d *driver) Unpause(c *execdriver.Command) error { // Unpause implements the exec driver Driver interface,
// it executes lxc-unfreeze to unpause a container.
func (d *Driver) Unpause(c *execdriver.Command) error {
_, err := exec.LookPath("lxc-unfreeze") _, err := exec.LookPath("lxc-unfreeze")
if err == nil { if err == nil {
output, errExec := exec.Command("lxc-unfreeze", "-n", c.ID).CombinedOutput() output, errExec := exec.Command("lxc-unfreeze", "-n", c.ID).CombinedOutput()
@ -547,11 +560,12 @@ func (d *driver) Unpause(c *execdriver.Command) error {
return err return err
} }
func (d *driver) Terminate(c *execdriver.Command) error { // Terminate implements the exec driver Driver interface.
return KillLxc(c.ID, 9) func (d *Driver) Terminate(c *execdriver.Command) error {
return killLxc(c.ID, 9)
} }
func (d *driver) version() string { func (d *Driver) version() string {
var ( var (
version string version string
output []byte output []byte
@ -571,7 +585,7 @@ func (d *driver) version() string {
return version return version
} }
func KillLxc(id string, sig int) error { func killLxc(id string, sig int) error {
var ( var (
err error err error
output []byte output []byte
@ -590,7 +604,7 @@ func KillLxc(id string, sig int) error {
} }
// wait for the process to start and return the pid for the process // wait for the process to start and return the pid for the process
func (d *driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (int, error) { func (d *Driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (int, error) {
var ( var (
err error err error
output []byte output []byte
@ -622,13 +636,13 @@ func (d *driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (in
return -1, execdriver.ErrNotRunning return -1, execdriver.ErrNotRunning
} }
func (d *driver) getInfo(id string) ([]byte, error) { func (d *Driver) getInfo(id string) ([]byte, error) {
return exec.Command("lxc-info", "-n", id).CombinedOutput() return exec.Command("lxc-info", "-n", id).CombinedOutput()
} }
type info struct { type info struct {
ID string ID string
driver *driver driver *Driver
} }
func (i *info) IsRunning() bool { func (i *info) IsRunning() bool {
@ -645,7 +659,8 @@ func (i *info) IsRunning() bool {
return running return running
} }
func (d *driver) Info(id string) execdriver.Info { // Info implements the exec driver Driver interface.
func (d *Driver) Info(id string) execdriver.Info {
return &info{ return &info{
ID: id, ID: id,
driver: d, driver: d,
@ -665,7 +680,8 @@ func findCgroupRootAndDir(subsystem string) (string, string, error) {
return cgroupRoot, cgroupDir, nil return cgroupRoot, cgroupDir, nil
} }
func (d *driver) GetPidsForContainer(id string) ([]int, error) { // GetPidsForContainer implements the exec driver Driver interface.
func (d *Driver) GetPidsForContainer(id string) ([]int, error) {
pids := []int{} pids := []int{}
// cpu is chosen because it is the only non optional subsystem in cgroups // cpu is chosen because it is the only non optional subsystem in cgroups
@ -730,11 +746,11 @@ func rootIsShared() bool {
return true return true
} }
func (d *driver) containerDir(containerId string) string { func (d *Driver) containerDir(containerID string) string {
return path.Join(d.libPath, "containers", containerId) return path.Join(d.libPath, "containers", containerID)
} }
func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) { func (d *Driver) generateLXCConfig(c *execdriver.Command) (string, error) {
root := path.Join(d.containerDir(c.ID), "config.lxc") root := path.Join(d.containerDir(c.ID), "config.lxc")
fo, err := os.Create(root) fo, err := os.Create(root)
@ -743,7 +759,7 @@ func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
} }
defer fo.Close() defer fo.Close()
if err := LxcTemplateCompiled.Execute(fo, struct { if err := lxcTemplateCompiled.Execute(fo, struct {
*execdriver.Command *execdriver.Command
AppArmor bool AppArmor bool
}{ }{
@ -756,7 +772,7 @@ func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
return root, nil return root, nil
} }
func (d *driver) generateEnvConfig(c *execdriver.Command) error { func (d *Driver) generateEnvConfig(c *execdriver.Command) error {
data, err := json.Marshal(c.ProcessConfig.Env) data, err := json.Marshal(c.ProcessConfig.Env)
if err != nil { if err != nil {
return err return err
@ -772,16 +788,21 @@ func (d *driver) generateEnvConfig(c *execdriver.Command) error {
return ioutil.WriteFile(p, data, 0600) return ioutil.WriteFile(p, data, 0600)
} }
// Clean not implemented for lxc // Clean implements the exec driver Driver interface,
func (d *driver) Clean(id string) error { // it's not implemented by lxc.
func (d *Driver) Clean(id string) error {
return nil return nil
} }
// TtyConsole implements the exec driver Terminal interface,
// it stores the master and slave ends of the container's pty.
type TtyConsole struct { type TtyConsole struct {
MasterPty *os.File MasterPty *os.File
SlavePty *os.File SlavePty *os.File
} }
// NewTtyConsole returns a new TtyConsole struct.
// Wired up to the provided process config and stdin/stdout/stderr pipes.
func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) { func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
// lxc is special in that we cannot create the master outside of the container without // lxc is special in that we cannot create the master outside of the container without
// opening the slave because we have nothing to provide to the cmd. We have to open both then do // opening the slave because we have nothing to provide to the cmd. We have to open both then do
@ -808,10 +829,12 @@ func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pi
return tty, nil return tty, nil
} }
// Resize implements Resize method of Terminal interface
func (t *TtyConsole) Resize(h, w int) error { func (t *TtyConsole) Resize(h, w int) error {
return term.SetWinsize(t.MasterPty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)}) return term.SetWinsize(t.MasterPty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
} }
// AttachPipes attaches given pipes to exec.Cmd
func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) error { func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) error {
command.Stdout = t.SlavePty command.Stdout = t.SlavePty
command.Stderr = t.SlavePty command.Stderr = t.SlavePty
@ -839,16 +862,22 @@ func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) err
return nil return nil
} }
// Close implements Close method of Terminal interface
func (t *TtyConsole) Close() error { func (t *TtyConsole) Close() error {
t.SlavePty.Close() t.SlavePty.Close()
return t.MasterPty.Close() return t.MasterPty.Close()
} }
func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) { // Exec implements the exec driver Driver interface,
// it is not implemented by lxc.
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
return -1, ErrExec return -1, ErrExec
} }
func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) { // Stats implements the exec driver Driver interface.
// Lxc doesn't implement it's own Stats, it does some trick by implementing
// execdriver.Stats to get stats info by libcontainer APIs.
func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
if _, ok := d.activeContainers[id]; !ok { if _, ok := d.activeContainers[id]; !ok {
return nil, fmt.Errorf("%s is not a key in active containers", id) return nil, fmt.Errorf("%s is not a key in active containers", id)
} }

View file

@ -9,6 +9,7 @@ import (
"strings" "strings"
) )
// Define error messages
var ( var (
ErrCannotParse = errors.New("cannot parse raw input") ErrCannotParse = errors.New("cannot parse raw input")
) )

View file

@ -16,11 +16,11 @@ import (
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
) )
// Args provided to the init function for a driver // InitArgs contains args provided to the init function for a driver
type InitArgs struct { type InitArgs struct {
User string User string
Gateway string Gateway string
Ip string IP string
WorkDir string WorkDir string
Privileged bool Privileged bool
Env []string Env []string
@ -94,7 +94,7 @@ func getArgs() *InitArgs {
return &InitArgs{ return &InitArgs{
User: *user, User: *user,
Gateway: *gateway, Gateway: *gateway,
Ip: *ip, IP: *ip,
WorkDir: *workDir, WorkDir: *workDir,
Privileged: *privileged, Privileged: *privileged,
Args: flag.Args(), Args: flag.Args(),

View file

@ -15,6 +15,8 @@ import (
"github.com/opencontainers/runc/libcontainer/label" "github.com/opencontainers/runc/libcontainer/label"
) )
// LxcTemplate is the template for lxc driver, it's used
// to configure LXC.
const LxcTemplate = ` const LxcTemplate = `
lxc.network.type = none lxc.network.type = none
# root filesystem # root filesystem
@ -94,11 +96,11 @@ lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.Memory}}
lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}} lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
{{end}} {{end}}
{{end}} {{end}}
{{if .Resources.CpuShares}} {{if .Resources.CPUShares}}
lxc.cgroup.cpu.shares = {{.Resources.CpuShares}} lxc.cgroup.cpu.shares = {{.Resources.CPUShares}}
{{end}} {{end}}
{{if .Resources.CpuPeriod}} {{if .Resources.CPUPeriod}}
lxc.cgroup.cpu.cfs_period_us = {{.Resources.CpuPeriod}} lxc.cgroup.cpu.cfs_period_us = {{.Resources.CPUPeriod}}
{{end}} {{end}}
{{if .Resources.CpusetCpus}} {{if .Resources.CpusetCpus}}
lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}} lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
@ -106,8 +108,8 @@ lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
{{if .Resources.CpusetMems}} {{if .Resources.CpusetMems}}
lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}} lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}}
{{end}} {{end}}
{{if .Resources.CpuQuota}} {{if .Resources.CPUQuota}}
lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CpuQuota}} lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CPUQuota}}
{{end}} {{end}}
{{if .Resources.BlkioWeight}} {{if .Resources.BlkioWeight}}
lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}} lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}}
@ -158,7 +160,7 @@ lxc.cap.drop = {{.}}
{{end}} {{end}}
` `
var LxcTemplateCompiled *template.Template var lxcTemplateCompiled *template.Template
// Escape spaces in strings according to the fstab documentation, which is the // Escape spaces in strings according to the fstab documentation, which is the
// format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab". // format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab".
@ -254,7 +256,7 @@ func init() {
"dropList": dropList, "dropList": dropList,
"getHostname": getHostname, "getHostname": getHostname,
} }
LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) lxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -47,7 +47,7 @@ func TestLXCConfig(t *testing.T) {
ID: "1", ID: "1",
Resources: &execdriver.Resources{ Resources: &execdriver.Resources{
Memory: int64(mem), Memory: int64(mem),
CpuShares: int64(cpu), CPUShares: int64(cpu),
}, },
Network: &execdriver.Network{ Network: &execdriver.Network{
Mtu: 1500, Mtu: 1500,

View file

@ -18,7 +18,7 @@ import (
// createContainer populates and configures the container type with the // createContainer populates and configures the container type with the
// data provided by the execdriver.Command // data provided by the execdriver.Command
func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) { func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
container := execdriver.InitContainer(c) container := execdriver.InitContainer(c)
if err := d.createIpc(container, c); err != nil { if err := d.createIpc(container, c); err != nil {
@ -113,7 +113,7 @@ func generateIfaceName() (string, error) {
return "", errors.New("Failed to find name for new interface") return "", errors.New("Failed to find name for new interface")
} }
func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error { func (d *Driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
if c.Network == nil { if c.Network == nil {
return nil return nil
} }
@ -143,7 +143,7 @@ func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command)
return nil return nil
} }
func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error { func (d *Driver) createIpc(container *configs.Config, c *execdriver.Command) error {
if c.Ipc.HostIpc { if c.Ipc.HostIpc {
container.Namespaces.Remove(configs.NEWIPC) container.Namespaces.Remove(configs.NEWIPC)
return nil return nil
@ -168,7 +168,7 @@ func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) err
return nil return nil
} }
func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error { func (d *Driver) createPid(container *configs.Config, c *execdriver.Command) error {
if c.Pid.HostPid { if c.Pid.HostPid {
container.Namespaces.Remove(configs.NEWPID) container.Namespaces.Remove(configs.NEWPID)
return nil return nil
@ -177,7 +177,7 @@ func (d *driver) createPid(container *configs.Config, c *execdriver.Command) err
return nil return nil
} }
func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) error { func (d *Driver) createUTS(container *configs.Config, c *execdriver.Command) error {
if c.UTS.HostUTS { if c.UTS.HostUTS {
container.Namespaces.Remove(configs.NEWUTS) container.Namespaces.Remove(configs.NEWUTS)
container.Hostname = "" container.Hostname = ""
@ -187,7 +187,7 @@ func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) err
return nil return nil
} }
func (d *driver) setPrivileged(container *configs.Config) (err error) { func (d *Driver) setPrivileged(container *configs.Config) (err error) {
container.Capabilities = execdriver.GetAllCapabilities() container.Capabilities = execdriver.GetAllCapabilities()
container.Cgroups.AllowAllDevices = true container.Cgroups.AllowAllDevices = true
@ -204,12 +204,12 @@ func (d *driver) setPrivileged(container *configs.Config) (err error) {
return nil return nil
} }
func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) { func (d *Driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop) container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
return err return err
} }
func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) { func (d *Driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
if c.Resources == nil { if c.Resources == nil {
return return
} }
@ -223,7 +223,7 @@ func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command)
} }
} }
func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error { func (d *Driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
userMounts := make(map[string]struct{}) userMounts := make(map[string]struct{})
for _, m := range c.Mounts { for _, m := range c.Mounts {
userMounts[m.Destination] = struct{}{} userMounts[m.Destination] = struct{}{}
@ -260,7 +260,7 @@ func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) e
return nil return nil
} }
func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) { func (d *Driver) setupLabels(container *configs.Config, c *execdriver.Command) {
container.ProcessLabel = c.ProcessLabel container.ProcessLabel = c.ProcessLabel
container.MountLabel = c.MountLabel container.MountLabel = c.MountLabel
} }

View file

@ -27,12 +27,15 @@ import (
"github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runc/libcontainer/utils"
) )
// Define constants for native driver
const ( const (
DriverName = "native" DriverName = "native"
Version = "0.2" Version = "0.2"
) )
type driver struct { // Driver contains all information for native driver,
// it implements execdriver.Driver.
type Driver struct {
root string root string
initPath string initPath string
activeContainers map[string]libcontainer.Container activeContainers map[string]libcontainer.Container
@ -41,7 +44,8 @@ type driver struct {
sync.Mutex sync.Mutex
} }
func NewDriver(root, initPath string, options []string) (*driver, error) { // NewDriver returns a new native driver, called from NewDriver of execdriver.
func NewDriver(root, initPath string, options []string) (*Driver, error) {
meminfo, err := sysinfo.ReadMemInfo() meminfo, err := sysinfo.ReadMemInfo()
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,7 +100,7 @@ func NewDriver(root, initPath string, options []string) (*driver, error) {
return nil, err return nil, err
} }
return &driver{ return &Driver{
root: root, root: root,
initPath: initPath, initPath: initPath,
activeContainers: make(map[string]libcontainer.Container), activeContainers: make(map[string]libcontainer.Container),
@ -110,7 +114,9 @@ type execOutput struct {
err error err error
} }
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) { // Run implements the exec driver Driver interface,
// it calls libcontainer APIs to run a container.
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
// take the Command and populate the libcontainer.Config from it // take the Command and populate the libcontainer.Config from it
container, err := d.createContainer(c) container, err := d.createContainer(c)
if err != nil { if err != nil {
@ -238,7 +244,8 @@ func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*o
} }
} }
func (d *driver) Kill(c *execdriver.Command, sig int) error { // Kill implements the exec driver Driver interface.
func (d *Driver) Kill(c *execdriver.Command, sig int) error {
d.Lock() d.Lock()
active := d.activeContainers[c.ID] active := d.activeContainers[c.ID]
d.Unlock() d.Unlock()
@ -252,7 +259,9 @@ func (d *driver) Kill(c *execdriver.Command, sig int) error {
return syscall.Kill(state.InitProcessPid, syscall.Signal(sig)) return syscall.Kill(state.InitProcessPid, syscall.Signal(sig))
} }
func (d *driver) Pause(c *execdriver.Command) error { // Pause implements the exec driver Driver interface,
// it calls libcontainer API to pause a container.
func (d *Driver) Pause(c *execdriver.Command) error {
d.Lock() d.Lock()
active := d.activeContainers[c.ID] active := d.activeContainers[c.ID]
d.Unlock() d.Unlock()
@ -262,7 +271,9 @@ func (d *driver) Pause(c *execdriver.Command) error {
return active.Pause() return active.Pause()
} }
func (d *driver) Unpause(c *execdriver.Command) error { // Unpause implements the exec driver Driver interface,
// it calls libcontainer API to unpause a container.
func (d *Driver) Unpause(c *execdriver.Command) error {
d.Lock() d.Lock()
active := d.activeContainers[c.ID] active := d.activeContainers[c.ID]
d.Unlock() d.Unlock()
@ -272,7 +283,8 @@ func (d *driver) Unpause(c *execdriver.Command) error {
return active.Resume() return active.Resume()
} }
func (d *driver) Terminate(c *execdriver.Command) error { // Terminate implements the exec driver Driver interface.
func (d *Driver) Terminate(c *execdriver.Command) error {
defer d.cleanContainer(c.ID) defer d.cleanContainer(c.ID)
container, err := d.factory.Load(c.ID) container, err := d.factory.Load(c.ID)
if err != nil { if err != nil {
@ -295,18 +307,21 @@ func (d *driver) Terminate(c *execdriver.Command) error {
return err return err
} }
func (d *driver) Info(id string) execdriver.Info { // Info implements the exec driver Driver interface.
func (d *Driver) Info(id string) execdriver.Info {
return &info{ return &info{
ID: id, ID: id,
driver: d, driver: d,
} }
} }
func (d *driver) Name() string { // Name implements the exec driver Driver interface.
func (d *Driver) Name() string {
return fmt.Sprintf("%s-%s", DriverName, Version) return fmt.Sprintf("%s-%s", DriverName, Version)
} }
func (d *driver) GetPidsForContainer(id string) ([]int, error) { // GetPidsForContainer implements the exec driver Driver interface.
func (d *Driver) GetPidsForContainer(id string) ([]int, error) {
d.Lock() d.Lock()
active := d.activeContainers[id] active := d.activeContainers[id]
d.Unlock() d.Unlock()
@ -317,22 +332,24 @@ func (d *driver) GetPidsForContainer(id string) ([]int, error) {
return active.Processes() return active.Processes()
} }
func (d *driver) cleanContainer(id string) error { func (d *Driver) cleanContainer(id string) error {
d.Lock() d.Lock()
delete(d.activeContainers, id) delete(d.activeContainers, id)
d.Unlock() d.Unlock()
return os.RemoveAll(filepath.Join(d.root, id)) return os.RemoveAll(filepath.Join(d.root, id))
} }
func (d *driver) createContainerRoot(id string) error { func (d *Driver) createContainerRoot(id string) error {
return os.MkdirAll(filepath.Join(d.root, id), 0655) return os.MkdirAll(filepath.Join(d.root, id), 0655)
} }
func (d *driver) Clean(id string) error { // Clean implements the exec driver Driver interface.
func (d *Driver) Clean(id string) error {
return os.RemoveAll(filepath.Join(d.root, id)) return os.RemoveAll(filepath.Join(d.root, id))
} }
func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) { // Stats implements the exec driver Driver interface.
func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
d.Lock() d.Lock()
c := d.activeContainers[id] c := d.activeContainers[id]
d.Unlock() d.Unlock()
@ -357,10 +374,12 @@ func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) {
}, nil }, nil
} }
// TtyConsole implements the exec driver Terminal interface.
type TtyConsole struct { type TtyConsole struct {
console libcontainer.Console console libcontainer.Console
} }
// NewTtyConsole returns a new TtyConsole struct.
func NewTtyConsole(console libcontainer.Console, pipes *execdriver.Pipes) (*TtyConsole, error) { func NewTtyConsole(console libcontainer.Console, pipes *execdriver.Pipes) (*TtyConsole, error) {
tty := &TtyConsole{ tty := &TtyConsole{
console: console, console: console,
@ -374,10 +393,12 @@ func NewTtyConsole(console libcontainer.Console, pipes *execdriver.Pipes) (*TtyC
return tty, nil return tty, nil
} }
// Resize implements Resize method of Terminal interface
func (t *TtyConsole) Resize(h, w int) error { func (t *TtyConsole) Resize(h, w int) error {
return term.SetWinsize(t.console.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)}) return term.SetWinsize(t.console.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
} }
// AttachPipes attaches given pipes to TtyConsole
func (t *TtyConsole) AttachPipes(pipes *execdriver.Pipes) error { func (t *TtyConsole) AttachPipes(pipes *execdriver.Pipes) error {
go func() { go func() {
if wb, ok := pipes.Stdout.(interface { if wb, ok := pipes.Stdout.(interface {
@ -400,6 +421,7 @@ func (t *TtyConsole) AttachPipes(pipes *execdriver.Pipes) error {
return nil return nil
} }
// Close implements Close method of Terminal interface
func (t *TtyConsole) Close() error { func (t *TtyConsole) Close() error {
return t.console.Close() return t.console.Close()
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
) )
// NewDriver returns a new native driver, called from NewDriver of execdriver.
func NewDriver(root, initPath string) (execdriver.Driver, error) { func NewDriver(root, initPath string) (execdriver.Driver, error) {
return nil, fmt.Errorf("native driver not supported on non-linux") return nil, fmt.Errorf("native driver not supported on non-linux")
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
) )
// NewDriver returns a new native driver, called from NewDriver of execdriver.
func NewDriver(root, initPath string) (execdriver.Driver, error) { func NewDriver(root, initPath string) (execdriver.Driver, error) {
return nil, fmt.Errorf("native driver not supported on non-linux") return nil, fmt.Errorf("native driver not supported on non-linux")
} }

View file

@ -10,12 +10,17 @@ import (
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
// Blank import 'nsenter' so that init in that package will call c
// function 'nsexec()' to do 'setns' before Go runtime take over,
// it's used for join to exist ns like 'docker exec' command.
_ "github.com/opencontainers/runc/libcontainer/nsenter" _ "github.com/opencontainers/runc/libcontainer/nsenter"
"github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runc/libcontainer/utils"
) )
// Exec implements the exec driver Driver interface,
// it calls libcontainer APIs to execute a container.
// TODO(vishh): Add support for running in privileged mode. // TODO(vishh): Add support for running in privileged mode.
func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) { func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
active := d.activeContainers[c.ID] active := d.activeContainers[c.ID]
if active == nil { if active == nil {
return -1, fmt.Errorf("No active container exists with ID %s", c.ID) return -1, fmt.Errorf("No active container exists with ID %s", c.ID)

View file

@ -4,7 +4,7 @@ package native
type info struct { type info struct {
ID string ID string
driver *driver driver *Driver
} }
// IsRunning is determined by looking for the // IsRunning is determined by looking for the

View file

@ -4,13 +4,14 @@ import (
"io" "io"
) )
// Pipes is a wrapper around a containers output for // Pipes is a wrapper around a container's output for
// stdin, stdout, stderr // stdin, stdout, stderr
type Pipes struct { type Pipes struct {
Stdin io.ReadCloser Stdin io.ReadCloser
Stdout, Stderr io.Writer Stdout, Stderr io.Writer
} }
// NewPipes returns a wrapper around a container's output
func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes { func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes {
p := &Pipes{ p := &Pipes{
Stdout: stdout, Stdout: stdout,

View file

@ -5,9 +5,11 @@ import (
"os/exec" "os/exec"
) )
// StdConsole defines standard console operations for execdriver
type StdConsole struct { type StdConsole struct {
} }
// NewStdConsole returns a new StdConsole struct
func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, error) { func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, error) {
std := &StdConsole{} std := &StdConsole{}
@ -17,6 +19,7 @@ func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, err
return std, nil return std, nil
} }
// AttachPipes attaches given pipes to exec.Cmd
func (s *StdConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error { func (s *StdConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error {
command.Stdout = pipes.Stdout command.Stdout = pipes.Stdout
command.Stderr = pipes.Stderr command.Stderr = pipes.Stderr
@ -35,11 +38,13 @@ func (s *StdConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error {
return nil return nil
} }
// Resize implements Resize method of Terminal interface
func (s *StdConsole) Resize(h, w int) error { func (s *StdConsole) Resize(h, w int) error {
// we do not need to reside a non tty // we do not need to reside a non tty
return nil return nil
} }
// Close implements Close method of Terminal interface
func (s *StdConsole) Close() error { func (s *StdConsole) Close() error {
// nothing to close here // nothing to close here
return nil return nil

View file

@ -30,17 +30,24 @@ func init() {
} }
type ( type (
// CapabilityMapping maps linux capability name to its value of capability.Cap type
// Capabilities is one of the security systems in Linux Security Module (LSM)
// framework provided by the kernel.
// For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
CapabilityMapping struct { CapabilityMapping struct {
Key string `json:"key,omitempty"` Key string `json:"key,omitempty"`
Value capability.Cap `json:"value,omitempty"` Value capability.Cap `json:"value,omitempty"`
} }
// Capabilities contains all CapabilityMapping
Capabilities []*CapabilityMapping Capabilities []*CapabilityMapping
) )
// String returns <key> of CapabilityMapping
func (c *CapabilityMapping) String() string { func (c *CapabilityMapping) String() string {
return c.Key return c.Key
} }
// GetCapability returns CapabilityMapping which contains specific key
func GetCapability(key string) *CapabilityMapping { func GetCapability(key string) *CapabilityMapping {
for _, capp := range capabilityList { for _, capp := range capabilityList {
if capp.Key == key { if capp.Key == key {
@ -51,6 +58,7 @@ func GetCapability(key string) *CapabilityMapping {
return nil return nil
} }
// GetAllCapabilities returns all of the capabilities
func GetAllCapabilities() []string { func GetAllCapabilities() []string {
output := make([]string, len(capabilityList)) output := make([]string, len(capabilityList))
for i, capability := range capabilityList { for i, capability := range capabilityList {
@ -59,6 +67,8 @@ func GetAllCapabilities() []string {
return output return output
} }
// TweakCapabilities can tweak capabilities by adding or dropping capabilities
// based on the basics capabilities.
func TweakCapabilities(basics, adds, drops []string) ([]string, error) { func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
var ( var (
newCaps []string newCaps []string

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
) )
// NewDriver returns a new execdriver.Driver
func NewDriver(root, initPath string) (execdriver.Driver, error) { func NewDriver(root, initPath string) (execdriver.Driver, error) {
return nil, fmt.Errorf("Windows driver not supported on non-Windows") return nil, fmt.Errorf("Windows driver not supported on non-Windows")
} }