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:
parent
4ed3e3a5b2
commit
3d17c3bb66
20 changed files with 231 additions and 99 deletions
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
)
|
)
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue