Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> --- .gitignore | 1 - configure.ac | 1 - src/python-lxc/lxc.c | 14 +- src/python-lxc/lxc/__init__.py | 470 +++++++++++++++++++++++++++++++++++++ src/python-lxc/lxc/__init__.py.in | 471 -------------------------------------- 5 files changed, 483 insertions(+), 474 deletions(-) create mode 100644 src/python-lxc/lxc/__init__.py delete mode 100644 src/python-lxc/lxc/__init__.py.in
diff --git a/.gitignore b/.gitignore index a3f46eb..b54ce3d 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,6 @@ src/lxc/lxc-wait src/lxc/legacy/lxc-ls src/python-lxc/build/ -src/python-lxc/lxc/__init__.py src/python-lxc/lxc/__pycache__/ src/tests/lxc-test-containertests diff --git a/configure.ac b/configure.ac index a9b2803..0c94d37 100644 --- a/configure.ac +++ b/configure.ac @@ -382,7 +382,6 @@ AC_CONFIG_FILES([ src/lxc/lxc.functions src/python-lxc/Makefile - src/python-lxc/lxc/__init__.py src/lua-lxc/Makefile diff --git a/src/python-lxc/lxc.c b/src/python-lxc/lxc.c index 2abdc4c..8fd0a78 100644 --- a/src/python-lxc/lxc.c +++ b/src/python-lxc/lxc.c @@ -95,6 +95,12 @@ Container_init(Container *self, PyObject *args, PyObject *kwds) return 0; } +static PyObject * +get_default_config_path(Container *self, PyObject *args, PyObject *kwds) +{ + return PyUnicode_FromString(lxc_get_default_config_path()); +} + // Container properties static PyObject * Container_config_file_name(Container *self, PyObject *args, PyObject *kwds) @@ -628,12 +634,18 @@ PyVarObject_HEAD_INIT(NULL, 0) Container_new, /* tp_new */ }; +static PyMethodDef LXC_methods[] = { + {"get_default_config_path", (PyCFunction)get_default_config_path, METH_NOARGS, + "Returns the current LXC config path"}, + {NULL, NULL, 0, NULL} +}; + static PyModuleDef _lxcmodule = { PyModuleDef_HEAD_INIT, "_lxc", "Binding for liblxc in python", -1, - NULL, NULL, NULL, NULL, NULL + LXC_methods }; PyMODINIT_FUNC diff --git a/src/python-lxc/lxc/__init__.py b/src/python-lxc/lxc/__init__.py new file mode 100644 index 0000000..828a1cb --- /dev/null +++ b/src/python-lxc/lxc/__init__.py @@ -0,0 +1,470 @@ +# +# python-lxc: Python bindings for LXC +# +# (C) Copyright Canonical Ltd. 2012 +# +# Authors: +# Stéphane Graber <stgra...@ubuntu.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import _lxc +import glob +import os +import subprocess +import stat +import time +import warnings + +warnings.warn("The python-lxc API isn't yet stable " + "and may change at any point in the future.", Warning, 2) + +default_config_path = _lxc.get_default_config_path() + + +class ContainerNetwork(): + props = {} + + def __init__(self, container, index): + self.container = container + self.index = index + + for key in self.container.get_keys("lxc.network.%s" % self.index): + if "." in key: + self.props[key.replace(".", "_")] = key + else: + self.props[key] = key + + if not self.props: + return False + + def __delattr__(self, key): + if key in ["container", "index", "props"]: + return object.__delattr__(self, key) + + if key not in self.props: + raise AttributeError("'%s' network has no attribute '%s'" % ( + self.__get_network_item("type"), key)) + + return self.__clear_network_item(self.props[key]) + + def __dir__(self): + return sorted(self.props.keys()) + + def __getattr__(self, key): + if key in ["container", "index", "props"]: + return object.__getattribute__(self, key) + + if key not in self.props: + raise AttributeError("'%s' network has no attribute '%s'" % ( + self.__get_network_item("type"), key)) + + return self.__get_network_item(self.props[key]) + + def __hasattr__(self, key): + if key in ["container", "index", "props"]: + return object.__hasattr__(self, key) + + if key not in self.props: + raise AttributeError("'%s' network has no attribute '%s'" % ( + self.__get_network_item("type"), key)) + + return True + + def __repr__(self): + return "'%s' network at index '%s'" % ( + self.__get_network_item("type"), self.index) + + def __setattr__(self, key, value): + if key in ["container", "index", "props"]: + return object.__setattr__(self, key, value) + + if key not in self.props: + raise AttributeError("'%s' network has no attribute '%s'" % ( + self.__get_network_item("type"), key)) + + return self.__set_network_item(self.props[key], value) + + def __clear_network_item(self, key): + return self.container.clear_config_item("lxc.network.%s.%s" % ( + self.index, key)) + + def __get_network_item(self, key): + return self.container.get_config_item("lxc.network.%s.%s" % ( + self.index, key)) + + def __set_network_item(self, key, value): + return self.container.set_config_item("lxc.network.%s.%s" % ( + self.index, key), value) + + +class ContainerNetworkList(): + def __init__(self, container): + self.container = container + + def __getitem__(self, index): + if index >= len(self): + raise IndexError("list index out of range") + + return ContainerNetwork(self.container, index) + + def __len__(self): + values = self.container.get_config_item("lxc.network") + + if values: + return len(values) + else: + return 0 + + def add(self, network_type): + index = len(self) + + return self.container.set_config_item("lxc.network.%s.type" % index, + network_type) + + def remove(self, index): + count = len(self) + if index >= count: + raise IndexError("list index out of range") + + return self.container.clear_config_item("lxc.network.%s" % index) + + +class Container(_lxc.Container): + def __init__(self, name, config_path=None): + """ + Creates a new Container instance. + """ + + if os.geteuid() != 0: + raise Exception("Running as non-root.") + + if config_path: + _lxc.Container.__init__(self, name, config_path) + else: + _lxc.Container.__init__(self, name) + + self.network = ContainerNetworkList(self) + + def add_device_node(self, path, destpath=None): + """ + Add block/char device to running container. + """ + + if not self.running: + return False + + if not destpath: + destpath = path + + if not os.path.exists(path): + return False + + # Lookup the source + path_stat = os.stat(path) + mode = stat.S_IMODE(path_stat.st_mode) + + # Allow the target + if stat.S_ISBLK(path_stat.st_mode): + self.set_cgroup_item("devices.allow", + "b %s:%s rwm" % + (int(path_stat.st_rdev / 256), + int(path_stat.st_rdev % 256))) + elif stat.S_ISCHR(path_stat.st_mode): + self.set_cgroup_item("devices.allow", + "c %s:%s rwm" % + (int(path_stat.st_rdev / 256), + int(path_stat.st_rdev % 256))) + + # Create the target + rootfs = "/proc/%s/root/" % self.init_pid + container_path = "%s/%s" % (rootfs, destpath) + + if os.path.exists(container_path): + os.remove(container_path) + + os.mknod(container_path, path_stat.st_mode, path_stat.st_rdev) + os.chmod(container_path, mode) + os.chown(container_path, 0, 0) + + return True + + def add_device_net(self, name, destname=None): + """ + Add network device to running container. + """ + + if not self.running: + return False + + if not destname: + destname = name + + if not os.path.exists("/sys/class/net/%s/" % name): + return False + + return subprocess.call(['ip', 'link', 'set', + 'dev', name, + 'netns', str(self.init_pid), + 'name', destname]) == 0 + + def append_config_item(self, key, value): + """ + Append 'value' to 'key', assuming 'key' is a list. + If 'key' isn't a list, 'value' will be set as the value of 'key'. + """ + + return _lxc.Container.set_config_item(self, key, value) + + def attach(self, namespace="ALL", *cmd): + """ + Attach to a running container. + """ + + if not self.running: + return False + + attach = ["lxc-attach", "-n", self.name, + "-P", self.get_config_path()] + if namespace != "ALL": + attach += ["-s", namespace] + + if cmd: + attach += ["--"] + list(cmd) + + if subprocess.call( + attach, + universal_newlines=True) != 0: + return False + return True + + def create(self, template, args={}): + """ + Create a new rootfs for the container. + + "template" must be a valid template name. + + "args" (optional) is a dictionary of parameters and values to pass + to the template. + """ + + template_args = [] + for item in args.items(): + template_args.append("--%s" % item[0]) + template_args.append("%s" % item[1]) + + return _lxc.Container.create(self, template, tuple(template_args)) + + def clone(self, container): + """ + Clone an existing container into a new one. + """ + + if self.defined: + return False + + if isinstance(container, Container): + source = container + else: + source = Container(container) + + if not source.defined: + return False + + if subprocess.call(["lxc-clone", "-o", source.name, "-n", self.name], + universal_newlines=True) != 0: + return False + + self.load_config() + return True + + def console(self, tty="1"): + """ + Access the console of a container. + """ + + if not self.running: + return False + + if subprocess.call(["lxc-console", "-n", self.name, "-t", "%s" % tty, + "-P", self.get_config_path()], + universal_newlines=True) != 0: + return False + return True + + def get_cgroup_item(self, key): + """ + Returns the value for a given cgroup entry. + A list is returned when multiple values are set. + """ + value = _lxc.Container.get_cgroup_item(self, key) + + if value is False: + return False + else: + return value.rstrip("\n") + + def get_config_item(self, key): + """ + Returns the value for a given config key. + A list is returned when multiple values are set. + """ + value = _lxc.Container.get_config_item(self, key) + + if value is False: + return False + elif value.endswith("\n"): + return value.rstrip("\n").split("\n") + else: + return value + + def get_ips(self, timeout=60, interface=None, protocol=None): + """ + Returns the list of IP addresses for the container. + """ + + if not self.running: + return False + + ips = [] + + count = 0 + while count < timeout: + if count != 0: + time.sleep(1) + + base_cmd = ["lxc-attach", "-s", "NETWORK", "-n", self.name, "--", + "ip"] + + # Get IPv6 + if protocol in ("ipv6", None): + ip6_cmd = base_cmd + ["-6", "addr", "show", "scope", "global"] + if interface: + ip = subprocess.Popen(ip6_cmd + ["dev", interface], + stdout=subprocess.PIPE, + universal_newlines=True) + else: + ip = subprocess.Popen(ip6_cmd, stdout=subprocess.PIPE, + universal_newlines=True) + + ip.wait() + for line in ip.stdout.read().split("\n"): + fields = line.split() + if len(fields) > 2 and fields[0] == "inet6": + ips.append(fields[1].split('/')[0]) + + # Get IPv4 + if protocol in ("ipv4", None): + ip4_cmd = base_cmd + ["-4", "addr", "show", "scope", "global"] + if interface: + ip = subprocess.Popen(ip4_cmd + ["dev", interface], + stdout=subprocess.PIPE, + universal_newlines=True) + else: + ip = subprocess.Popen(ip4_cmd, stdout=subprocess.PIPE, + universal_newlines=True) + + ip.wait() + for line in ip.stdout.read().split("\n"): + fields = line.split() + if len(fields) > 2 and fields[0] == "inet": + ips.append(fields[1].split('/')[0]) + + if ips: + break + + count += 1 + + return ips + + def get_keys(self, key=None): + """ + Returns a list of valid sub-keys. + """ + if key: + value = _lxc.Container.get_keys(self, key) + else: + value = _lxc.Container.get_keys(self) + + if value is False: + return False + elif value.endswith("\n"): + return value.rstrip("\n").split("\n") + else: + return value + + def set_config_item(self, key, value): + """ + Set a config key to a provided value. + The value can be a list for the keys supporting multiple values. + """ + old_value = self.get_config_item(key) + + # Check if it's a list + def set_key(key, value): + self.clear_config_item(key) + if isinstance(value, list): + for entry in value: + if not _lxc.Container.set_config_item(self, key, entry): + return False + else: + _lxc.Container.set_config_item(self, key, value) + + set_key(key, value) + new_value = self.get_config_item(key) + + if (isinstance(value, str) and isinstance(new_value, str) and + value == new_value): + return True + elif (isinstance(value, list) and isinstance(new_value, list) and + set(value) == set(new_value)): + return True + elif (isinstance(value, str) and isinstance(new_value, list) and + set([value]) == set(new_value)): + return True + elif old_value: + set_key(key, old_value) + return False + else: + self.clear_config_item(key) + return False + + def wait(self, state, timeout=-1): + """ + Wait for the container to reach a given state or timeout. + """ + + if isinstance(state, str): + state = state.upper() + + return _lxc.Container.wait(self, state, timeout) + + +def list_containers(as_object=False, config_path=None): + """ + List the containers on the system. + """ + + if not config_path: + config_path = default_config_path + + containers = [] + for entry in glob.glob("%s/*/config" % config_path): + if as_object: + containers.append(Container(entry.split("/")[-2], config_path)) + else: + containers.append(entry.split("/")[-2]) + return containers diff --git a/src/python-lxc/lxc/__init__.py.in b/src/python-lxc/lxc/__init__.py.in deleted file mode 100644 index f1848f2..0000000 --- a/src/python-lxc/lxc/__init__.py.in +++ /dev/null @@ -1,471 +0,0 @@ -# -# python-lxc: Python bindings for LXC -# -# (C) Copyright Canonical Ltd. 2012 -# -# Authors: -# Stéphane Graber <stgra...@ubuntu.com> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -import _lxc -import glob -import os -import subprocess -import stat -import tempfile -import time -import warnings - -warnings.warn("The python-lxc API isn't yet stable " - "and may change at any point in the future.", Warning, 2) - -default_config_path = "@LXCPATH@" - - -class ContainerNetwork(): - props = {} - - def __init__(self, container, index): - self.container = container - self.index = index - - for key in self.container.get_keys("lxc.network.%s" % self.index): - if "." in key: - self.props[key.replace(".", "_")] = key - else: - self.props[key] = key - - if not self.props: - return False - - def __delattr__(self, key): - if key in ["container", "index", "props"]: - return object.__delattr__(self, key) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return self.__clear_network_item(self.props[key]) - - def __dir__(self): - return sorted(self.props.keys()) - - def __getattr__(self, key): - if key in ["container", "index", "props"]: - return object.__getattribute__(self, key) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return self.__get_network_item(self.props[key]) - - def __hasattr__(self, key): - if key in ["container", "index", "props"]: - return object.__hasattr__(self, key) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return True - - def __repr__(self): - return "'%s' network at index '%s'" % ( - self.__get_network_item("type"), self.index) - - def __setattr__(self, key, value): - if key in ["container", "index", "props"]: - return object.__setattr__(self, key, value) - - if key not in self.props: - raise AttributeError("'%s' network has no attribute '%s'" % ( - self.__get_network_item("type"), key)) - - return self.__set_network_item(self.props[key], value) - - def __clear_network_item(self, key): - return self.container.clear_config_item("lxc.network.%s.%s" % ( - self.index, key)) - - def __get_network_item(self, key): - return self.container.get_config_item("lxc.network.%s.%s" % ( - self.index, key)) - - def __set_network_item(self, key, value): - return self.container.set_config_item("lxc.network.%s.%s" % ( - self.index, key), value) - - -class ContainerNetworkList(): - def __init__(self, container): - self.container = container - - def __getitem__(self, index): - if index >= len(self): - raise IndexError("list index out of range") - - return ContainerNetwork(self.container, index) - - def __len__(self): - values = self.container.get_config_item("lxc.network") - - if values: - return len(values) - else: - return 0 - - def add(self, network_type): - index = len(self) - - return self.container.set_config_item("lxc.network.%s.type" % index, - network_type) - - def remove(self, index): - count = len(self) - if index >= count: - raise IndexError("list index out of range") - - return self.container.clear_config_item("lxc.network.%s" % index) - - -class Container(_lxc.Container): - def __init__(self, name, config_path=None): - """ - Creates a new Container instance. - """ - - if os.geteuid() != 0: - raise Exception("Running as non-root.") - - if config_path: - _lxc.Container.__init__(self, name, config_path) - else: - _lxc.Container.__init__(self, name) - - self.network = ContainerNetworkList(self) - - def add_device_node(self, path, destpath=None): - """ - Add block/char device to running container. - """ - - if not self.running: - return False - - if not destpath: - destpath = path - - if not os.path.exists(path): - return False - - # Lookup the source - path_stat = os.stat(path) - mode = stat.S_IMODE(path_stat.st_mode) - - # Allow the target - if stat.S_ISBLK(path_stat.st_mode): - self.set_cgroup_item("devices.allow", - "b %s:%s rwm" % - (int(path_stat.st_rdev / 256), - int(path_stat.st_rdev % 256))) - elif stat.S_ISCHR(path_stat.st_mode): - self.set_cgroup_item("devices.allow", - "c %s:%s rwm" % - (int(path_stat.st_rdev / 256), - int(path_stat.st_rdev % 256))) - - # Create the target - rootfs = "/proc/%s/root/" % self.init_pid - container_path = "%s/%s" % (rootfs, destpath) - - if os.path.exists(container_path): - os.remove(container_path) - - os.mknod(container_path, path_stat.st_mode, path_stat.st_rdev) - os.chmod(container_path, mode) - os.chown(container_path, 0, 0) - - return True - - def add_device_net(self, name, destname=None): - """ - Add network device to running container. - """ - - if not self.running: - return False - - if not destname: - destname = name - - if not os.path.exists("/sys/class/net/%s/" % name): - return False - - return subprocess.call(['ip', 'link', 'set', - 'dev', name, - 'netns', str(self.init_pid), - 'name', destname]) == 0 - - def append_config_item(self, key, value): - """ - Append 'value' to 'key', assuming 'key' is a list. - If 'key' isn't a list, 'value' will be set as the value of 'key'. - """ - - return _lxc.Container.set_config_item(self, key, value) - - def attach(self, namespace="ALL", *cmd): - """ - Attach to a running container. - """ - - if not self.running: - return False - - attach = ["lxc-attach", "-n", self.name, - "-P", self.get_config_path()] - if namespace != "ALL": - attach += ["-s", namespace] - - if cmd: - attach += ["--"] + list(cmd) - - if subprocess.call( - attach, - universal_newlines=True) != 0: - return False - return True - - def create(self, template, args={}): - """ - Create a new rootfs for the container. - - "template" must be a valid template name. - - "args" (optional) is a dictionary of parameters and values to pass - to the template. - """ - - template_args = [] - for item in args.items(): - template_args.append("--%s" % item[0]) - template_args.append("%s" % item[1]) - - return _lxc.Container.create(self, template, tuple(template_args)) - - def clone(self, container): - """ - Clone an existing container into a new one. - """ - - if self.defined: - return False - - if isinstance(container, Container): - source = container - else: - source = Container(container) - - if not source.defined: - return False - - if subprocess.call(["lxc-clone", "-o", source.name, "-n", self.name], - universal_newlines=True) != 0: - return False - - self.load_config() - return True - - def console(self, tty="1"): - """ - Access the console of a container. - """ - - if not self.running: - return False - - if subprocess.call(["lxc-console", "-n", self.name, "-t", "%s" % tty, - "-P", self.get_config_path()], - universal_newlines=True) != 0: - return False - return True - - def get_cgroup_item(self, key): - """ - Returns the value for a given cgroup entry. - A list is returned when multiple values are set. - """ - value = _lxc.Container.get_cgroup_item(self, key) - - if value is False: - return False - else: - return value.rstrip("\n") - - def get_config_item(self, key): - """ - Returns the value for a given config key. - A list is returned when multiple values are set. - """ - value = _lxc.Container.get_config_item(self, key) - - if value is False: - return False - elif value.endswith("\n"): - return value.rstrip("\n").split("\n") - else: - return value - - def get_ips(self, timeout=60, interface=None, protocol=None): - """ - Returns the list of IP addresses for the container. - """ - - if not self.running: - return False - - ips = [] - - count = 0 - while count < timeout: - if count != 0: - time.sleep(1) - - base_cmd = ["lxc-attach", "-s", "NETWORK", "-n", self.name, "--", - "ip"] - - # Get IPv6 - if protocol in ("ipv6", None): - ip6_cmd = base_cmd + ["-6", "addr", "show", "scope", "global"] - if interface: - ip = subprocess.Popen(ip6_cmd + ["dev", interface], - stdout=subprocess.PIPE, - universal_newlines=True) - else: - ip = subprocess.Popen(ip6_cmd, stdout=subprocess.PIPE, - universal_newlines=True) - - ip.wait() - for line in ip.stdout.read().split("\n"): - fields = line.split() - if len(fields) > 2 and fields[0] == "inet6": - ips.append(fields[1].split('/')[0]) - - # Get IPv4 - if protocol in ("ipv4", None): - ip4_cmd = base_cmd + ["-4", "addr", "show", "scope", "global"] - if interface: - ip = subprocess.Popen(ip4_cmd + ["dev", interface], - stdout=subprocess.PIPE, - universal_newlines=True) - else: - ip = subprocess.Popen(ip4_cmd, stdout=subprocess.PIPE, - universal_newlines=True) - - ip.wait() - for line in ip.stdout.read().split("\n"): - fields = line.split() - if len(fields) > 2 and fields[0] == "inet": - ips.append(fields[1].split('/')[0]) - - if ips: - break - - count += 1 - - return ips - - def get_keys(self, key=None): - """ - Returns a list of valid sub-keys. - """ - if key: - value = _lxc.Container.get_keys(self, key) - else: - value = _lxc.Container.get_keys(self) - - if value is False: - return False - elif value.endswith("\n"): - return value.rstrip("\n").split("\n") - else: - return value - - def set_config_item(self, key, value): - """ - Set a config key to a provided value. - The value can be a list for the keys supporting multiple values. - """ - old_value = self.get_config_item(key) - - # Check if it's a list - def set_key(key, value): - self.clear_config_item(key) - if isinstance(value, list): - for entry in value: - if not _lxc.Container.set_config_item(self, key, entry): - return False - else: - _lxc.Container.set_config_item(self, key, value) - - set_key(key, value) - new_value = self.get_config_item(key) - - if (isinstance(value, str) and isinstance(new_value, str) and - value == new_value): - return True - elif (isinstance(value, list) and isinstance(new_value, list) and - set(value) == set(new_value)): - return True - elif (isinstance(value, str) and isinstance(new_value, list) and - set([value]) == set(new_value)): - return True - elif old_value: - set_key(key, old_value) - return False - else: - self.clear_config_item(key) - return False - - def wait(self, state, timeout=-1): - """ - Wait for the container to reach a given state or timeout. - """ - - if isinstance(state, str): - state = state.upper() - - return _lxc.Container.wait(self, state, timeout) - - -def list_containers(as_object=False, config_path=None): - """ - List the containers on the system. - """ - - if not config_path: - config_path = default_config_path - - containers = [] - for entry in glob.glob("%s/*/config" % config_path): - if as_object: - containers.append(Container(entry.split("/")[-2], config_path)) - else: - containers.append(entry.split("/")[-2]) - return containers -- 1.8.1.2 ------------------------------------------------------------------------------ Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the endpoint security space. For insight on selecting the right partner to tackle endpoint security challenges, access the full report. http://p.sf.net/sfu/symantec-dev2dev _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel