Quoting Stéphane Graber (stgra...@ubuntu.com): > Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hal...@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 ------------------------------------------------------------------------------ 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