Addresses: #14756
Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
| ... | ... |
@@ -272,11 +272,11 @@ func populateCommand(c *Container, env []string) error {
|
| 272 | 272 |
resources := &execdriver.Resources{
|
| 273 | 273 |
Memory: c.hostConfig.Memory, |
| 274 | 274 |
MemorySwap: c.hostConfig.MemorySwap, |
| 275 |
- CpuShares: c.hostConfig.CPUShares, |
|
| 275 |
+ CPUShares: c.hostConfig.CPUShares, |
|
| 276 | 276 |
CpusetCpus: c.hostConfig.CpusetCpus, |
| 277 | 277 |
CpusetMems: c.hostConfig.CpusetMems, |
| 278 |
- CpuPeriod: c.hostConfig.CPUPeriod, |
|
| 279 |
- CpuQuota: c.hostConfig.CPUQuota, |
|
| 278 |
+ CPUPeriod: c.hostConfig.CPUPeriod, |
|
| 279 |
+ CPUQuota: c.hostConfig.CPUQuota, |
|
| 280 | 280 |
BlkioWeight: c.hostConfig.BlkioWeight, |
| 281 | 281 |
Rlimits: rlimits, |
| 282 | 282 |
OomKillDisable: c.hostConfig.OomKillDisable, |
| ... | ... |
@@ -16,6 +16,7 @@ import ( |
| 16 | 16 |
// arbatrary data to be sent |
| 17 | 17 |
type Context map[string]string |
| 18 | 18 |
|
| 19 |
+// Define error messages |
|
| 19 | 20 |
var ( |
| 20 | 21 |
ErrNotRunning = errors.New("Container is not running")
|
| 21 | 22 |
ErrWaitTimeoutReached = errors.New("Wait timeout reached")
|
| ... | ... |
@@ -23,17 +24,19 @@ var ( |
| 23 | 23 |
ErrDriverNotFound = errors.New("The requested docker init has not been found")
|
| 24 | 24 |
) |
| 25 | 25 |
|
| 26 |
+// StartCallback defines a callback function. |
|
| 27 |
+// It's used by 'Run' and 'Exec', does some work in parent process |
|
| 28 |
+// after child process is started. |
|
| 26 | 29 |
type StartCallback func(*ProcessConfig, int) |
| 27 | 30 |
|
| 28 |
-// Driver specific information based on |
|
| 31 |
+// Info is driver specific information based on |
|
| 29 | 32 |
// processes registered with the driver |
| 30 | 33 |
type Info interface {
|
| 31 | 34 |
IsRunning() bool |
| 32 | 35 |
} |
| 33 | 36 |
|
| 34 |
-// Terminal in an interface for drivers to implement |
|
| 35 |
-// if they want to support Close and Resize calls from |
|
| 36 |
-// the core |
|
| 37 |
+// Terminal represents a pseudo TTY, it is for when |
|
| 38 |
+// using a container interactively. |
|
| 37 | 39 |
type Terminal interface {
|
| 38 | 40 |
io.Closer |
| 39 | 41 |
Resize(height, width int) error |
| ... | ... |
@@ -48,19 +51,44 @@ type ExitStatus struct {
|
| 48 | 48 |
OOMKilled bool |
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 |
+// Driver is an interface for drivers to implement |
|
| 52 |
+// including all basic functions a driver should have |
|
| 51 | 53 |
type Driver interface {
|
| 52 |
- Run(c *Command, pipes *Pipes, startCallback StartCallback) (ExitStatus, error) // Run executes the process and blocks until the process exits and returns the exit code |
|
| 53 |
- // Exec executes the process in an existing container, blocks until the process exits and returns the exit code |
|
| 54 |
+ // Run executes the process, blocks until the process exits and returns |
|
| 55 |
+ // the exit code. It's the last stage on Docker side for running a container. |
|
| 56 |
+ Run(c *Command, pipes *Pipes, startCallback StartCallback) (ExitStatus, error) |
|
| 57 |
+ |
|
| 58 |
+ // Exec executes the process in an existing container, blocks until the |
|
| 59 |
+ // process exits and returns the exit code. |
|
| 54 | 60 |
Exec(c *Command, processConfig *ProcessConfig, pipes *Pipes, startCallback StartCallback) (int, error) |
| 61 |
+ |
|
| 62 |
+ // Kill sends signals to process in container. |
|
| 55 | 63 |
Kill(c *Command, sig int) error |
| 64 |
+ |
|
| 65 |
+ // Pause pauses a container. |
|
| 56 | 66 |
Pause(c *Command) error |
| 67 |
+ |
|
| 68 |
+ // Unpause unpauses a container. |
|
| 57 | 69 |
Unpause(c *Command) error |
| 58 |
- Name() string // Driver name |
|
| 59 |
- Info(id string) Info // "temporary" hack (until we move state from core to plugins) |
|
| 60 |
- GetPidsForContainer(id string) ([]int, error) // Returns a list of pids for the given container. |
|
| 61 |
- Terminate(c *Command) error // kill it with fire |
|
| 62 |
- Clean(id string) error // clean all traces of container exec |
|
| 63 |
- Stats(id string) (*ResourceStats, error) // Get resource stats for a running container |
|
| 70 |
+ |
|
| 71 |
+ // Name returns the name of the driver. |
|
| 72 |
+ Name() string |
|
| 73 |
+ |
|
| 74 |
+ // Info returns the configuration stored in the driver struct, |
|
| 75 |
+ // "temporary" hack (until we move state from core to plugins). |
|
| 76 |
+ Info(id string) Info |
|
| 77 |
+ |
|
| 78 |
+ // GetPidsForContainer returns a list of pid for the processes running in a container. |
|
| 79 |
+ GetPidsForContainer(id string) ([]int, error) |
|
| 80 |
+ |
|
| 81 |
+ // Terminate kills a container by sending signal SIGKILL. |
|
| 82 |
+ Terminate(c *Command) error |
|
| 83 |
+ |
|
| 84 |
+ // Clean removes all traces of container exec. |
|
| 85 |
+ Clean(id string) error |
|
| 86 |
+ |
|
| 87 |
+ // Stats returns resource stats for a running container |
|
| 88 |
+ Stats(id string) (*ResourceStats, error) |
|
| 64 | 89 |
} |
| 65 | 90 |
|
| 66 | 91 |
// Network settings of the container |
| ... | ... |
@@ -72,22 +100,37 @@ type Network struct {
|
| 72 | 72 |
HostNetworking bool `json:"host_networking"` |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
-// IPC settings of the container |
|
| 75 |
+// Ipc settings of the container |
|
| 76 |
+// It is for IPC namespace setting. Usually different containers |
|
| 77 |
+// have their own IPC namespace, however this specifies to use |
|
| 78 |
+// an existing IPC namespace. |
|
| 79 |
+// You can join the host's or a container's IPC namespace. |
|
| 76 | 80 |
type Ipc struct {
|
| 77 | 81 |
ContainerID string `json:"container_id"` // id of the container to join ipc. |
| 78 | 82 |
HostIpc bool `json:"host_ipc"` |
| 79 | 83 |
} |
| 80 | 84 |
|
| 81 |
-// PID settings of the container |
|
| 85 |
+// Pid settings of the container |
|
| 86 |
+// It is for PID namespace setting. Usually different containers |
|
| 87 |
+// have their own PID namespace, however this specifies to use |
|
| 88 |
+// an existing PID namespace. |
|
| 89 |
+// Joining the host's PID namespace is currently the only supported |
|
| 90 |
+// option. |
|
| 82 | 91 |
type Pid struct {
|
| 83 | 92 |
HostPid bool `json:"host_pid"` |
| 84 | 93 |
} |
| 85 | 94 |
|
| 86 | 95 |
// UTS settings of the container |
| 96 |
+// It is for UTS namespace setting. Usually different containers |
|
| 97 |
+// have their own UTS namespace, however this specifies to use |
|
| 98 |
+// an existing UTS namespace. |
|
| 99 |
+// Joining the host's UTS namespace is currently the only supported |
|
| 100 |
+// option. |
|
| 87 | 101 |
type UTS struct {
|
| 88 | 102 |
HostUTS bool `json:"host_uts"` |
| 89 | 103 |
} |
| 90 | 104 |
|
| 105 |
+// NetworkInterface contains all network configs for a driver |
|
| 91 | 106 |
type NetworkInterface struct {
|
| 92 | 107 |
Gateway string `json:"gateway"` |
| 93 | 108 |
IPAddress string `json:"ip"` |
| ... | ... |
@@ -101,21 +144,24 @@ type NetworkInterface struct {
|
| 101 | 101 |
HairpinMode bool `json:"hairpin_mode"` |
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 |
+// Resources contains all resource configs for a driver. |
|
| 105 |
+// Currently these are all for cgroup configs. |
|
| 104 | 106 |
// TODO Windows: Factor out ulimit.Rlimit |
| 105 | 107 |
type Resources struct {
|
| 106 | 108 |
Memory int64 `json:"memory"` |
| 107 | 109 |
MemorySwap int64 `json:"memory_swap"` |
| 108 |
- CpuShares int64 `json:"cpu_shares"` |
|
| 110 |
+ CPUShares int64 `json:"cpu_shares"` |
|
| 109 | 111 |
CpusetCpus string `json:"cpuset_cpus"` |
| 110 | 112 |
CpusetMems string `json:"cpuset_mems"` |
| 111 |
- CpuPeriod int64 `json:"cpu_period"` |
|
| 112 |
- CpuQuota int64 `json:"cpu_quota"` |
|
| 113 |
+ CPUPeriod int64 `json:"cpu_period"` |
|
| 114 |
+ CPUQuota int64 `json:"cpu_quota"` |
|
| 113 | 115 |
BlkioWeight int64 `json:"blkio_weight"` |
| 114 | 116 |
Rlimits []*ulimit.Rlimit `json:"rlimits"` |
| 115 | 117 |
OomKillDisable bool `json:"oom_kill_disable"` |
| 116 | 118 |
MemorySwappiness int64 `json:"memory_swappiness"` |
| 117 | 119 |
} |
| 118 | 120 |
|
| 121 |
+// ResourceStats contains information about resource usage by a container. |
|
| 119 | 122 |
type ResourceStats struct {
|
| 120 | 123 |
*libcontainer.Stats |
| 121 | 124 |
Read time.Time `json:"read"` |
| ... | ... |
@@ -123,6 +169,7 @@ type ResourceStats struct {
|
| 123 | 123 |
SystemUsage uint64 `json:"system_usage"` |
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 |
+// Mount contains information for a mount operation. |
|
| 126 | 127 |
type Mount struct {
|
| 127 | 128 |
Source string `json:"source"` |
| 128 | 129 |
Destination string `json:"destination"` |
| ... | ... |
@@ -131,7 +178,7 @@ type Mount struct {
|
| 131 | 131 |
Slave bool `json:"slave"` |
| 132 | 132 |
} |
| 133 | 133 |
|
| 134 |
-// Describes a process that will be run inside a container. |
|
| 134 |
+// ProcessConfig describes a process that will be run inside a container. |
|
| 135 | 135 |
type ProcessConfig struct {
|
| 136 | 136 |
exec.Cmd `json:"-"` |
| 137 | 137 |
|
| ... | ... |
@@ -145,10 +192,10 @@ type ProcessConfig struct {
|
| 145 | 145 |
ConsoleSize [2]int `json:"-"` // h,w of initial console size |
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 |
+// Command wrapps an os/exec.Cmd to add more metadata |
|
| 149 |
+// |
|
| 148 | 150 |
// TODO Windows: Factor out unused fields such as LxcConfig, AppArmorProfile, |
| 149 | 151 |
// and CgroupParent. |
| 150 |
-// |
|
| 151 |
-// Process wrapps an os/exec.Cmd to add more metadata |
|
| 152 | 152 |
type Command struct {
|
| 153 | 153 |
ID string `json:"id"` |
| 154 | 154 |
Rootfs string `json:"rootfs"` // root fs of the container |
| ... | ... |
@@ -15,6 +15,9 @@ import ( |
| 15 | 15 |
"github.com/opencontainers/runc/libcontainer/configs" |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 |
+// InitContainer is the initialization of a container config. |
|
| 19 |
+// It returns the initial configs for a container. It's mostly |
|
| 20 |
+// defined by the default template. |
|
| 18 | 21 |
func InitContainer(c *Command) *configs.Config {
|
| 19 | 22 |
container := template.New() |
| 20 | 23 |
|
| ... | ... |
@@ -46,16 +49,17 @@ func getEnv(key string, env []string) string {
|
| 46 | 46 |
return "" |
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 |
+// SetupCgroups setups cgroup resources for a container. |
|
| 49 | 50 |
func SetupCgroups(container *configs.Config, c *Command) error {
|
| 50 | 51 |
if c.Resources != nil {
|
| 51 |
- container.Cgroups.CpuShares = c.Resources.CpuShares |
|
| 52 |
+ container.Cgroups.CpuShares = c.Resources.CPUShares |
|
| 52 | 53 |
container.Cgroups.Memory = c.Resources.Memory |
| 53 | 54 |
container.Cgroups.MemoryReservation = c.Resources.Memory |
| 54 | 55 |
container.Cgroups.MemorySwap = c.Resources.MemorySwap |
| 55 | 56 |
container.Cgroups.CpusetCpus = c.Resources.CpusetCpus |
| 56 | 57 |
container.Cgroups.CpusetMems = c.Resources.CpusetMems |
| 57 |
- container.Cgroups.CpuPeriod = c.Resources.CpuPeriod |
|
| 58 |
- container.Cgroups.CpuQuota = c.Resources.CpuQuota |
|
| 58 |
+ container.Cgroups.CpuPeriod = c.Resources.CPUPeriod |
|
| 59 |
+ container.Cgroups.CpuQuota = c.Resources.CPUQuota |
|
| 59 | 60 |
container.Cgroups.BlkioWeight = c.Resources.BlkioWeight |
| 60 | 61 |
container.Cgroups.OomKillDisable = c.Resources.OomKillDisable |
| 61 | 62 |
container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness |
| ... | ... |
@@ -109,6 +113,7 @@ func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) {
|
| 109 | 109 |
return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) |
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 |
+// Stats collects all the resource usage information from a container. |
|
| 112 | 113 |
func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) {
|
| 113 | 114 |
f, err := os.Open(filepath.Join(containerDir, "state.json")) |
| 114 | 115 |
if err != nil {
|
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/pkg/sysinfo" |
| 13 | 13 |
) |
| 14 | 14 |
|
| 15 |
+// NewDriver returns a new execdriver.Driver from the given name configured with the provided options. |
|
| 15 | 16 |
func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) {
|
| 16 | 17 |
switch name {
|
| 17 | 18 |
case "lxc": |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/pkg/sysinfo" |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 |
+// NewDriver returns a new execdriver.Driver from the given name configured with the provided options. |
|
| 13 | 14 |
func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) {
|
| 14 | 15 |
switch name {
|
| 15 | 16 |
case "windows": |
| ... | ... |
@@ -34,11 +34,15 @@ import ( |
| 34 | 34 |
"github.com/vishvananda/netns" |
| 35 | 35 |
) |
| 36 | 36 |
|
| 37 |
+// DriverName for lxc driver |
|
| 37 | 38 |
const DriverName = "lxc" |
| 38 | 39 |
|
| 40 |
+// ErrExec defines unsupported error message |
|
| 39 | 41 |
var ErrExec = errors.New("Unsupported: Exec is not supported by the lxc driver")
|
| 40 | 42 |
|
| 41 |
-type driver struct {
|
|
| 43 |
+// Driver contains all information for lxc driver, |
|
| 44 |
+// it implements execdriver.Driver |
|
| 45 |
+type Driver struct {
|
|
| 42 | 46 |
root string // root path for the driver to use |
| 43 | 47 |
libPath string |
| 44 | 48 |
initPath string |
| ... | ... |
@@ -54,7 +58,8 @@ type activeContainer struct {
|
| 54 | 54 |
cmd *exec.Cmd |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 |
-func NewDriver(root, libPath, initPath string, apparmor bool) (*driver, error) {
|
|
| 57 |
+// NewDriver returns a new lxc driver, called from NewDriver of execdriver |
|
| 58 |
+func NewDriver(root, libPath, initPath string, apparmor bool) (*Driver, error) {
|
|
| 58 | 59 |
if err := os.MkdirAll(root, 0700); err != nil {
|
| 59 | 60 |
return nil, err |
| 60 | 61 |
} |
| ... | ... |
@@ -66,7 +71,7 @@ func NewDriver(root, libPath, initPath string, apparmor bool) (*driver, error) {
|
| 66 | 66 |
if err != nil {
|
| 67 | 67 |
return nil, err |
| 68 | 68 |
} |
| 69 |
- return &driver{
|
|
| 69 |
+ return &Driver{
|
|
| 70 | 70 |
apparmor: apparmor, |
| 71 | 71 |
root: root, |
| 72 | 72 |
libPath: libPath, |
| ... | ... |
@@ -77,7 +82,8 @@ func NewDriver(root, libPath, initPath string, apparmor bool) (*driver, error) {
|
| 77 | 77 |
}, nil |
| 78 | 78 |
} |
| 79 | 79 |
|
| 80 |
-func (d *driver) Name() string {
|
|
| 80 |
+// Name implements the exec driver Driver interface. |
|
| 81 |
+func (d *Driver) Name() string {
|
|
| 81 | 82 |
version := d.version() |
| 82 | 83 |
return fmt.Sprintf("%s-%s", DriverName, version)
|
| 83 | 84 |
} |
| ... | ... |
@@ -117,7 +123,9 @@ func killNetNsProc(proc *os.Process) {
|
| 117 | 117 |
proc.Wait() |
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 |
-func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
|
| 120 |
+// Run implements the exec driver Driver interface, |
|
| 121 |
+// it calls 'exec.Cmd' to launch lxc commands to run a container. |
|
| 122 |
+func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
|
| 121 | 123 |
var ( |
| 122 | 124 |
term execdriver.Terminal |
| 123 | 125 |
err error |
| ... | ... |
@@ -392,7 +400,7 @@ func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
|
| 392 | 392 |
|
| 393 | 393 |
// createContainer populates and configures the container type with the |
| 394 | 394 |
// data provided by the execdriver.Command |
| 395 |
-func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
|
|
| 395 |
+func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
|
|
| 396 | 396 |
container := execdriver.InitContainer(c) |
| 397 | 397 |
if err := execdriver.SetupCgroups(container, c); err != nil {
|
| 398 | 398 |
return nil, err |
| ... | ... |
@@ -400,8 +408,8 @@ func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) |
| 400 | 400 |
return container, nil |
| 401 | 401 |
} |
| 402 | 402 |
|
| 403 |
-// Return an map of susbystem -> container cgroup |
|
| 404 |
-func cgroupPaths(containerId string) (map[string]string, error) {
|
|
| 403 |
+// Return an map of susbystem -> absolute container cgroup path |
|
| 404 |
+func cgroupPaths(containerID string) (map[string]string, error) {
|
|
| 405 | 405 |
subsystems, err := cgroups.GetAllSubsystems() |
| 406 | 406 |
if err != nil {
|
| 407 | 407 |
return nil, err |
| ... | ... |
@@ -415,7 +423,7 @@ func cgroupPaths(containerId string) (map[string]string, error) {
|
| 415 | 415 |
//unsupported subystem |
| 416 | 416 |
continue |
| 417 | 417 |
} |
| 418 |
- path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerId) |
|
| 418 |
+ path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerID) |
|
| 419 | 419 |
paths[subsystem] = path |
| 420 | 420 |
} |
| 421 | 421 |
|
| ... | ... |
@@ -506,8 +514,8 @@ func setupUser(userSpec string) error {
|
| 506 | 506 |
return nil |
| 507 | 507 |
} |
| 508 | 508 |
|
| 509 |
-/// Return the exit code of the process |
|
| 510 |
-// if the process has not exited -1 will be returned |
|
| 509 |
+// getExitCode returns the exit code of the process. |
|
| 510 |
+// If the process has not exited -1 will be returned. |
|
| 511 | 511 |
func getExitCode(c *execdriver.Command) int {
|
| 512 | 512 |
if c.ProcessConfig.ProcessState == nil {
|
| 513 | 513 |
return -1 |
| ... | ... |
@@ -515,15 +523,18 @@ func getExitCode(c *execdriver.Command) int {
|
| 515 | 515 |
return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() |
| 516 | 516 |
} |
| 517 | 517 |
|
| 518 |
-func (d *driver) Kill(c *execdriver.Command, sig int) error {
|
|
| 518 |
+// Kill implements the exec driver Driver interface. |
|
| 519 |
+func (d *Driver) Kill(c *execdriver.Command, sig int) error {
|
|
| 519 | 520 |
if sig == 9 || c.ProcessConfig.Process == nil {
|
| 520 |
- return KillLxc(c.ID, sig) |
|
| 521 |
+ return killLxc(c.ID, sig) |
|
| 521 | 522 |
} |
| 522 | 523 |
|
| 523 | 524 |
return c.ProcessConfig.Process.Signal(syscall.Signal(sig)) |
| 524 | 525 |
} |
| 525 | 526 |
|
| 526 |
-func (d *driver) Pause(c *execdriver.Command) error {
|
|
| 527 |
+// Pause implements the exec driver Driver interface, |
|
| 528 |
+// it executes lxc-freeze to pause a container. |
|
| 529 |
+func (d *Driver) Pause(c *execdriver.Command) error {
|
|
| 527 | 530 |
_, err := exec.LookPath("lxc-freeze")
|
| 528 | 531 |
if err == nil {
|
| 529 | 532 |
output, errExec := exec.Command("lxc-freeze", "-n", c.ID).CombinedOutput()
|
| ... | ... |
@@ -535,7 +546,9 @@ func (d *driver) Pause(c *execdriver.Command) error {
|
| 535 | 535 |
return err |
| 536 | 536 |
} |
| 537 | 537 |
|
| 538 |
-func (d *driver) Unpause(c *execdriver.Command) error {
|
|
| 538 |
+// Unpause implements the exec driver Driver interface, |
|
| 539 |
+// it executes lxc-unfreeze to unpause a container. |
|
| 540 |
+func (d *Driver) Unpause(c *execdriver.Command) error {
|
|
| 539 | 541 |
_, err := exec.LookPath("lxc-unfreeze")
|
| 540 | 542 |
if err == nil {
|
| 541 | 543 |
output, errExec := exec.Command("lxc-unfreeze", "-n", c.ID).CombinedOutput()
|
| ... | ... |
@@ -547,11 +560,12 @@ func (d *driver) Unpause(c *execdriver.Command) error {
|
| 547 | 547 |
return err |
| 548 | 548 |
} |
| 549 | 549 |
|
| 550 |
-func (d *driver) Terminate(c *execdriver.Command) error {
|
|
| 551 |
- return KillLxc(c.ID, 9) |
|
| 550 |
+// Terminate implements the exec driver Driver interface. |
|
| 551 |
+func (d *Driver) Terminate(c *execdriver.Command) error {
|
|
| 552 |
+ return killLxc(c.ID, 9) |
|
| 552 | 553 |
} |
| 553 | 554 |
|
| 554 |
-func (d *driver) version() string {
|
|
| 555 |
+func (d *Driver) version() string {
|
|
| 555 | 556 |
var ( |
| 556 | 557 |
version string |
| 557 | 558 |
output []byte |
| ... | ... |
@@ -571,7 +585,7 @@ func (d *driver) version() string {
|
| 571 | 571 |
return version |
| 572 | 572 |
} |
| 573 | 573 |
|
| 574 |
-func KillLxc(id string, sig int) error {
|
|
| 574 |
+func killLxc(id string, sig int) error {
|
|
| 575 | 575 |
var ( |
| 576 | 576 |
err error |
| 577 | 577 |
output []byte |
| ... | ... |
@@ -590,7 +604,7 @@ func KillLxc(id string, sig int) error {
|
| 590 | 590 |
} |
| 591 | 591 |
|
| 592 | 592 |
// wait for the process to start and return the pid for the process |
| 593 |
-func (d *driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (int, error) {
|
|
| 593 |
+func (d *Driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (int, error) {
|
|
| 594 | 594 |
var ( |
| 595 | 595 |
err error |
| 596 | 596 |
output []byte |
| ... | ... |
@@ -622,13 +636,13 @@ func (d *driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (in
|
| 622 | 622 |
return -1, execdriver.ErrNotRunning |
| 623 | 623 |
} |
| 624 | 624 |
|
| 625 |
-func (d *driver) getInfo(id string) ([]byte, error) {
|
|
| 625 |
+func (d *Driver) getInfo(id string) ([]byte, error) {
|
|
| 626 | 626 |
return exec.Command("lxc-info", "-n", id).CombinedOutput()
|
| 627 | 627 |
} |
| 628 | 628 |
|
| 629 | 629 |
type info struct {
|
| 630 | 630 |
ID string |
| 631 |
- driver *driver |
|
| 631 |
+ driver *Driver |
|
| 632 | 632 |
} |
| 633 | 633 |
|
| 634 | 634 |
func (i *info) IsRunning() bool {
|
| ... | ... |
@@ -645,7 +659,8 @@ func (i *info) IsRunning() bool {
|
| 645 | 645 |
return running |
| 646 | 646 |
} |
| 647 | 647 |
|
| 648 |
-func (d *driver) Info(id string) execdriver.Info {
|
|
| 648 |
+// Info implements the exec driver Driver interface. |
|
| 649 |
+func (d *Driver) Info(id string) execdriver.Info {
|
|
| 649 | 650 |
return &info{
|
| 650 | 651 |
ID: id, |
| 651 | 652 |
driver: d, |
| ... | ... |
@@ -665,7 +680,8 @@ func findCgroupRootAndDir(subsystem string) (string, string, error) {
|
| 665 | 665 |
return cgroupRoot, cgroupDir, nil |
| 666 | 666 |
} |
| 667 | 667 |
|
| 668 |
-func (d *driver) GetPidsForContainer(id string) ([]int, error) {
|
|
| 668 |
+// GetPidsForContainer implements the exec driver Driver interface. |
|
| 669 |
+func (d *Driver) GetPidsForContainer(id string) ([]int, error) {
|
|
| 669 | 670 |
pids := []int{}
|
| 670 | 671 |
|
| 671 | 672 |
// cpu is chosen because it is the only non optional subsystem in cgroups |
| ... | ... |
@@ -730,11 +746,11 @@ func rootIsShared() bool {
|
| 730 | 730 |
return true |
| 731 | 731 |
} |
| 732 | 732 |
|
| 733 |
-func (d *driver) containerDir(containerId string) string {
|
|
| 734 |
- return path.Join(d.libPath, "containers", containerId) |
|
| 733 |
+func (d *Driver) containerDir(containerID string) string {
|
|
| 734 |
+ return path.Join(d.libPath, "containers", containerID) |
|
| 735 | 735 |
} |
| 736 | 736 |
|
| 737 |
-func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
|
|
| 737 |
+func (d *Driver) generateLXCConfig(c *execdriver.Command) (string, error) {
|
|
| 738 | 738 |
root := path.Join(d.containerDir(c.ID), "config.lxc") |
| 739 | 739 |
|
| 740 | 740 |
fo, err := os.Create(root) |
| ... | ... |
@@ -743,7 +759,7 @@ func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
|
| 743 | 743 |
} |
| 744 | 744 |
defer fo.Close() |
| 745 | 745 |
|
| 746 |
- if err := LxcTemplateCompiled.Execute(fo, struct {
|
|
| 746 |
+ if err := lxcTemplateCompiled.Execute(fo, struct {
|
|
| 747 | 747 |
*execdriver.Command |
| 748 | 748 |
AppArmor bool |
| 749 | 749 |
}{
|
| ... | ... |
@@ -756,7 +772,7 @@ func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
|
| 756 | 756 |
return root, nil |
| 757 | 757 |
} |
| 758 | 758 |
|
| 759 |
-func (d *driver) generateEnvConfig(c *execdriver.Command) error {
|
|
| 759 |
+func (d *Driver) generateEnvConfig(c *execdriver.Command) error {
|
|
| 760 | 760 |
data, err := json.Marshal(c.ProcessConfig.Env) |
| 761 | 761 |
if err != nil {
|
| 762 | 762 |
return err |
| ... | ... |
@@ -772,16 +788,21 @@ func (d *driver) generateEnvConfig(c *execdriver.Command) error {
|
| 772 | 772 |
return ioutil.WriteFile(p, data, 0600) |
| 773 | 773 |
} |
| 774 | 774 |
|
| 775 |
-// Clean not implemented for lxc |
|
| 776 |
-func (d *driver) Clean(id string) error {
|
|
| 775 |
+// Clean implements the exec driver Driver interface, |
|
| 776 |
+// it's not implemented by lxc. |
|
| 777 |
+func (d *Driver) Clean(id string) error {
|
|
| 777 | 778 |
return nil |
| 778 | 779 |
} |
| 779 | 780 |
|
| 781 |
+// TtyConsole implements the exec driver Terminal interface, |
|
| 782 |
+// it stores the master and slave ends of the container's pty. |
|
| 780 | 783 |
type TtyConsole struct {
|
| 781 | 784 |
MasterPty *os.File |
| 782 | 785 |
SlavePty *os.File |
| 783 | 786 |
} |
| 784 | 787 |
|
| 788 |
+// NewTtyConsole returns a new TtyConsole struct. |
|
| 789 |
+// Wired up to the provided process config and stdin/stdout/stderr pipes. |
|
| 785 | 790 |
func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
| 786 | 791 |
// lxc is special in that we cannot create the master outside of the container without |
| 787 | 792 |
// 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 |
| 808 | 808 |
return tty, nil |
| 809 | 809 |
} |
| 810 | 810 |
|
| 811 |
+// Resize implements Resize method of Terminal interface |
|
| 811 | 812 |
func (t *TtyConsole) Resize(h, w int) error {
|
| 812 | 813 |
return term.SetWinsize(t.MasterPty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
| 813 | 814 |
} |
| 814 | 815 |
|
| 816 |
+// AttachPipes attaches given pipes to exec.Cmd |
|
| 815 | 817 |
func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) error {
|
| 816 | 818 |
command.Stdout = t.SlavePty |
| 817 | 819 |
command.Stderr = t.SlavePty |
| ... | ... |
@@ -839,16 +862,22 @@ func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) err |
| 839 | 839 |
return nil |
| 840 | 840 |
} |
| 841 | 841 |
|
| 842 |
+// Close implements Close method of Terminal interface |
|
| 842 | 843 |
func (t *TtyConsole) Close() error {
|
| 843 | 844 |
t.SlavePty.Close() |
| 844 | 845 |
return t.MasterPty.Close() |
| 845 | 846 |
} |
| 846 | 847 |
|
| 847 |
-func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
|
| 848 |
+// Exec implements the exec driver Driver interface, |
|
| 849 |
+// it is not implemented by lxc. |
|
| 850 |
+func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
|
| 848 | 851 |
return -1, ErrExec |
| 849 | 852 |
} |
| 850 | 853 |
|
| 851 |
-func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
|
| 854 |
+// Stats implements the exec driver Driver interface. |
|
| 855 |
+// Lxc doesn't implement it's own Stats, it does some trick by implementing |
|
| 856 |
+// execdriver.Stats to get stats info by libcontainer APIs. |
|
| 857 |
+func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
|
| 852 | 858 |
if _, ok := d.activeContainers[id]; !ok {
|
| 853 | 859 |
return nil, fmt.Errorf("%s is not a key in active containers", id)
|
| 854 | 860 |
} |
| ... | ... |
@@ -16,11 +16,11 @@ import ( |
| 16 | 16 |
"github.com/docker/docker/pkg/reexec" |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 |
-// Args provided to the init function for a driver |
|
| 19 |
+// InitArgs contains args provided to the init function for a driver |
|
| 20 | 20 |
type InitArgs struct {
|
| 21 | 21 |
User string |
| 22 | 22 |
Gateway string |
| 23 |
- Ip string |
|
| 23 |
+ IP string |
|
| 24 | 24 |
WorkDir string |
| 25 | 25 |
Privileged bool |
| 26 | 26 |
Env []string |
| ... | ... |
@@ -94,7 +94,7 @@ func getArgs() *InitArgs {
|
| 94 | 94 |
return &InitArgs{
|
| 95 | 95 |
User: *user, |
| 96 | 96 |
Gateway: *gateway, |
| 97 |
- Ip: *ip, |
|
| 97 |
+ IP: *ip, |
|
| 98 | 98 |
WorkDir: *workDir, |
| 99 | 99 |
Privileged: *privileged, |
| 100 | 100 |
Args: flag.Args(), |
| ... | ... |
@@ -15,6 +15,8 @@ import ( |
| 15 | 15 |
"github.com/opencontainers/runc/libcontainer/label" |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 |
+// LxcTemplate is the template for lxc driver, it's used |
|
| 19 |
+// to configure LXC. |
|
| 18 | 20 |
const LxcTemplate = ` |
| 19 | 21 |
lxc.network.type = none |
| 20 | 22 |
# root filesystem |
| ... | ... |
@@ -94,11 +96,11 @@ lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.Memory}}
|
| 94 | 94 |
lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
|
| 95 | 95 |
{{end}}
|
| 96 | 96 |
{{end}}
|
| 97 |
-{{if .Resources.CpuShares}}
|
|
| 98 |
-lxc.cgroup.cpu.shares = {{.Resources.CpuShares}}
|
|
| 97 |
+{{if .Resources.CPUShares}}
|
|
| 98 |
+lxc.cgroup.cpu.shares = {{.Resources.CPUShares}}
|
|
| 99 | 99 |
{{end}}
|
| 100 |
-{{if .Resources.CpuPeriod}}
|
|
| 101 |
-lxc.cgroup.cpu.cfs_period_us = {{.Resources.CpuPeriod}}
|
|
| 100 |
+{{if .Resources.CPUPeriod}}
|
|
| 101 |
+lxc.cgroup.cpu.cfs_period_us = {{.Resources.CPUPeriod}}
|
|
| 102 | 102 |
{{end}}
|
| 103 | 103 |
{{if .Resources.CpusetCpus}}
|
| 104 | 104 |
lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
|
| ... | ... |
@@ -106,8 +108,8 @@ lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
|
| 106 | 106 |
{{if .Resources.CpusetMems}}
|
| 107 | 107 |
lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}}
|
| 108 | 108 |
{{end}}
|
| 109 |
-{{if .Resources.CpuQuota}}
|
|
| 110 |
-lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CpuQuota}}
|
|
| 109 |
+{{if .Resources.CPUQuota}}
|
|
| 110 |
+lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CPUQuota}}
|
|
| 111 | 111 |
{{end}}
|
| 112 | 112 |
{{if .Resources.BlkioWeight}}
|
| 113 | 113 |
lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}}
|
| ... | ... |
@@ -158,7 +160,7 @@ lxc.cap.drop = {{.}}
|
| 158 | 158 |
{{end}}
|
| 159 | 159 |
` |
| 160 | 160 |
|
| 161 |
-var LxcTemplateCompiled *template.Template |
|
| 161 |
+var lxcTemplateCompiled *template.Template |
|
| 162 | 162 |
|
| 163 | 163 |
// Escape spaces in strings according to the fstab documentation, which is the |
| 164 | 164 |
// format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab". |
| ... | ... |
@@ -254,7 +256,7 @@ func init() {
|
| 254 | 254 |
"dropList": dropList, |
| 255 | 255 |
"getHostname": getHostname, |
| 256 | 256 |
} |
| 257 |
- LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
|
|
| 257 |
+ lxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
|
|
| 258 | 258 |
if err != nil {
|
| 259 | 259 |
panic(err) |
| 260 | 260 |
} |
| ... | ... |
@@ -18,7 +18,7 @@ import ( |
| 18 | 18 |
|
| 19 | 19 |
// createContainer populates and configures the container type with the |
| 20 | 20 |
// data provided by the execdriver.Command |
| 21 |
-func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
|
|
| 21 |
+func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
|
|
| 22 | 22 |
container := execdriver.InitContainer(c) |
| 23 | 23 |
|
| 24 | 24 |
if err := d.createIpc(container, c); err != nil {
|
| ... | ... |
@@ -113,7 +113,7 @@ func generateIfaceName() (string, error) {
|
| 113 | 113 |
return "", errors.New("Failed to find name for new interface")
|
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 |
-func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
|
|
| 116 |
+func (d *Driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
|
|
| 117 | 117 |
if c.Network == nil {
|
| 118 | 118 |
return nil |
| 119 | 119 |
} |
| ... | ... |
@@ -143,7 +143,7 @@ func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) |
| 143 | 143 |
return nil |
| 144 | 144 |
} |
| 145 | 145 |
|
| 146 |
-func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error {
|
|
| 146 |
+func (d *Driver) createIpc(container *configs.Config, c *execdriver.Command) error {
|
|
| 147 | 147 |
if c.Ipc.HostIpc {
|
| 148 | 148 |
container.Namespaces.Remove(configs.NEWIPC) |
| 149 | 149 |
return nil |
| ... | ... |
@@ -168,7 +168,7 @@ func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) err |
| 168 | 168 |
return nil |
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 |
-func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error {
|
|
| 171 |
+func (d *Driver) createPid(container *configs.Config, c *execdriver.Command) error {
|
|
| 172 | 172 |
if c.Pid.HostPid {
|
| 173 | 173 |
container.Namespaces.Remove(configs.NEWPID) |
| 174 | 174 |
return nil |
| ... | ... |
@@ -177,7 +177,7 @@ func (d *driver) createPid(container *configs.Config, c *execdriver.Command) err |
| 177 | 177 |
return nil |
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 |
-func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) error {
|
|
| 180 |
+func (d *Driver) createUTS(container *configs.Config, c *execdriver.Command) error {
|
|
| 181 | 181 |
if c.UTS.HostUTS {
|
| 182 | 182 |
container.Namespaces.Remove(configs.NEWUTS) |
| 183 | 183 |
container.Hostname = "" |
| ... | ... |
@@ -187,7 +187,7 @@ func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) err |
| 187 | 187 |
return nil |
| 188 | 188 |
} |
| 189 | 189 |
|
| 190 |
-func (d *driver) setPrivileged(container *configs.Config) (err error) {
|
|
| 190 |
+func (d *Driver) setPrivileged(container *configs.Config) (err error) {
|
|
| 191 | 191 |
container.Capabilities = execdriver.GetAllCapabilities() |
| 192 | 192 |
container.Cgroups.AllowAllDevices = true |
| 193 | 193 |
|
| ... | ... |
@@ -204,12 +204,12 @@ func (d *driver) setPrivileged(container *configs.Config) (err error) {
|
| 204 | 204 |
return nil |
| 205 | 205 |
} |
| 206 | 206 |
|
| 207 |
-func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
|
|
| 207 |
+func (d *Driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
|
|
| 208 | 208 |
container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop) |
| 209 | 209 |
return err |
| 210 | 210 |
} |
| 211 | 211 |
|
| 212 |
-func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
|
|
| 212 |
+func (d *Driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
|
|
| 213 | 213 |
if c.Resources == nil {
|
| 214 | 214 |
return |
| 215 | 215 |
} |
| ... | ... |
@@ -223,7 +223,7 @@ func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) |
| 223 | 223 |
} |
| 224 | 224 |
} |
| 225 | 225 |
|
| 226 |
-func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
|
|
| 226 |
+func (d *Driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
|
|
| 227 | 227 |
userMounts := make(map[string]struct{})
|
| 228 | 228 |
for _, m := range c.Mounts {
|
| 229 | 229 |
userMounts[m.Destination] = struct{}{}
|
| ... | ... |
@@ -260,7 +260,7 @@ func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) e |
| 260 | 260 |
return nil |
| 261 | 261 |
} |
| 262 | 262 |
|
| 263 |
-func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) {
|
|
| 263 |
+func (d *Driver) setupLabels(container *configs.Config, c *execdriver.Command) {
|
|
| 264 | 264 |
container.ProcessLabel = c.ProcessLabel |
| 265 | 265 |
container.MountLabel = c.MountLabel |
| 266 | 266 |
} |
| ... | ... |
@@ -27,12 +27,15 @@ import ( |
| 27 | 27 |
"github.com/opencontainers/runc/libcontainer/utils" |
| 28 | 28 |
) |
| 29 | 29 |
|
| 30 |
+// Define constants for native driver |
|
| 30 | 31 |
const ( |
| 31 | 32 |
DriverName = "native" |
| 32 | 33 |
Version = "0.2" |
| 33 | 34 |
) |
| 34 | 35 |
|
| 35 |
-type driver struct {
|
|
| 36 |
+// Driver contains all information for native driver, |
|
| 37 |
+// it implements execdriver.Driver. |
|
| 38 |
+type Driver struct {
|
|
| 36 | 39 |
root string |
| 37 | 40 |
initPath string |
| 38 | 41 |
activeContainers map[string]libcontainer.Container |
| ... | ... |
@@ -41,7 +44,8 @@ type driver struct {
|
| 41 | 41 |
sync.Mutex |
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 |
-func NewDriver(root, initPath string, options []string) (*driver, error) {
|
|
| 44 |
+// NewDriver returns a new native driver, called from NewDriver of execdriver. |
|
| 45 |
+func NewDriver(root, initPath string, options []string) (*Driver, error) {
|
|
| 45 | 46 |
meminfo, err := sysinfo.ReadMemInfo() |
| 46 | 47 |
if err != nil {
|
| 47 | 48 |
return nil, err |
| ... | ... |
@@ -96,7 +100,7 @@ func NewDriver(root, initPath string, options []string) (*driver, error) {
|
| 96 | 96 |
return nil, err |
| 97 | 97 |
} |
| 98 | 98 |
|
| 99 |
- return &driver{
|
|
| 99 |
+ return &Driver{
|
|
| 100 | 100 |
root: root, |
| 101 | 101 |
initPath: initPath, |
| 102 | 102 |
activeContainers: make(map[string]libcontainer.Container), |
| ... | ... |
@@ -110,7 +114,9 @@ type execOutput struct {
|
| 110 | 110 |
err error |
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 |
-func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
|
| 113 |
+// Run implements the exec driver Driver interface, |
|
| 114 |
+// it calls libcontainer APIs to run a container. |
|
| 115 |
+func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
|
| 114 | 116 |
// take the Command and populate the libcontainer.Config from it |
| 115 | 117 |
container, err := d.createContainer(c) |
| 116 | 118 |
if err != nil {
|
| ... | ... |
@@ -238,7 +244,8 @@ func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*o |
| 238 | 238 |
} |
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 |
-func (d *driver) Kill(c *execdriver.Command, sig int) error {
|
|
| 241 |
+// Kill implements the exec driver Driver interface. |
|
| 242 |
+func (d *Driver) Kill(c *execdriver.Command, sig int) error {
|
|
| 242 | 243 |
d.Lock() |
| 243 | 244 |
active := d.activeContainers[c.ID] |
| 244 | 245 |
d.Unlock() |
| ... | ... |
@@ -252,7 +259,9 @@ func (d *driver) Kill(c *execdriver.Command, sig int) error {
|
| 252 | 252 |
return syscall.Kill(state.InitProcessPid, syscall.Signal(sig)) |
| 253 | 253 |
} |
| 254 | 254 |
|
| 255 |
-func (d *driver) Pause(c *execdriver.Command) error {
|
|
| 255 |
+// Pause implements the exec driver Driver interface, |
|
| 256 |
+// it calls libcontainer API to pause a container. |
|
| 257 |
+func (d *Driver) Pause(c *execdriver.Command) error {
|
|
| 256 | 258 |
d.Lock() |
| 257 | 259 |
active := d.activeContainers[c.ID] |
| 258 | 260 |
d.Unlock() |
| ... | ... |
@@ -262,7 +271,9 @@ func (d *driver) Pause(c *execdriver.Command) error {
|
| 262 | 262 |
return active.Pause() |
| 263 | 263 |
} |
| 264 | 264 |
|
| 265 |
-func (d *driver) Unpause(c *execdriver.Command) error {
|
|
| 265 |
+// Unpause implements the exec driver Driver interface, |
|
| 266 |
+// it calls libcontainer API to unpause a container. |
|
| 267 |
+func (d *Driver) Unpause(c *execdriver.Command) error {
|
|
| 266 | 268 |
d.Lock() |
| 267 | 269 |
active := d.activeContainers[c.ID] |
| 268 | 270 |
d.Unlock() |
| ... | ... |
@@ -272,7 +283,8 @@ func (d *driver) Unpause(c *execdriver.Command) error {
|
| 272 | 272 |
return active.Resume() |
| 273 | 273 |
} |
| 274 | 274 |
|
| 275 |
-func (d *driver) Terminate(c *execdriver.Command) error {
|
|
| 275 |
+// Terminate implements the exec driver Driver interface. |
|
| 276 |
+func (d *Driver) Terminate(c *execdriver.Command) error {
|
|
| 276 | 277 |
defer d.cleanContainer(c.ID) |
| 277 | 278 |
container, err := d.factory.Load(c.ID) |
| 278 | 279 |
if err != nil {
|
| ... | ... |
@@ -295,18 +307,21 @@ func (d *driver) Terminate(c *execdriver.Command) error {
|
| 295 | 295 |
return err |
| 296 | 296 |
} |
| 297 | 297 |
|
| 298 |
-func (d *driver) Info(id string) execdriver.Info {
|
|
| 298 |
+// Info implements the exec driver Driver interface. |
|
| 299 |
+func (d *Driver) Info(id string) execdriver.Info {
|
|
| 299 | 300 |
return &info{
|
| 300 | 301 |
ID: id, |
| 301 | 302 |
driver: d, |
| 302 | 303 |
} |
| 303 | 304 |
} |
| 304 | 305 |
|
| 305 |
-func (d *driver) Name() string {
|
|
| 306 |
+// Name implements the exec driver Driver interface. |
|
| 307 |
+func (d *Driver) Name() string {
|
|
| 306 | 308 |
return fmt.Sprintf("%s-%s", DriverName, Version)
|
| 307 | 309 |
} |
| 308 | 310 |
|
| 309 |
-func (d *driver) GetPidsForContainer(id string) ([]int, error) {
|
|
| 311 |
+// GetPidsForContainer implements the exec driver Driver interface. |
|
| 312 |
+func (d *Driver) GetPidsForContainer(id string) ([]int, error) {
|
|
| 310 | 313 |
d.Lock() |
| 311 | 314 |
active := d.activeContainers[id] |
| 312 | 315 |
d.Unlock() |
| ... | ... |
@@ -317,22 +332,24 @@ func (d *driver) GetPidsForContainer(id string) ([]int, error) {
|
| 317 | 317 |
return active.Processes() |
| 318 | 318 |
} |
| 319 | 319 |
|
| 320 |
-func (d *driver) cleanContainer(id string) error {
|
|
| 320 |
+func (d *Driver) cleanContainer(id string) error {
|
|
| 321 | 321 |
d.Lock() |
| 322 | 322 |
delete(d.activeContainers, id) |
| 323 | 323 |
d.Unlock() |
| 324 | 324 |
return os.RemoveAll(filepath.Join(d.root, id)) |
| 325 | 325 |
} |
| 326 | 326 |
|
| 327 |
-func (d *driver) createContainerRoot(id string) error {
|
|
| 327 |
+func (d *Driver) createContainerRoot(id string) error {
|
|
| 328 | 328 |
return os.MkdirAll(filepath.Join(d.root, id), 0655) |
| 329 | 329 |
} |
| 330 | 330 |
|
| 331 |
-func (d *driver) Clean(id string) error {
|
|
| 331 |
+// Clean implements the exec driver Driver interface. |
|
| 332 |
+func (d *Driver) Clean(id string) error {
|
|
| 332 | 333 |
return os.RemoveAll(filepath.Join(d.root, id)) |
| 333 | 334 |
} |
| 334 | 335 |
|
| 335 |
-func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
|
| 336 |
+// Stats implements the exec driver Driver interface. |
|
| 337 |
+func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
|
| 336 | 338 |
d.Lock() |
| 337 | 339 |
c := d.activeContainers[id] |
| 338 | 340 |
d.Unlock() |
| ... | ... |
@@ -357,10 +374,12 @@ func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
| 357 | 357 |
}, nil |
| 358 | 358 |
} |
| 359 | 359 |
|
| 360 |
+// TtyConsole implements the exec driver Terminal interface. |
|
| 360 | 361 |
type TtyConsole struct {
|
| 361 | 362 |
console libcontainer.Console |
| 362 | 363 |
} |
| 363 | 364 |
|
| 365 |
+// NewTtyConsole returns a new TtyConsole struct. |
|
| 364 | 366 |
func NewTtyConsole(console libcontainer.Console, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
| 365 | 367 |
tty := &TtyConsole{
|
| 366 | 368 |
console: console, |
| ... | ... |
@@ -374,10 +393,12 @@ func NewTtyConsole(console libcontainer.Console, pipes *execdriver.Pipes) (*TtyC |
| 374 | 374 |
return tty, nil |
| 375 | 375 |
} |
| 376 | 376 |
|
| 377 |
+// Resize implements Resize method of Terminal interface |
|
| 377 | 378 |
func (t *TtyConsole) Resize(h, w int) error {
|
| 378 | 379 |
return term.SetWinsize(t.console.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
| 379 | 380 |
} |
| 380 | 381 |
|
| 382 |
+// AttachPipes attaches given pipes to TtyConsole |
|
| 381 | 383 |
func (t *TtyConsole) AttachPipes(pipes *execdriver.Pipes) error {
|
| 382 | 384 |
go func() {
|
| 383 | 385 |
if wb, ok := pipes.Stdout.(interface {
|
| ... | ... |
@@ -400,6 +421,7 @@ func (t *TtyConsole) AttachPipes(pipes *execdriver.Pipes) error {
|
| 400 | 400 |
return nil |
| 401 | 401 |
} |
| 402 | 402 |
|
| 403 |
+// Close implements Close method of Terminal interface |
|
| 403 | 404 |
func (t *TtyConsole) Close() error {
|
| 404 | 405 |
return t.console.Close() |
| 405 | 406 |
} |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/daemon/execdriver" |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 |
+// NewDriver returns a new native driver, called from NewDriver of execdriver. |
|
| 11 | 12 |
func NewDriver(root, initPath string) (execdriver.Driver, error) {
|
| 12 | 13 |
return nil, fmt.Errorf("native driver not supported on non-linux")
|
| 13 | 14 |
} |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/daemon/execdriver" |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 |
+// NewDriver returns a new native driver, called from NewDriver of execdriver. |
|
| 11 | 12 |
func NewDriver(root, initPath string) (execdriver.Driver, error) {
|
| 12 | 13 |
return nil, fmt.Errorf("native driver not supported on non-linux")
|
| 13 | 14 |
} |
| ... | ... |
@@ -10,12 +10,17 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/daemon/execdriver" |
| 12 | 12 |
"github.com/opencontainers/runc/libcontainer" |
| 13 |
+ // Blank import 'nsenter' so that init in that package will call c |
|
| 14 |
+ // function 'nsexec()' to do 'setns' before Go runtime take over, |
|
| 15 |
+ // it's used for join to exist ns like 'docker exec' command. |
|
| 13 | 16 |
_ "github.com/opencontainers/runc/libcontainer/nsenter" |
| 14 | 17 |
"github.com/opencontainers/runc/libcontainer/utils" |
| 15 | 18 |
) |
| 16 | 19 |
|
| 20 |
+// Exec implements the exec driver Driver interface, |
|
| 21 |
+// it calls libcontainer APIs to execute a container. |
|
| 17 | 22 |
// TODO(vishh): Add support for running in privileged mode. |
| 18 |
-func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
|
| 23 |
+func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
|
| 19 | 24 |
active := d.activeContainers[c.ID] |
| 20 | 25 |
if active == nil {
|
| 21 | 26 |
return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
|
| ... | ... |
@@ -4,13 +4,14 @@ import ( |
| 4 | 4 |
"io" |
| 5 | 5 |
) |
| 6 | 6 |
|
| 7 |
-// Pipes is a wrapper around a containers output for |
|
| 7 |
+// Pipes is a wrapper around a container's output for |
|
| 8 | 8 |
// stdin, stdout, stderr |
| 9 | 9 |
type Pipes struct {
|
| 10 | 10 |
Stdin io.ReadCloser |
| 11 | 11 |
Stdout, Stderr io.Writer |
| 12 | 12 |
} |
| 13 | 13 |
|
| 14 |
+// NewPipes returns a wrapper around a container's output |
|
| 14 | 15 |
func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes {
|
| 15 | 16 |
p := &Pipes{
|
| 16 | 17 |
Stdout: stdout, |
| ... | ... |
@@ -5,9 +5,11 @@ import ( |
| 5 | 5 |
"os/exec" |
| 6 | 6 |
) |
| 7 | 7 |
|
| 8 |
+// StdConsole defines standard console operations for execdriver |
|
| 8 | 9 |
type StdConsole struct {
|
| 9 | 10 |
} |
| 10 | 11 |
|
| 12 |
+// NewStdConsole returns a new StdConsole struct |
|
| 11 | 13 |
func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, error) {
|
| 12 | 14 |
std := &StdConsole{}
|
| 13 | 15 |
|
| ... | ... |
@@ -17,6 +19,7 @@ func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, err |
| 17 | 17 |
return std, nil |
| 18 | 18 |
} |
| 19 | 19 |
|
| 20 |
+// AttachPipes attaches given pipes to exec.Cmd |
|
| 20 | 21 |
func (s *StdConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error {
|
| 21 | 22 |
command.Stdout = pipes.Stdout |
| 22 | 23 |
command.Stderr = pipes.Stderr |
| ... | ... |
@@ -35,11 +38,13 @@ func (s *StdConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error {
|
| 35 | 35 |
return nil |
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 |
+// Resize implements Resize method of Terminal interface |
|
| 38 | 39 |
func (s *StdConsole) Resize(h, w int) error {
|
| 39 | 40 |
// we do not need to reside a non tty |
| 40 | 41 |
return nil |
| 41 | 42 |
} |
| 42 | 43 |
|
| 44 |
+// Close implements Close method of Terminal interface |
|
| 43 | 45 |
func (s *StdConsole) Close() error {
|
| 44 | 46 |
// nothing to close here |
| 45 | 47 |
return nil |
| ... | ... |
@@ -30,17 +30,24 @@ func init() {
|
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 | 32 |
type ( |
| 33 |
+ // CapabilityMapping maps linux capability name to its value of capability.Cap type |
|
| 34 |
+ // Capabilities is one of the security systems in Linux Security Module (LSM) |
|
| 35 |
+ // framework provided by the kernel. |
|
| 36 |
+ // For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html |
|
| 33 | 37 |
CapabilityMapping struct {
|
| 34 | 38 |
Key string `json:"key,omitempty"` |
| 35 | 39 |
Value capability.Cap `json:"value,omitempty"` |
| 36 | 40 |
} |
| 41 |
+ // Capabilities contains all CapabilityMapping |
|
| 37 | 42 |
Capabilities []*CapabilityMapping |
| 38 | 43 |
) |
| 39 | 44 |
|
| 45 |
+// String returns <key> of CapabilityMapping |
|
| 40 | 46 |
func (c *CapabilityMapping) String() string {
|
| 41 | 47 |
return c.Key |
| 42 | 48 |
} |
| 43 | 49 |
|
| 50 |
+// GetCapability returns CapabilityMapping which contains specific key |
|
| 44 | 51 |
func GetCapability(key string) *CapabilityMapping {
|
| 45 | 52 |
for _, capp := range capabilityList {
|
| 46 | 53 |
if capp.Key == key {
|
| ... | ... |
@@ -51,6 +58,7 @@ func GetCapability(key string) *CapabilityMapping {
|
| 51 | 51 |
return nil |
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 |
+// GetAllCapabilities returns all of the capabilities |
|
| 54 | 55 |
func GetAllCapabilities() []string {
|
| 55 | 56 |
output := make([]string, len(capabilityList)) |
| 56 | 57 |
for i, capability := range capabilityList {
|
| ... | ... |
@@ -59,6 +67,8 @@ func GetAllCapabilities() []string {
|
| 59 | 59 |
return output |
| 60 | 60 |
} |
| 61 | 61 |
|
| 62 |
+// TweakCapabilities can tweak capabilities by adding or dropping capabilities |
|
| 63 |
+// based on the basics capabilities. |
|
| 62 | 64 |
func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
|
| 63 | 65 |
var ( |
| 64 | 66 |
newCaps []string |