[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