Authors: Simon Rastello (Bull), Adrien Kantcheff (Bull), Yves Vinter (Bull)
*** Summary of new features added in hyperv driver version 1.2.9 ***
- Added a mutex to prevent concurrent requests from being run simultaneously [WSMAN libray
not thread-safe]
- Support of default authentication (credentials specified in
~/.config/libvirt/auth.conf)
- Support of new types of WSMAN requests involving passing complex parameters (simple
types, EPR, embedded objects)
Required a new auto-generated header file to get the type of objects attributes
(hyperv_wmi_classes_attr.generated.h)
- New functions:
- host management (in hyperv_driver module)
- capabilities (limited)
- domain management (in hyperv_driver module)
- domain creation from an XML description
- domain destruction
- attachment of pre-existing disk images on IDE controller
- attachment of Synthetic network devices
- memory and vcpu management (get and set methods)
- autostart, shutdown, ...
- network management (in hyperv_network_driver module)
- list available networks
- informations for a specified network
Required the declaration of new classes (in hyperv_wmi_generator.input)
- Fixed several memory leak issues
*** Important note ***
The current implementation of the driver does not support the new WMI
root/virtualization/v2 name space.
It is not compatible with the last version of Hyper-V coming with Windows Server 2012 R2.
*** Detail of the updates by module ***
hyperv_driver.c
+++++++++++++++
- Support of default authentication (credentials specified in
~/.config/libvirt/auth.conf)
- Support of new libvirt functions
.domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.9 */
.domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.9 */
.domainShutdown = hypervDomainShutdown, /* 1.2.9 */
.domainShutdownFlags = hypervDomainShutdownFlags, /* 1.2.9 */
.domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /* 1.2.9
*/
.domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.9 */
.domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.9 */
.connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.9 */
.connectGetVersion = hypervConnectGetVersion, /* 1.2.9 */
.domainSetAutostart = hypervDomainSetAutostart, /* 1.2.9 */
.domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.9 */
.domainDefineXML = hypervDomainDefineXML, /* 1.2.9 */
.domainSetMemory = hypervDomainSetMemory, /* 1.2.9 */
.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.9 */
.domainSetVcpus = hypervDomainSetVcpus, /* 1.2.9 */
.domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.9 */
.domainAttachDevice = hypervDomainAttachDevice, /* 1.2.9 */
.domainAttachDeviceFlags = hypervDomainAttachDeviceFlags, /* 1.2.9 */
.connectGetMaxVcpus = hypervConnectGetMaxVcpus, /* 1.2.9 */
.domainCreateXML = hypervDomainCreateXML, /* 1.2.9 */
.nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.9 */
.domainGetVcpus = hypervDomainGetVcpus, /* 1.2.9 */
.domainUndefine = hypervDomainUndefine, /* 1.2.9 */
.domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.9 */
.domainGetAutostart = hypervDomainGetAutostart, /* 1.2.9 */
- Updated libvirt functions
.connectOpen = hypervConnectOpen, /* 0.9.5 */
Support of default authentication (credentials specified in
~/.config/libvirt/auth.conf)
- New internal functions
- hypervLookupHostSystemBiosUuid
- hypervCapsInit
- hypervGetResourceAllocationSettingDataPATH
- hypervGetSwitchPortPATH
- hypervDomainAttachDisk
Used by hypervDomainAttachDevice
Currently support only attachments on the IDE controller (targets hda, hdb, hdc, hdd)
- hypervDomainAttachNetwork
Used by hypervDomainAttachDevice
Support attachment of synthetic network adapters (Legacy adapters are not supported)
- integer2string
- Notes related to devices attachments
- hypervDomainAttachDevice does not support attachment of ISO images (DVD drives)
- attachment of disk drives on the iSCSI controller is not yet supported
- devices detachment (drives or network) is not yet implemented
- networks and disk images must have been provisioned manually
- attached devices are not displayed in the domain XML description
(hypervDomainGetXMLDesc)
hyperv_network_driver.c
+++++++++++++++++++++++
- Support of new libvirt function
.connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.9 */
.connectListNetworks = hypervConnectListNetworks, /* 1.2.9 */
.connectNumOfDefinedNetworks = hypervConnectNumOfDefinedNetworks, /* 1.2.9 */
.connectListDefinedNetworks = hypervConnectListDefinedNetworks, /* 1.2.9 */
.networkLookupByName = hypervNetworkLookupByName, /* 1.2.9 */
.networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.9 */
hyperv_private.h
++++++++++++++++
- Added Caps, XMLOption and a Mutex in the private structure
hyperv_wmi.c
++++++++++++
- Added an internal flag to dump WSMAN requests (DUMP_REQUEST)
- Support of new types of WSMAN requests involving passing complex parameters (simple
types, EPR, embedded objects)
- New functions
- hypervInvokeMethod
- hypervMsvmVirtualSwitchToNetwork
Used by hypervNetworkLookupByName (hyperv_network_driver.c)
- New internal functions (used by hypervInvokeMethod)
- hypervCreateXmlStruct
- hypervGetPropType
- hypervAddEmbeddedParam
- hypervAddSimpleParam
- hypervAddEprParam
- hypervInvokeMethodXml
- Updated functions
- hypervEnumAndPull
- hypervInvokeMsvmComputerSystemRequestStateChange
Added a mutex to protect against concurrent requests
Added a call to dump WSMAN request in dump mode
hyperv_wmi.h
++++++++++++
- Added structures for passing new types of parameters (Simple, EPR, Embedded)
- Defined a new method to allow WSMAN requests with these different types of parameters
(hypervInvokeMethod)
hyperv_wmi_generator.input
++++++++++++++++++++++++++
- Added new classes
- CIM_DataFile
- Win32_ComputerSystemProduct
- Msvm_VirtualSystemManagementService
- Msvm_VirtualSystemGlobalSettingData
- Msvm_ResourceAllocationSettingData
- Msvm_AllocationCapabilities
- Msvm_VirtualSwitch
- Msvm_SwitchPort
- Msvm_SyntheticEthernetPortSettingData
- Msvm_VirtualSwitchManagementService
- Win32_OperatingSystem
- Win32_PerfFormattedData_HvStats_HyperVHypervisorVirtualProcessor
- Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
hyperv_wmi_generator.py
+++++++++++++++++++++++
- Takes into account the CIM_DataFile class (from the root/cimv2 WMI name space)
- Generated a new header file "hyperv_wmi_classes_attr.generated.h" for getting
the type of objects attributes
- Added new functions for generating this new file
- generate_tab_classes
Generates an entry for the declaration of cimClasses types
- generate_tabs_types
Generates declarations of cimTypes types
- generate_type_tab
Generates an entry for the declaration of cimTypes types
- print_type_header
Generates the declaration of structures cimClasses and cimTypes
openwsman.h
+++++++++++
- Added functions prototypes from wsman-xml.h to handle XmlDoc
Reported-by: Yves Vinter <yves.vinter(a)bull.net>
---
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index aed9307..80fbb92 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -20,7 +20,15 @@
*
*/
+/*
+ * This implementation does not support the new WMI root/virtualization/v2 namespace.
+ * It is therefore not compatible with Hyper-V v3 and Windows Server 2012 R2.
+ *
+ */
+
#include <config.h>
+#include <string.h>
+#include <stdlib.h>
#include "internal.h"
#include "datatypes.h"
@@ -41,6 +49,7 @@
#include "hyperv_wmi.h"
#include "openwsman.h"
#include "virstring.h"
+#include "virtypedparam.h"
#define VIR_FROM_THIS VIR_FROM_HYPERV
@@ -58,12 +67,100 @@ hypervFreePrivate(hypervPrivate **priv)
wsmc_release((*priv)->client);
}
+ if ((*priv)->caps != NULL)
+ virObjectUnref((*priv)->caps);
+ if ((*priv)->xmlopt != NULL)
+ virObjectUnref((*priv)->xmlopt);
+
+ /* Destroy the mutex */
+ pthread_mutex_destroy(&(*priv)->mutex);
+
hypervFreeParsedUri(&(*priv)->parsedUri);
VIR_FREE(*priv);
}
+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 virDrvOpenStatus
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
{
@@ -108,12 +205,16 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
unsigned int flags
return VIR_DRV_OPEN_ERROR;
}
- /* Require auth */
- if (auth == NULL || auth->cb == NULL) {
+ /* Uses default authentification mechanism when not provided */
+ if (auth == NULL)
+ auth = virConnectAuthPtrDefault;
+ else {
+ if (auth->cb == NULL) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
_("Missing or invalid auth pointer"));
return VIR_DRV_OPEN_ERROR;
}
+ }
/* Allocate per-connection private data */
if (VIR_ALLOC(priv) < 0)
@@ -192,7 +293,20 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
unsigned int flags
goto cleanup;
}
+ /* Setup capabilities */
+ priv->caps = hypervCapsInit(priv);
+ if (priv->caps == NULL) {
+ goto cleanup;
+ }
+
+ /* Init xmlopt to parse Domain XML */
+ priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL);
+
conn->privateData = priv;
+
+ /* Initialize the mutex */
+ pthread_mutex_init(&priv->mutex, NULL);
+
priv = NULL;
result = VIR_DRV_OPEN_SUCCESS;
@@ -200,6 +314,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned
int flags
hypervFreePrivate(&priv);
VIR_FREE(username);
VIR_FREE(password);
+ virBufferFreeAndReset(&query);
hypervFreeObject(priv, (hypervObject *)computerSystem);
return result;
@@ -254,6 +369,7 @@ hypervConnectGetHostname(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return hostname;
}
@@ -352,6 +468,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
hypervFreeObject(priv, (hypervObject *)processorList);
+ virBufferFreeAndReset(&query);
return result;
}
@@ -396,6 +513,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -432,6 +550,7 @@ hypervConnectNumOfDomains(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -464,6 +583,7 @@ hypervDomainLookupByID(virConnectPtr conn, int id)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -500,6 +620,7 @@ hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char
*uuid)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -533,6 +654,7 @@ hypervDomainLookupByName(virConnectPtr conn, const char *name)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
return domain;
}
@@ -748,6 +870,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
hypervFreeObject(priv, (hypervObject *)processorSettingData);
hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
return result;
}
@@ -783,7 +906,10 @@ hypervDomainGetState(virDomainPtr domain, int *state, int *reason,
}
-
+/* hypervDomainGetXMLDesc
+ * FIXME:
+ * - does not display attached devices (disk, nic)
+ */
static char *
hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
{
@@ -915,6 +1041,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
hypervFreeObject(priv, (hypervObject *)processorSettingData);
hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
return xml;
}
@@ -971,6 +1098,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const
names, int maxn
}
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return count;
}
@@ -1007,6 +1135,7 @@ hypervConnectNumOfDefinedDomains(virConnectPtr conn)
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return success ? count : -1;
}
@@ -1346,6 +1475,7 @@ hypervConnectListAllDomains(virConnectPtr conn,
}
hypervFreeObject(priv, (hypervObject *)computerSystemList);
+ virBufferFreeAndReset(&query);
return ret;
}
@@ -1353,6 +1483,1778 @@ hypervConnectListAllDomains(virConnectPtr conn,
+static int
+hypervConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
+{
+ int res = -1;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+
+ /* Get Msvm_ProcessorSettingData maximum definition */
+ virBufferAddLit(&query, "SELECT * FROM Msvm_ProcessorSettingData "
+ "WHERE InstanceID LIKE
'Microsoft:Definition%Maximum'");
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
&processorSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get maximum definition of
Msvm_ProcessorSettingData"));
+ goto cleanup;
+ }
+
+ res = processorSettingData->data->SocketCount *
+ processorSettingData->data->ProcessorsPerSocket;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) processorSettingData);
+ return res;
+}
+
+
+
+static int
+hypervDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+ int ret = -1;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |VIR_DOMAIN_VCPU_CONFIG |VIR_DOMAIN_VCPU_MAXIMUM,
-1);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Get Msvm_ComputerSystem */
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ // If @flags includes VIR_DOMAIN_VCPU_LIVE,
+ // this will query a running domain (which will fail if domain is not active)
+ if (flags & VIR_DOMAIN_VCPU_LIVE) {
+ if (computerSystem->data->EnabledState !=
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is
not active"));
+ goto cleanup;
+ }
+ }
+
+ // If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then the maximum virtual CPU limit is
queried
+ if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
+ ret = hypervConnectGetMaxVcpus(domain->conn, NULL);
+ goto cleanup;
+ }
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+ if (virtualSystemSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain
%s"),
+ "Msvm_VirtualSystemSettingData",
computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ /* Get Msvm_ProcessorSettingData */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_ProcessorSettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
+ &processorSettingData) < 0) {
+ goto cleanup;
+ }
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain
%s"),
+ "Msvm_ProcessorSettingData",
computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ ret = processorSettingData->data->VirtualQuantity;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ return ret;
+}
+
+
+
+static int
+hypervDomainGetMaxVcpus(virDomainPtr dom)
+{
+ // If the guest is inactive, this is basically the same as virConnectGetMaxVcpus()
+ return (hypervDomainIsActive(dom)) ?
+ hypervDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |VIR_DOMAIN_VCPU_MAXIMUM))
+ : hypervConnectGetMaxVcpus(dom->conn, NULL);
+}
+
+
+
+static int
+hypervDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
+{
+ int result = -1;
+ hypervPrivate *priv = domain->conn->privateData;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ bool in_transition = false;
+
+ virCheckFlags(0, -1);
+
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) ||
+ in_transition) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Domain is not active or is in state transition"));
+ goto cleanup;
+ }
+
+ result = hypervInvokeMsvmComputerSystemRequestStateChange
+ (domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED);
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ return result;
+}
+
+
+
+static int hypervDomainShutdown(virDomainPtr dom)
+{
+ return hypervDomainShutdownFlags(dom, 0);
+}
+
+
+
+static int
+hypervDomainGetSchedulerParametersFlags(virDomainPtr dom, virTypedParameterPtr params,
+ int *nparams, unsigned int flags)
+{
+ hypervPrivate *priv = dom->conn->privateData;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ int ret = -1;
+ int saved_nparams = 0;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |VIR_DOMAIN_AFFECT_CONFIG
|VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ /* We don't return strings, and thus trivially support this flag. */
+ flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
+
+ virUUIDFormat(dom->uuid, uuid_string);
+
+ /* Get Msvm_ComputerSystem */
+ if (hypervMsvmComputerSystemFromDomain(dom, &computerSystem) < 0) { goto
cleanup;}
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+
+ if (virtualSystemSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for domain %s"),
+ "Msvm_VirtualSystemSettingData",
+ computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ /* Get Msvm_ProcessorSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_ProcessorSettingData",
+ virtualSystemSettingData->data->InstanceID);
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
+ &processorSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain
%s"),
+
"Msvm_ProcessorSettingData",computerSystem->data->ElementName);
+ goto cleanup;
+ }
+
+ if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_LIMIT,
+ VIR_TYPED_PARAM_LLONG,
processorSettingData->data->Limit) < 0)
+ goto cleanup;
+ saved_nparams++;
+
+ if (*nparams > saved_nparams) {
+ if (virTypedParameterAssign(¶ms[1],VIR_DOMAIN_SCHEDULER_RESERVATION,
+ VIR_TYPED_PARAM_LLONG,
processorSettingData->data->Reservation) < 0)
+ goto cleanup;
+ saved_nparams++;
+ }
+
+ if (*nparams > saved_nparams) {
+ if (virTypedParameterAssign(¶ms[2],VIR_DOMAIN_SCHEDULER_WEIGHT,
+ VIR_TYPED_PARAM_UINT,
processorSettingData->data->Weight) < 0)
+ goto cleanup;
+ saved_nparams++;
+ }
+
+ *nparams = saved_nparams;
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ virBufferFreeAndReset(&query);
+ return ret;
+}
+
+
+
+static int
+hypervDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int
*nparams)
+{
+ return hypervDomainGetSchedulerParametersFlags(dom, params, nparams,
VIR_DOMAIN_AFFECT_CURRENT);
+}
+
+
+
+static char*
+hypervDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams)
+{
+ char *type = strdup("allocation");
+
+ if (type == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ if (nparams != NULL) {
+ *nparams = 3; /* reservation, limit, weight */
+ }
+
+ return type;
+}
+
+
+
+static char*
+hypervConnectGetCapabilities(virConnectPtr conn)
+{
+ hypervPrivate *priv = conn->privateData;
+ char *xml = virCapabilitiesFormatXML(priv->caps);
+
+ if (xml == NULL) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return xml;
+}
+
+
+static int
+hypervConnectGetVersion(virConnectPtr conn, unsigned long *version)
+{
+ int ret = -1;
+ hypervPrivate *priv = conn->privateData;
+ CIM_DataFile *datafile = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ char * p;
+
+ virBufferAddLit(&query, " Select * from CIM_DataFile where
Name='c:\\\\windows\\\\system32\\\\vmms.exe' ");
+
+ if (hypervGetCIMDataFileList(priv, &query, &datafile) < 0) {goto
cleanup;}
+
+ // check the result of convertion
+ if (datafile == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for domain %s"),
+ "Msvm_VirtualSystemSettingData",
+ datafile->data->Version);
+ goto cleanup;
+ }
+
+ /* Delete release number and last digit of build number 1.1.111x.xxxx */
+ p = strrchr(datafile->data->Version,'.');
+ if (p == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse version number from '%s'"),
+ datafile->data->Version);
+ goto cleanup;
+ }
+ p--;
+ *p = '\0';
+
+ /*Parse Version String to Long*/
+ if (virParseVersionString(datafile->data->Version,
+ version, true) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse version number from '%s'"),
+ datafile->data->Version);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)datafile);
+ virBufferFreeAndReset(&query);
+ return ret;
+}
+
+
+
+static unsigned long long
+hypervNodeGetFreeMemory(virConnectPtr conn)
+{
+ unsigned long long res = 0;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Win32_OperatingSystem *operatingSystem = NULL;
+
+ /* Get Win32_OperatingSystem */
+ virBufferAddLit(&query, WIN32_OPERATINGSYSTEM_WQL_SELECT);
+
+ if (hypervGetWin32OperatingSystemList(priv, &query, &operatingSystem) < 0)
{
+ goto cleanup;
+ }
+
+ if (operatingSystem == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get Win32_OperatingSystem"));
+ goto cleanup;
+ }
+
+ // return free memory in bytes
+ res = operatingSystem->data->FreePhysicalMemory * 1024;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) operatingSystem);
+ return res;
+}
+
+
+
+static int
+hypervDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
+{
+ int count = 0, i;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
+ *hypervVirtualProcessor = NULL;
+
+ //FIXME: no information stored in cpumaps
+ if (cpumaps == NULL) {
+ cpumaps = (unsigned char *) calloc(maxinfo, maplen);
+ }
+
+ /* Loop for each vCPU */
+ for (i = 0; i < maxinfo; i++) {
+
+ /* Get vCPU stats */
+ hypervFreeObject(priv, (hypervObject *)hypervVirtualProcessor);
+ hypervVirtualProcessor = NULL;
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query,
+ WIN32_PERFRAWDATA_HVSTATS_HYPERVHYPERVISORVIRTUALPROCESSOR_WQL_SELECT);
+ // Attribute Name format : <domain_name>:Hv VP <vCPU_number>
+ virBufferAsprintf(&query, "where Name = \"%s:Hv VP %d\"",
domain->name, i);
+
+ if (hypervGetWin32PerfRawDataHvStatsHyperVHypervisorVirtualProcessorList(
+ priv, &query, &hypervVirtualProcessor) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get stats on vCPU #%d"), i);
+ continue;
+ }
+
+ /* Fill structure info */
+ info[i].number = i;
+ if (hypervVirtualProcessor == NULL) {
+ info[i].state = VIR_VCPU_OFFLINE;
+ info[i].cpuTime = 0LLU;
+ info[i].cpu = -1;
+ } else {
+ info[i].state = VIR_VCPU_RUNNING;
+ info[i].cpuTime = hypervVirtualProcessor->data->PercentTotalRunTime;
+ info[i].cpu = i;
+ }
+
+ count++;
+ }
+
+ hypervFreeObject(priv, (hypervObject *)hypervVirtualProcessor);
+ virBufferFreeAndReset(&query);
+ return count;
+}
+
+
+
+static int
+hypervDomainSetAutostart(virDomainPtr domain, int autostart)
+{
+ int res = -1;
+ invokeXmlParam *params = NULL;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer queryVssd = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ properties_t *tab_props = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* PREPARE EPR PARAM */
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name =
\"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ /* PREPARE EMBEDDED PARAM */
+ virBufferAsprintf(&queryVssd,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &queryVssd,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "AutomaticStartupAction";
+ (*tab_props).val = autostart ? "2" : "0";
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = virtualSystemSettingData->data->InstanceID;
+
+ embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData";
+ embeddedparam.prop_t = tab_props;
+
+ /* CREATE invokeXmlParam tab */
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "SystemSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ res = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystem",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI,
selector);
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&queryVssd);
+ return res;
+}
+
+
+
+static int
+hypervDomainGetAutostart(virDomainPtr domain, int *autostart)
+{
+ int res = -1;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemGlobalSettingData *vsgsd = NULL;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+ virBufferAddLit(&query, MSVM_VIRTUALSYSTEMGLOBALSETTINGDATA_WQL_SELECT);
+ virBufferAsprintf(&query, "where SystemName = \"%s\"",
uuid_string);
+
+ if (hypervGetMsvmVirtualSystemGlobalSettingDataList(priv,
+ &query, &vsgsd) < 0)
{
+ goto cleanup;
+ }
+
+ *autostart = vsgsd->data->AutomaticStartupAction;
+ res = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)vsgsd);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+/* Convert an integer value into a string */
+static char *integer2string(unsigned long value)
+{
+ int sz;
+ char *ret;
+
+ sz = snprintf (NULL, 0, "%lu", value);
+ ret = (char *) malloc ((sz+1)*sizeof(char));
+ if (ret != NULL)
+ sprintf(ret, "%lu", value);
+
+ return ret;
+}
+
+
+static int
+hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+ int res = -1;
+ invokeXmlParam *params = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ properties_t *tab_props = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer query2 = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_MemorySettingData *memorySettingData = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ unsigned long memory_mb = memory/1024;
+ char *memory_str = NULL;
+
+ // Memory value must be a multiple of 2 MB; round up it accordingly if necessary
+ if (memory_mb % 2) memory_mb++;
+
+ // Convert the memory value as a string value
+ memory_str = integer2string(memory_mb);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string);
+
+ // PREPARE EPR PARAM
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name =
\"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM 1
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query2,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query2,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+
+ /* Get Msvm_MemorySettingData */
+ virBufferFreeAndReset(&query2);
+ virBufferAsprintf(&query2,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_MemorySettingData",
+ virtualSystemSettingData->data->InstanceID);
+
+ if (hypervGetMsvmMemorySettingDataList(priv, &query2,
+ &memorySettingData) < 0) {
+ goto cleanup;
+ }
+
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Limit";
+ (*tab_props).val = memory_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = memorySettingData->data->InstanceID;
+ embeddedparam.instanceName = "Msvm_MemorySettingData";
+ embeddedparam.prop_t = tab_props;
+ embeddedparam.nbProps = 2;
+
+ // CREATE invokeXmlParam
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ res = hypervInvokeMethod(priv, params, nb_params,
"ModifyVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI,
selector);
+
+ cleanup:
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ VIR_FREE(memory_str);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&query2);
+ return res;
+}
+
+
+
+/*
+ * Create the attribute __PATH for the RASD object. The attribute is build like this:
+ *
\\<host_name>\root\virtualization:Msvm_ResourceAllocationSettingData.InstanceID="<rasdInstanceID>"
+ * where backslashes in rasdInstanceID are doubled
+ */
+static int
+hypervGetResourceAllocationSettingDataPATH(virDomainPtr domain, char *rasdInstanceID,
char **__path)
+{
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ char *strTemp = NULL;
+ int ret = -1, i = 0, j = 0, n = 0;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Get host name */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_HostedDependency "
+ "ResultClass = Msvm_ComputerSystem",
+ uuid_string);
+ if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
+ goto cleanup;
+ }
+ if (computerSystem == NULL) {
+ virReportError(VIR_ERR_NO_DOMAIN, _("No domain with UUID %s"),
uuid_string);
+ goto cleanup;
+ }
+
+ /* Count the number of backslash character */
+ strTemp = strchr(rasdInstanceID, '\\');
+ while (strTemp != NULL) {
+ n++;
+ strTemp = strchr(++strTemp, '\\');
+ }
+ /* Double the blackslashes */
+ strTemp = (char *) malloc(strlen(rasdInstanceID) + (n+1)*sizeof(char));
+ while (rasdInstanceID[i] != '\0') {
+ strTemp[j] = rasdInstanceID[i];
+ if (rasdInstanceID[i] == '\\') {
+ j++;
+ strTemp[j] = '\\';
+ }
+ i++;
+ j++;
+ }
+ strTemp[j] = '\0';
+
+ /* Create the attribute __PATH */
+ //FIXME: ret is allocated with 255 characters (static value)
+ *__path = (char *) malloc(sizeof(*__path) * 255);
+ sprintf(*__path, "\\\\");
+ strcat(*__path, computerSystem->data->ElementName);
+ strcat(*__path,
"\\root\\virtualization:Msvm_ResourceAllocationSettingData.InstanceID=\"");
+ strcat(*__path, strTemp);
+ strcat(*__path, "\"");
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+ free(strTemp);
+ return ret;
+}
+
+
+
+/*
+ * Create the attribute __PATH for the SwitchPort object. The attribute is build like
this:
+ *
\\<host_name>\root\virtualization:Msvm_SwitchPort.CreationClassName="Msvm_SwitchPort",
+ *
Name="<switchPortName>",SystemCreationClassName="Msvm_VirtualSwitch",
+ * SystemName="<virtualSwitchSystemName>"
+ */
+static int
+hypervGetSwitchPortPATH(virDomainPtr domain, char *switchPortName,
+ char *virtualSwitchSystemName, char **__path)
+{
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ComputerSystem *computerSystem = NULL;
+ char *strTemp = NULL;
+ int ret = -1;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ /* Get host name */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_HostedDependency "
+ "ResultClass = Msvm_ComputerSystem",
+ uuid_string);
+ if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
+ goto cleanup;
+ }
+ if (computerSystem == NULL) {
+ virReportError(VIR_ERR_NO_DOMAIN,
+ _("No domain with UUID %s"), uuid_string);
+ goto cleanup;
+ }
+
+
+ /* Create the attribute __PATH */
+ //FIXME: ret is allocated with 511 characters (static value)
+ *__path = (char *) malloc(sizeof(*__path) * 511);
+ sprintf(*__path,
+
"\\\\%s\\root\\virtualization:Msvm_SwitchPort.CreationClassName=\"Msvm_SwitchPort\","
+
"Name=\"%s\",SystemCreationClassName=\"Msvm_VirtualSwitch\",SystemName=\"%s\"",
+ computerSystem->data->ElementName, switchPortName,
virtualSwitchSystemName);
+
+ ret = 0;
+
+ cleanup:
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+ free(strTemp);
+ return ret;
+}
+
+
+
+/*
+ * Memory size in KiB
+ */
+static int
+hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int res = -1, nb_params;
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ invokeXmlParam *params = NULL;
+ properties_t *tab_props = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_MemorySettingData *memorySettingData = NULL;
+ unsigned long memory_mb = memory/1024;
+ char *memory_str = NULL;
+
+ // Memory value must be a multiple of 2 MB; round up it accordingly if necessary
+ if (memory_mb % 2) memory_mb++;
+
+ // Convert the memory value as a string value
+ memory_str = integer2string(memory_mb);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string);
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+
+ /* Get Msvm_MemorySettingData */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_MemorySettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmMemorySettingDataList(priv, &query,
+ &memorySettingData) < 0) {
+ goto cleanup;
+ }
+
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name =
\"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "VirtualQuantity";
+ (*tab_props).val = memory_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = memorySettingData->data->InstanceID;
+ embeddedparam.instanceName = "Msvm_MemorySettingData";
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ if (hypervInvokeMethod(priv, params, nb_params,
"ModifyVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain
memory"));
+ goto cleanup;
+ }
+
+ res = 0;
+
+ cleanup:
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ VIR_FREE(memory_str);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)memorySettingData);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+static int
+hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
+{
+ return hypervDomainSetMemoryFlags(domain, memory, 0);
+}
+
+
+static int
+hypervDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int res = -1;
+ invokeXmlParam *params = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ properties_t *tab_props = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_ProcessorSettingData *processorSettingData = NULL;
+ eprParam eprparam;
+ embeddedParam embeddedparam;
+ int nb_params;
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ char *nvcpus_str = NULL;
+
+ // Convert nvcpus as a string value
+ nvcpus_str = integer2string(nvcpus);
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("nvcpus=%s, uuid=%s", nvcpus_str, uuid_string);
+
+ /* Get Msvm_VirtualSystemSettingData */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+
+ /* Get Msvm_ProcessorSettingData */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_ProcessorSettingData",
+ virtualSystemSettingData->data->InstanceID);
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
+ &processorSettingData) < 0) {
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup Msvm_ProcessorSettingData for domain
%s"),
+ virtualSystemSettingData->data->ElementName);
+ goto cleanup;
+ }
+
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name =
\"%s\"",uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM
+ embeddedparam.nbProps = 2;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "VirtualQuantity";
+ (*tab_props).val = nvcpus_str;
+ (*(tab_props+1)).name = "InstanceID";
+ (*(tab_props+1)).val = processorSettingData->data->InstanceID;
+ embeddedparam.instanceName = "Msvm_ProcessorSettingData";
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ if (hypervInvokeMethod(priv, params, nb_params,
"ModifyVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain
vcpus"));
+ goto cleanup;
+ }
+
+ res = 0;
+
+ cleanup:
+ VIR_FREE(tab_props);
+ VIR_FREE(params);
+ VIR_FREE(nvcpus_str);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)processorSettingData);
+ virBufferFreeAndReset(&query);
+ return res;
+}
+
+
+
+static int
+hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+ return hypervDomainSetVcpusFlags(domain, nvcpus, 0);
+}
+
+
+/* hypervDomainAttachDisk
+ * FIXME:
+ * - added ressources must me removed in case of error
+ * - allow attaching disks on iSCSI (implemented only on IDE)
+ * - allow attaching ISO images (on DVD devices)
+ * - implement corresponding detach function
+ */
+static int
+hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk)
+{
+ int ret = -1, nb_params;
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ char *ideRasdPath = NULL, *newDiskDrivePath = NULL;
+ char *ideControler = NULL, *ideControlerAddr = NULL;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData2 = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData3 = NULL;
+ Msvm_ResourceAllocationSettingData *resourceAllocationSettingData4 = NULL;
+ Msvm_ResourceAllocationSettingData *ideRasd = NULL; /* Part of
resourceAllocationSettingData -> do not disallocate */
+ Msvm_ResourceAllocationSettingData *diskRasd = NULL; /* Part of
resourceAllocationSettingData2 -> do not disallocate */
+ Msvm_ResourceAllocationSettingData *newDiskDrive = NULL; /* Part of
resourceAllocationSettingData3 -> do not disallocate */
+ Msvm_AllocationCapabilities *allocationCapabilities = NULL;
+ Msvm_AllocationCapabilities *allocationCapabilities2 = NULL;
+ invokeXmlParam *params = NULL;
+ properties_t *tab_props = NULL;
+ eprParam eprparam1, eprparam2;
+ embeddedParam embeddedparam1, embeddedparam2;
+
+ /* Initialization */
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ // Set IDE Controler 0 or 1 and address 0 or 1
+ ideControler = (char *) malloc(2*sizeof(char));
+ ideControlerAddr = (char *) malloc(2*sizeof(char));
+ if (strcmp(disk->dst, "hda") == 0) {
+ sprintf(ideControler, "%d", 0);
+ sprintf(ideControlerAddr, "%d", 0);
+ } else if (strcmp(disk->dst, "hdb") == 0) {
+ sprintf(ideControler, "%d", 0);
+ sprintf(ideControlerAddr, "%d", 1);
+ } else if (strcmp(disk->dst, "hdc") == 0) {
+ sprintf(ideControler, "%d", 1);
+ sprintf(ideControlerAddr, "%d", 0);
+ } else if (strcmp(disk->dst, "hdd") == 0) {
+ sprintf(ideControler, "%d", 1);
+ sprintf(ideControlerAddr, "%d", 1);
+ } else {
+ // IDE Controler 0 and address 0 by default
+ sprintf(ideControler, "%d", 0);
+ sprintf(ideControlerAddr, "%d", 0);
+ }
+
+ VIR_DEBUG("src=%s, dst=IDE Controller %s:%s, uuid=%s",
+ disk->src->path, ideControler, ideControlerAddr, uuid_string);
+
+ /* Get the current VM settings object */
+ virBufferAsprintf(&query,
+ "associators of "
+
"{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+ "Name=\"%s\"} "
+ "where AssocClass = Msvm_SettingsDefineState "
+ "ResultClass = Msvm_VirtualSystemSettingData",
+ uuid_string);
+ if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
+ &virtualSystemSettingData) < 0)
{
+ goto cleanup;
+ }
+
+ /* Get the settings for IDE Controller on the VM */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+
&resourceAllocationSettingData) < 0) {
+ goto cleanup;
+ }
+ ideRasd = resourceAllocationSettingData;
+ while (ideRasd != NULL) {
+ if (ideRasd->data->ResourceType == 5 &&
+ strcmp(ideRasd->data->Address, ideControler) == 0) {
+ // IDE Controller 0 or 1
+ break;
+ }
+ ideRasd = ideRasd->next;
+ }
+ if (ideRasd == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find IDE Controller %s"), ideControler);
+ goto cleanup;
+ }
+
+ /* Get the settings for 'Microsoft Synthetic Disk Drive' */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_ALLOCATIONCAPABILITIES_WQL_SELECT);
+ virBufferAddLit(&query, "WHERE ResourceSubType = 'Microsoft Synthetic
Disk Drive'");
+ if (hypervGetMsvmAllocationCapabilitiesList(priv, &query,
+ &allocationCapabilities) < 0) {
+ goto cleanup;
+ }
+
+ /* Get default values for 'Microsoft Synthetic Disk Drive' */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_AllocationCapabilities.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_SettingsDefineCapabilities "
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ allocationCapabilities->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+
&resourceAllocationSettingData2) < 0) {
+ goto cleanup;
+ }
+ diskRasd = resourceAllocationSettingData2;
+ while (diskRasd != NULL) {
+ if (strstr(diskRasd->data->InstanceID, "Default") != NULL) {
+ // Default values
+ break;
+ }
+ diskRasd = diskRasd->next;
+ }
+ if (diskRasd == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get default values for 'Microsoft Synthetic
Disk Drive'"));
+ goto cleanup;
+ }
+
+ /* Create the attribute _PATH for the RASD object */
+ if (hypervGetResourceAllocationSettingDataPATH(domain,
+ ideRasd->data->InstanceID,
&ideRasdPath) < 0) {
+ goto cleanup;
+ }
+
+ /* Add default disk drive */
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",
uuid_string);
+ eprparam1.query = &query;
+ eprparam1.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM 1
+ embeddedparam1.nbProps = 4;
+ tab_props = (properties_t *) malloc(embeddedparam1.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Parent";
+ (*tab_props).val = ideRasdPath;
+ (*(tab_props+1)).name = "Address";
+ (*(tab_props+1)).val = ideControlerAddr;
+ (*(tab_props+2)).name = "ResourceType";
+ (*(tab_props+2)).val = "22";
+ (*(tab_props+3)).name = "ResourceSubType";
+ (*(tab_props+3)).val = diskRasd->data->ResourceSubType;
+ embeddedparam1.instanceName = MSVM_RESOURCEALLOCATIONSETTINGDATA_CLASSNAME;
+ embeddedparam1.prop_t = tab_props;
+
+ // CREATE invokeXmlParam tab
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "TargetSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam1;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam1;
+
+ if (hypervInvokeMethod(priv, params,
nb_params, "AddVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add
default disk drive"));
+ goto cleanup;
+ }
+
+ /* Get the instance of the new default drive disk */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_VirtualSystemSettingDataComponent
"
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ virtualSystemSettingData->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+
&resourceAllocationSettingData3) < 0) {
+ goto cleanup;
+ }
+ newDiskDrive = resourceAllocationSettingData3;
+ while (newDiskDrive != NULL) {
+ if (newDiskDrive->data->ResourceType == 22 &&
+ strcmp(newDiskDrive->data->ResourceSubType, "Microsoft Synthetic
Disk Drive") == 0 &&
+ strcmp(newDiskDrive->data->Parent, ideRasdPath) == 0 &&
+ strcmp(newDiskDrive->data->Address, ideControlerAddr) == 0) {
+ break;
+ }
+ newDiskDrive = newDiskDrive->next;
+ }
+ if (newDiskDrive == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not find 'Microsoft Synthetic Disk
Drive'"));
+ goto cleanup;
+ }
+
+ /* Get the settings for 'Microsoft Virtual Hard Disk' */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_ALLOCATIONCAPABILITIES_WQL_SELECT);
+ virBufferAddLit(&query, "WHERE ResourceSubType = 'Microsoft Virtual Hard
Disk'");
+ if (hypervGetMsvmAllocationCapabilitiesList(priv, &query,
+ &allocationCapabilities2) < 0) {
+ goto cleanup;
+ }
+
+ /* Get default values for 'Microsoft Virtual Hard Drive' */
+ virBufferFreeAndReset(&query);
+ virBufferAsprintf(&query,
+ "associators of "
+ "{Msvm_AllocationCapabilities.InstanceID=\"%s\"}
"
+ "where AssocClass = Msvm_SettingsDefineCapabilities "
+ "ResultClass = Msvm_ResourceAllocationSettingData",
+ allocationCapabilities2->data->InstanceID);
+ if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query,
+
&resourceAllocationSettingData4) < 0) {
+ goto cleanup;
+ }
+ diskRasd = resourceAllocationSettingData4;
+ while (diskRasd != NULL) {
+ if (strstr(diskRasd->data->InstanceID, "Default") != NULL) {
+ // Default values
+ break;
+ }
+ diskRasd = diskRasd->next;
+ }
+ if (diskRasd == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get default values for 'Microsoft Virtual
Hard Drive'"));
+ goto cleanup;
+ }
+
+ /* Create the attribute _PATH for the RASD object */
+ if (hypervGetResourceAllocationSettingDataPATH(domain,
+ newDiskDrive->data->InstanceID,
&newDiskDrivePath) < 0) {
+ goto cleanup;
+ }
+
+ /* Add the new VHD */
+ // PREPARE EPR PARAM 2
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",
uuid_string);
+ eprparam2.query = &query;
+ eprparam2.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM 2
+ VIR_FREE(tab_props);
+ embeddedparam2.nbProps = 4;
+ tab_props = (properties_t *) malloc(embeddedparam2.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Parent";
+ (*tab_props).val = newDiskDrivePath;
+ (*(tab_props+1)).name = "Connection";
+ (*(tab_props+1)).val = disk->src->path;
+ (*(tab_props+2)).name = "ResourceType";
+ (*(tab_props+2)).val = "21";
+ (*(tab_props+3)).name = "ResourceSubType";
+ (*(tab_props+3)).val = diskRasd->data->ResourceSubType;
+ embeddedparam2.instanceName = MSVM_RESOURCEALLOCATIONSETTINGDATA_CLASSNAME;
+ embeddedparam2.prop_t = tab_props;
+
+ // CREATE invokeXmlParam tab
+ VIR_FREE(params);
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "TargetSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam2;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam2;
+
+ if (hypervInvokeMethod(priv, params, nb_params,
"AddVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not attach hard disk drive"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (ideRasdPath != NULL) VIR_FREE(ideRasdPath);
+ if (newDiskDrivePath != NULL) VIR_FREE(newDiskDrivePath);
+ if (ideControler != NULL) VIR_FREE(ideControler);
+ if (ideControlerAddr != NULL) VIR_FREE(ideControlerAddr);
+ if (tab_props != NULL) VIR_FREE(tab_props);
+ if (params != NULL) VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData2);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData3);
+ hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData4);
+ hypervFreeObject(priv, (hypervObject *)allocationCapabilities);
+ hypervFreeObject(priv, (hypervObject *)allocationCapabilities2);
+ virBufferFreeAndReset(&query);
+
+ return ret;
+}
+
+
+
+/* hypervDomainAttachNetwork
+ * FIXME:
+ * - implement corresponding detach function
+ */
+static int
+hypervDomainAttachNetwork(virDomainPtr domain, virDomainNetDefPtr net)
+{
+ int ret = -1, nb_params;
+ const char *selector1 =
"CreationClassName=Msvm_VirtualSwitchManagementService";
+ const char *selector2 =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN], guid_string[VIR_UUID_STRING_BUFLEN];
+ unsigned char guid[VIR_UUID_BUFLEN];
+ char *virtualSystemIdentifiers = NULL, *switchPortPATH = NULL;
+ hypervPrivate *priv = domain->conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ eprParam eprparam1, eprparam2;
+ simpleParam simpleparam1, simpleparam2, simpleparam3;
+ embeddedParam embeddedparam;
+ properties_t *tab_props = NULL;
+ invokeXmlParam *params = NULL;
+ Msvm_SwitchPort *switchPort = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ /* Initialization */
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ VIR_DEBUG("network=%s, uuid=%s", net->data.network.name, uuid_string);
+
+ /* Create virtual switch port */
+ // PREPARE EPR PARAM 1
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where ElementName = \"%s\"",
net->data.network.name);
+ eprparam1.query = &query;
+ eprparam1.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE SIMPLE PARAMS
+ virUUIDGenerate(guid);
+ virUUIDFormat(guid, guid_string);
+ simpleparam1.value = guid_string;
+ simpleparam2.value = "Dynamic Ethernet Switch Port";
+ simpleparam3.value = "";
+
+ // CREATE invokeXmlParam tab
+ nb_params = 4;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "VirtualSwitch";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam1;
+ (*(params+1)).name = "Name";
+ (*(params+1)).type = SIMPLE_PARAM;
+ (*(params+1)).param = &simpleparam1;
+ (*(params+2)).name = "FriendlyName";
+ (*(params+2)).type = SIMPLE_PARAM;
+ (*(params+2)).param = &simpleparam2;
+ (*(params+3)).name = "ScopeOfResidence";
+ (*(params+3)).type = SIMPLE_PARAM;
+ (*(params+3)).param = &simpleparam3;
+
+ if (hypervInvokeMethod(priv, params, nb_params, "CreateSwitchPort",
+ MSVM_VIRTUALSWITCHMANAGEMENTSERVICE_RESOURCE_URI, selector1)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not create port for virtual switch
'%s'"), net->data.network.name);
+ goto cleanup;
+ }
+
+ /* Get a reference of the switch port created previously */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_SWITCHPORT_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",
guid_string);
+ if (hypervGetMsvmSwitchPortList(priv, &query, &switchPort) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Method hypervGetMsvmSwitchPortList failed with
query=%s"), query.e);
+ goto cleanup;
+ }
+ if (switchPort == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get switch port with Name=%s"),
guid_string);
+ goto cleanup;
+ }
+
+ /* Get a reference of the given virtual switch */
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where ElementName = \"%s\"",
net->data.network.name);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Method hypervGetMsvmVirtualSwitchList failed with
query=%s"), query.e);
+ goto cleanup;
+ }
+ if (virtualSwitch == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get virtual switch '%s'"),
net->data.network.name);
+ goto cleanup;
+ }
+
+ /* Add the synthetic ethernet port to the VM */
+ // PREPARE EPR PARAM 2
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",
uuid_string);
+ eprparam2.query = &query;
+ eprparam2.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // PREPARE EMBEDDED PARAM
+ virUUIDGenerate(guid);
+ virUUIDFormat(guid, guid_string);
+ virtualSystemIdentifiers = (char *) malloc((strlen(guid_string)+3) * sizeof(char));
+ sprintf(virtualSystemIdentifiers, "{%s}", guid_string);
+ hypervGetSwitchPortPATH(domain, switchPort->data->Name,
+ virtualSwitch->data->Name, &switchPortPATH);
+ embeddedparam.nbProps = 5;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps * sizeof(properties_t));
+ (*tab_props).name = "Connection";
+ (*tab_props).val = switchPortPATH;
+ (*(tab_props+1)).name = "ElementName";
+ (*(tab_props+1)).val = "Network Adapter";
+ (*(tab_props+2)).name = "VirtualSystemIdentifiers";
+ (*(tab_props+2)).val = virtualSystemIdentifiers;
+ (*(tab_props+3)).name = "ResourceType";
+ (*(tab_props+3)).val = "10";
+ (*(tab_props+4)).name = "ResourceSubType";
+ (*(tab_props+4)).val = "Microsoft Synthetic Ethernet Port";
+ embeddedparam.instanceName = MSVM_SYNTHETICETHERNETPORTSETTINGDATA_CLASSNAME;
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam tab
+ VIR_FREE(params);
+ nb_params = 2;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "TargetSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam2;
+ (*(params+1)).name = "ResourceSettingData";
+ (*(params+1)).type = EMBEDDED_PARAM;
+ (*(params+1)).param = &embeddedparam;
+
+ if (hypervInvokeMethod(priv, params, nb_params,
"AddVirtualSystemResources",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector2)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach the network"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (virtualSystemIdentifiers != NULL) VIR_FREE(virtualSystemIdentifiers);
+ if (switchPortPATH != NULL) VIR_FREE(switchPortPATH);
+ if (tab_props!= NULL) VIR_FREE(tab_props);
+ if (params != NULL) VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)switchPort);
+ hypervFreeObject(priv, (hypervObject *)virtualSwitch);
+ virBufferFreeAndReset(&query);
+
+ return ret;
+}
+
+
+static int
+hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml,
+ unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int ret = -1;
+ hypervPrivate *priv = domain->conn->privateData;
+ virDomainDefPtr def = NULL;
+ virDomainDeviceDefPtr dev = NULL;
+ char *xmlDomain = NULL;
+
+ // Get domain definition
+ if ((xmlDomain = hypervDomainGetXMLDesc(domain, 0)) == NULL) {
+ goto cleanup;
+ }
+ if ((def = virDomainDefParseString(xmlDomain, priv->caps, priv->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_HYPERV,
VIR_DOMAIN_XML_INACTIVE)) == NULL) {
+ goto cleanup;
+ }
+
+ // Get domain device definition
+ if ((dev = virDomainDeviceDefParse(xml, def, priv->caps,
+ priv->xmlopt, VIR_DOMAIN_XML_INACTIVE)) ==
NULL) {
+ goto cleanup;
+ }
+
+ switch (dev->type) {
+ /* Device = disk */
+ case VIR_DOMAIN_DEVICE_DISK:
+ if (hypervDomainAttachDisk(domain, dev->data.disk) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach disk"));
+ goto cleanup;
+ }
+ VIR_DEBUG("Disk attached");
+ break;
+
+ /* Device = network */
+ case VIR_DOMAIN_DEVICE_NET:
+ if (hypervDomainAttachNetwork(domain,
dev->data.net) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach network"));
+ goto cleanup;
+ }
+ VIR_DEBUG("Network attached");
+ break;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Device attachment of type %d is not implemented"),
dev->type);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ virDomainDefFree(def);
+ virDomainDeviceDefFree(dev);
+ if (xmlDomain != NULL) VIR_FREE(xmlDomain);
+
+ return ret;
+}
+
+
+
+static int
+hypervDomainAttachDevice(virDomainPtr domain, const char *xml)
+{
+ return hypervDomainAttachDeviceFlags(domain, xml, 0);
+}
+
+
+
+static virDomainPtr
+hypervDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+ hypervPrivate *priv = conn->privateData;
+ virDomainDefPtr def = NULL;
+ virDomainPtr domain = NULL;
+ invokeXmlParam *params = NULL;
+ properties_t *tab_props = NULL;
+ embeddedParam embeddedparam;
+ int nb_params, i;
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+
+ // Parsing XML
+ if ((def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_HYPERV,
VIR_DOMAIN_XML_INACTIVE)) == NULL) {
+ goto cleanup;
+ }
+
+ /* Create the VM if not exists */
+ if (!(def->uuid != NULL &&
+ (domain = hypervDomainLookupByUUID(conn, def->uuid)) != NULL)) {
+
+ // PREPARE EMBEDDED PARAM
+ /* Edit only VM name */
+ //FIXME: cannot edit VM UUID
+ embeddedparam.nbProps = 1;
+ tab_props = (properties_t *) malloc(embeddedparam.nbProps *
sizeof(properties_t));
+ (*tab_props).name = "ElementName";
+ (*tab_props).val = def->name;
+ embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData";
+ embeddedparam.prop_t = tab_props;
+
+ // CREATE invokeXmlParam
+ nb_params = 1;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "SystemSettingData";
+ (*params).type = EMBEDDED_PARAM;
+ (*params).param = &embeddedparam;
+
+ /* Create VM */
+ if (hypervInvokeMethod(priv, params, nb_params, "DefineVirtualSystem",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI,
selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not create new domain %s"), def->name);
+ goto cleanup;
+ }
+
+ // Get domain pointer
+ domain = hypervDomainLookupByName(conn, def->name);
+
+ VIR_DEBUG("Domain created: name=%s, uuid=%s",
+ domain->name, virUUIDFormat(domain->uuid, uuid_string));
+ }
+
+ /* Set VM maximum memory */
+ if (def->mem.max_balloon > 0) {
+ if (hypervDomainSetMaxMemory(domain, def->mem.max_balloon) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not set VM maximum memory"));
+ }
+ }
+
+ /* Set VM memory */
+ if (def->mem.cur_balloon > 0) {
+ if (hypervDomainSetMemory(domain, def->mem.cur_balloon) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not set VM memory"));
+ }
+ }
+
+ /* Set VM vcpus */
+ if (def->vcpus > 0) {
+ if (hypervDomainSetVcpus(domain, def->vcpus) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not set VM vCPUs"));
+ }
+ }
+
+ /* Attach networks */
+ for (i = 0; i < def->nnets; i++) {
+ if (hypervDomainAttachNetwork(domain, def->nets[i]) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach network"));
+ }
+ }
+
+ /* Attach disks */
+ for (i = 0; i < def->ndisks; i++) {
+ if (hypervDomainAttachDisk(domain, def->disks[i]) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not attach disk"));
+ }
+ }
+
+ cleanup:
+ virDomainDefFree(def);
+ if (tab_props != NULL) VIR_FREE(tab_props);
+ if (params != NULL) VIR_FREE(params);
+
+ return domain;
+}
+
+
+
+static virDomainPtr
+hypervDomainCreateXML(virConnectPtr conn, const char *xmlDesc, unsigned int flags)
+{
+ virDomainPtr domain;
+
+ virCheckFlags(VIR_DOMAIN_NONE |VIR_DOMAIN_START_PAUSED |VIR_DOMAIN_START_AUTODESTROY,
NULL);
+
+ // Create new domain
+ domain = hypervDomainDefineXML(conn, xmlDesc);
+ if (domain == NULL)
+ return NULL;
+
+ // Start domain
+ if (hypervInvokeMsvmComputerSystemRequestStateChange(domain,
+
MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not start the domain %s"), domain->name);
+ return domain;
+ }
+
+ // If the VIR_DOMAIN_START_PAUSED flag is set,
+ // the guest domain will be started, but its CPUs will remain paused
+ if (flags & VIR_DOMAIN_START_PAUSED) {
+ if (hypervDomainSuspend(domain) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not pause the domain %s"),
domain->name);
+ }
+ }
+
+ // If the VIR_DOMAIN_START_AUTODESTROY flag is set,
+ // the guest domain will be automatically destroyed
+ // when the virConnectPtr object is finally released
+ if (flags & VIR_DOMAIN_START_AUTODESTROY) {
+ //FIXME: wait till virConnectPtr is released
+ if (hypervDomainDestroy(domain) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not destroy the domain %s"),
domain->name);
+ }
+ }
+
+ return domain;
+}
+
+
+
+static int
+hypervDomainUndefineFlags(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
+{
+ int result = -1, nb_params;
+ const char *selector =
"CreationClassName=Msvm_VirtualSystemManagementService";
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = domain->conn->privateData;
+ invokeXmlParam *params = NULL;
+ eprParam eprparam;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ComputerSystem *computerSystem = NULL;
+
+ virCheckFlags(0, -1);
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+ goto cleanup;
+ }
+
+ /* Shutdown the VM if not disabled */
+ if (computerSystem->data->EnabledState !=
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_DISABLED) {
+ if (hypervDomainShutdown(domain) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Deleting the VM */
+
+ // PREPARE EPR PARAM
+ virBufferFreeAndReset(&query);
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",
uuid_string);
+ eprparam.query = &query;
+ eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
+
+ // CREATE invokeXmlParam tab
+ nb_params = 1;
+ params = (invokeXmlParam *) malloc(nb_params * sizeof(invokeXmlParam));
+ (*params).name = "ComputerSystem";
+ (*params).type = EPR_PARAM;
+ (*params).param = &eprparam;
+
+ // DESTROY VM
+ if (hypervInvokeMethod(priv, params, nb_params, "DestroyVirtualSystem",
+ MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not delete
domain"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (params != NULL) VIR_FREE(params);
+ hypervFreeObject(priv, (hypervObject *)computerSystem);
+ virBufferFreeAndReset(&query);
+
+ return result;
+}
+
+
+
+static int
+hypervDomainUndefine(virDomainPtr domain)
+{
+ return hypervDomainUndefineFlags(domain, 0);
+}
+
+
static virDriver hypervDriver = {
.no = VIR_DRV_HYPERV,
@@ -1389,6 +3291,31 @@ static virDriver hypervDriver = {
.domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */
.domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */
.connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
+ .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.9 */
+ .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.9 */
+ .domainShutdown = hypervDomainShutdown, /* 1.2.9 */
+ .domainShutdownFlags = hypervDomainShutdownFlags, /* 1.2.9 */
+ .domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /*
1.2.9 */
+ .domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.9 */
+ .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.9 */
+ .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.9 */
+ .connectGetVersion = hypervConnectGetVersion, /* 1.2.9 */
+ .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.9 */
+ .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.9 */
+ .domainDefineXML = hypervDomainDefineXML, /* 1.2.9 */
+ .domainSetMemory = hypervDomainSetMemory, /* 1.2.9 */
+ .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.9 */
+ .domainSetVcpus = hypervDomainSetVcpus, /* 1.2.9 */
+ .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.9 */
+ .domainAttachDevice = hypervDomainAttachDevice, /* 1.2.9 */
+ .domainAttachDeviceFlags = hypervDomainAttachDeviceFlags, /* 1.2.9 */
+ .connectGetMaxVcpus = hypervConnectGetMaxVcpus, /* 1.2.9 */
+ .domainCreateXML = hypervDomainCreateXML, /* 1.2.9 */
+ .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.9 */
+ .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.9 */
+ .domainUndefine = hypervDomainUndefine, /* 1.2.9 */
+ .domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.9 */
+ .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.9 */
};
diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c
index 6f54f44..ad24431 100644
--- a/src/hyperv/hyperv_network_driver.c
+++ b/src/hyperv/hyperv_network_driver.c
@@ -28,6 +28,9 @@
#include "viralloc.h"
#include "viruuid.h"
#include "hyperv_network_driver.h"
+#include "virstring.h"
+#include "hyperv_wmi.h"
+#include "network_conf.h"
#define VIR_FROM_THIS VIR_FROM_HYPERV
@@ -60,11 +63,246 @@ hypervNetworkClose(virConnectPtr conn)
}
+static int
+hypervConnectNumOfNetworks(virConnectPtr conn)
+{
+ int ret = -1, count = 0;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState = %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0)
{
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ count++;
+ }
+
+ ret = count;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return ret;
+}
+
+
+static int
+hypervConnectListNetworks(virConnectPtr conn, char **const names, int maxnames)
+{
+ int i, count = 0;
+ bool success = false;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ if (maxnames <= 0) {
+ return 0;
+ }
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState = %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0)
{
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ if (VIR_STRDUP(names[count], virtualSwitch->data->ElementName) < 0) {
+ goto cleanup;
+ }
+ count++;
+ if (count >= maxnames) {
+ break;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (!success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return count;
+}
+
+
+static int
+hypervConnectNumOfDefinedNetworks(virConnectPtr conn)
+{
+ int ret = -1, count = 0;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState <> %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0)
{
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ count++;
+ }
+
+ ret = count;
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return ret;
+}
+
+
+static int
+hypervConnectListDefinedNetworks(virConnectPtr conn, char **const names, int maxnames)
+{
+ int i, count = 0;
+ bool success = false;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitchList = NULL;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ if (maxnames <= 0) {
+ return 0;
+ }
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where HealthState <> %d", 5);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0)
{
+ goto cleanup;
+ }
+
+ for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL;
+ virtualSwitch = virtualSwitch->next) {
+ if (VIR_STRDUP(names[count], virtualSwitch->data->ElementName) < 0) {
+ goto cleanup;
+ }
+ count++;
+ if (count >= maxnames) {
+ break;
+ }
+ }
+
+ success = true;
+
+ cleanup:
+ if (!success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+ count = -1;
+ }
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitchList);
+ return count;
+}
+
+
+static virNetworkPtr
+hypervNetworkLookupByName(virConnectPtr conn, const char *name)
+{
+ virNetworkPtr network = NULL;
+ hypervPrivate *priv = conn->privateData;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where Description = \"%s\" and
ElementName = \"%s\"",
+ "Microsoft Virtual Switch", name);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) {
+ goto cleanup;
+ }
+ if (virtualSwitch == NULL) {
+ virReportError(VIR_ERR_NO_NETWORK,
+ _("No network found with name %s"), name);
+ goto cleanup;
+ }
+
+ hypervMsvmVirtualSwitchToNetwork(conn, virtualSwitch, &network);
+
+ cleanup:
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *) virtualSwitch);
+ return network;
+}
+
+
+static char *
+hypervNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags)
+{
+ char *xml = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ hypervPrivate *priv = network->conn->privateData;
+ virNetworkDefPtr def = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_VirtualSwitch *virtualSwitch = NULL;
+
+ /* Flags checked by virNetworkDefFormat */
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ virUUIDFormat(network->uuid, uuid_string);
+
+ /* Get Msvm_VirtualSwitch */
+ virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT);
+ virBufferAsprintf(&query, "where Name = \"%s\"",
uuid_string);
+ if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) {
+ goto cleanup;
+ }
+ if (virtualSwitch == NULL) {
+ virReportError(VIR_ERR_NO_NETWORK,
+ _("No network found with UUID %s"), uuid_string);
+ goto cleanup;
+ }
+
+ /* Fill struct */
+ if (virUUIDParse(virtualSwitch->data->Name, def->uuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ virtualSwitch->data->Name);
+ return NULL;
+ }
+
+ if (VIR_STRDUP(def->name, virtualSwitch->data->ElementName) < 0)
+ goto cleanup;
+
+ xml = virNetworkDefFormat(def, flags);
+
+ cleanup:
+ virNetworkDefFree(def);
+ virBufferFreeAndReset(&query);
+ hypervFreeObject(priv, (hypervObject *)virtualSwitch);
+ return xml;
+}
static virNetworkDriver hypervNetworkDriver = {
.name = "Hyper-V",
.networkOpen = hypervNetworkOpen, /* 0.9.5 */
.networkClose = hypervNetworkClose, /* 0.9.5 */
+ .connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.9 */
+ .connectListNetworks = hypervConnectListNetworks, /* 1.2.9 */
+ .connectNumOfDefinedNetworks = hypervConnectNumOfDefinedNetworks, /* 1.2.9 */
+ .connectListDefinedNetworks = hypervConnectListDefinedNetworks, /* 1.2.9 */
+ .networkLookupByName = hypervNetworkLookupByName, /* 1.2.9 */
+ .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.9 */
};
diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h
index 574bb5f..7c28053 100644
--- a/src/hyperv/hyperv_private.h
+++ b/src/hyperv/hyperv_private.h
@@ -27,12 +27,21 @@
# include "virerror.h"
# include "hyperv_util.h"
# include "openwsman.h"
+# include "capabilities.h"
+# include "domain_conf.h"
+
+#ifndef WIN32
+# include <pthread.h>
+#endif
typedef struct _hypervPrivate hypervPrivate;
struct _hypervPrivate {
hypervParsedUri *parsedUri;
WsManClient *client;
+ virCapsPtr caps;
+ virDomainXMLOptionPtr xmlopt; /* to parse Domain XML */
+ pthread_mutex_t mutex; /* to protect against concurrent calls (openwsman library not
thread-safe) */
};
#endif /* __HYPERV_PRIVATE_H__ */
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
index acb705c..e84e208 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -33,16 +33,752 @@
#include "hyperv_wmi.h"
#include "virstring.h"
+# include <wsman-xml-api.h>
+# include <wsman-client.h>
+# include <wsman-client-transport.h>
+# include <wsman-soap.h>
+# include <libxml/tree.h>
+# include "hyperv_wmi_classes_attr.generated.h"
+
#define WS_SERIALIZER_FREE_MEM_WORKS 0
-#define ROOT_CIMV2 \
- "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
+#define VIR_FROM_THIS VIR_FROM_HYPERV
-#define ROOT_VIRTUALIZATION \
- "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
+/* Flag to dump WSMAN requests */
+#define DUMP_REQUEST 0
-#define VIR_FROM_THIS VIR_FROM_HYPERV
+/*
+ CAUTION: Special note regarding multi-threading
+ The openwsman library is not thread-safe (as reported in issue #10 "Simultaneous
WsMan queries")
+ It has not been designed to allow to share the same connection for concurrent calls to
wsmc_action_xxxx fonctions.
+ This implementation of this hyperv libvirt driver shares the same connection for all
these calls.
+ Therefore, we have used a mutex to protect all functions that make usage of the
wsmc_action_xxxx fonctions.
+*/
+
+
+/*
+ * Prototypes of internals functions
+ */
+
+const char *
+hypervGetPropType(const char * className, const char *attrName);
+
+int
+hypervCreateXmlStruct(const char *methodName, const char *classURI, WsXmlDocH
*xmlDocRoot, WsXmlNodeH *xmlNodeMethod);
+
+int
+hypervAddEmbeddedParam(properties_t *prop_t, int nbProps, const char *paramName, const
char *instanceName, const char *classURI, WsXmlNodeH *parentNode);
+
+int
+hypervAddSimpleParam(const char *paramName, const char* value, const char *classURI,
WsXmlNodeH *parentNode);
+
+int
+hypervAddEprParam(const char *paramName, virBufferPtr query, const char *root, const char
*classURI, WsXmlNodeH *parentNode, WsXmlDocH doc, hypervPrivate *priv);
+
+int
+hypervInvokeMethodXml(hypervPrivate *priv, WsXmlDocH xmlDocRoot, const char *methodName,
const char *ressourceURI, const char *selector);
+
+
+
+/* Create XML structure */
+int
+hypervCreateXmlStruct(const char *methodName, const char *classURI,
+ WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod)
+{
+
+ virBuffer method_buff = VIR_BUFFER_INITIALIZER;
+ char *methodNameInput = NULL;
+
+ virBufferAsprintf(&method_buff, "%s_INPUT", methodName);
+ methodNameInput = virBufferContentAndReset(&method_buff);
+
+ if (methodNameInput == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create Xml Doc"));
+ goto cleanup;
+ }
+
+ *xmlDocRoot = ws_xml_create_doc(NULL, methodNameInput);
+ if (*xmlDocRoot == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create Xml Doc with given parameter
xmlDocRoot"));
+ goto cleanup;
+ }
+
+ *xmlNodeMethod = xml_parser_get_root(*xmlDocRoot);
+ if (*xmlNodeMethod == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get xmlDocRoot root node"));
+ goto cleanup;
+ }
+
+ //add namespace to xmlNodeMethode
+ ws_xml_set_ns(*xmlNodeMethod, classURI, "p");
+
+ VIR_FREE(methodNameInput);
+ return 0;
+
+ cleanup:
+
+ VIR_FREE(methodNameInput);
+ if (*xmlDocRoot != NULL) {
+ ws_xml_destroy_doc(*xmlDocRoot);
+ *xmlDocRoot = NULL;
+ }
+ return -1;
+}
+
+
+/* Get attribute type of a given attribute */
+const char *
+hypervGetPropType(const char * className, const char *attrName)
+{
+ const char * res = NULL;
+ int i,y;
+
+ i = 0;
+ while ( cimClasses[i].name[0] != '\0') {
+ if(strcmp(cimClasses[i].name,className ) == 0){
+ y = 0;
+ while ( cimClasses[i].cimTypesPtr[y].name[0] != '\0') {
+ if(strcmp(cimClasses[i].cimTypesPtr[y].name,attrName ) == 0){
+ res = cimClasses[i].cimTypesPtr[y].type;
+ break;
+ }
+ y++;
+ }
+ break;
+ }
+ i++;
+ }
+ return res;
+}
+
+
+/* Adding an Embedded Instance node to a parent node given in parameter */
+int
+hypervAddEmbeddedParam(properties_t *prop_t, int nbProps, const char *paramName,
+ const char *instanceName, const char *classURI, WsXmlNodeH
*parentNode)
+{
+
+ int result = -1;
+ WsXmlNodeH xmlNodeInstance = NULL;
+ WsXmlNodeH xmlNodeProperty = NULL;
+ WsXmlNodeH xmlNodeParam = NULL;
+ WsXmlNodeH xmlNodeArray = NULL;
+ WsXmlDocH xmlDocTemp = NULL;
+ WsXmlDocH xmlDocCdata = NULL;
+ xmlBufferPtr xmlBufferNode = NULL;
+ const xmlChar *xmlCharCdataContent = NULL;
+ xmlNodePtr xmlNodeCdata = NULL;
+ char* type = NULL; /* Must not be freed */
+ char* typeCopy = NULL;
+ bool isArray = false;
+ int len = 0;
+ int i = 0;
+
+ /* Add child to given parent node*/
+ xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL);
+ if (xmlNodeParam == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child node to xmlNodeParam"));
+ goto cleanup;
+ }
+
+ /* Create temp Xml doc */
+ /* INSTANCE node */
+ xmlDocTemp = ws_xml_create_doc(NULL, "INSTANCE");
+ if (xmlDocTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create temporary Xml doc"));
+ goto cleanup;
+ }
+
+ xmlNodeInstance = xml_parser_get_root(xmlDocTemp);
+ if (xmlNodeInstance == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+
+ /* Add CLASSNAME node to INSTANCE node */
+ if (ws_xml_add_node_attr(xmlNodeInstance, NULL, "CLASSNAME", instanceName)
== NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add attribute to node "));
+ goto cleanup;
+ }
+
+ /* Property nodes */
+ while (i < nbProps) {
+
+ if (prop_t[i].name == NULL && prop_t[i].val == NULL ) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get properties from array "));
+ goto cleanup;
+ }
+
+ type = (char *) hypervGetPropType(instanceName,prop_t[i].name);
+ if (type == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get properties from array "));
+ goto cleanup;
+ }
+
+ /* Check if the attribute is an array or not */
+ if (strstr(type, "[]") != NULL) {
+ // The attribute is an array
+ isArray = true;
+ // Remove "[]" from the type; must be done on a copy
+ if (typeCopy != NULL) VIR_FREE(typeCopy);
+ typeCopy = strndup(type, strlen(type)-2);
+ type = typeCopy;
+ } else {
+ isArray = false;
+ }
+
+ xmlNodeProperty = ws_xml_add_child(xmlNodeInstance, NULL,
+
(isArray)?"PROPERTY.ARRAY":"PROPERTY", NULL);
+ if (xmlNodeProperty == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add child to node"));
+ goto cleanup;
+ }
+
+ if (ws_xml_add_node_attr(xmlNodeProperty, NULL, "NAME", prop_t[i].name)
== NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add attribute to node"));
+ goto cleanup;
+ }
+
+ if (ws_xml_add_node_attr(xmlNodeProperty, NULL, "TYPE", type) == NULL)
{
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add attribute to node"));
+ goto cleanup;
+ }
+
+ /* Add the node VALUE.ARRAY if the attribute is an array */
+ if (isArray) {
+ xmlNodeArray = ws_xml_add_child(xmlNodeProperty, NULL,
"VALUE.ARRAY", NULL);
+ if (xmlNodeArray == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add child to node"));
+ goto cleanup;
+ }
+ }
+
+ if (ws_xml_add_child((isArray)?xmlNodeArray:xmlNodeProperty, NULL,
"VALUE",prop_t[i].val) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add child to node"));
+ goto cleanup;
+ }
+
+ xmlNodeArray = NULL;
+ xmlNodeProperty = NULL;
+ i++;
+ }
+
+ /* Create CDATA node */
+ xmlBufferNode = xmlBufferCreate();
+ if (xmlNodeDump(xmlBufferNode,(xmlDocPtr)xmlDocTemp->parserDoc , (xmlNodePtr)
xmlNodeInstance, 0, 0) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+
+ len = xmlBufferLength(xmlBufferNode);
+ xmlCharCdataContent = xmlBufferContent(xmlBufferNode);
+ xmlNodeCdata = xmlNewCDataBlock ((xmlDocPtr)xmlDocCdata, xmlCharCdataContent, len );
+ if (xmlNodeCdata == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+ /*adding CDATA node child to the root node of the main doc given*/
+ if (xmlAddChild((xmlNodePtr)xmlNodeParam, xmlNodeCdata ) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not get root of temporary Xml doc"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ ws_xml_destroy_doc(xmlDocCdata);
+ ws_xml_destroy_doc(xmlDocTemp);
+ if (typeCopy != NULL) VIR_FREE(typeCopy);
+ if (xmlBufferNode != NULL) xmlBufferFree(xmlBufferNode);
+
+ return result;
+}
+
+
+/* Adding an Simple param node to a parent node given in parameter */
+int
+hypervAddSimpleParam(const char *paramName, const char* value,
+ const char *classURI, WsXmlNodeH *parentNode)
+{
+
+ int result = -1;
+ WsXmlNodeH xmlNodeParam = NULL;
+
+ xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, value);
+ if (xmlNodeParam == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not create simple param"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ return result;
+}
+
+
+/* Adding EPR param node to a parent node given in parameter */
+int
+hypervAddEprParam(const char *paramName, virBufferPtr query, const char *root,
+ const char *classURI, WsXmlNodeH *parentNode, WsXmlDocH doc,
hypervPrivate *priv)
+{
+
+ int result = -1;
+ WsXmlNodeH xmlNodeParam = NULL;
+ WsXmlNodeH xmlNodTemp = NULL;
+ WsXmlNodeH xmlNodeAdr = NULL;
+ WsXmlNodeH xmlNodeRef = NULL;
+ WsXmlDocH xmlDocResponse = NULL;
+ WsXmlNsH ns = NULL;
+ client_opt_t *options = NULL;
+ filter_t *filter = NULL;
+ char *enumContext = NULL;
+ char *query_string;
+ xmlNodePtr xmlNodeAdrPtr = NULL;
+ xmlNodePtr xmlNodeRefPtr = NULL;
+ xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc;
+
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
+
+ /* Request options and filter */
+ options = wsmc_options_init();
+
+ if (options == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not initialize options"));
+ goto cleanup;
+ }
+
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
+ wsmc_set_action_option(options, FLAG_ENUMERATION_ENUM_EPR);
+
+ query_string = virBufferContentAndReset(query);
+ filter = filter_create_simple(WSM_WQL_FILTER_DIALECT,query_string);
+ if (filter == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not create filter"));
+ goto cleanup;
+ }
+
+ /* Invoke enumerate action*/
+ xmlDocResponse = wsmc_action_enumerate(priv->client,root, options, filter);
+
+ /* Check return value */
+ if (hyperyVerifyResponse(priv->client, xmlDocResponse, "enumeration")
< 0) {
+ goto cleanup;
+ }
+
+ /* Get enumerate conext*/
+ enumContext = wsmc_get_enum_context(xmlDocResponse);
+
+ ws_xml_destroy_doc(xmlDocResponse);
+
+
+ /* Invoke pull action*/
+ xmlDocResponse = wsmc_action_pull(priv->client, classURI, options, filter,
enumContext);
+
+ /* Check return value */
+ if (hyperyVerifyResponse(priv->client, xmlDocResponse, "pull") < 0)
{
+ goto cleanup;
+ }
+
+ /* Extract EPR nodes childs */
+ xmlNodTemp = ws_xml_get_soap_body(xmlDocResponse);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup SOAP body"));
+ goto cleanup;
+ }
+
+ xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_PULL_RESP);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response"));
+ goto cleanup;
+ }
+
+ xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ENUMERATION, WSENUM_ITEMS);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response items"));
+ goto cleanup;
+ }
+
+ xmlNodTemp = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_EPR);
+ if (xmlNodTemp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response item EPR"));
+ goto cleanup;
+ }
+
+ xmlNodeAdr = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING, WSA_ADDRESS);
+ if (xmlNodeAdr == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response item ADDRESS"));
+ goto cleanup;
+ }
+ xmlNodeAdrPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeAdr, docPtr, 1);
+ if (xmlNodeAdrPtr == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not copy item ADDRESS"));
+ goto cleanup;
+ }
+
+ xmlNodeRef = ws_xml_get_child(xmlNodTemp, 0, XML_NS_ADDRESSING,
WSA_REFERENCE_PARAMETERS);
+ if (xmlNodeRef == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response item REFERENCE
PARAMETERS"));
+ goto cleanup;
+ }
+ xmlNodeRefPtr = xmlDocCopyNode((xmlNodePtr) xmlNodeRef, docPtr, 1);
+ if (xmlNodeRefPtr == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not copy item REFERENCE PARAMETERS"));
+ goto cleanup;
+ }
+
+ /* Build XmlDoc with adding previous EPR nodes childs */
+ xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, NULL);
+ if (xmlNodeParam == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child node to xmlNodeParam"));
+ goto cleanup;
+ }
+
+/*
+ The folowing line has been commented because of a memory corruption issue reported in
the openwsman library
+ [ issue #43 - xml_parser_ns_add: alloc item size, not pointer size ]
+ xmlNodeSetLang((xmlNodePtr) xmlNodeParam, BAD_CAST "en-US");
+*/
+ ns = ws_xml_ns_add(xmlNodeParam,
"http://schemas.xmlsoap.org/ws/2004/08/addressing", "a");
+ if (ns == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not set namespace adressing to
xmlNodeParam"));
+ goto cleanup;
+ }
+
+ ns = NULL;
+ ns = ws_xml_ns_add(xmlNodeParam,
"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd", "w");
+ if (ns == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not set namespace wsman to xmlNodeParam"));
+ goto cleanup;
+ }
+
+ if (xmlAddChild( (xmlNodePtr)*parentNode,(xmlNodePtr) xmlNodeParam) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child to xml parent node"));
+ goto cleanup;
+ }
+
+ if (xmlAddChild( (xmlNodePtr)xmlNodeParam, xmlNodeAdrPtr) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child to xml parent node"));
+ goto cleanup;
+ }
+
+ if (xmlAddChild( (xmlNodePtr)xmlNodeParam, xmlNodeRefPtr) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not add child to xml parent node"));
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (options != NULL) {
+ wsmc_options_destroy(options);
+ }
+ if (filter != NULL) {
+ filter_destroy(filter);
+ }
+ ws_xml_destroy_doc(xmlDocResponse);
+ VIR_FREE(enumContext);
+ VIR_FREE(query_string);
+ /* Unlock the mutex */
+ pthread_mutex_unlock(&priv->mutex);
+
+ return result;
+}
+
+
+/* Call wsmc_action_invoke() function of OpenWsman API with XML tree given in
parameters*/
+int
+hypervInvokeMethodXml(hypervPrivate *priv,WsXmlDocH xmlDocRoot,
+ const char *methodName, const char *ressourceURI, const char
*selector)
+{
+
+ int result = -1;
+ int returnCode;
+ char *instanceID = NULL;
+ char *xpath_expr_string = NULL;
+ char *returnValue = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ virBuffer xpath_expr_buff = VIR_BUFFER_INITIALIZER;
+ client_opt_t *options = NULL;
+ WsXmlDocH response = NULL;
+ Msvm_ConcreteJob *concreteJob = NULL;
+ bool completed = false;
+ bool locked;
+
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
+ locked = true;
+
+ options = wsmc_options_init();
+
+ if (options == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not initialize options"));
+ goto cleanup;
+ }
+
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
+ wsmc_add_selectors_from_str(options, selector);
+
+ /* Invoke action */
+ response =
wsmc_action_invoke(priv->client,ressourceURI,options,methodName,xmlDocRoot);
+
+ virBufferAsprintf(&xpath_expr_buff,
"/s:Envelope/s:Body/p:%s_OUTPUT/p:ReturnValue", methodName);
+ xpath_expr_string = virBufferContentAndReset(&xpath_expr_buff);
+
+ if (xpath_expr_string == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "ReturnValue", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* Check return value */
+ returnValue = ws_xml_get_xpath_value(response, xpath_expr_string);
+
+ VIR_FREE(xpath_expr_string);
+ xpath_expr_string = NULL;
+
+ if (returnValue == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "ReturnValue", "RequestStateChange");
+ goto cleanup;
+ }
+
+ if (virStrToLong_i(returnValue, NULL, 10, &returnCode) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse return code from '%s'"),
returnValue);
+ goto cleanup;
+ }
+
+ if (returnCode == CIM_RETURNCODE_TRANSITION_STARTED) {
+
+ virBufferAsprintf(&xpath_expr_buff,
"/s:Envelope/s:Body/p:%s_OUTPUT/p:Job/a:ReferenceParameters/w:SelectorSet/w:Selector[@Name='InstanceID']",
methodName);
+ xpath_expr_string = virBufferContentAndReset(&xpath_expr_buff);
+
+ if (xpath_expr_string == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "InstanceID", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* Get concrete job object */
+ instanceID = ws_xml_get_xpath_value(response, xpath_expr_string);
+
+ if (instanceID == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "InstanceID", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* hypervGetMsvmConcreteJobList calls hypervEnumAndPull which also tries to lock
priv->mutex */
+ pthread_mutex_unlock(&priv->mutex);
+ locked = false;
+
+ /* FIXME: Poll every 100ms until the job completes or fails. There
+ * seems to be no other way than polling. */
+ while (!completed) {
+ virBufferAddLit(&query, MSVM_CONCRETEJOB_WQL_SELECT);
+ virBufferAsprintf(&query, "where InstanceID =
\"%s\"", instanceID);
+
+ if (hypervGetMsvmConcreteJobList(priv, &query, &concreteJob) < 0)
{
+ goto cleanup;
+ }
+
+ if (concreteJob == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "Msvm_ConcreteJob",
"RequestStateChange");
+ goto cleanup;
+ }
+
+ switch (concreteJob->data->JobState) {
+ case MSVM_CONCRETEJOB_JOBSTATE_NEW:
+ case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
+ case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
+ case MSVM_CONCRETEJOB_JOBSTATE_SHUTTING_DOWN:
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+ concreteJob = NULL;
+
+ usleep(100 * 1000);
+ continue;
+
+ case MSVM_CONCRETEJOB_JOBSTATE_COMPLETED:
+ completed = true;
+ break;
+
+ case MSVM_CONCRETEJOB_JOBSTATE_TERMINATED:
+ case MSVM_CONCRETEJOB_JOBSTATE_KILLED:
+ case MSVM_CONCRETEJOB_JOBSTATE_EXCEPTION:
+ case MSVM_CONCRETEJOB_JOBSTATE_SERVICE:
+ goto cleanup;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Concrete job for %s invocation is in unknown
state"),
+ "RequestStateChange");
+ goto cleanup;
+ }
+ }
+ } else if (returnCode != CIM_RETURNCODE_COMPLETED_WITH_NO_ERROR) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invocation of %s returned an error: %s (%d)"),
+ "RequestStateChange",
hypervReturnCodeToString(returnCode),
+ returnCode);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (options != NULL)
+ wsmc_options_destroy(options);
+ if (response != NULL)
+ ws_xml_destroy_doc(response);
+ VIR_FREE(returnValue);
+ VIR_FREE(instanceID);
+ VIR_FREE(xpath_expr_string);
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+ virBufferFreeAndReset(&query);
+ virBufferFreeAndReset(&xpath_expr_buff);
+
+ /* Unlock the mutex if needed */
+ if (locked == true) pthread_mutex_unlock(&priv->mutex);
+
+ return result;
+}
+
+
+/* Generate a XML tree with all param_t given in parameters */
+int
+hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *param_t, int nbParameters,
+ const char* methodName, const char* providerURI, const char
*selector)
+{
+
+ int res = -1;
+ WsXmlDocH doc = NULL;
+ WsXmlNodeH methodNode = NULL;
+ eprParam *epr;
+ embeddedParam *embedded;
+ simpleParam *simple;
+ int i =0;
+
+ if (hypervCreateXmlStruct(methodName,providerURI,&doc,&methodNode) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not create xml base structure"));
+ goto cleanup;
+ }
+
+ while ( i < nbParameters) {
+ switch (param_t[i].type){
+ case EPR_PARAM:
+ epr = (eprParam*)param_t[i].param;
+ if (hypervAddEprParam(param_t[i].name,
epr->query,epr->wmiProviderURI,providerURI,&methodNode,doc,priv) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add EPR param to xml base structure
"));
+ goto cleanup;
+ }
+ break;
+ case EMBEDDED_PARAM:
+ embedded = (embeddedParam*)param_t[i].param;
+ if
(hypervAddEmbeddedParam(embedded->prop_t,embedded->nbProps,param_t[i].name,embedded->instanceName,providerURI,&methodNode)
< 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add embedded instance param to xml base
structure "));
+ goto cleanup;
+ }
+ break;
+ case SIMPLE_PARAM:
+ simple = (simpleParam*)param_t[i].param;
+ if
(hypervAddSimpleParam(param_t[i].name,simple->value,providerURI,&methodNode) <
0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Could not add embedded instance param to xml base
structure "));
+ goto cleanup;
+ }
+ break;
+ }
+ i++;
+ }
+
+ if (hypervInvokeMethodXml(priv,doc,methodName,providerURI,selector) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Error during invocation action"));
+ goto cleanup;
+ }
+
+ res = 0;
+
+ cleanup:
+ if (doc != NULL)
+ ws_xml_destroy_doc(doc);
+
+ return res;
+}
int
@@ -128,8 +864,13 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char
*root,
return -1;
}
- if (virBufferCheckError(query) < 0)
+ if (virBufferError(query)) {
+ virReportOOMError();
return -1;
+ }
+
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
serializerContext = wsmc_get_serialization_context(priv->client);
@@ -141,6 +882,10 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char
*root,
goto cleanup;
}
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
query_string = virBufferContentAndReset(query);
filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
@@ -259,6 +1004,9 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char
*root,
VIR_FREE(enumContext);
hypervFreeObject(priv, head);
+ /* Unlock the mutex */
+ pthread_mutex_unlock(&priv->mutex);
+
return result;
}
@@ -403,9 +1151,14 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr
domain,
virBuffer query = VIR_BUFFER_INITIALIZER;
Msvm_ConcreteJob *concreteJob = NULL;
bool completed = false;
+ bool locked;
virUUIDFormat(domain->uuid, uuid_string);
+ /* Protection against concurrent calls (the openwsman library is not thread-safe) */
+ pthread_mutex_lock(&priv->mutex);
+ locked = true;
+
if (virAsprintf(&selector,
"Name=%s&CreationClassName=Msvm_ComputerSystem",
uuid_string) < 0 ||
virAsprintf(&properties, "RequestedState=%d", requestedState) <
0)
@@ -419,6 +1172,10 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr
domain,
goto cleanup;
}
+#if DUMP_REQUEST
+ wsmc_set_action_option(options, FLAG_DUMP_REQUEST);
+#endif
+
wsmc_add_selectors_from_str(options, selector);
wsmc_add_prop_from_str(options, properties);
@@ -457,6 +1214,10 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr
domain,
goto cleanup;
}
+ /* hypervGetMsvmConcreteJobList calls hypervEnumAndPull which also tries to lock
priv->mutex */
+ pthread_mutex_unlock(&priv->mutex);
+ locked = false;
+
/* FIXME: Poll every 100ms until the job completes or fails. There
* seems to be no other way than polling. */
while (!completed) {
@@ -527,12 +1288,15 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr
domain,
VIR_FREE(instanceID);
hypervFreeObject(priv, (hypervObject *)concreteJob);
+ /* Unlock the mutex if needed */
+ if (locked == true) pthread_mutex_unlock(&priv->mutex);
+
return result;
}
int
hypervMsvmComputerSystemEnabledStateToDomainState
- (Msvm_ComputerSystem *computerSystem)
+(Msvm_ComputerSystem *computerSystem)
{
switch (computerSystem->data->EnabledState) {
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
@@ -676,5 +1440,31 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
}
+int
+hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn,
+ Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr
*network)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+
+ if (network == NULL || *network != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
argument"));
+ return -1;
+ }
+
+ if (virUUIDParse(virtualSwitch->data->Name, uuid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ virtualSwitch->data->Name);
+ return -1;
+ }
+
+ *network = virGetNetwork(conn, virtualSwitch->data->ElementName, uuid);
+
+ if (*network == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
#include "hyperv_wmi.generated.c"
diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h
index 5fbbbac..f4ac319 100644
--- a/src/hyperv/hyperv_wmi.h
+++ b/src/hyperv/hyperv_wmi.h
@@ -24,11 +24,61 @@
#ifndef __HYPERV_WMI_H__
# define __HYPERV_WMI_H__
+#define ROOT_CIMV2 \
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
+
+#define ROOT_VIRTUALIZATION \
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
+
# include "virbuffer.h"
# include "hyperv_private.h"
# include "hyperv_wmi_classes.h"
# include "openwsman.h"
+/*
+ * Type of parameters for hypervInvokeMethod function
+ */
+
+enum _PARAM_Type {
+ EPR_PARAM = 0,
+ SIMPLE_PARAM = 1,
+ EMBEDDED_PARAM = 2,
+};
+
+typedef struct _invokeXmlParam invokeXmlParam;
+struct _invokeXmlParam{
+ const char *name;
+ int type;
+ void *param;
+};
+
+typedef struct _eprParam eprParam;
+struct _eprParam{
+ virBufferPtr query;
+ const char *wmiProviderURI;
+};
+
+typedef struct _simpleParam simpleParam;
+struct _simpleParam{
+ const char *value;
+};
+
+typedef struct _properties_t properties_t;
+struct _properties_t{
+ const char *name;
+ const char *val;
+};
+
+typedef struct _embeddedParam embeddedParam;
+struct _embeddedParam{
+ const char *instanceName;
+ properties_t *prop_t;
+ int nbProps;
+};
+
+
+int
+hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *parameters, int
nbParameters,const char* methodName, const char* providerURI, const char *selector);
typedef struct _hypervObject hypervObject;
@@ -53,7 +103,7 @@ int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query,
const char *resourceUri, const char *className,
hypervObject **list);
-void hypervFreeObject(hypervPrivate *priv, hypervObject *object);
+void hypervFreeObject(hypervPrivate *priv ATTRIBUTE_UNUSED, hypervObject *object);
@@ -114,6 +164,13 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
Msvm_ComputerSystem **computerSystem);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_VirtualSwitch
+ */
+
+int hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn,
+ Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr *network);
+
# include "hyperv_wmi.generated.h"
diff --git a/src/hyperv/hyperv_wmi_generator.input
b/src/hyperv/hyperv_wmi_generator.input
index 97f9dff..7f828d3 100644
--- a/src/hyperv/hyperv_wmi_generator.input
+++ b/src/hyperv/hyperv_wmi_generator.input
@@ -12,8 +12,8 @@
# ...
# end
#
-# Allowed values for <type> are: boolean, string, datetime, int8, int16,
-# int32, int64, uint8, uint16, uint32 and uint64
+# Allowed values for <type> are: boolean, string, datetime, sint8, sint16,
+# sint32, sint64, uint8, uint16, uint32 and uint64
#
# The property <name> can be followed by [] to define a dynamic array.
#
@@ -72,8 +72,8 @@ class Msvm_ConcreteJob
datetime ElapsedTime
uint32 JobRunTimes
uint8 RunMonth
- int8 RunDay
- int8 RunDayOfWeek
+ sint8 RunDay
+ sint8 RunDayOfWeek
datetime RunStartInterval
uint16 LocalOrUtcTime
datetime UntilTime
@@ -196,7 +196,7 @@ class Win32_ComputerSystem
string Caption
uint16 ChassisBootupState
string CreationClassName
- int16 CurrentTimeZone
+ sint16 CurrentTimeZone
boolean DaylightInEffect
string Description
string DNSHostName
@@ -219,7 +219,7 @@ class Win32_ComputerSystem
uint8 OEMLogoBitmap[]
string OEMStringArray[]
boolean PartOfDomain
- int64 PauseAfterReset
+ sint64 PauseAfterReset
uint16 PCSystemType
uint16 PowerManagementCapabilities[]
boolean PowerManagementSupported
@@ -229,8 +229,8 @@ class Win32_ComputerSystem
string PrimaryOwnerContact
string PrimaryOwnerName
uint16 ResetCapability
- int16 ResetCount
- int16 ResetLimit
+ sint16 ResetCount
+ sint16 ResetLimit
string Roles[]
string Status
string SupportContactDescription[]
@@ -296,3 +296,517 @@ class Win32_Processor
string Version
uint32 VoltageCaps
end
+
+
+class CIM_DataFile
+ uint32 AccessMask
+ boolean Archive
+ string Caption
+ boolean Compressed
+ string CompressionMethod
+ string CreationClassName
+ datetime CreationDate
+ string CSCreationClassName
+ string CSName
+ string Description
+ string Drive
+ string EightDotThreeFileName
+ boolean Encrypted
+ string EncryptionMethod
+ string Extension
+ string FileName
+ uint64 FileSize
+ string FileType
+ string FSCreationClassName
+ string FSName
+ boolean Hidden
+ datetime InstallDate
+ uint64 InUseCount
+ datetime LastAccessed
+ datetime LastModified
+ string Manufacturer
+ string Name
+ string Path
+ boolean Readable
+ string Status
+ boolean System
+ 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
+
+class Msvm_VirtualSystemManagementService
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus
+ string StatusDescriptions
+ string Status
+ uint16 HealthState
+ uint16 EnabledState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ datetime TimeOfLastStateChange
+ string SystemCreationClassName
+ string SystemName
+ string CreationClassName
+ string Name
+ string PrimaryOwnerName
+ string PrimaryOwnerContact
+ string StartMode
+ boolean Started
+end
+
+class Msvm_VirtualSystemGlobalSettingData
+ string Caption
+ string Description
+ string ElementName
+ string InstanceID
+ string SystemName
+ uint16 SettingType
+ uint16 VirtualSystemType
+ string OtherVirtualSystemType
+ boolean AutoActivate
+ datetime CreationTime
+ string ExternalDataRoot
+ string SnapshotDataRoot
+ uint16 AutomaticStartupAction
+ datetime AutomaticStartupActionDelay
+ uint16 AutomaticShutdownAction
+ uint16 AutomaticRecoveryAction
+ string AdditionalRecoveryInformation
+ string ScopeOfResidence
+ uint32 DebugChannelId
+ boolean AllowFullSCSICommandSet
+ string Version
+end
+
+class Msvm_ResourceAllocationSettingData
+ string Caption
+ string Description
+ string InstanceID
+ string ElementName
+ uint16 ResourceType
+ string OtherResourceType
+ string ResourceSubType
+ string PoolID
+ uint16 ConsumerVisibility
+ string HostResource[]
+ string AllocationUnits
+ uint64 VirtualQuantity
+ uint64 Reservation
+ uint64 Limit
+ uint32 Weight
+ boolean AutomaticAllocation
+ boolean AutomaticDeallocation
+ string Parent
+ string Connection[]
+ string Address
+ uint16 MappingBehavior
+ string VirtualSystemIdentifiers[]
+end
+
+class Msvm_AllocationCapabilities
+ string Caption
+ string Description
+ string ElementName
+ string InstanceID
+ string OtherResourceType
+ uint16 RequestTypesSupported
+ string ResourceSubType
+ uint16 ResourceType
+ uint16 SharingMode
+ uint16 SupportedAddStates[]
+ uint16 SupportedRemoveStates[]
+end
+
+class Msvm_VirtualSwitch
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus[]
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ uint16 EnabledState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ datetime TimeOfLastStateChange
+ string CreationClassName
+ string Name
+ string PrimaryOwnerContact
+ string PrimaryOwnerName
+ string Roles[]
+ string NameFormat
+ string OtherIdentifyingInfo[]
+ string IdentifyingDescriptions[]
+ uint16 Dedicated[]
+ string OtherDedicatedDescriptions[]
+ uint16 ResetCapability
+ uint16 PowerManagementCapabilities[]
+ string ScopeOfResidence
+ uint32 NumLearnableAddresses
+ uint32 MaxVMQOffloads
+ uint32 MaxChimneyOffloads
+end
+
+class Msvm_SwitchPort
+ string Caption
+ string ElementName
+ datetime InstallDate
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ string SystemCreationClassName
+ string SystemName
+ string CreationClassName
+ string Description
+ uint16 OperationalStatus[]
+ uint16 EnabledState
+ datetime TimeOfLastStateChange
+ string Name
+ string NameFormat
+ uint16 ProtocolType
+ uint16 ProtocolIFType
+ string OtherTypeDescription
+ boolean BroadcastResetSupported
+ uint16 PortNumber
+ string ScopeOfResidence
+ uint32 VMQOffloadWeight
+ uint32 ChimneyOffloadWeight
+ uint32 VMQOffloadUsage
+ uint32 ChimneyOffloadUsage
+ uint32 VMQOffloadLimit
+ uint32 ChimneyOffloadLimit
+ boolean AllowMacSpoofing
+end
+
+class Msvm_SyntheticEthernetPortSettingData
+ string Caption
+ string Description
+ string InstanceID
+ string ElementName
+ uint16 ResourceType
+ string OtherResourceType
+ string ResourceSubType
+ string PoolID
+ uint16 ConsumerVisibility
+ string HostResource[]
+ string AllocationUnits
+ uint64 VirtualQuantity
+ uint64 Reservation
+ uint64 Limit
+ uint32 Weight
+ boolean AutomaticAllocation
+ boolean AutomaticDeallocation
+ string Parent
+ string Connection[]
+ string Address
+ uint16 MappingBehavior
+ string VirtualSystemIdentifiers[]
+ boolean StaticMacAddress
+end
+
+class Msvm_VirtualSwitchManagementService
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus[]
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ uint16 EnabledState
+ string OtherEnabledState
+ uint16 RequestedState
+ uint16 EnabledDefault
+ datetime TimeOfLastStateChange
+ string SystemCreationClassName
+ string SystemName
+ string CreationClassName
+ string Name
+ string PrimaryOwnerName
+ string PrimaryOwnerContact
+ string StartMode
+ boolean Started
+end
+
+class Win32_OperatingSystem
+ string BootDevice
+ string BuildNumber
+ string BuildType
+ string Caption
+ string CodeSet
+ string CountryCode
+ string CreationClassName
+ string CSCreationClassName
+ string CSDVersion
+ string CSName
+ sint16 CurrentTimeZone
+ boolean DataExecutionPrevention_Available
+ boolean DataExecutionPrevention_32BitApplications
+ boolean DataExecutionPrevention_Drivers
+ uint8 DataExecutionPrevention_SupportPolicy
+ boolean Debug
+ string Description
+ boolean Distributed
+ uint32 EncryptionLevel
+ uint8 ForegroundApplicationBoost
+ uint64 FreePhysicalMemory
+ uint64 FreeSpaceInPagingFiles
+ uint64 FreeVirtualMemory
+ datetime InstallDate
+ uint32 LargeSystemCache
+ datetime LastBootUpTime
+ datetime LocalDateTime
+ string Locale
+ string Manufacturer
+ uint32 MaxNumberOfProcesses
+ uint64 MaxProcessMemorySize
+ string MUILanguages[]
+ string Name
+ uint32 NumberOfLicensedUsers
+ uint32 NumberOfProcesses
+ uint32 NumberOfUsers
+ uint32 OperatingSystemSKU
+ string Organization
+ string OSArchitecture
+ uint32 OSLanguage
+ uint32 OSProductSuite
+ uint16 OSType
+ string OtherTypeDescription
+ boolean PAEEnabled
+ string PlusProductID
+ string PlusVersionNumber
+ boolean PortableOperatingSystem
+ boolean Primary
+ uint32 ProductType
+ string RegisteredUser
+ string SerialNumber
+ uint16 ServicePackMajorVersion
+ uint16 ServicePackMinorVersion
+ uint64 SizeStoredInPagingFiles
+ string Status
+ uint32 SuiteMask
+ string SystemDevice
+ string SystemDirectory
+ string SystemDrive
+ uint64 TotalSwapSpaceSize
+ uint64 TotalVirtualMemorySize
+ uint64 TotalVisibleMemorySize
+ string Version
+ string WindowsDirectory
+end
+
+class Win32_PerfFormattedData_HvStats_HyperVHypervisorVirtualProcessor
+ uint64 AddressDomainFlushesPersec
+ uint64 AddressSpaceEvictionsPersec
+ uint64 AddressSpaceFlushesPersec
+ uint64 AddressSpaceSwitchesPersec
+ uint64 APICEOIAccessesPersec
+ uint64 APICIPIsSentPersec
+ uint64 APICMMIOAccessesPersec
+ uint64 APICSelfIPIsSentPersec
+ uint64 APICTPRAccessesPersec
+ string Caption
+ uint64 ControlRegisterAccessesCost
+ uint64 ControlRegisterAccessesPersec
+ uint64 CPUIDInstructionsCost
+ uint64 CPUIDInstructionsPersec
+ uint64 CPUWaitTimePerDispatch
+ uint64 DebugRegisterAccessesCost
+ uint64 DebugRegisterAccessesPersec
+ string Description
+ uint64 EmulatedInstructionsCost
+ uint64 EmulatedInstructionsPersec
+ uint64 ExternalInterruptsCost
+ uint64 ExternalInterruptsPersec
+ uint64 Frequency_Object
+ uint64 Frequency_PerfTime
+ uint64 Frequency_Sys100NS
+ uint64 GlobalGVARangeFlushesPersec
+ uint64 GPASpaceHypercallsPersec
+ uint64 GuestPageTableMapsPersec
+ uint64 HardwareInterruptsPersec
+ uint64 HLTInstructionsCost
+ uint64 HLTInstructionsPersec
+ uint64 HypercallsCost
+ uint64 HypercallsPersec
+ uint64 IOInstructionsCost
+ uint64 IOInstructionsPersec
+ uint64 IOInterceptMessagesPersec
+ uint64 LargePageTLBFillsPersec
+ uint64 LocalFlushedGVARangesPersec
+ uint64 LogicalProcessorDispatchesPersec
+ uint64 LogicalProcessorHypercallsPersec
+ uint64 LogicalProcessorMigrationsPersec
+ uint64 LongSpinWaitHypercallsPersec
+ uint64 MemoryInterceptMessagesPersec
+ uint64 MSRAccessesCost
+ uint64 MSRAccessesPersec
+ uint64 MWAITInstructionsCost
+ uint64 MWAITInstructionsPersec
+ string Name
+ uint64 NestedPageFaultInterceptsCost
+ uint64 NestedPageFaultInterceptsPersec
+ uint64 OtherHypercallsPersec
+ uint64 OtherInterceptsCost
+ uint64 OtherInterceptsPersec
+ uint64 OtherMessagesPersec
+ uint64 PageFaultInterceptsCost
+ uint64 PageFaultInterceptsPersec
+ uint64 PageInvalidationsCost
+ uint64 PageInvalidationsPersec
+ uint64 PageTableAllocationsPersec
+ uint64 PageTableEvictionsPersec
+ uint64 PageTableReclamationsPersec
+ uint64 PageTableResetsPersec
+ uint64 PageTableValidationsPersec
+ uint64 PageTableWriteInterceptsPersec
+ uint64 PendingInterruptsCost
+ uint64 PendingInterruptsPersec
+ uint64 PercentGuestRunTime
+ uint64 PercentHypervisorRunTime
+ uint64 PercentRemoteRunTime
+ uint64 PercentTotalRunTime
+ uint64 ReflectedGuestPageFaultsPersec
+ uint64 SmallPageTLBFillsPersec
+ uint64 SyntheticInterruptHypercallsPersec
+ uint64 SyntheticInterruptsPersec
+ uint64 Timestamp_Object
+ uint64 Timestamp_PerfTime
+ uint64 Timestamp_Sys100NS
+ uint64 TotalInterceptsCost
+ uint64 TotalInterceptsPersec
+ uint64 TotalMessagesPersec
+ uint64 VirtualInterruptHypercallsPersec
+ uint64 VirtualInterruptsPersec
+ uint64 VirtualMMUHypercallsPersec
+ uint64 VirtualProcessorHypercallsPersec
+end
+
+class Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
+ uint64 AddressDomainFlushesPersec
+ uint64 AddressSpaceEvictionsPersec
+ uint64 AddressSpaceFlushesPersec
+ uint64 AddressSpaceSwitchesPersec
+ uint64 APICEOIAccessesPersec
+ uint64 APICIPIsSentPersec
+ uint64 APICMMIOAccessesPersec
+ uint64 APICSelfIPIsSentPersec
+ uint64 APICTPRAccessesPersec
+ string Caption
+ uint64 ControlRegisterAccessesCost
+ uint64 ControlRegisterAccessesCost_Base
+ uint64 ControlRegisterAccessesPersec
+ uint64 CPUIDInstructionsCost
+ uint64 CPUIDInstructionsCost_Base
+ uint64 CPUIDInstructionsPersec
+ uint64 CPUWaitTimePerDispatch
+ uint64 CPUWaitTimePerDispatch_Base
+ uint64 DebugRegisterAccessesCost
+ uint64 DebugRegisterAccessesCost_Base
+ uint64 DebugRegisterAccessesPersec
+ string Description
+ uint64 EmulatedInstructionsCost
+ uint64 EmulatedInstructionsCost_Base
+ uint64 EmulatedInstructionsPersec
+ uint64 ExternalInterruptsCost
+ uint64 ExternalInterruptsCost_Base
+ uint64 ExternalInterruptsPersec
+ uint64 Frequency_Object
+ uint64 Frequency_PerfTime
+ uint64 Frequency_Sys100NS
+ uint64 GlobalGVARangeFlushesPersec
+ uint64 GPASpaceHypercallsPersec
+ uint64 GuestPageTableMapsPersec
+ uint64 HardwareInterruptsPersec
+ uint64 HLTInstructionsCost
+ uint64 HLTInstructionsCost_Base
+ uint64 HLTInstructionsPersec
+ uint64 HypercallsCost
+ uint64 HypercallsCost_Base
+ uint64 HypercallsPersec
+ uint64 IOInstructionsCost
+ uint64 IOInstructionsCost_Base
+ uint64 IOInstructionsPersec
+ uint64 IOInterceptMessagesPersec
+ uint64 LargePageTLBFillsPersec
+ uint64 LocalFlushedGVARangesPersec
+ uint64 LogicalProcessorDispatchesPersec
+ uint64 LogicalProcessorHypercallsPersec
+ uint64 LogicalProcessorMigrationsPersec
+ uint64 LongSpinWaitHypercallsPersec
+ uint64 MemoryInterceptMessagesPersec
+ uint64 MSRAccessesCost
+ uint64 MSRAccessesCost_Base
+ uint64 MSRAccessesPersec
+ uint64 MWAITInstructionsCost
+ uint64 MWAITInstructionsCost_Base
+ uint64 MWAITInstructionsPersec
+ string Name
+ uint64 NestedPageFaultInterceptsCost
+ uint64 NestedPageFaultInterceptsCost_Base
+ uint64 NestedPageFaultInterceptsPersec
+ uint64 OtherHypercallsPersec
+ uint64 OtherInterceptsCost
+ uint64 OtherInterceptsCost_Base
+ uint64 OtherInterceptsPersec
+ uint64 OtherMessagesPersec
+ uint64 PageFaultInterceptsCost
+ uint64 PageFaultInterceptsCost_Base
+ uint64 PageFaultInterceptsPersec
+ uint64 PageInvalidationsCost
+ uint64 PageInvalidationsCost_Base
+ uint64 PageInvalidationsPersec
+ uint64 PageTableAllocationsPersec
+ uint64 PageTableEvictionsPersec
+ uint64 PageTableReclamationsPersec
+ uint64 PageTableResetsPersec
+ uint64 PageTableValidationsPersec
+ uint64 PageTableWriteInterceptsPersec
+ uint64 PendingInterruptsCost
+ uint64 PendingInterruptsCost_Base
+ uint64 PendingInterruptsPersec
+ uint64 PercentGuestRunTime
+ uint64 PercentGuestRunTime_Base
+ uint64 PercentHypervisorRunTime
+ uint64 PercentHypervisorRunTime_Base
+ uint64 PercentRemoteRunTime
+ uint64 PercentRemoteRunTime_Base
+ uint64 PercentTotalRunTime
+ uint64 PercentTotalRunTime_Base
+ uint64 ReflectedGuestPageFaultsPersec
+ uint64 SmallPageTLBFillsPersec
+ uint64 SyntheticInterruptHypercallsPersec
+ uint64 SyntheticInterruptsPersec
+ uint64 Timestamp_Object
+ uint64 Timestamp_PerfTime
+ uint64 Timestamp_Sys100NS
+ uint64 TotalInterceptsCost
+ uint64 TotalInterceptsCost_Base
+ uint64 TotalInterceptsPersec
+ uint64 TotalMessagesPersec
+ uint64 VirtualInterruptHypercallsPersec
+ uint64 VirtualInterruptsPersec
+ uint64 VirtualMMUHypercallsPersec
+ uint64 VirtualProcessorHypercallsPersec
+end
\ No newline at end of file
diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py
index f767d54..a785df2 100755
--- a/src/hyperv/hyperv_wmi_generator.py
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -68,7 +68,7 @@ class Class:
header += "\n"
header += "#define %s_RESOURCE_URI \\\n" % name_upper
- if self.name.startswith("Win32_"):
+ if self.name.startswith("Win32_") or
self.name.startswith("CIM_DataFile"):
header += "
\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/%s\"\n" %
self.name
else:
header += "
\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/%s\"\n"
% self.name
@@ -113,7 +113,7 @@ class Class:
% (self.name.replace("_", ""), self.name)
source += "{\n"
- if self.name.startswith("Win32_"):
+ if self.name.startswith("Win32_") or
self.name.startswith("CIM_DataFile"):
source += " return hypervEnumAndPull(priv, query,
ROOT_CIMV2,\n"
else:
source += " return hypervEnumAndPull(priv, query,
ROOT_VIRTUALIZATION,\n"
@@ -149,15 +149,32 @@ class Class:
return source
+ def generate_tab_classes(self):
+ tab_class = " {(\"%s" % self.name
+ tab_class += "\"),cimTypes_%s" % self.name
+ tab_class += "}"
+
+ return tab_class
+
+ def generate_tabs_types(self):
+ tab_types = "CimTypes cimTypes_%s[] = {\n" % self.name
+ for property in self.properties[:-1]:
+ tab_types += property.generate_type_tab()
+ tab_types += ",\n"
+ property = self.properties[len(self.properties)-1]
+ tab_types += property.generate_type_tab()
+ tab_types += ",\n\t{(\"\\0\"),(\"\\0\")}\n};\n"
+
+ return tab_types
class Property:
typemap = {"boolean" : "BOOL",
"string" : "STR",
"datetime" : "STR",
- "int8" : "INT8",
- "int16" : "INT16",
- "int32" : "INT32",
- "int64" : "INT64",
+ "sint8" : "INT8",
+ "sint16" : "INT16",
+ "sint32" : "INT32",
+ "sint64" : "INT64",
"uint8" : "UINT8",
"uint16" : "UINT16",
"uint32" : "UINT32",
@@ -189,7 +206,14 @@ class Property:
return " SER_NS_%s(%s_RESOURCE_URI, \"%s\", 1),\n" \
% (Property.typemap[self.type], class_name.upper(), self.name)
-
+ def generate_type_tab(self):
+ tab_class = " {(\"%s" % self.name
+ tab_class += "\"),(\"%s" % self.type
+ #If the attribute is an array, "[]" is added at the end of the type
+ if self.is_array:
+ tab_class += "[]"
+ tab_class += "\")}"
+ return tab_class
def open_and_print(filename):
if filename.startswith("./"):
@@ -238,7 +262,19 @@ def parse_class(block):
return Class(name=name, properties=properties)
+def print_type_header():
+ header_types = "struct cimTypes{\n"
+ header_types += " const char *name;\n"
+ header_types += " const char *type;\n"
+ header_types += "};\n"
+ header_types += "typedef struct cimTypes CimTypes;\n\n"
+ header_types += "struct cimClasses{\n"
+ header_types += " const char *name;\n"
+ header_types += " CimTypes *cimTypesPtr;\n"
+ header_types += "};\n"
+ header_types += "typedef struct cimClasses CimClasses;\n\n"
+ return header_types
def main():
if "srcdir" in os.environ:
@@ -254,6 +290,8 @@ def main():
classes_header = open_and_print(os.path.join(output_dirname,
"hyperv_wmi_classes.generated.h"))
classes_source = open_and_print(os.path.join(output_dirname,
"hyperv_wmi_classes.generated.c"))
+ classes_test_header = open_and_print(os.path.join(output_dirname,
"hyperv_wmi_classes_attr.generated.h"))
+
# parse input file
number = 0
classes_by_name = {}
@@ -295,6 +333,9 @@ def main():
classes_header.write(notice)
classes_source.write(notice)
+ classes_test_header.write(notice)
+ classes_test_header.write(print_type_header())
+
names = classes_by_name.keys()
names.sort()
@@ -305,7 +346,15 @@ def main():
classes_header.write(classes_by_name[name].generate_classes_header())
classes_source.write(classes_by_name[name].generate_classes_source())
-
+ for name in names:
+ classes_test_header.write(classes_by_name[name].generate_tabs_types())
+ classes_test_header.write("CimClasses cimClasses[] = {\n")
+ for name in names[:-1]:
+ classes_test_header.write(classes_by_name[name].generate_tab_classes())
+ classes_test_header.write(",\n")
+ last_name = names[len(names)-1]
+ classes_test_header.write(classes_by_name[last_name].generate_tab_classes())
+ classes_test_header.write(",\n\t{(\"\\0\"),NULL}\n};")
if __name__ == "__main__":
main()
diff --git a/src/hyperv/openwsman.h b/src/hyperv/openwsman.h
index f66ed86..49b3e39 100644
--- a/src/hyperv/openwsman.h
+++ b/src/hyperv/openwsman.h
@@ -44,3 +44,7 @@
# endif
#endif /* __OPENWSMAN_H__ */
+
+/*wsman-xml.h*/
+WsXmlDocH ws_xml_create_doc( const char *rootNsUri, const char *rootName);
+WsXmlNodeH xml_parser_get_root(WsXmlDocH doc);