From: yvinter <yves.vinter(a)bull.net>
---
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