From dbb515f01ff1f3b323b7bbc2c712bfae0455245a Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 8 Jul 2014 10:17:05 -0700 Subject: [PATCH] Update api proposal Move concepts into specific files for easy management Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: vmarmol) --- api.go | 150 ---------------------------- api_temp.go | 1 - config.go | 86 ++++++++++++++++ container_test.go => config_test.go | 0 container.go | 141 +++++++++++--------------- process.go | 27 +++++ state.go | 23 ++++- 7 files changed, 193 insertions(+), 235 deletions(-) delete mode 100644 api.go create mode 100644 config.go rename container_test.go => config_test.go (100%) create mode 100644 process.go diff --git a/api.go b/api.go deleted file mode 100644 index 6de0284a52e..00000000000 --- a/api.go +++ /dev/null @@ -1,150 +0,0 @@ -/* -API for libcontainer. - -NOTE: The API is in flux and mainly not implemented. Proceed with caution until further notice. -*/ -package libcontainer - -import ( - "io" -) - -// Name of a container. -// -// Allowable characters for container names are: -// - Alpha numeric ([a-zA-Z0-9]) -// - Underscores (_) -type Name string - -// The running state of the container. -type RunState int - -const ( - // The container exists and is running. - RUNNING RunState = iota - - // The container exists, it is in the process of being paused. - PAUSING RunState = iota - - // The container exists, but all its processes are paused. - PAUSED RunState = iota - - // The container does not exist. - DESTROYED RunState = iota -) - -// Configuration for a process to be run inside a container. -type ProcessConfig struct { - // The command to be run followed by any arguments. - Args []string - - // Map of environment variables to their values. - Env []string - - // Stdin is a pointer to a reader which provides the standard input stream. - // Stdout is a pointer to a writer which receives the standard output stream. - // Stderr is a pointer to a writer which receives the standard error stream. - // - // If a reader or writer is nil, the input stream is assumed to be empty and the output is - // discarded. - // - // The readers and writers, if supplied, are closed when the process terminates. Their Close - // methods should be idempotent. - // - // Stdout and Stderr may refer to the same writer in which case the output is interspersed. - Stdin *io.ReadCloser - Stdout *io.WriteCloser - Stderr *io.WriteCloser - - // TODO(vmarmol): Complete. - // ProcessConfig take over some of the runtime config from Config. - // This is anything that can be set per-process that enters the container and its namespaces. - // - // Things like: - // - Namespaces - // - Capabilities - // - User/Groups - // - Working directory -} - -// Factory of libcontainer containers. -type Factory interface { - // Creates a new container as specified, and starts an init process inside. - // - // The container and PID of the init process is returned. The init must be reaped by the caller. - // - // Errors: name already exists, - // config or initialConfig invalid, - // system error. - // - // Arguments: - // name: The user-provided name of the container. Used to identify this container, must be unique - // in this machine. - // config: The configuration of the new container. - // initialProcess: The configuration of the init to run inside the container. - // - // On error, any partially created container parts are cleaned up (the operation is atomic). - Create(name Name, config *Config, initialProcess *ProcessConfig) (*Container, int, error) -} - -// A libcontainer container object. Must be created by the Factory above. -// -// Each container is thread-safe within the same process. Since a container can -// be destroyed by a separate process, any function may return that the container -// was not found. -type Container interface { - // Returns the name of this container. - Name() Name - - // Returns the current run state of the container. - // - // Errors: container no longer exists, - // system error. - RunState() (RunState, error) - - // Returns the current config of the container. - // - // Errors: container no longer exists, - // system error. - Config() (*Config, error) - - // Destroys the container after killing all running processes. - // - // Any event registrations are removed before the container is destroyed. - // No error is returned if the container is already destroyed. - // - // Errors: system error. - Destroy() error - - // Returns the PIDs inside this container. The PIDs are in the namespace of the calling process. - // - // Errors: container no longer exists, - // system error. - // - // Some of the returned PIDs may no longer refer to processes in the Container, unless - // the Container state is PAUSED in which case every PID in the slice is valid. - Processes() ([]int, error) - - // Returns statistics for the container. - // - // Errors: container no longer exists, - // system error. - Stats() (*ContainerStats, error) - - // If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses - // the execution of any user processes. Asynchronously, when the container finished being paused the - // state is changed to PAUSED. - // If the Container state is PAUSED, do nothing. - // - // Errors: container no longer exists, - // system error. - Pause() error - - // If the Container state is PAUSED, resumes the execution of any user processes in the - // Container before setting the Container state to RUNNING. - // If the Container state is RUNNING, do nothing. - // - // Errors: container no longer exists, - // system error. - Resume() error -} diff --git a/api_temp.go b/api_temp.go index 85de7c89bcd..be57fbf649c 100644 --- a/api_temp.go +++ b/api_temp.go @@ -10,7 +10,6 @@ import ( // TODO(vmarmol): Complete Stats() in final libcontainer API and move users to that. // DEPRECATED: The below portions are only to be used during the transition to the official API. - // Returns all available stats for the given container. func GetStats(container *Config, state *State) (*ContainerStats, error) { var containerStats ContainerStats diff --git a/config.go b/config.go new file mode 100644 index 00000000000..8fe95c24f72 --- /dev/null +++ b/config.go @@ -0,0 +1,86 @@ +package libcontainer + +import ( + "github.com/docker/libcontainer/cgroups" + "github.com/docker/libcontainer/mount" + "github.com/docker/libcontainer/network" +) + +type MountConfig mount.MountConfig + +type Network network.Network + +// Config defines configuration options for executing a process inside a contained environment. +type Config struct { + // Mount specific options. + MountConfig *MountConfig `json:"mount_config,omitempty"` + + // Hostname optionally sets the container's hostname if provided + Hostname string `json:"hostname,omitempty"` + + // User will set the uid and gid of the executing process running inside the container + User string `json:"user,omitempty"` + + // WorkingDir will change the processes current working directory inside the container's rootfs + WorkingDir string `json:"working_dir,omitempty"` + + // Env will populate the processes environment with the provided values + // Any values from the parent processes will be cleared before the values + // provided in Env are provided to the process + Env []string `json:"environment,omitempty"` + + // Tty when true will allocate a pty slave on the host for access by the container's process + // and ensure that it is mounted inside the container's rootfs + Tty bool `json:"tty,omitempty"` + + // Namespaces specifies the container's namespaces that it should setup when cloning the init process + // If a namespace is not provided that namespace is shared from the container's parent process + Namespaces map[string]bool `json:"namespaces,omitempty"` + + // Capabilities specify the capabilities to keep when executing the process inside the container + // All capbilities not specified will be dropped from the processes capability mask + Capabilities []string `json:"capabilities,omitempty"` + + // Networks specifies the container's network setup to be created + Networks []*Network `json:"networks,omitempty"` + + // Routes can be specified to create entries in the route table as the container is started + Routes []*Route `json:"routes,omitempty"` + + // Cgroups specifies specific cgroup settings for the various subsystems that the container is + // placed into to limit the resources the container has available + Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` + + // AppArmorProfile specifies the profile to apply to the process running in the container and is + // change at the time the process is execed + AppArmorProfile string `json:"apparmor_profile,omitempty"` + + // ProcessLabel specifies the label to apply to the process running in the container. It is + // commonly used by selinux + ProcessLabel string `json:"process_label,omitempty"` + + // RestrictSys will remount /proc/sys, /sys, and mask over sysrq-trigger as well as /proc/irq and + // /proc/bus + RestrictSys bool `json:"restrict_sys,omitempty"` +} + +// Routes can be specified to create entries in the route table as the container is started +// +// All of destination, source, and gateway should be either IPv4 or IPv6. +// One of the three options must be present, and ommitted entries will use their +// IP family default for the route table. For IPv4 for example, setting the +// gateway to 1.2.3.4 and the interface to eth0 will set up a standard +// destination of 0.0.0.0(or *) when viewed in the route table. +type Route struct { + // Sets the destination and mask, should be a CIDR. Accepts IPv4 and IPv6 + Destination string `json:"destination,omitempty"` + + // Sets the source and mask, should be a CIDR. Accepts IPv4 and IPv6 + Source string `json:"source,omitempty"` + + // Sets the gateway. Accepts IPv4 and IPv6 + Gateway string `json:"gateway,omitempty"` + + // The device to set this route up for, for example: eth0 + InterfaceName string `json:"interface_name,omitempty"` +} diff --git a/container_test.go b/config_test.go similarity index 100% rename from container_test.go rename to config_test.go diff --git a/container.go b/container.go index 8fe95c24f72..6e6c2bd8d94 100644 --- a/container.go +++ b/container.go @@ -1,86 +1,63 @@ +/* +NOTE: The API is in flux and mainly not implemented. Proceed with caution until further notice. +*/ package libcontainer -import ( - "github.com/docker/libcontainer/cgroups" - "github.com/docker/libcontainer/mount" - "github.com/docker/libcontainer/network" -) - -type MountConfig mount.MountConfig - -type Network network.Network - -// Config defines configuration options for executing a process inside a contained environment. -type Config struct { - // Mount specific options. - MountConfig *MountConfig `json:"mount_config,omitempty"` - - // Hostname optionally sets the container's hostname if provided - Hostname string `json:"hostname,omitempty"` - - // User will set the uid and gid of the executing process running inside the container - User string `json:"user,omitempty"` - - // WorkingDir will change the processes current working directory inside the container's rootfs - WorkingDir string `json:"working_dir,omitempty"` - - // Env will populate the processes environment with the provided values - // Any values from the parent processes will be cleared before the values - // provided in Env are provided to the process - Env []string `json:"environment,omitempty"` - - // Tty when true will allocate a pty slave on the host for access by the container's process - // and ensure that it is mounted inside the container's rootfs - Tty bool `json:"tty,omitempty"` - - // Namespaces specifies the container's namespaces that it should setup when cloning the init process - // If a namespace is not provided that namespace is shared from the container's parent process - Namespaces map[string]bool `json:"namespaces,omitempty"` - - // Capabilities specify the capabilities to keep when executing the process inside the container - // All capbilities not specified will be dropped from the processes capability mask - Capabilities []string `json:"capabilities,omitempty"` - - // Networks specifies the container's network setup to be created - Networks []*Network `json:"networks,omitempty"` - - // Routes can be specified to create entries in the route table as the container is started - Routes []*Route `json:"routes,omitempty"` - - // Cgroups specifies specific cgroup settings for the various subsystems that the container is - // placed into to limit the resources the container has available - Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` - - // AppArmorProfile specifies the profile to apply to the process running in the container and is - // change at the time the process is execed - AppArmorProfile string `json:"apparmor_profile,omitempty"` - - // ProcessLabel specifies the label to apply to the process running in the container. It is - // commonly used by selinux - ProcessLabel string `json:"process_label,omitempty"` - - // RestrictSys will remount /proc/sys, /sys, and mask over sysrq-trigger as well as /proc/irq and - // /proc/bus - RestrictSys bool `json:"restrict_sys,omitempty"` -} - -// Routes can be specified to create entries in the route table as the container is started +// A libcontainer container object. // -// All of destination, source, and gateway should be either IPv4 or IPv6. -// One of the three options must be present, and ommitted entries will use their -// IP family default for the route table. For IPv4 for example, setting the -// gateway to 1.2.3.4 and the interface to eth0 will set up a standard -// destination of 0.0.0.0(or *) when viewed in the route table. -type Route struct { - // Sets the destination and mask, should be a CIDR. Accepts IPv4 and IPv6 - Destination string `json:"destination,omitempty"` - - // Sets the source and mask, should be a CIDR. Accepts IPv4 and IPv6 - Source string `json:"source,omitempty"` - - // Sets the gateway. Accepts IPv4 and IPv6 - Gateway string `json:"gateway,omitempty"` - - // The device to set this route up for, for example: eth0 - InterfaceName string `json:"interface_name,omitempty"` +// Each container is thread-safe within the same process. Since a container can +// be destroyed by a separate process, any function may return that the container +// was not found. +type Container interface { + // Returns the ID of this container. + ID() string + + // Returns the current run state of the container. + // + // Errors: container no longer exists, + // system error. + RunState() (*RunState, error) + + // Returns the current config of the container. + Config() *Config + + // Destroys the container after killing all running processes. + // + // Any event registrations are removed before the container is destroyed. + // No error is returned if the container is already destroyed. + // + // Errors: system error. + Destroy() error + + // Returns the PIDs inside this container. The PIDs are in the namespace of the calling process. + // + // Errors: container no longer exists, + // system error. + // + // Some of the returned PIDs may no longer refer to processes in the Container, unless + // the Container state is PAUSED in which case every PID in the slice is valid. + Processes() ([]int, error) + + // Returns statistics for the container. + // + // Errors: container no longer exists, + // system error. + Stats() (*ContainerStats, error) + + // If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses + // the execution of any user processes. Asynchronously, when the container finished being paused the + // state is changed to PAUSED. + // If the Container state is PAUSED, do nothing. + // + // Errors: container no longer exists, + // system error. + Pause() error + + // If the Container state is PAUSED, resumes the execution of any user processes in the + // Container before setting the Container state to RUNNING. + // If the Container state is RUNNING, do nothing. + // + // Errors: container no longer exists, + // system error. + Resume() error } diff --git a/process.go b/process.go new file mode 100644 index 00000000000..489666a5878 --- /dev/null +++ b/process.go @@ -0,0 +1,27 @@ +package libcontainer + +import "io" + +// Configuration for a process to be run inside a container. +type ProcessConfig struct { + // The command to be run followed by any arguments. + Args []string + + // Map of environment variables to their values. + Env []string + + // Stdin is a pointer to a reader which provides the standard input stream. + // Stdout is a pointer to a writer which receives the standard output stream. + // Stderr is a pointer to a writer which receives the standard error stream. + // + // If a reader or writer is nil, the input stream is assumed to be empty and the output is + // discarded. + // + // The readers and writers, if supplied, are closed when the process terminates. Their Close + // methods should be idempotent. + // + // Stdout and Stderr may refer to the same writer in which case the output is interspersed. + Stdin io.ReadCloser + Stdout io.WriteCloser + Stderr io.WriteCloser +} diff --git a/state.go b/state.go index a055bb0ffe8..ee5d14d2ece 100644 --- a/state.go +++ b/state.go @@ -12,14 +12,33 @@ import ( type State struct { // InitPid is the init process id in the parent namespace InitPid int `json:"init_pid,omitempty"` + // InitStartTime is the init process start time InitStartTime string `json:"init_start_time,omitempty"` + // Network runtime state. NetworkState network.NetworkState `json:"network_state,omitempty"` } -// The name of the runtime state file -const stateFile = "state.json" +// The running state of the container. +type RunState int + +const ( + // The name of the runtime state file + stateFile = "state.json" + + // The container exists and is running. + Running RunState = iota + + // The container exists, it is in the process of being paused. + Pausing + + // The container exists, but all its processes are paused. + Paused + + // The container does not exist. + Destroyed +) // SaveState writes the container's runtime state to a state.json file // in the specified path