[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