Add methods attach() and attach_wait() to the Python API that give
access to the attach functionality of LXC. Both accept two main
arguments:
1. run: A python function that is executed inside the container
2. payload: (optional) A parameter that will be passed to the python
function
Additionally, the following keyword arguments are supported:
attach_flags: How attach should operate, i.e. whether to attach to
cgroups, whether to drop capabilities, etc. The following
constants are defined as part of the lxc module that may
be OR'd together for this option:
LXC_ATTACH_MOVE_TO_CGROUP
LXC_ATTACH_DROP_CAPABILITIES
LXC_ATTACH_SET_PERSONALITY
LXC_ATTACH_APPARMOR
LXC_ATTACH_REMOUNT_PROC_SYS
LXC_ATTACH_DEFAULT
namespaces: Which namespaces to attach to, as defined as the flags that
may be passed to the clone(2) system call. Note: maybe we
should export these flags too.
personality: The personality of the process, it will be passed to the
personality(2) syscall. Note: maybe we should provide
access to the function that converts arch into
personality.
initial_cwd: The initial working directory after attaching.
uid: The user id after attaching.
gid: The group id after attaching.
env_policy: The environment policy, may be one of:
LXC_ATTACH_KEEP_ENV
LXC_ATTACH_CLEAR_ENV
extra_env_vars: A list (or tuple) of environment variables (in the form
KEY=VALUE) that should be set once attach has
succeeded.
extra_keep_env: A list (or tuple) of names of environment variables
that should be kept regardless of policy.
stdin: A file/socket/... object that should be used as stdin for the
attached process. (If not a standard Python object, it has to
implemented the fileno() method and provide a fd as the result.)
stdout, stderr: See stdin.
attach() returns the PID of the attached process, or -1 on failure.
attach_wait() returns the return code of the attached process after
that has finished executing, or -1 on failure. Note that if the exit
status of the process is 255, -1 will also be returned, since attach
failures result in an exit code of 255.
Two default run functions are also provided in the lxc module:
attach_run_command: Runs the specified command
attach_run_shell: Runs a shell in the container
Examples (assumeing c is a Container object):
c.attach_wait(lxc.attach_run_command, 'id')
c.attach_wait(lxc.attach_run_shell)
def foo():
print("Hello World")
# the following line is important, otherwise the exit code of
# the attached program will be -1
# sys.exit(0) will also work
return 0
c.attach_wait(foo)
c.attach_wait(lxc.attach_run_command, ['cat', '/proc/self/cgroup'])
c.attach_wait(lxc.attach_run_command, ['cat', '/proc/self/cgroup'],
attach_flags=(lxc.LXC_ATTACH_DEFAULT &
~lxc.LXC_ATTACH_MOVE_TO_CGROUP))
Note that while it is possible to execute Python code inside the
container by passing a function (see example), it is unwise to import
modules, since there is no guarantee that the Python installation
inside the container is in any way compatible with that outside of it.
If you want to run Python code directly, please import all modules
before attaching and only use them within the container.
Signed-off-by: Christian Seiler <christian@iwakd.de> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>