[lxc-devel] [PATCH 1/3] python: Don't hardcode LXCPATH in python module
Serge Hallyn
serge.hallyn at ubuntu.com
Mon Mar 11 16:02:09 UTC 2013
Quoting Stéphane Graber (stgraber at ubuntu.com):
> Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hallyn at 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 <stgraber at 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 <stgraber at 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 at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel
More information about the lxc-devel
mailing list