[libvirt] [PATCH] virConnectListAllDomains (version 3, still no Xen)
Richard W.M. Jones
rjones at redhat.com
Wed Sep 3 15:58:17 UTC 2008
This is a third version of the virConnectListAllDomains patch. The
API is now slightly different from previous proposals. We only allow
filtering on All/Active/Inactive, and not by a long list of
fine-grained states. The reason is twofold: (1) a simpler
implementation and (2) doubtful that anyone would actually use the
fine-grained filtering feature.
The new API is shown below.
I have tested this out with mlvirsh and virt-top and of course in the
remote case there is a substantial saving in terms of round-trip
times, although it's hard to precisely measure what the difference is
when I've got only a couple of guests running.
There is still no Xen-specific implementation, but note that in the
remote case you get some of the benefit anyway.
Rich.
----------------------------------------------------------------------
/**
* 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
* @flags: other flags (always 0)
*
* 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. Callers must pass one of:
* 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,
* 0 to return no domains.
*
* @flags may be used in the future. Always pass 0 for this parameter.
*
* If there is no error then @domains will be updated to point to an
* array of virDomainPtr.
*
* If there is no error and @infos is not NULL, then @infos will be
* updated to point to an array of virDomainInfo structures, with
* the same length as the array of domains.
*
* 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 if necessary free the array of @infos structures.
*/
int
virConnectListAllDomains(virConnectPtr conn,
virDomainPtr **domains,
virDomainInfo **infos,
unsigned long stateflags,
unsigned long flags);
----------------------------------------------------------------------
--
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 3 Sep 2008 15:43:56 -0000
@@ -75,6 +75,11 @@
VIR_DOMAIN_CRASHED = 6 /* the domain is crashed */
} virDomainState;
+/* For virConnectListAllDomains. */
+#define VIR_DOMAIN_LIST_ACTIVE 1
+#define VIR_DOMAIN_LIST_INACTIVE 2
+#define VIR_DOMAIN_LIST_ALL (VIR_DOMAIN_LIST_ACTIVE | VIR_DOMAIN_LIST_INACTIVE)
+
/**
* virDomainInfoPtr:
*
@@ -417,6 +422,15 @@
unsigned long long virNodeGetFreeMemory (virConnectPtr conn);
/*
+ * New-style list-all-domains call.
+ */
+int virConnectListAllDomains(virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags);
+
+/*
* 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 3 Sep 2008 15:43:59 -0000
@@ -1904,6 +1904,71 @@
}
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,
+ args->flags);
+ 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 3 Sep 2008 15:43:59 -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,17 @@
opaque buffer<REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX>;
};
+struct remote_list_all_domains_args {
+ int want_infos;
+ unsigned hyper stateflags;
+ unsigned hyper flags;
+};
+
+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 +481,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 +1114,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 3 Sep 2008 15:44:00 -0000
@@ -97,6 +97,12 @@
typedef char *
(*virDrvGetCapabilities) (virConnectPtr conn);
typedef int
+ (*virDrvListAllDomains) (virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags);
+typedef int
(*virDrvListDomains) (virConnectPtr conn,
int *ids,
int maxids);
@@ -307,6 +313,7 @@
virDrvGetMaxVcpus getMaxVcpus;
virDrvNodeGetInfo nodeGetInfo;
virDrvGetCapabilities getCapabilities;
+ virDrvListAllDomains listAllDomains;
virDrvListDomains listDomains;
virDrvNumOfDomains numOfDomains;
virDrvDomainCreateLinux domainCreateLinux;
Index: src/internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/internal.h,v
retrieving revision 1.78
diff -u -r1.78 internal.h
--- src/internal.h 27 Aug 2008 20:05:59 -0000 1.78
+++ src/internal.h 3 Sep 2008 15:44:00 -0000
@@ -362,6 +362,8 @@
int __virDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long bandwidth);
virDomainPtr __virDomainMigrateFinish (virConnectPtr dconn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags);
+int virEmulateListAllDomains (virConnectPtr conn, virDomainPtr **domains, virDomainInfo **infos, unsigned long stateflags, unsigned long flags);
+
typedef struct _virStringList virStringList;
struct _virStringList {
Index: src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.155
diff -u -r1.155 libvirt.c
--- src/libvirt.c 2 Sep 2008 15:00:09 -0000 1.155
+++ src/libvirt.c 3 Sep 2008 15:44:03 -0000
@@ -1145,6 +1145,216 @@
}
/**
+ * 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
+ * @flags: other flags (always 0)
+ *
+ * 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. Callers must pass one of:
+ * 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,
+ * 0 to return no domains.
+ *
+ * @flags may be used in the future. Always pass 0 for this parameter.
+ *
+ * If there is no error then @domains will be updated to point to an
+ * array of virDomainPtr.
+ *
+ * If there is no error and @infos is not NULL, then @infos will be
+ * updated to point to an array of virDomainInfo structures, with
+ * the same length as the array of domains.
+ *
+ * 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 if necessary free the array of @infos structures.
+ */
+int
+virConnectListAllDomains(virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags)
+{
+ DEBUG("conn=%p, domains=%p, infos=%p, stateflags=%lu, flags=%lu",
+ conn, domains, infos, stateflags, flags);
+
+ if (!VIR_IS_CONNECT (conn)) {
+ virLibConnError (NULL, VIR_ERR_INVALID_CONN, __FUNCTION__);
+ return -1;
+ }
+
+ if (flags != 0) {
+ virLibConnError (conn, VIR_ERR_INVALID_ARG,
+ _("flags must always be 0"));
+ 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, flags);
+ else
+ return virEmulateListAllDomains (conn, domains, infos,
+ stateflags, flags);
+}
+
+int
+virEmulateListAllDomains (virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags ATTRIBUTE_UNUSED)
+{
+ 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;
+
+ 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 (infos) {
+ if (virDomainGetInfo (tdom, &tinfo) == -1) {
+ virDomainFree (tdom);
+ continue;
+ }
+ }
+
+ (*domains)[j] = tdom;
+ tdom = NULL;
+ if (infos)
+ (*infos)[j] = tinfo;
+ j++;
+ }
+ }
+
+ 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 (infos) {
+ if (virDomainGetInfo (tdom, &tinfo) == -1) {
+ virDomainFree (tdom);
+ continue;
+ }
+ }
+
+ (*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
* @ids: array to collect the list of IDs of active domains
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 3 Sep 2008 15:44:03 -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 3 Sep 2008 15:44:04 -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 3 Sep 2008 15:44:04 -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.116
diff -u -r1.116 qemu_driver.c
--- src/qemu_driver.c 3 Sep 2008 15:05:31 -0000 1.116
+++ src/qemu_driver.c 3 Sep 2008 15:44:07 -0000
@@ -3922,6 +3922,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 3 Sep 2008 15:44:11 -0000
@@ -1339,6 +1339,83 @@
return ret.freeMem;
}
+static int
+remoteListAllDomains (virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags)
+{
+ 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;
+ args.flags = flags;
+
+ 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 +4907,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 3 Sep 2008 15:44:12 -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.165
diff -u -r1.165 virsh.c
--- src/virsh.c 3 Sep 2008 12:38:28 -0000 1.165
+++ src/virsh.c 3 Sep 2008 15:44:16 -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, 0);
+ 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;
}
Index: src/xen_unified.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_unified.c,v
retrieving revision 1.53
diff -u -r1.53 xen_unified.c
--- src/xen_unified.c 20 Aug 2008 20:48:36 -0000 1.53
+++ src/xen_unified.c 3 Sep 2008 15:44:17 -0000
@@ -481,6 +481,31 @@
return NULL;
}
+#if 0
+static int
+xenUnifiedListAllDomains (virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags)
+{
+ GET_PRIVATE(conn);
+ int ret;
+
+ if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
+ ret = xenDaemonListAllDomains (conn, domains, infos, stateflags, flags);
+ return ret;
+ }
+
+ /* Kind of hackish that we call back out to libvirt.c. However
+ * this doesn't cause any infinite loops because emulation uses
+ * the old-style calls.
+ */
+ ret = virEmulateListAllDomains (conn, domains, infos, stateflags, flags);
+ return ret;
+}
+#endif
+
static int
xenUnifiedListDomains (virConnectPtr conn, int *ids, int maxids)
{
@@ -1318,6 +1343,9 @@
.getMaxVcpus = xenUnifiedGetMaxVcpus,
.nodeGetInfo = xenUnifiedNodeGetInfo,
.getCapabilities = xenUnifiedGetCapabilities,
+#if 0
+ .listAllDomains = xenUnifiedListAllDomains,
+#endif
.listDomains = xenUnifiedListDomains,
.numOfDomains = xenUnifiedNumOfDomains,
.domainCreateLinux = xenUnifiedDomainCreateLinux,
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.211
diff -u -r1.211 xend_internal.c
--- src/xend_internal.c 28 Aug 2008 11:59:07 -0000 1.211
+++ src/xend_internal.c 3 Sep 2008 15:44:21 -0000
@@ -3434,6 +3434,33 @@
}
#ifndef PROXY
+#if 0
+/**
+ * xenDaemonListAllDomains:
+ * @conn: pointer to the hypervisor connection
+ * @domains: array of domains returned (may not be NULL)
+ * @infos: array of virDomainInfo structures returned (may be NULL)
+ * @stateflags: which domains we are interested in
+ *
+ * Collect the list of all (active/inactive) domains, and store their
+ * domain objects and optional virDomainInfo structures in @domains
+ * and @infos.
+ *
+ * Returns the number of domains found or -1 in case of error
+ */
+int
+xenDaemonListAllDomains (virConnectPtr conn,
+ virDomainPtr **domains,
+ virDomainInfo **infos,
+ unsigned long stateflags,
+ unsigned long flags ATTRIBUTE_UNUSED)
+{
+
+
+
+}
+#endif
+
/**
* xenDaemonListDomains:
* @conn: pointer to the hypervisor connection
Index: src/xend_internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.h,v
retrieving revision 1.50
diff -u -r1.50 xend_internal.h
--- src/xend_internal.h 20 Aug 2008 20:48:36 -0000 1.50
+++ src/xend_internal.h 3 Sep 2008 15:44:21 -0000
@@ -179,4 +179,8 @@
int xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path, unsigned long long offset, size_t size, void *buffer);
+#if 0
+int xenDaemonListAllDomains (virConnectPtr conn, virDomainPtr **domains, virDomainInfo **infos, unsigned long stateflags, unsigned long flags);
+#endif
+
#endif /* __XEND_INTERNAL_H_ */
More information about the libvir-list
mailing list