[lxc-devel] [PATCH] python3: Add list_containers to C API

Stéphane Graber stgraber at ubuntu.com
Tue Nov 26 21:41:28 UTC 2013


This adds a new list_containers function to the python3 binding and a
matching override in __init__.py that adds the as_object parameter.

This should be compatible to the previous pure python implementation
with the advantage of also listing active non-defined containers (fixing
github issue #68).

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 src/python-lxc/lxc.c           | 71 ++++++++++++++++++++++++++++++++++++++++--
 src/python-lxc/lxc/__init__.py | 22 +++++++------
 2 files changed, 80 insertions(+), 13 deletions(-)

diff --git a/src/python-lxc/lxc.c b/src/python-lxc/lxc.c
index e42ed35..9e6f9d9 100644
--- a/src/python-lxc/lxc.c
+++ b/src/python-lxc/lxc.c
@@ -170,6 +170,65 @@ LXC_get_version(PyObject *self, PyObject *args)
     return PyUnicode_FromString(lxc_get_version());
 }
 
+static PyObject *
+LXC_list_containers(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    char **names = NULL;
+    PyObject *list = NULL;
+    int list_count = 0;
+
+    int list_active = 1;
+    int list_defined = 1;
+
+    PyObject *py_list_active = NULL;
+    PyObject *py_list_defined = NULL;
+
+    char* config_path = NULL;
+
+    int i = 0;
+    PyObject *vargs = NULL;
+    static char *kwlist[] = {"active", "defined", "config_path", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOs", kwlist,
+                                      &py_list_active,
+                                      &py_list_defined,
+                                      &config_path, &vargs))
+        return NULL;
+
+    /* We default to listing everything */
+    if (py_list_active && py_list_active != Py_True) {
+        list_active = 0;
+    }
+
+    if (py_list_defined && py_list_defined != Py_True) {
+        list_defined = 0;
+    }
+
+    /* Call the right API function based on filters */
+    if (list_active == 1 && list_defined == 1)
+        list_count = list_all_containers(config_path, &names, NULL);
+    else if (list_active == 1)
+        list_count = list_active_containers(config_path, &names, NULL);
+    else if (list_defined == 1)
+        list_count = list_defined_containers(config_path, &names, NULL);
+
+    /* Handle failure */
+    if (list_count < 0) {
+        PyErr_SetString(PyExc_ValueError, "failure to list containers");
+        return NULL;
+    }
+
+    /* Generate the tuple */
+    list = PyTuple_New(list_count);
+    for (i = 0; i < list_count; i++) {
+        PyTuple_SET_ITEM(list, i, PyUnicode_FromString(names[i]));
+        free(names[i]);
+    }
+    free(names);
+
+    return list;
+}
+
 // Container properties
 static PyObject *
 Container_config_file_name(Container *self, void *closure)
@@ -1219,15 +1278,21 @@ PyVarObject_HEAD_INIT(NULL, 0)
 
 static PyMethodDef LXC_methods[] = {
     {"attach_run_shell", (PyCFunction)LXC_attach_run_shell, METH_O,
-     "Starts up a shell when attaching, to use as the run parameter for attach or attach_wait"},
+     "Starts up a shell when attaching, to use as the run parameter for "
+     "attach or attach_wait"},
     {"attach_run_command", (PyCFunction)LXC_attach_run_command, METH_O,
-     "Runs a command when attaching, to use as the run parameter for attach or attach_wait"},
+     "Runs a command when attaching, to use as the run parameter for attach "
+     "or attach_wait"},
     {"arch_to_personality", (PyCFunction)LXC_arch_to_personality, METH_O,
      "Returns the process personality of the corresponding architecture"},
-    {"get_default_config_path", (PyCFunction)LXC_get_default_config_path, METH_NOARGS,
+    {"get_default_config_path", (PyCFunction)LXC_get_default_config_path,
+     METH_NOARGS,
      "Returns the current LXC config path"},
     {"get_version", (PyCFunction)LXC_get_version, METH_NOARGS,
      "Returns the current LXC library version"},
+    {"list_containers", (PyCFunction)LXC_list_containers,
+     METH_VARARGS|METH_KEYWORDS,
+     "Returns a list of container names or objects"},
     {NULL, NULL, 0, NULL}
 };
 
diff --git a/src/python-lxc/lxc/__init__.py b/src/python-lxc/lxc/__init__.py
index 8ae7852..e0d4b51 100644
--- a/src/python-lxc/lxc/__init__.py
+++ b/src/python-lxc/lxc/__init__.py
@@ -417,21 +417,23 @@ class Container(_lxc.Container):
         return _lxc.Container.wait(self, state, timeout)
 
 
-def list_containers(as_object=False, config_path=None):
+def list_containers(active=True, defined=True,
+                    as_object=False, config_path=None):
     """
         List the containers on the system.
     """
 
-    if not config_path:
-        config_path = default_config_path
+    if config_path:
+        entries = _lxc.list_containers(active=active, defined=defined,
+                                       config_path=config_path)
+    else:
+        entries = _lxc.list_containers(active=active, defined=defined)
+
+    if as_object:
+        return tuple([Container(name, config_path) for name in entries])
+    else:
+        return entries
 
-    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
 
 def attach_run_command(cmd):
     """
-- 
1.8.4.4





More information about the lxc-devel mailing list