Two new commands are defined: list_defined_containers() and
list_active_containers().  Both take an lxcpath (NULL means
use the default lxcpath) and return the number of containers
found.  If a lxc_container ** is passed in, then an array of
lxc_container's is returned, one for each container found.
The caller must then lxc_container_put() each container and
free the array, as shown in the new list testcase.

Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
---
 src/lxc/lxccontainer.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/lxccontainer.h |  19 ++++++
 src/tests/Makefile.am  |   6 +-
 src/tests/list.c       |  57 ++++++++++++++++++
 4 files changed, 235 insertions(+), 2 deletions(-)
 create mode 100644 src/tests/list.c

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 13ed4d2..5a0edce 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2744,3 +2744,158 @@ int lxc_get_wait_states(const char **states)
                        states[i] = lxc_state2str(i);
        return MAX_STATE;
 }
+
+
+bool add_to_clist(struct lxc_container ***list, struct lxc_container *c, int 
pos)
+{
+       struct lxc_container **newlist = realloc(*list, pos * sizeof(struct 
lxc_container *));
+       if (!newlist) {
+               free(*list);
+               *list = NULL;
+               ERROR("Out of memory");
+               return false;
+       }
+
+       *list = newlist;
+       newlist[pos-1] = c;
+       return true;
+}
+
+int list_defined_containers(const char *lxcpath, struct lxc_container ***cret)
+{
+       DIR *dir;
+       int nfound = 0;
+       struct dirent dirent, *direntp;
+
+       if (!lxcpath)
+               lxcpath = default_lxc_path();
+
+       process_lock();
+       dir = opendir(lxcpath);
+       process_unlock();
+
+       if (!dir) {
+               SYSERROR("opendir on lxcpath");
+               return -1;
+       }
+
+       if (cret)
+               *cret = NULL;
+
+       while (!readdir_r(dir, &dirent, &direntp)) {
+               if (!direntp)
+                       break;
+               if (!strcmp(direntp->d_name, "."))
+                       continue;
+               if (!strcmp(direntp->d_name, ".."))
+                       continue;
+
+               struct lxc_container *c = lxc_container_new(direntp->d_name, 
lxcpath);
+               if (!c)
+                       continue;
+               if (!lxcapi_is_defined(c)) {
+                       lxc_container_put(c);
+                       continue;
+               }
+
+               nfound++;
+
+               if (cret) {
+                       if (!add_to_clist(cret, c, nfound))
+                               goto free_bad;
+               } else {
+                       lxc_container_put(c);
+               }
+       }
+
+       process_lock();
+       closedir(dir);
+       process_unlock();
+       return nfound;
+
+free_bad:
+       if (cret && *cret) {
+               while (--nfound >= 0)
+                       lxc_container_put((*cret)[nfound]);
+               free(*cret);
+       }
+       process_lock();
+       closedir(dir);
+       process_unlock();
+       return -1;
+}
+
+int list_active_containers(const char *lxcpath, struct lxc_container ***cret)
+{
+       int nfound = 0;
+       int lxcpath_len;
+       char *line = NULL;
+       size_t len = 0;
+       struct lxc_container *c;
+
+       if (!lxcpath)
+               lxcpath = default_lxc_path();
+       lxcpath_len = strlen(lxcpath);
+       if (cret)
+               *cret = NULL;
+       process_lock();
+       FILE *f = fopen("/proc/net/unix", "r");
+       process_unlock();
+       if (!f)
+               return -1;
+
+       while (getline(&line, &len, f) != -1) {
+               char *p = rindex(line, ' '), *p2;
+               if (!p)
+                       continue;
+               p++;
+               if (*p != 0x40)
+                       continue;
+               p++;
+               if (strncmp(p, lxcpath, lxcpath_len) != 0)
+                       continue;
+               p += lxcpath_len;
+               while (*p == '/')
+                       p++;
+               // Now p is the start of lxc_name
+               p2 = index(p, '/');
+               if (!p2 || strncmp(p2, "/command", 8) != 0)
+                       continue;
+               *p2 = '\0';
+               c = lxc_container_new(p, lxcpath);
+               if (!c)
+                       continue;
+               
+               /* 
+                * If this is an anonymous container, then is_defined *can*
+                * return false.  So we don't do that check.  Count on the
+                * fact that the command socket exists.
+                */
+
+               nfound++;
+
+               if (cret) {
+                       if (!add_to_clist(cret, c, nfound))
+                               goto free_bad;
+               } else {
+                       lxc_container_put(c);
+               }
+
+       }
+
+       process_lock();
+       fclose(f);
+       process_unlock();
+       return nfound;
+
+free_bad:
+       if (cret && *cret) {
+               while (--nfound >= 0)
+                       lxc_container_put((*cret)[nfound]);
+               free(*cret);
+       }
+       process_lock();
+       fclose(f);
+       process_unlock();
+       return -1;
+}
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 20ab8e8..691e7d9 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -248,6 +248,25 @@ const char *lxc_get_default_lvm_vg(void);
 const char *lxc_get_default_zfs_root(void);
 const char *lxc_get_version(void);
 
+/*
+ * Get a list of defined containers in a lxcpath.
+ * @lxcpath: lxcpath under which to look.
+ * @cret: if not null, then a list of lxc_containers will be returned here.
+ *
+ * Returns the number of containers found, or -1 on error.
+ */
+int list_defined_containers(const char *lxcpath, struct lxc_container ***cret);
+
+/*
+ * Get a list of active containers in a lxcpath.  Note that some of these
+ * containers may not be "defined".
+ * @lxcpath: lxcpath under which to look
+ * @cret: if not null, then a list of lxc_containers will be returned here.
+ *
+ * Returns the number of containers found, or -1 on error.
+ */
+int list_active_containers(const char *lxcpath, struct lxc_container ***cret);
+
 #if 0
 char ** lxc_get_valid_keys();
 char ** lxc_get_valid_values(char *key);
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 1814c4b..5fce195 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -21,6 +21,7 @@ lxc_test_snapshot_SOURCES = snapshot.c
 lxc_test_concurrent_SOURCES = concurrent.c
 lxc_test_may_control_SOURCES = may_control.c
 lxc_test_reboot_SOURCES = reboot.c
+lxc_test_list_SOURCES = list.c
 
 AM_CFLAGS=-I$(top_srcdir)/src \
        -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
@@ -34,7 +35,7 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests 
lxc-test-startone \
        lxc-test-shutdowntest lxc-test-get_item lxc-test-getkeys 
lxc-test-lxcpath \
        lxc-test-cgpath lxc-test-clonetest lxc-test-console lxc-usernic-test \
        lxc-test-snapshot lxc-test-concurrent lxc-test-may-control \
-       lxc-test-reboot
+       lxc-test-reboot lxc-test-list
 
 bin_SCRIPTS = lxc-test-usernic
 
@@ -61,4 +62,5 @@ EXTRA_DIST = \
        lxc-test-usernic \
        snapshot.c \
        concurrent.c \
-       may_control.c
+       may_control.c \
+       list.c
diff --git a/src/tests/list.c b/src/tests/list.c
new file mode 100644
index 0000000..01018eb
--- /dev/null
+++ b/src/tests/list.c
@@ -0,0 +1,57 @@
+/* list.c
+ *
+ * Copyright © 2013 Canonical, Inc
+ * Author: Serge Hallyn <serge.hal...@ubuntu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <lxc/lxccontainer.h>
+
+int main(int argc, char *argv[])
+{
+       char *lxcpath = NULL;
+       struct lxc_container **clist;
+       int n, n2;
+
+       if (argc > 1)
+               lxcpath = argv[1];
+
+       n = list_defined_containers(lxcpath, NULL);
+       printf("Found %d defined containers\n", n);
+       n2 = list_defined_containers(lxcpath, &clist);
+       if (n2 != n)
+               printf("Warning: first call returned %d, second %d\n", n, n2);
+       for (n=0; n<n2; n++) {
+               struct lxc_container *c = clist[n];
+               printf("Found defined container %s\n", c->name);
+               lxc_container_put(c);
+       }
+       free(clist);
+
+       n = list_active_containers(lxcpath, NULL);
+       printf("Found %d active containers\n", n);
+       n2 = list_active_containers(lxcpath, &clist);
+       if (n2 != n)
+               printf("Warning: first call returned %d, second %d\n", n, n2);
+       for (n=0; n<n2; n++) {
+               printf("Found active container %s\n", clist[n]->name);
+               lxc_container_put(clist[n]);
+       }
+       free(clist);
+
+       exit(0);
+}
-- 
1.8.1.2


------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to