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

Windows: Refactor execdriver.Command

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2015-10-05 14:27:39 -07:00
parent a154b95d06
commit 9d14866d71
9 changed files with 171 additions and 163 deletions

View file

@ -329,30 +329,32 @@ func populateCommand(c *Container, env []string) error {
uidMap, gidMap := c.daemon.GetUIDGIDMaps() uidMap, gidMap := c.daemon.GetUIDGIDMaps()
c.command = &execdriver.Command{ c.command = &execdriver.Command{
ID: c.ID, CommonCommand: execdriver.CommonCommand{
Rootfs: c.rootfsPath(), ID: c.ID,
ReadonlyRootfs: c.hostConfig.ReadonlyRootfs, InitPath: "/.dockerinit",
InitPath: "/.dockerinit", MountLabel: c.getMountLabel(),
WorkingDir: c.Config.WorkingDir, Network: en,
Network: en, ProcessConfig: processConfig,
Ipc: ipc, ProcessLabel: c.getProcessLabel(),
UIDMapping: uidMap, Rootfs: c.rootfsPath(),
GIDMapping: gidMap, Resources: resources,
RemappedRoot: remappedRoot, WorkingDir: c.Config.WorkingDir,
Pid: pid, },
UTS: uts,
Resources: resources,
AllowedDevices: allowedDevices, AllowedDevices: allowedDevices,
AppArmorProfile: c.AppArmorProfile,
AutoCreatedDevices: autoCreatedDevices, AutoCreatedDevices: autoCreatedDevices,
CapAdd: c.hostConfig.CapAdd.Slice(), CapAdd: c.hostConfig.CapAdd.Slice(),
CapDrop: c.hostConfig.CapDrop.Slice(), CapDrop: c.hostConfig.CapDrop.Slice(),
GroupAdd: c.hostConfig.GroupAdd,
ProcessConfig: processConfig,
ProcessLabel: c.getProcessLabel(),
MountLabel: c.getMountLabel(),
LxcConfig: lxcConfig,
AppArmorProfile: c.AppArmorProfile,
CgroupParent: c.hostConfig.CgroupParent, CgroupParent: c.hostConfig.CgroupParent,
GIDMapping: gidMap,
GroupAdd: c.hostConfig.GroupAdd,
Ipc: ipc,
LxcConfig: lxcConfig,
Pid: pid,
ReadonlyRootfs: c.hostConfig.ReadonlyRootfs,
RemappedRoot: remappedRoot,
UIDMapping: uidMap,
UTS: uts,
} }
return nil return nil

View file

@ -80,11 +80,6 @@ func populateCommand(c *Container, env []string) error {
return derr.ErrorCodeInvalidNetworkMode.WithArgs(c.hostConfig.NetworkMode) return derr.ErrorCodeInvalidNetworkMode.WithArgs(c.hostConfig.NetworkMode)
} }
pid := &execdriver.Pid{}
// TODO Windows. This can probably be factored out.
pid.HostPid = c.hostConfig.PidMode.IsHost()
// TODO Windows. More resource controls to be implemented later. // TODO Windows. More resource controls to be implemented later.
resources := &execdriver.Resources{ resources := &execdriver.Resources{
CommonResources: execdriver.CommonResources{ CommonResources: execdriver.CommonResources{
@ -126,26 +121,23 @@ func populateCommand(c *Container, env []string) error {
} }
layerFolder := m["dir"] layerFolder := m["dir"]
// TODO Windows: Factor out remainder of unused fields.
c.command = &execdriver.Command{ c.command = &execdriver.Command{
ID: c.ID, CommonCommand: execdriver.CommonCommand{
Rootfs: c.rootfsPath(), ID: c.ID,
ReadonlyRootfs: c.hostConfig.ReadonlyRootfs, Rootfs: c.rootfsPath(),
InitPath: "/.dockerinit", InitPath: "/.dockerinit",
WorkingDir: c.Config.WorkingDir, WorkingDir: c.Config.WorkingDir,
Network: en, Network: en,
Pid: pid, MountLabel: c.getMountLabel(),
Resources: resources, Resources: resources,
CapAdd: c.hostConfig.CapAdd.Slice(), ProcessConfig: processConfig,
CapDrop: c.hostConfig.CapDrop.Slice(), ProcessLabel: c.getProcessLabel(),
ProcessConfig: processConfig, },
ProcessLabel: c.getProcessLabel(), FirstStart: !c.HasBeenStartedBefore,
MountLabel: c.getMountLabel(), LayerFolder: layerFolder,
FirstStart: !c.HasBeenStartedBefore, LayerPaths: layerPaths,
LayerFolder: layerFolder, Hostname: c.Config.Hostname,
LayerPaths: layerPaths, Isolated: c.hostConfig.Isolation.IsHyperV(),
Hostname: c.Config.Hostname,
Isolated: c.hostConfig.Isolation.IsHyperV(),
} }
return nil return nil

View file

@ -219,7 +219,9 @@ func (daemon *Daemon) Register(container *Container) error {
container.setStoppedLocking(&execdriver.ExitStatus{ExitCode: 137}) container.setStoppedLocking(&execdriver.ExitStatus{ExitCode: 137})
// use the current driver and ensure that the container is dead x.x // use the current driver and ensure that the container is dead x.x
cmd := &execdriver.Command{ cmd := &execdriver.Command{
ID: container.ID, CommonCommand: execdriver.CommonCommand{
ID: container.ID,
},
} }
daemon.execDriver.Terminate(cmd) daemon.execDriver.Terminate(cmd)

View file

@ -6,9 +6,7 @@ import (
"os/exec" "os/exec"
"time" "time"
"github.com/docker/docker/pkg/idtools"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/configs"
) )
// Context is a generic key value pair that allows // Context is a generic key value pair that allows
@ -106,36 +104,6 @@ type Driver interface {
SupportsHooks() bool SupportsHooks() bool
} }
// 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 {
ContainerID string `json:"container_id"` // id of the container to join ipc.
HostIpc bool `json:"host_ipc"`
}
// 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 {
HostPid bool `json:"host_pid"`
}
// 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 {
HostUTS bool `json:"host_uts"`
}
// CommonResources contains the resource configs for a driver that are // CommonResources contains the resource configs for a driver that are
// common across platforms. // common across platforms.
type CommonResources struct { type CommonResources struct {
@ -169,46 +137,23 @@ type ProcessConfig struct {
Tty bool `json:"tty"` Tty bool `json:"tty"`
Entrypoint string `json:"entrypoint"` Entrypoint string `json:"entrypoint"`
Arguments []string `json:"arguments"` Arguments []string `json:"arguments"`
Terminal Terminal `json:"-"` // standard or tty terminal Terminal Terminal `json:"-"` // standard or tty terminal (Unix)
Console string `json:"-"` // dev/console path Console string `json:"-"` // dev/console path (Unix)
ConsoleSize [2]int `json:"-"` // h,w of initial console size ConsoleSize [2]int `json:"-"` // h,w of initial console size (Windows)
} }
// Command wraps an os/exec.Cmd to add more metadata // CommonCommand is the common platform agnostic part of the Command structure
// // which wraps an os/exec.Cmd to add more metadata
// TODO Windows: Factor out unused fields such as LxcConfig, AppArmorProfile, type CommonCommand struct {
// and CgroupParent. ContainerPid int `json:"container_pid"` // the pid for the process inside a container
type Command struct { ID string `json:"id"`
ID string `json:"id"` InitPath string `json:"initpath"` // dockerinit
Rootfs string `json:"rootfs"` // root fs of the container MountLabel string `json:"mount_label"` // TODO Windows. More involved, but can be factored out
ReadonlyRootfs bool `json:"readonly_rootfs"` Mounts []Mount `json:"mounts"`
InitPath string `json:"initpath"` // dockerinit Network *Network `json:"network"`
WorkingDir string `json:"working_dir"` ProcessConfig ProcessConfig `json:"process_config"` // Describes the init process of the container.
ConfigPath string `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver ProcessLabel string `json:"process_label"` // TODO Windows. More involved, but can be factored out
Network *Network `json:"network"` Resources *Resources `json:"resources"`
Ipc *Ipc `json:"ipc"` Rootfs string `json:"rootfs"` // root fs of the container
Pid *Pid `json:"pid"` WorkingDir string `json:"working_dir"`
UTS *UTS `json:"uts"`
RemappedRoot *User `json:"remap_root"`
UIDMapping []idtools.IDMap `json:"uidmapping"`
GIDMapping []idtools.IDMap `json:"gidmapping"`
Resources *Resources `json:"resources"`
Mounts []Mount `json:"mounts"`
AllowedDevices []*configs.Device `json:"allowed_devices"`
AutoCreatedDevices []*configs.Device `json:"autocreated_devices"`
CapAdd []string `json:"cap_add"`
CapDrop []string `json:"cap_drop"`
GroupAdd []string `json:"group_add"`
ContainerPid int `json:"container_pid"` // the pid for the process inside a container
ProcessConfig ProcessConfig `json:"process_config"` // Describes the init process of the container.
ProcessLabel string `json:"process_label"`
MountLabel string `json:"mount_label"`
LxcConfig []string `json:"lxc_config"`
AppArmorProfile string `json:"apparmor_profile"`
CgroupParent string `json:"cgroup_parent"` // The parent cgroup for this command.
FirstStart bool `json:"first_start"`
LayerPaths []string `json:"layer_paths"` // Windows needs to know the layer paths and folder for a command
LayerFolder string `json:"layer_folder"`
Hostname string `json:"hostname"` // Windows sets the hostname in the execdriver
Isolated bool `json:"isolated"` // Windows: Isolated is a Hyper-V container rather than Windows Server Container
} }

View file

@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/docker/docker/daemon/execdriver/native/template" "github.com/docker/docker/daemon/execdriver/native/template"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/ulimit" "github.com/docker/docker/pkg/ulimit"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
@ -46,6 +47,36 @@ type Resources struct {
MemorySwappiness int64 `json:"memory_swappiness"` MemorySwappiness int64 `json:"memory_swappiness"`
} }
// 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 {
ContainerID string `json:"container_id"` // id of the container to join ipc.
HostIpc bool `json:"host_ipc"`
}
// 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 {
HostPid bool `json:"host_pid"`
}
// 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 {
HostUTS bool `json:"host_uts"`
}
// Network settings of the container // Network settings of the container
type Network struct { type Network struct {
Mtu int `json:"mtu"` Mtu int `json:"mtu"`
@ -54,6 +85,29 @@ type Network struct {
HostNetworking bool `json:"host_networking"` HostNetworking bool `json:"host_networking"`
} }
// Command wraps an os/exec.Cmd to add more metadata
type Command struct {
CommonCommand
// Fields below here are platform specific
AllowedDevices []*configs.Device `json:"allowed_devices"`
AppArmorProfile string `json:"apparmor_profile"`
AutoCreatedDevices []*configs.Device `json:"autocreated_devices"`
CapAdd []string `json:"cap_add"`
CapDrop []string `json:"cap_drop"`
CgroupParent string `json:"cgroup_parent"` // The parent cgroup for this command.
GIDMapping []idtools.IDMap `json:"gidmapping"`
GroupAdd []string `json:"group_add"`
Ipc *Ipc `json:"ipc"`
LxcConfig []string `json:"lxc_config"`
Pid *Pid `json:"pid"`
ReadonlyRootfs bool `json:"readonly_rootfs"`
RemappedRoot *User `json:"remap_root"`
UIDMapping []idtools.IDMap `json:"uidmapping"`
UTS *UTS `json:"uts"`
}
// InitContainer is the initialization of a container config. // InitContainer is the initialization of a container config.
// It returns the initial configs for a container. It's mostly // It returns the initial configs for a container. It's mostly
// defined by the default template. // defined by the default template.

View file

@ -33,3 +33,16 @@ type NetworkInterface struct {
// container and the port on the host. // container and the port on the host.
PortBindings nat.PortMap `json:"port_bindings"` PortBindings nat.PortMap `json:"port_bindings"`
} }
// Command wraps an os/exec.Cmd to add more metadata
type Command struct {
CommonCommand
// Fields below here are platform specific
FirstStart bool `json:"first_start"` // Optimisation for first boot of Windows
Hostname string `json:"hostname"` // Windows sets the hostname in the execdriver
LayerFolder string `json:"layer_folder"` // Layer folder for a command
LayerPaths []string `json:"layer_paths"` // Layer paths for a command
Isolated bool `json:"isolated"` // True if a Hyper-V container
}

View file

@ -45,19 +45,21 @@ func TestLXCConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
command := &execdriver.Command{ command := &execdriver.Command{
ID: "1", CommonCommand: execdriver.CommonCommand{
Resources: &execdriver.Resources{ ID: "1",
MemorySwap: int64(swap), Network: &execdriver.Network{
CommonResources: execdriver.CommonResources{ Mtu: 1500,
Memory: int64(mem), },
CPUShares: int64(cpu), ProcessConfig: execdriver.ProcessConfig{},
Resources: &execdriver.Resources{
MemorySwap: int64(swap),
CommonResources: execdriver.CommonResources{
Memory: int64(mem),
CPUShares: int64(cpu),
},
}, },
}, },
Network: &execdriver.Network{
Mtu: 1500,
},
AllowedDevices: make([]*configs.Device, 0), AllowedDevices: make([]*configs.Device, 0),
ProcessConfig: execdriver.ProcessConfig{},
} }
p, err := driver.generateLXCConfig(command) p, err := driver.generateLXCConfig(command)
if err != nil { if err != nil {
@ -87,15 +89,17 @@ func TestCustomLxcConfig(t *testing.T) {
Privileged: false, Privileged: false,
} }
command := &execdriver.Command{ command := &execdriver.Command{
ID: "1", CommonCommand: execdriver.CommonCommand{
ID: "1",
Network: &execdriver.Network{
Mtu: 1500,
},
ProcessConfig: processConfig,
},
LxcConfig: []string{ LxcConfig: []string{
"lxc.utsname = docker", "lxc.utsname = docker",
"lxc.cgroup.cpuset.cpus = 0,1", "lxc.cgroup.cpuset.cpus = 0,1",
}, },
Network: &execdriver.Network{
Mtu: 1500,
},
ProcessConfig: processConfig,
} }
p, err := driver.generateLXCConfig(command) p, err := driver.generateLXCConfig(command)
@ -218,16 +222,18 @@ func TestCustomLxcConfigMounts(t *testing.T) {
}, },
} }
command := &execdriver.Command{ command := &execdriver.Command{
ID: "1", CommonCommand: execdriver.CommonCommand{
ID: "1",
Network: &execdriver.Network{
Mtu: 1500,
},
Mounts: mounts,
ProcessConfig: processConfig,
},
LxcConfig: []string{ LxcConfig: []string{
"lxc.utsname = docker", "lxc.utsname = docker",
"lxc.cgroup.cpuset.cpus = 0,1", "lxc.cgroup.cpuset.cpus = 0,1",
}, },
Network: &execdriver.Network{
Mtu: 1500,
},
Mounts: mounts,
ProcessConfig: processConfig,
} }
p, err := driver.generateLXCConfig(command) p, err := driver.generateLXCConfig(command)
@ -260,14 +266,16 @@ func TestCustomLxcConfigMisc(t *testing.T) {
processConfig.Env = []string{"HOSTNAME=testhost"} processConfig.Env = []string{"HOSTNAME=testhost"}
command := &execdriver.Command{ command := &execdriver.Command{
ID: "1", CommonCommand: execdriver.CommonCommand{
ID: "1",
Network: &execdriver.Network{
Mtu: 1500,
},
ProcessConfig: processConfig,
},
LxcConfig: []string{ LxcConfig: []string{
"lxc.cgroup.cpuset.cpus = 0,1", "lxc.cgroup.cpuset.cpus = 0,1",
}, },
Network: &execdriver.Network{
Mtu: 1500,
},
ProcessConfig: processConfig,
CapAdd: []string{"net_admin", "syslog"}, CapAdd: []string{"net_admin", "syslog"},
CapDrop: []string{"kill", "mknod"}, CapDrop: []string{"kill", "mknod"},
AppArmorProfile: "lxc-container-default-with-nesting", AppArmorProfile: "lxc-container-default-with-nesting",
@ -311,17 +319,19 @@ func TestCustomLxcConfigMiscOverride(t *testing.T) {
processConfig.Env = []string{"HOSTNAME=testhost"} processConfig.Env = []string{"HOSTNAME=testhost"}
command := &execdriver.Command{ command := &execdriver.Command{
ID: "1", CommonCommand: execdriver.CommonCommand{
ID: "1",
Network: &execdriver.Network{
Mtu: 1500,
},
ProcessConfig: processConfig,
},
LxcConfig: []string{ LxcConfig: []string{
"lxc.cgroup.cpuset.cpus = 0,1", "lxc.cgroup.cpuset.cpus = 0,1",
"lxc.network.ipv4 = 172.0.0.1", "lxc.network.ipv4 = 172.0.0.1",
}, },
Network: &execdriver.Network{ CapAdd: []string{"NET_ADMIN", "SYSLOG"},
Mtu: 1500, CapDrop: []string{"KILL", "MKNOD"},
},
ProcessConfig: processConfig,
CapAdd: []string{"NET_ADMIN", "SYSLOG"},
CapDrop: []string{"KILL", "MKNOD"},
} }
p, err := driver.generateLXCConfig(command) p, err := driver.generateLXCConfig(command)

View file

@ -9,21 +9,11 @@ import (
) )
func checkSupportedOptions(c *execdriver.Command) error { func checkSupportedOptions(c *execdriver.Command) error {
// Windows doesn't support read-only root filesystem
if c.ReadonlyRootfs {
return errors.New("Windows does not support the read-only root filesystem option")
}
// Windows doesn't support username // Windows doesn't support username
if c.ProcessConfig.User != "" { if c.ProcessConfig.User != "" {
return errors.New("Windows does not support the username option") return errors.New("Windows does not support the username option")
} }
// Windows doesn't support custom lxc options
if c.LxcConfig != nil {
return errors.New("Windows does not support lxc options")
}
// TODO Windows: Validate other fields which Windows doesn't support, factor // TODO Windows: Validate other fields which Windows doesn't support, factor
// out where applicable per platform. // out where applicable per platform.

View file

@ -250,15 +250,15 @@ type HostConfig struct {
VolumesFrom []string // List of volumes to take from other container VolumesFrom []string // List of volumes to take from other container
Devices []DeviceMapping // List of devices to map inside the container Devices []DeviceMapping // List of devices to map inside the container
NetworkMode NetworkMode // Network namespace to use for the container NetworkMode NetworkMode // Network namespace to use for the container
IpcMode IpcMode // IPC namespace to use for the container IpcMode IpcMode // IPC namespace to use for the container // Unix specific
PidMode PidMode // PID namespace to use for the container PidMode PidMode // PID namespace to use for the container // Unix specific
UTSMode UTSMode // UTS namespace to use for the container UTSMode UTSMode // UTS namespace to use for the container // Unix specific
CapAdd *stringutils.StrSlice // List of kernel capabilities to add to the container CapAdd *stringutils.StrSlice // List of kernel capabilities to add to the container
CapDrop *stringutils.StrSlice // List of kernel capabilities to remove from the container CapDrop *stringutils.StrSlice // List of kernel capabilities to remove from the container
GroupAdd []string // List of additional groups that the container process will run as GroupAdd []string // List of additional groups that the container process will run as
RestartPolicy RestartPolicy // Restart policy to be used for the container RestartPolicy RestartPolicy // Restart policy to be used for the container
SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
ReadonlyRootfs bool // Is the container root filesystem in read-only ReadonlyRootfs bool // Is the container root filesystem in read-only // Unix specific
Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container
LogConfig LogConfig // Configuration of the logs for this container LogConfig LogConfig // Configuration of the logs for this container
CgroupParent string // Parent cgroup. CgroupParent string // Parent cgroup.