From: yvinter <yves.vinter@xxxxxxxx> --- src/hyperv/hyperv_driver.c | 112 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_private.h | 2 + src/hyperv/hyperv_wmi_generator.input | 12 ++++ 3 files changed, 126 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f2017c3..dd56fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -58,12 +58,19 @@ hypervFreePrivate(hypervPrivate **priv) wsmc_release((*priv)->client); } + if ((*priv)->caps != NULL) + virObjectUnref((*priv)->caps); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } +/* Forward declaration of hypervCapsInit */ +static virCapsPtr hypervCapsInit(hypervPrivate *priv); + + static virDrvOpenStatus hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) { @@ -192,6 +199,12 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags goto cleanup; } + /* Setup capabilities */ + priv->caps = hypervCapsInit(priv); + if (priv->caps == NULL) { + goto cleanup; + } + conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; @@ -1420,6 +1433,104 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) } +/* Retrieves host system UUID */ +static int +hypervLookupHostSystemBiosUuid(hypervPrivate *priv, unsigned char *uuid) +{ + Win32_ComputerSystemProduct *computerSystem = NULL; + virBuffer query = VIR_BUFFER_INITIALIZER; + int result = -1; + + virBufferAddLit(&query, WIN32_COMPUTERSYSTEMPRODUCT_WQL_SELECT); + + if (hypervGetWin32ComputerSystemProductList(priv, &query, &computerSystem) < 0) { + goto cleanup; + } + + if (computerSystem == NULL) { + virReportError(VIR_ERR_NO_DOMAIN, + _("Unable to get Win32_ComputerSystemProduct")); + goto cleanup; + } + + if (virUUIDParse(computerSystem->data->UUID, uuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not parse UUID from string '%s'"), + computerSystem->data->UUID); + goto cleanup; + } + + result = 0; + + cleanup: + hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); + + return result; +} + + + +static virCapsPtr hypervCapsInit(hypervPrivate *priv) +{ + virCapsPtr caps = NULL; + virCapsGuestPtr guest = NULL; + + caps = virCapabilitiesNew(VIR_ARCH_X86_64, 1, 1); + + if (caps == NULL) { + virReportOOMError(); + return NULL; + } + + /* virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 }); */ + + if (hypervLookupHostSystemBiosUuid(priv,caps->host.host_uuid) < 0) { + goto failure; + } + + /* i686 */ + guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, NULL, NULL, 0, NULL); + if (guest == NULL) { + goto failure; + } + if (virCapabilitiesAddGuestDomain(guest, "hyperv", NULL, NULL, 0, NULL) == NULL) { + goto failure; + } + + /* x86_64 */ + guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, NULL, NULL, 0, NULL); + if (guest == NULL) { + goto failure; + } + if (virCapabilitiesAddGuestDomain(guest, "hyperv", NULL, NULL, 0, NULL) == NULL) { + goto failure; + } + + return caps; + + failure: + virObjectUnref(caps); + return NULL; +} + + + +static char* +hypervConnectGetCapabilities(virConnectPtr conn) +{ + hypervPrivate *priv = conn->privateData; + char *xml = virCapabilitiesFormatXML(priv->caps); + + if (xml == NULL) { + virReportOOMError(); + return NULL; + } + + return xml; +} + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1457,6 +1568,7 @@ static virDriver hypervDriver = { .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ + .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h index 574bb5f..d9aa0bd 100644 --- a/src/hyperv/hyperv_private.h +++ b/src/hyperv/hyperv_private.h @@ -26,6 +26,7 @@ # include "internal.h" # include "virerror.h" # include "hyperv_util.h" +# include "capabilities.h" # include "openwsman.h" typedef struct _hypervPrivate hypervPrivate; @@ -33,6 +34,7 @@ typedef struct _hypervPrivate hypervPrivate; struct _hypervPrivate { hypervParsedUri *parsedUri; WsManClient *client; + virCapsPtr caps; }; #endif /* __HYPERV_PRIVATE_H__ */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 6b969df..f1e0c81 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -333,3 +333,15 @@ class CIM_DataFile string Version boolean Writeable end + + +class Win32_ComputerSystemProduct + string Caption + string Description + string IdentifyingNumber + string Name + string SKUNumber + string UUID + string Vendor + string Version +end -- 1.9.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list