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
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_ */
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list