[libvirt] [PATCH] virConnectListAllDomains (version 2)

Richard W.M. Jones rjones at redhat.com
Fri Aug 29 14:47:59 UTC 2008


Here's a second version of the patch which allows 'infos' to be NULL,
but doesn't yet include a Xen driver.

Rich.

-- 
Richard Jones, Emerging Technologies, Red Hat  http://et.redhat.com/~rjones
Read my OCaml programming blog: http://camltastic.blogspot.com/
Fedora now supports 64 OCaml packages (the OPEN alternative to F#)
http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora
-------------- next part --------------
Index: include/libvirt/libvirt.h.in
===================================================================
RCS file: /data/cvs/libvirt/include/libvirt/libvirt.h.in,v
retrieving revision 1.53
diff -u -r1.53 libvirt.h.in
--- include/libvirt/libvirt.h.in	27 Aug 2008 20:05:58 -0000	1.53
+++ include/libvirt/libvirt.h.in	29 Aug 2008 14:51:52 -0000
@@ -75,6 +75,24 @@
      VIR_DOMAIN_CRASHED = 6  /* the domain is crashed */
 } virDomainState;
 
+/* For virConnectListAllDomains. */
+#define VIR_DOMAIN_LIST_NOSTATE (1 << VIR_DOMAIN_NOSTATE)
+#define VIR_DOMAIN_LIST_RUNNING (1 << VIR_DOMAIN_RUNNING)
+#define VIR_DOMAIN_LIST_BLOCKED (1 << VIR_DOMAIN_BLOCKED)
+#define VIR_DOMAIN_LIST_PAUSED (1 << VIR_DOMAIN_PAUSED)
+#define VIR_DOMAIN_LIST_SHUTDOWN (1 << VIR_DOMAIN_SHUTDOWN)
+#define VIR_DOMAIN_LIST_SHUTOFF (1 << VIR_DOMAIN_SHUTOFF)
+#define VIR_DOMAIN_LIST_CRASHED (1 << VIR_DOMAIN_CRASHED)
+
+#define VIR_DOMAIN_LIST_ACTIVE (VIR_DOMAIN_LIST_NOSTATE |       \
+                                VIR_DOMAIN_LIST_RUNNING |       \
+                                VIR_DOMAIN_LIST_BLOCKED |       \
+                                VIR_DOMAIN_LIST_PAUSED |        \
+                                VIR_DOMAIN_LIST_SHUTDOWN |      \
+                                VIR_DOMAIN_LIST_CRASHED)
+#define VIR_DOMAIN_LIST_INACTIVE VIR_DOMAIN_LIST_SHUTOFF
+#define VIR_DOMAIN_LIST_ALL (VIR_DOMAIN_LIST_ACTIVE | VIR_DOMAIN_LIST_INACTIVE)
+
 /**
  * virDomainInfoPtr:
  *
@@ -417,6 +435,14 @@
 unsigned long long      virNodeGetFreeMemory    (virConnectPtr conn);
 
 /*
+ * New-style list-all-domains call.
+ */
+int                     virConnectListAllDomains(virConnectPtr conn,
+                                                 virDomainPtr **domains,
+                                                 virDomainInfo **infos,
+                                                 int stateflags);
+
+/*
  * Gather list of running domains
  */
 int                     virConnectListDomains   (virConnectPtr conn,
Index: qemud/remote.c
===================================================================
RCS file: /data/cvs/libvirt/qemud/remote.c,v
retrieving revision 1.39
diff -u -r1.39 remote.c
--- qemud/remote.c	27 Aug 2008 20:05:59 -0000	1.39
+++ qemud/remote.c	29 Aug 2008 14:51:55 -0000
@@ -1904,6 +1904,70 @@
 }
 
 static int
+remoteDispatchListAllDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
+                              struct qemud_client *client,
+                              remote_message_header *req,
+                              remote_list_all_domains_args *args,
+                              remote_list_all_domains_ret *ret)
+{
+    virDomainPtr *domains;
+    virDomainInfo *infos = NULL;
+    int i, nr;
+    int retcode = -2;
+
+    CHECK_CONN(client);
+
+    nr = virConnectListAllDomains (client->conn, &domains,
+                                   args->want_infos ? &infos : NULL,
+                                   args->stateflags);
+    if (nr == -1) return -1;
+
+    if (nr > REMOTE_DOMAIN_LIST_MAX || nr > REMOTE_DOMAIN_INFO_LIST_MAX) {
+        remoteDispatchSendError (client, req, VIR_ERR_RPC,
+                                 _("too many domains to return"));
+        goto done;
+    }
+
+    if (VIR_ALLOC_N (ret->doms.doms_val, nr) == -1) {
+        remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+        goto done;
+    }
+    ret->doms.doms_len = nr;
+
+    if (args->want_infos) {
+        if (VIR_ALLOC_N (ret->infos.infos_val, nr) == -1) {
+            remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL);
+            VIR_FREE (ret->doms.doms_val);
+            goto done;
+        }
+        ret->infos.infos_len = nr;
+    } else {
+        ret->infos.infos_val = NULL;
+        ret->infos.infos_len = 0;
+    }
+
+    for (i = 0; i < nr; ++i) {
+        make_nonnull_domain (&ret->doms.doms_val[i], domains[i]);
+        if (args->want_infos) {
+            ret->infos.infos_val[i].state = infos[i].state;
+            ret->infos.infos_val[i].max_mem = infos[i].maxMem;
+            ret->infos.infos_val[i].memory = infos[i].memory;
+            ret->infos.infos_val[i].nr_virt_cpu = infos[i].nrVirtCpu;
+            ret->infos.infos_val[i].cpu_time = infos[i].cpuTime;
+        }
+    }
+    retcode = 0;
+
+done:
+    for (i = 0; i < nr; ++i)
+        virDomainFree (domains[i]);
+    free (domains);
+    free (infos);
+
+    return retcode;
+}
+
+static int
 remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client,
                            remote_message_header *req,
Index: qemud/remote_protocol.x
===================================================================
RCS file: /data/cvs/libvirt/qemud/remote_protocol.x,v
retrieving revision 1.17
diff -u -r1.17 remote_protocol.x
--- qemud/remote_protocol.x	27 Aug 2008 20:05:59 -0000	1.17
+++ qemud/remote_protocol.x	29 Aug 2008 14:51:55 -0000
@@ -64,6 +64,12 @@
 /* Upper limit on lists of domain names. */
 const REMOTE_DOMAIN_NAME_LIST_MAX = 1024;
 
+/* Upper limit on lists of domain structures. */
+const REMOTE_DOMAIN_LIST_MAX = 1024;
+
+/* Upper limit on lists of virDomainInfo structures. */
+const REMOTE_DOMAIN_INFO_LIST_MAX = 1024;
+
 /* Upper limit on cpumap (bytes) passed to virDomainPinVcpu. */
 const REMOTE_CPUMAP_MAX = 256;
 
@@ -205,6 +211,15 @@
     remote_sched_param_value value;
 };
 
+/* virDomainInfo on the wire */
+struct remote_domain_info {
+    unsigned char state;
+    unsigned hyper max_mem;
+    unsigned hyper memory;
+    unsigned short nr_virt_cpu;
+    unsigned hyper cpu_time;
+};
+
 /*----- Calls. -----*/
 
 /* For each call we may have a 'remote_CALL_args' and 'remote_CALL_ret'
@@ -358,6 +373,16 @@
     opaque buffer<REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX>;
 };
 
+struct remote_list_all_domains_args {
+    int want_infos;
+    int stateflags;
+};
+
+struct remote_list_all_domains_ret {
+    remote_nonnull_domain doms<REMOTE_DOMAIN_LIST_MAX>;
+    remote_domain_info infos<REMOTE_DOMAIN_INFO_LIST_MAX>;
+};
+
 struct remote_list_domains_args {
     int maxids;
 };
@@ -455,6 +480,9 @@
 };
 
 struct remote_domain_get_info_ret {
+    /* remote_domain_info info; - but we have to maintain ABI compatibility
+     * so we cannot use the structure directly.
+     */
     unsigned char state;
     unsigned hyper max_mem;
     unsigned hyper memory;
@@ -1085,7 +1113,9 @@
     REMOTE_PROC_NODE_GET_FREE_MEMORY = 102,
 
     REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103,
-    REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104
+    REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104,
+
+    REMOTE_PROC_LIST_ALL_DOMAINS = 105
 };
 
 /* Custom RPC structure. */
Index: src/driver.h
===================================================================
RCS file: /data/cvs/libvirt/src/driver.h,v
retrieving revision 1.53
diff -u -r1.53 driver.h
--- src/driver.h	27 Aug 2008 20:05:59 -0000	1.53
+++ src/driver.h	29 Aug 2008 14:51:56 -0000
@@ -97,6 +97,11 @@
 typedef char *
         (*virDrvGetCapabilities) (virConnectPtr conn);
 typedef int
+        (*virDrvListAllDomains)		(virConnectPtr conn,
+                                         virDomainPtr **domains,
+                                         virDomainInfo **infos,
+                                         int stateflags);
+typedef int
         (*virDrvListDomains)		(virConnectPtr conn,
                                          int *ids,
                                          int maxids);
@@ -307,6 +312,7 @@
     virDrvGetMaxVcpus		getMaxVcpus;
     virDrvNodeGetInfo		nodeGetInfo;
     virDrvGetCapabilities		getCapabilities;
+    virDrvListAllDomains	listAllDomains;
     virDrvListDomains		listDomains;
     virDrvNumOfDomains		numOfDomains;
     virDrvDomainCreateLinux		domainCreateLinux;
Index: src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.154
diff -u -r1.154 libvirt.c
--- src/libvirt.c	27 Aug 2008 20:05:59 -0000	1.154
+++ src/libvirt.c	29 Aug 2008 14:51:59 -0000
@@ -1144,6 +1144,207 @@
     return -1;
 }
 
+static int emulateListAllDomains (virConnectPtr conn, virDomainPtr **domains, virDomainInfo **infos, int stateflags);
+
+/**
+ * virConnectListAllDomains:
+ * @conn: pointer to the hypervisor connection
+ * @domains: pointer to returned array of domain pointers (must not be NULL)
+ * @infos: pointer to returned array of virDomainInfo structures (may be NULL)
+ * @stateflags: state of domains of interest
+ *
+ * This call returns the list of all domains, active or inactive,
+ * and their virDomainInfo structures.
+ *
+ * This call is usually more efficient than using the old method
+ * of calling virConnectListDomains and virConnectListDefinedDomains
+ * and then loading each domain and its info.  This call is supported
+ * for all hypervisor types.  (If the backend driver doesn't support it
+ * directly, then the call is emulated for you).
+ *
+ * @stateflags allows only the domains of interest to be
+ * returned.  Common values are:
+ * VIR_DOMAIN_LIST_ACTIVE to return running domains.
+ * VIR_DOMAIN_LIST_INACTIVE to return defined but not running domains.
+ * VIR_DOMAIN_LIST_ALL to return all domains.
+ * And VIR_DOMAIN_LIST_NOSTATE (etc) to return domains in particular
+ * states.  You may logically 'or' together several flags.
+ *
+ * Returns the number of domains in the @domains array, or -1 in
+ * case of error.
+ *
+ * If there was no error then the caller must free each domain
+ * with virDomainFree, free the array of @domains pointers,
+ * and free the array of @infos structures.
+ */
+int
+virConnectListAllDomains(virConnectPtr conn,
+                         virDomainPtr **domains,
+                         virDomainInfo **infos,
+                         int stateflags)
+{
+    DEBUG("conn=%p, domains=%p, infos=%p, stateflags=%d",
+          conn, domains, infos, stateflags);
+
+    if (!VIR_IS_CONNECT (conn)) {
+        virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return -1;
+    }
+
+    /* Nothing can match an empty flag set.  Error?  Possibly, but
+     * avoid having to special-case the calling code.
+     */
+    if (stateflags == 0) {
+        *domains = NULL;
+        if (infos)
+            *infos = NULL;
+        return 0;
+    }
+
+    if (domains == NULL) {
+        virLibConnError (conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return -1;
+    }
+
+    /* Supported by this driver? */
+    if (conn->driver->listAllDomains)
+        return conn->driver->listAllDomains (conn, domains, infos, stateflags);
+    else
+        /* Not supported, so emulate it. */
+        return emulateListAllDomains (conn, domains, infos, stateflags);
+}
+
+static int
+emulateListAllDomains (virConnectPtr conn,
+                       virDomainPtr **domains,
+                       virDomainInfo **infos,
+                       int stateflags)
+{
+    int n_active, n_inactive;
+    int i, j, ret = -1;
+    int *ids = NULL;
+    char **names = NULL;
+    virDomainPtr tdom = NULL;
+    virDomainInfo tinfo;
+
+    n_active =
+        (stateflags & VIR_DOMAIN_LIST_ACTIVE) ?
+        virConnectNumOfDomains (conn) :
+        0;
+    if (n_active == -1) return -1;
+    n_inactive =
+        (stateflags & VIR_DOMAIN_LIST_INACTIVE) ?
+        virConnectNumOfDefinedDomains (conn) :
+        0;
+    if (n_inactive == -1) return -1;
+
+    /* This over-allocates the return arrays, but that doesn't
+     * matter.
+     */
+    if (VIR_ALLOC_N (*domains, n_active + n_inactive) == -1) {
+        virLibConnError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
+        return -1;
+    }
+    if (infos) {
+        if (VIR_ALLOC_N (*infos, n_active + n_inactive) == -1) {
+            VIR_FREE (*domains);
+            virLibConnError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
+            return -1;
+        }
+    }
+
+    /* 'j' is the next free position in the return array. */
+    j = 0;
+
+    if (n_active) {
+        if (VIR_ALLOC_N (ids, n_active) == -1) {
+            virLibConnError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
+            goto done;
+        }
+
+        n_active = virConnectListDomains (conn, ids, n_active);
+        if (n_active == -1) goto done;
+
+        for (i = 0; i < n_active; ++i) {
+            /* Note: domains are allowed to disappear unexpectedly. */
+            tdom = virDomainLookupByID (conn, ids[i]);
+            if (!tdom) continue;
+
+            if (virDomainGetInfo (tdom, &tinfo) == -1) {
+                virDomainFree (tdom);
+                continue;
+            }
+
+            if (tinfo.state & stateflags) {
+                (*domains)[j] = tdom;
+                tdom = NULL;
+                if (infos)
+                    (*infos)[j] = tinfo;
+                j++;
+            } else
+                virDomainFree (tdom);
+        }
+    }
+
+    if (n_inactive) {
+        if (VIR_ALLOC_N (names, n_inactive) == -1) {
+            virLibConnError (conn, VIR_ERR_NO_MEMORY, __FUNCTION__);
+            goto done;
+        }
+
+        n_inactive = virConnectListDefinedDomains (conn, names, n_inactive);
+        if (n_inactive == -1) goto done;
+
+        for (i = 0; i < n_inactive; ++i) {
+            /* Note: domains are allowed to disappear unexpectedly. */
+            tdom = virDomainLookupByName (conn, names[i]);
+            if (!tdom) continue;
+
+            if (virDomainGetInfo (tdom, &tinfo) == -1) {
+                virDomainFree (tdom);
+                continue;
+            }
+
+            /* By the logic above, if we are here at all then the
+             * caller must have requested inactive domains, so
+             * unconditionally add it to the list.  Don't need to
+             * check the state flag.
+             */
+            (*domains)[j] = tdom;
+            tdom = NULL;
+            if (infos)
+                (*infos)[j] = tinfo;
+            j++;
+        }
+    }
+
+    /* Return the number of domains in the resulting list. */
+    ret = j;
+
+done:
+    VIR_FREE (ids);
+    VIR_FREE (names);
+
+    if (ret == -1) {
+        /* Error path: Free up any domains which we referenced, and
+         * also the domains & infos arrays.
+         */
+        for (i = 0; i < j; ++i)
+            virDomainFree ((*domains)[i]);
+
+        VIR_FREE (*domains);
+
+        if (infos)
+            VIR_FREE (*infos);
+
+        /* Free up the temporary domain. */
+        if (tdom)
+            virDomainFree (tdom);
+    }
+
+    return ret;
+}
+
 /**
  * virConnectListDomains:
  * @conn: pointer to the hypervisor connection
Index: src/libvirt_sym.version
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt_sym.version,v
retrieving revision 1.44
diff -u -r1.44 libvirt_sym.version
--- src/libvirt_sym.version	27 Aug 2008 20:05:59 -0000	1.44
+++ src/libvirt_sym.version	29 Aug 2008 14:51:59 -0000
@@ -12,6 +12,7 @@
 	virConnectGetHostname;
 	virConnectGetURI;
 	virDomainGetConnect;
+	virConnectListAllDomains;
 	virConnectListDomains;
 	virConnectNumOfDomains;
         virDomainCreate;
Index: src/lxc_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/lxc_driver.c,v
retrieving revision 1.25
diff -u -r1.25 lxc_driver.c
--- src/lxc_driver.c	27 Aug 2008 11:42:52 -0000	1.25
+++ src/lxc_driver.c	29 Aug 2008 14:52:00 -0000
@@ -1127,6 +1127,7 @@
     NULL, /* getMaxVcpus */
     NULL, /* nodeGetInfo */
     NULL, /* getCapabilities */
+    NULL, /* listAllDomains */
     lxcListDomains, /* listDomains */
     lxcNumDomains, /* numOfDomains */
     lxcDomainCreateAndStart, /* domainCreateLinux */
Index: src/openvz_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_driver.c,v
retrieving revision 1.44
diff -u -r1.44 openvz_driver.c
--- src/openvz_driver.c	27 Aug 2008 11:19:45 -0000	1.44
+++ src/openvz_driver.c	29 Aug 2008 14:52:01 -0000
@@ -930,6 +930,7 @@
     openvzGetMaxVCPUs, /* getMaxVcpus */
     openvzGetNodeInfo, /* nodeGetInfo */
     NULL, /* getCapabilities */
+    NULL, /* listAllDomains */
     openvzListDomains, /* listDomains */
     openvzNumDomains, /* numOfDomains */
     openvzDomainCreateLinux, /* domainCreateLinux */
Index: src/qemu_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_driver.c,v
retrieving revision 1.113
diff -u -r1.113 qemu_driver.c
--- src/qemu_driver.c	29 Aug 2008 07:11:15 -0000	1.113
+++ src/qemu_driver.c	29 Aug 2008 14:52:03 -0000
@@ -3872,6 +3872,7 @@
     qemudGetMaxVCPUs, /* getMaxVcpus */
     qemudGetNodeInfo, /* nodeGetInfo */
     qemudGetCapabilities, /* getCapabilities */
+    NULL, /* listAllDomains */
     qemudListDomains, /* listDomains */
     qemudNumDomains, /* numOfDomains */
     qemudDomainCreate, /* domainCreateLinux */
Index: src/remote_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/remote_internal.c,v
retrieving revision 1.83
diff -u -r1.83 remote_internal.c
--- src/remote_internal.c	29 Aug 2008 07:11:15 -0000	1.83
+++ src/remote_internal.c	29 Aug 2008 14:52:07 -0000
@@ -1339,6 +1339,81 @@
     return ret.freeMem;
 }
 
+static int
+remoteListAllDomains (virConnectPtr conn,
+                      virDomainPtr **domains,
+                      virDomainInfo **infos,
+                      int stateflags)
+{
+    int want_infos;
+    int i, nr;
+    remote_list_all_domains_args args;
+    remote_list_all_domains_ret ret;
+    GET_PRIVATE (conn, -1);
+
+    args.want_infos = want_infos = infos != NULL;
+    args.stateflags = stateflags;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_LIST_ALL_DOMAINS,
+              (xdrproc_t) xdr_remote_list_all_domains_args, (char *) &args,
+              (xdrproc_t) xdr_remote_list_all_domains_ret, (char *) &ret) == -1)
+        return -1;
+
+    nr = ret.doms.doms_len;
+    if (want_infos) {
+        if (ret.infos.infos_len != nr) {
+            errorf (conn, VIR_ERR_RPC,
+                    _("length of domains and infos doesn't match: %d != %d"),
+                    ret.infos.infos_len, ret.doms.doms_len);
+            xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
+            return -1;
+        }
+    } else {
+        /* If I didn't ask for the infos, don't give me any! */
+        if (ret.infos.infos_len != 0) {
+            errorf (conn, VIR_ERR_RPC,
+                    _("length of infos should be zero, but is %d"),
+                    ret.infos.infos_len);
+            xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
+            return -1;
+        }
+    }
+    if (nr > REMOTE_DOMAIN_LIST_MAX || nr > REMOTE_DOMAIN_INFO_LIST_MAX) {
+        errorf (conn, VIR_ERR_RPC,
+                _("length of domains list too long: %d > %d or > %d"),
+                nr, REMOTE_DOMAIN_LIST_MAX, REMOTE_DOMAIN_INFO_LIST_MAX);
+        xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
+        return -1;
+    }
+
+    if (VIR_ALLOC_N (*domains, nr) == -1) {
+        errorf (conn, VIR_ERR_NO_MEMORY, _("out of memory"));
+        xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
+        return -1;
+    }
+    if (want_infos && VIR_ALLOC_N (*infos, nr) == -1) {
+        xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
+        VIR_FREE (*domains);
+        errorf (conn, VIR_ERR_NO_MEMORY, _("out of memory"));
+        return -1;
+    }
+
+    for (i = 0; i < nr; ++i) {
+        (*domains)[i] = get_nonnull_domain (conn, ret.doms.doms_val[i]);
+        if (want_infos) {
+            (*infos)[i].state = ret.infos.infos_val[i].state;
+            (*infos)[i].maxMem = ret.infos.infos_val[i].max_mem;
+            (*infos)[i].memory = ret.infos.infos_val[i].memory;
+            (*infos)[i].nrVirtCpu = ret.infos.infos_val[i].nr_virt_cpu;
+            (*infos)[i].cpuTime = ret.infos.infos_val[i].cpu_time;
+        }
+    }
+
+    xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
+
+    return nr;
+}
 
 static int
 remoteListDomains (virConnectPtr conn, int *ids, int maxids)
@@ -4830,6 +4905,7 @@
         .getMaxVcpus = remoteGetMaxVcpus,
         .nodeGetInfo = remoteNodeGetInfo,
     .getCapabilities = remoteGetCapabilities,
+    .listAllDomains = remoteListAllDomains,
     .listDomains = remoteListDomains,
     .numOfDomains = remoteNumOfDomains,
     .domainCreateLinux = remoteDomainCreateLinux,
Index: src/test.c
===================================================================
RCS file: /data/cvs/libvirt/src/test.c,v
retrieving revision 1.84
diff -u -r1.84 test.c
--- src/test.c	20 Aug 2008 20:48:36 -0000	1.84
+++ src/test.c	29 Aug 2008 14:52:08 -0000
@@ -1550,6 +1550,7 @@
     testGetMaxVCPUs, /* getMaxVcpus */
     testNodeGetInfo, /* nodeGetInfo */
     testGetCapabilities, /* getCapabilities */
+    NULL, /* listAllDomains */
     testListDomains, /* listDomains */
     testNumOfDomains, /* numOfDomains */
     testDomainCreateLinux, /* domainCreateLinux */
Index: src/virsh.c
===================================================================
RCS file: /data/cvs/libvirt/src/virsh.c,v
retrieving revision 1.163
diff -u -r1.163 virsh.c
--- src/virsh.c	27 Aug 2008 20:05:59 -0000	1.163
+++ src/virsh.c	29 Aug 2008 14:52:12 -0000
@@ -308,17 +308,6 @@
 static char *_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line);
 #define vshStrdup(_ctl, _s)    _vshStrdup(_ctl, _s, __FILE__, __LINE__)
 
-
-static int idsorter(const void *a, const void *b) {
-  const int *ia = (const int *)a;
-  const int *ib = (const int *)b;
-
-  if (*ia > *ib)
-    return 1;
-  else if (*ia < *ib)
-    return -1;
-  return 0;
-}
 static int namesorter(const void *a, const void *b) {
   const char **sa = (const char**)a;
   const char **sb = (const char**)b;
@@ -326,7 +315,6 @@
   return strcasecmp(*sa, *sb);
 }
 
-
 /* ---------------
  * Commands
  * ---------------
@@ -559,104 +547,91 @@
 };
 
 
+struct listedDom {
+    int id;                     /* INT_MAX if inactive. */
+    const char *name;
+    const char *state_str;
+};
+
+static int
+sortListedDoms (const void *a, const void *b)
+{
+    struct listedDom *sa = (struct listedDom *) a;
+    struct listedDom *sb = (struct listedDom *) b;
+
+    if (sa->id == sb->id) {
+        return strcmp (sa->name, sb->name);
+    } else {
+        return sa->id - sb->id;
+    }
+}
+
 static int
 cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
 {
     int inactive = vshCommandOptBool(cmd, "inactive");
     int all = vshCommandOptBool(cmd, "all");
-    int active = !inactive || all ? 1 : 0;
-    int *ids = NULL, maxid = 0, i;
-    char **names = NULL;
-    int maxname = 0;
-    inactive |= all;
+    virDomainPtr *domains;
+    virDomainInfo *infos;
+    int stateflags, i, nr, id;
+    struct listedDom *doms;
+
+    if (all)
+        stateflags = VIR_DOMAIN_LIST_ALL;
+    else if (inactive)
+        stateflags = VIR_DOMAIN_LIST_INACTIVE;
+    else
+        stateflags = VIR_DOMAIN_LIST_ACTIVE;
 
     if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
         return FALSE;
 
-    if (active) {
-        maxid = virConnectNumOfDomains(ctl->conn);
-        if (maxid < 0) {
-            vshError(ctl, FALSE, "%s", _("Failed to list active domains"));
-            return FALSE;
-        }
-        if (maxid) {
-            ids = vshMalloc(ctl, sizeof(int) * maxid);
+    nr = virConnectListAllDomains (ctl->conn, &domains, &infos, stateflags);
+    if (nr == -1) {
+        vshError(ctl, FALSE, "%s", _("Failed to list domains"));
+        return FALSE;
+    }
 
-            if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) {
-                vshError(ctl, FALSE, "%s", _("Failed to list active domains"));
-                free(ids);
-                return FALSE;
-            }
+    /* Not quite so simple: The previous version showed domains
+     * sorted by ID, followed by inactive domains sorted by name.
+     * We must emulate this by pulling out the fields we need from
+     * the domains and infos structures and then sorting it.
+     */
+    doms = vshMalloc (ctl, sizeof (struct listedDom) * nr);
+    for (i = 0; i < nr; ++i) {
+        id = virDomainGetID (domains[i]);
+        if (id == -1) id = INT_MAX;
 
-            qsort(&ids[0], maxid, sizeof(int), idsorter);
-        }
+        doms[i].id = id;
+        doms[i].name = virDomainGetName (domains[i]);
+        doms[i].state_str = N_(vshDomainStateToString (infos[i].state));
     }
-    if (inactive) {
-        maxname = virConnectNumOfDefinedDomains(ctl->conn);
-        if (maxname < 0) {
-            vshError(ctl, FALSE, "%s", _("Failed to list inactive domains"));
-            free(ids);
-            return FALSE;
-        }
-        if (maxname) {
-            names = vshMalloc(ctl, sizeof(char *) * maxname);
 
-            if ((maxname = virConnectListDefinedDomains(ctl->conn, names, maxname)) < 0) {
-                vshError(ctl, FALSE, "%s", _("Failed to list inactive domains"));
-                free(ids);
-                free(names);
-                return FALSE;
-            }
+    qsort (doms, nr, sizeof (struct listedDom), sortListedDoms);
 
-            qsort(&names[0], maxname, sizeof(char*), namesorter);
-        }
-    }
     vshPrintExtra(ctl, "%3s %-20s %s\n", _("Id"), _("Name"), _("State"));
     vshPrintExtra(ctl, "----------------------------------\n");
 
-    for (i = 0; i < maxid; i++) {
-        virDomainInfo info;
-        virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]);
-        const char *state;
-
-        /* this kind of work with domains is not atomic operation */
-        if (!dom)
-            continue;
-
-        if (virDomainGetInfo(dom, &info) < 0)
-            state = _("no state");
+    for (i = 0; i < nr; ++i) {
+        if (doms[i].id != INT_MAX)
+            vshPrint(ctl, "%3d %-20s %s\n",
+                     doms[i].id,
+                     doms[i].name,
+                     doms[i].state_str);
         else
-            state = N_(vshDomainStateToString(info.state));
-
-        vshPrint(ctl, "%3d %-20s %s\n",
-                 virDomainGetID(dom),
-                 virDomainGetName(dom),
-                 state);
-        virDomainFree(dom);
+            vshPrint(ctl, "%3s %-20s %s\n",
+                     "-",
+                     doms[i].name,
+                     doms[i].state_str);
     }
-    for (i = 0; i < maxname; i++) {
-        virDomainInfo info;
-        virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]);
-        const char *state;
-
-        /* this kind of work with domains is not atomic operation */
-        if (!dom) {
-            free(names[i]);
-            continue;
-        }
 
-        if (virDomainGetInfo(dom, &info) < 0)
-            state = _("no state");
-        else
-            state = N_(vshDomainStateToString(info.state));
+    for (i = 0; i < nr; ++i)
+        virDomainFree (domains[i]);
+    free (domains);
+    free (infos);
 
-        vshPrint(ctl, "%3s %-20s %s\n", "-", names[i], state);
+    free (doms);
 
-        virDomainFree(dom);
-        free(names[i]);
-    }
-    free(ids);
-    free(names);
     return TRUE;
 }
 


More information about the libvir-list mailing list