diff --git a/ChangeLog b/ChangeLog index abb1442f98..33aa391680 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Fri Aug 10 14:25:00 EST 2007 Daniel P. Berrange + + * src/xen_internal.c, src/xen_internal.h, src/xen_unified.c: + Add impls of the DomainGetOSType, DomainLookupByID and + DomainLookupByName drivers using the HV for speed + * src/xs_internal.c, src/xs_internal.h: Add helper method to + lookup a domain name based on its ID + Thu Aug 9 14:27:00 EST 2007 Daniel P. Berrange * src/libvirt.c, src/openvz_conf.c, src/qemu_conf.c, diff --git a/src/xen_internal.c b/src/xen_internal.c index 17df827faa..638e340d45 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -27,6 +27,7 @@ #include #include #include +#include "xs_internal.h" /* required for dom0_getdomaininfo_t */ #include @@ -229,6 +230,13 @@ typedef union xen_getschedulerid xen_getschedulerid; domlist.v2[n].domain : \ domlist.v2d5[n].domain)) +#define XEN_GETDOMAININFOLIST_UUID(domlist, n) \ + (hypervisor_version < 2 ? \ + domlist.v0[n].handle : \ + (dom_interface_version < 5 ? \ + domlist.v2[n].handle : \ + domlist.v2d5[n].handle)) + #define XEN_GETDOMAININFOLIST_DATA(domlist) \ (hypervisor_version < 2 ? \ (void*)(domlist->v0) : \ @@ -299,6 +307,13 @@ typedef union xen_getschedulerid xen_getschedulerid; dominfo.v2.max_pages : \ dominfo.v2d5.max_pages)) +#define XEN_GETDOMAININFO_UUID(dominfo) \ + (hypervisor_version < 2 ? \ + dominfo.v0.handle : \ + (dom_interface_version < 5 ? \ + dominfo.v2.handle : \ + dominfo.v2d5.handle)) + struct xen_v0_getdomaininfolistop { @@ -626,7 +641,7 @@ struct xenUnifiedDriver xenHypervisorDriver = { NULL, /* domainShutdown */ NULL, /* domainReboot */ xenHypervisorDestroyDomain, /* domainDestroy */ - NULL, /* domainGetOSType */ + xenHypervisorDomainGetOSType, /* domainGetOSType */ xenHypervisorGetMaxMemory, /* domainGetMaxMemory */ xenHypervisorSetMaxMemory, /* domainSetMaxMemory */ NULL, /* domainSetMemory */ @@ -2437,6 +2452,136 @@ xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids) return (nbids); } + +#ifndef PROXY +char * +xenHypervisorDomainGetOSType (virDomainPtr dom) +{ + xenUnifiedPrivatePtr priv; + xen_getdomaininfo dominfo; + + priv = (xenUnifiedPrivatePtr) dom->conn->privateData; + if (priv->handle < 0) + return (NULL); + + /* HV's earlier than 3.1.0 don't include the HVM flags in guests status*/ + if (hypervisor_version < 2 || + dom_interface_version < 4) + return (NULL); + + XEN_GETDOMAININFO_CLEAR(dominfo); + + if (virXen_getdomaininfo(priv->handle, dom->id, &dominfo) < 0) + return (NULL); + + if (XEN_GETDOMAININFO_DOMAIN(dominfo) != dom->id) + return (NULL); + + if (XEN_GETDOMAININFO_FLAGS(dominfo) & DOMFLAGS_HVM) + return strdup("hvm"); + return strdup("linux"); +} + +virDomainPtr +xenHypervisorLookupDomainByID(virConnectPtr conn, + int id) +{ + xenUnifiedPrivatePtr priv; + xen_getdomaininfo dominfo; + virDomainPtr ret; + char *name; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + if (priv->handle < 0) + return (NULL); + + XEN_GETDOMAININFO_CLEAR(dominfo); + + if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0) + return (NULL); + + if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id) + return (NULL); + + + if (!(name = xenStoreDomainGetName(conn, id))) + return (NULL); + + ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo)); + if (ret) + ret->id = id; + free(name); + return ret; +} + + +virDomainPtr +xenHypervisorLookupDomainByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + xen_getdomaininfolist dominfos; + xenUnifiedPrivatePtr priv; + virDomainPtr ret; + char *name; + int maxids = 100, nids, i, id; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + if (priv->handle < 0) + return (NULL); + + retry: + if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) { + virXenError(VIR_ERR_NO_MEMORY, "allocating %d domain info", + maxids); + return(NULL); + } + + XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids); + + nids = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos); + + if (nids < 0) { + XEN_GETDOMAININFOLIST_FREE(dominfos); + return (NULL); + } + + /* Can't possibly have more than 65,000 concurrent guests + * so limit how many times we try, to avoid increasing + * without bound & thus allocating all of system memory ! + * XXX I'll regret this comment in a few years time ;-) + */ + if (nids == maxids) { + XEN_GETDOMAININFOLIST_FREE(dominfos); + if (maxids < 65000) { + maxids *= 2; + goto retry; + } + return (NULL); + } + + id = -1; + for (i = 0 ; i < nids ; i++) { + if (memcmp(XEN_GETDOMAININFOLIST_UUID(dominfos, i), uuid, VIR_UUID_BUFLEN) == 0) { + id = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i); + break; + } + } + XEN_GETDOMAININFOLIST_FREE(dominfos); + + if (id == -1) + return (NULL); + + if (!(name = xenStoreDomainGetName(conn, id))) + return (NULL); + + ret = virGetDomain(conn, name, uuid); + if (ret) + ret->id = id; + free(name); + return ret; +} +#endif + /** * xenHypervisorGetMaxVcpus: * diff --git a/src/xen_internal.h b/src/xen_internal.h index 65a7ace8ec..6d5c1cbce4 100644 --- a/src/xen_internal.h +++ b/src/xen_internal.h @@ -20,6 +20,15 @@ int xenHypervisorInit (void); /* The following calls are made directly by the Xen proxy: */ +virDomainPtr + xenHypervisorLookupDomainByID (virConnectPtr conn, + int id); +virDomainPtr +xenHypervisorLookupDomainByUUID(virConnectPtr conn, + const unsigned char *uuid); +char * + xenHypervisorDomainGetOSType (virDomainPtr dom); + int xenHypervisorOpen (virConnectPtr conn, const char *name, int flags); diff --git a/src/xen_unified.c b/src/xen_unified.c index 69bc1e6fb2..5d9bb9418e 100644 --- a/src/xen_unified.c +++ b/src/xen_unified.c @@ -377,6 +377,13 @@ xenUnifiedDomainLookupByID (virConnectPtr conn, int id) */ virConnResetLastError (conn); + /* Try hypervisor/xenstore combo. */ + if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) { + ret = xenHypervisorLookupDomainByID (conn, id); + if (ret || conn->err.code != VIR_ERR_OK) + return ret; + } + /* Try proxy. */ if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) { ret = xenProxyLookupByID (conn, id); @@ -408,6 +415,13 @@ xenUnifiedDomainLookupByUUID (virConnectPtr conn, */ virConnResetLastError (conn); + /* Try hypervisor/xenstore combo. */ + if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) { + ret = xenHypervisorLookupDomainByUUID (conn, uuid); + if (ret || conn->err.code != VIR_ERR_OK) + return ret; + } + /* Try proxy. */ if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) { ret = xenProxyLookupByUUID (conn, uuid); diff --git a/src/xs_internal.c b/src/xs_internal.c index 4569e54688..ef7248fc61 100644 --- a/src/xs_internal.c +++ b/src/xs_internal.c @@ -875,6 +875,22 @@ xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) { return(ret); } +char *xenStoreDomainGetName(virConnectPtr conn, + int id) { + char prop[200]; + xenUnifiedPrivatePtr priv; + unsigned int len; + + priv = (xenUnifiedPrivatePtr) conn->privateData; + if (priv->xshandle == NULL) + return(NULL); + + snprintf(prop, 199, "/local/domain/%d/name", id); + prop[199] = 0; + return xs_read(priv->xshandle, 0, prop, &len); +} + + #endif /* WITH_XEN */ /* * Local variables: diff --git a/src/xs_internal.h b/src/xs_internal.h index a5001e5612..cd2f0ed55e 100644 --- a/src/xs_internal.h +++ b/src/xs_internal.h @@ -15,6 +15,8 @@ extern "C" { #endif +#include "internal.h" + extern struct xenUnifiedDriver xenStoreDriver; int xenStoreInit (void); @@ -48,6 +50,8 @@ char * xenStoreDomainGetOSTypeID(virConnectPtr conn, char * xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac); +char * xenStoreDomainGetName(virConnectPtr conn, + int id); #ifdef __cplusplus }