Authors: Simon Rastello (Bull), Adrien Kantcheff (Bull), Yves Vinter (Bull) Summary of new added features by modules: hyperv_driver.c - hypervDomainDefineXML - hypervDomainCreateXML - hypervDomainUndefine - hypervDomainUndefineFlags - hypervDomainShutdown - hypervDomainShutdownFlags - hypervDomainGetVcpus - hypervDomainGetVcpusFlags - hypervConnectGetMaxVcpus - hypervDomainGetMaxVcpus - hypervDomainSetVcpus - hypervDomainSetVcpusFlags - hypervDomainSetMemory - hypervDomainSetMemoryFlags - hypervDomainSetMaxMemory - hypervNodeGetFreeMemory - hypervDomainAttachDevice - hypervDomainAttachDeviceFlags - hypervDomainGetSchedulerParameters - hypervDomainGetSchedulerParametersFlags - hypervDomainGetSchedulerType - hypervConnectGetCapabilities - hypervConnectGetVersion - hypervDomainSetAutostart - hypervDomainGetAutostart hyperv_network.c - hypervConnectNumOfNetworks - hypervConnectListNetworks - hypervConnectNumOfDefinedNetworks - hypervConnectListDefinedNetworks - hypervNetworkLookupByName - hypervNetworkGetXMLDesc hyperv_private.h - Add mutex to protect against concurrent calls (the openwsman library being not thread-safe, as reported in issue #10 Simultaneous WsMan queries) - Add virDomainXMLOptionPtr to parse Domain XML hyperv_wmi.h - Structures for passing complex arguments: objects, EPR (end point references) and embedded instances hyperv_wmi.c - Methods to invoke WMI methods with complex arguments hyperv_wmi_generator.input - 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 - Add CIM_DataFile class header to be generated - Add tab classes and types to be generated - Add a function to print header types openwsman.h - Add ws_xml_create_doc function prototype - Add xml_parser_get_root function prototype Reported-by: Yves Vinter <yves.vinter@xxxxxxxx> --- diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index aed9307..bdf45a7 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -42,6 +42,12 @@ #include "openwsman.h" #include "virstring.h" +/* Bull */ +#include "virtypedparam.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + #define VIR_FROM_THIS VIR_FROM_HYPERV VIR_LOG_INIT("hyperv.hyperv_driver"); @@ -58,12 +64,97 @@ hypervFreePrivate(hypervPrivate **priv) wsmc_release((*priv)->client); } + /* Bull */ + pthread_mutex_destroy(&(*priv)->mutex); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } +/* Bull */ +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; +} + + + +/* Bull */ +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 +199,17 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags return VIR_DRV_OPEN_ERROR; } - /* Require auth */ - if (auth == NULL || auth->cb == NULL) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("Missing or invalid auth pointer")); - return VIR_DRV_OPEN_ERROR; - } + /* Require auth */ + /* Bull - if auth is null, auth=virConnectAuthPtrDefault */ + 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,14 +288,28 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags goto cleanup; } + /* Bull - Setup capabilities */ + priv->caps = hypervCapsInit(priv); + if (priv->caps == NULL) { + goto cleanup; + } + + /* Bull - Init xmlopt to parse Domain XML */ + priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL); + conn->privateData = priv; - priv = NULL; + + /* Bull */ + pthread_mutex_init(&priv->mutex, NULL); + + priv = NULL; result = VIR_DRV_OPEN_SUCCESS; cleanup: hypervFreePrivate(&priv); VIR_FREE(username); VIR_FREE(password); + virBufferFreeAndReset(&query); hypervFreeObject(priv, (hypervObject *)computerSystem); return result; @@ -254,6 +364,7 @@ hypervConnectGetHostname(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return hostname; } @@ -352,6 +463,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)processorList); + virBufferFreeAndReset(&query); return result; } @@ -396,6 +508,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return success ? count : -1; } @@ -432,6 +545,7 @@ hypervConnectNumOfDomains(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return success ? count : -1; } @@ -464,6 +578,7 @@ hypervDomainLookupByID(virConnectPtr conn, int id) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return domain; } @@ -500,6 +615,7 @@ hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return domain; } @@ -533,6 +649,7 @@ hypervDomainLookupByName(virConnectPtr conn, const char *name) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); + virBufferFreeAndReset(&query); return domain; } @@ -748,6 +865,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); hypervFreeObject(priv, (hypervObject *)processorSettingData); hypervFreeObject(priv, (hypervObject *)memorySettingData); + virBufferFreeAndReset(&query); return result; } @@ -915,6 +1033,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 +1090,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn } hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return count; } @@ -1007,6 +1127,7 @@ hypervConnectNumOfDefinedDomains(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return success ? count : -1; } @@ -1346,6 +1467,7 @@ hypervConnectListAllDomains(virConnectPtr conn, } hypervFreeObject(priv, (hypervObject *)computerSystemList); + virBufferFreeAndReset(&query); return ret; } @@ -1353,6 +1475,1767 @@ hypervConnectListAllDomains(virConnectPtr conn, +/* Bull */ +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; +} + + + +/* Bull */ +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; +} + + + +/* Bull */ +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); +} + + + +/* Bull */ +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; +} + + + +/* Bull */ +static int hypervDomainShutdown(virDomainPtr dom) +{ + return hypervDomainShutdownFlags(dom, 0); +} + + + +/* Bull */ +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; +} + + + +/* Bull */ +static int +hypervDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int *nparams) +{ + return hypervDomainGetSchedulerParametersFlags(dom, params, nparams, VIR_DOMAIN_AFFECT_CURRENT); +} + + + +/* Bull */ +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; +} + + + +/* Bull */ +static char* +hypervConnectGetCapabilities(virConnectPtr conn) +{ + hypervPrivate *priv = conn->privateData; + char *xml = virCapabilitiesFormatXML(priv->caps); + + if (xml == NULL) { + virReportOOMError(); + return NULL; + } + + return xml; +} + + +/* Bull */ +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,'.'); + datafile->data->Version[p-datafile->data->Version-1] = '\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); + //VIR_FREE(p); + virBufferFreeAndReset(&query); + return ret; +} + + + +/* Bull */ +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; +} + + + +/* Bull */ +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; + hypervPrivate *priv = domain->conn->privateData; + virBuffer query = VIR_BUFFER_INITIALIZER; + virBuffer queryVssd = VIR_BUFFER_INITIALIZER; + Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; + properties_t *tab_props; + eprParam eprparam; + embeddedParam embeddedparam; + int nb_params; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; + // Convert autostart integer to string + const int n = snprintf(NULL, 0, "%u", autostart); + char autostart_str[n+1]; + sprintf(autostart_str, "%u", autostart); + + 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 ? "1" : "2";; + (*tab_props).val = autostart_str; + (*(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; +} + + + +static int +hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) +{ + int res = -1; + invokeXmlParam *params; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + hypervPrivate *priv = domain->conn->privateData; + properties_t *tab_props; + 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"; + // Convert memory to string in Mb + const unsigned long memoryMb = memory/1024; + const int n = snprintf(NULL, 0, "%lu", memoryMb); + char memory_str[n+1]; + sprintf(memory_str, "%lu", memoryMb); + + 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); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)memorySettingData); + virBufferFreeAndReset(&query); + virBufferFreeAndReset(&query2); + return res; +} + + + +/* Bull */ +/* + * 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; + } + + /* Double the blackslashes */ + //FIXME: normally there are only 2 backslashes in rasdInstanceID + /* Count the number of backslash character */ + strTemp = strchr(rasdInstanceID, '\\'); + while (strTemp != NULL) { + n++; + strTemp = strchr(++strTemp, '\\'); + } + strTemp = (char *) malloc(strlen(rasdInstanceID) + (n * sizeof(char)) + 1); + while (rasdInstanceID[i] != '\0') { + strTemp[j] = rasdInstanceID[i]; + if (rasdInstanceID[i] == '\\') { + j++; + strTemp[j] = '\\'; + } + i++; + j++; + } + + /* 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; +} + + + +/* Bull */ +/* + * 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; +} + + + +/* Bull */ +/* + * 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; + properties_t *tab_props; + eprParam eprparam; + embeddedParam embeddedparam; + virBuffer query = VIR_BUFFER_INITIALIZER; + Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; + Msvm_MemorySettingData *memorySettingData = NULL; + // Convert memory to string in Mb + const unsigned long memoryMb = memory/1024; + const int n = snprintf(NULL, 0, "%lu", memoryMb); + char memory_str[n+1]; + sprintf(memory_str, "%lu", memoryMb); + + 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); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)memorySettingData); + virBufferFreeAndReset(&query); + return res; +} + + +/* Bull */ +static int +hypervDomainSetMemory(virDomainPtr domain, unsigned long memory) +{ + return hypervDomainSetMemoryFlags(domain, memory, 0); +} + + +/* Bull */ +static int +hypervDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, + unsigned int flags ATTRIBUTE_UNUSED) +{ + int res = -1; + invokeXmlParam *params; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + hypervPrivate *priv = domain->conn->privateData; + properties_t *tab_props; + 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"; + // Convert nvcpus to string + const int n = snprintf(NULL, 0, "%u", nvcpus); + char nvcpus_str[n+1]; + sprintf(nvcpus_str, "%u", 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); + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); + hypervFreeObject(priv, (hypervObject *)processorSettingData); + virBufferFreeAndReset(&query); + return res; +} + + + +/* Bull */ +static int +hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) +{ + return hypervDomainSetVcpusFlags(domain, nvcpus, 0); +} + + + +/* Bull */ +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, *ideControlerAddr; + 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; + Msvm_ResourceAllocationSettingData *diskRasd = NULL; + Msvm_ResourceAllocationSettingData *newDiskDrive = NULL; + Msvm_AllocationCapabilities *allocationCapabilities = NULL; + Msvm_AllocationCapabilities *allocationCapabilities2 = NULL; + invokeXmlParam *params; + properties_t *tab_props; + 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(sizeof(char)+1); + ideControlerAddr = (char *) malloc(sizeof(char)+1); + 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) { + 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: + free(ideRasdPath); + free(newDiskDrivePath); + virBufferFreeAndReset(&query); + if (!tab_props) + VIR_FREE(tab_props); + if (!params) + 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); + + return ret; +} + + + +/* Bull */ +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; + invokeXmlParam *params; + 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(sizeof(char) * (strlen(guid_string) + 3)); + 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: + free(virtualSystemIdentifiers); + free(switchPortPATH); + virBufferFreeAndReset(&query); + if (!tab_props) + VIR_FREE(tab_props); + if (!params) + VIR_FREE(params); + hypervFreeObject(priv, (hypervObject *)switchPort); + hypervFreeObject(priv, (hypervObject *)virtualSwitch); + return ret; +} + + + +/* Bull */ +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: + free(xmlDomain); + return ret; +} + + + +/* Bull */ +static int +hypervDomainAttachDevice(virDomainPtr domain, const char *xml) +{ + return hypervDomainAttachDeviceFlags(domain, xml, 0); +} + + + +/* Bull */ +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: + if (tab_props != NULL) + VIR_FREE(tab_props); + if (params != NULL) + VIR_FREE(params); + return domain; +} + + + +/* Bull */ +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); + + // 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; +} + + + +/* Bull */ +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; + 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: + virBufferFreeAndReset(&query); + if (!params) + VIR_FREE(params); + hypervFreeObject(priv, (hypervObject *)computerSystem); + return result; +} + + + +/* Bull */ +static int +hypervDomainUndefine(virDomainPtr domain) +{ + return hypervDomainUndefineFlags(domain, 0); +} + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1389,6 +3272,33 @@ static virDriver hypervDriver = { .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ + + /* Bull */ + .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..dd89207 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -29,6 +29,11 @@ #include "viruuid.h" #include "hyperv_network_driver.h" +/* Bull */ +#include "virstring.h" +#include "hyperv_wmi.h" +#include "network_conf.h" + #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -60,11 +65,254 @@ hypervNetworkClose(virConnectPtr conn) } +/* Bull */ +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; +} + + +/* Bull */ +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; +} + + +/* Bull */ +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; +} + + +/* Bull */ +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; +} + + +/* Bull */ +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; +} + + +/* Bull */ +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 */ + + /* Bull */ + .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..c543f1a 100644 --- a/src/hyperv/hyperv_private.h +++ b/src/hyperv/hyperv_private.h @@ -28,11 +28,26 @@ # include "hyperv_util.h" # include "openwsman.h" +/* Bull */ +# include "capabilities.h" +#include "domain_conf.h" + +/* Bull - Add mutex to protect against concurrent calls + (OpenWsMan client API is not thread-safe) */ +#ifndef WIN32 +# include <pthread.h> +#endif + typedef struct _hypervPrivate hypervPrivate; struct _hypervPrivate { hypervParsedUri *parsedUri; WsManClient *client; + + /* Bull */ + pthread_mutex_t mutex; + virCapsPtr caps; + virDomainXMLOptionPtr xmlopt; /* to parse Domain XML */ }; #endif /* __HYPERV_PRIVATE_H__ */ diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index acb705c..c0ea00b 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -1,3 +1,4 @@ + /* * hyperv_wmi.c: general WMI over WSMAN related functions and structures for * managing Microsoft Hyper-V hosts @@ -33,16 +34,704 @@ #include "hyperv_wmi.h" #include "virstring.h" +/* Bull */ +# 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/*" +/* Bull */ +/* #define DUMP_REQUEST 1 */ -#define VIR_FROM_THIS VIR_FROM_HYPERV +/* Bull */ +/* 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; +} + + +/* Bull */ +/* 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; +} + + +/* Bull */ +/* 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; + int len = 0; + int i = 0; + char* type = NULL; + bool isArray = false; + char* typeTmp = NULL; + int n = 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 + n = strlen(type) - 2; + typeTmp = (char *) malloc(sizeof(char) * (n+1)); + strncpy(typeTmp, type, n); + type = (char *) malloc(sizeof(char) * (n+1)); + strcpy(type, typeTmp); + free(typeTmp); + } 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); + //VIR_FREE((char*)type); + if (xmlBufferNode != NULL){ + xmlBufferFree(xmlBufferNode); + } + + return result; +} + + +/* Bull */ +/* 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; +} + + +/* Bull */ +/* 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; + + /* Request options and filter */ + options = wsmc_options_init(); + + 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); + + return result; +} + + +/* Bull */ +/* 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; + Msvm_ConcreteJob *concreteJob = NULL; + bool completed = false; + bool locked; + + options = wsmc_options_init(); + + wsmc_add_selectors_from_str(options, selector); + +#ifdef DUMP_REQUEST + wsmc_set_action_option(options, FLAG_DUMP_REQUEST); +#endif + + /* 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); + + 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; + } + + /* Unlock mutex */ + /* 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); + } + ws_xml_destroy_doc(response); + VIR_FREE(returnValue); + VIR_FREE(instanceID); + VIR_FREE(xpath_expr_string); + hypervFreeObject(priv, (hypervObject *)concreteJob); + + if (locked == true) pthread_mutex_unlock(&priv->mutex); + + return result; +} + + +/* Bull */ +/* 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 +817,13 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root, return -1; } - if (virBufferCheckError(query) < 0) + if (virBufferError(query)) { + virReportOOMError(); return -1; + } + + /* Bull - Lock mutex */ + pthread_mutex_lock(&priv->mutex); serializerContext = wsmc_get_serialization_context(priv->client); @@ -258,6 +952,9 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root, ws_xml_destroy_doc(response); VIR_FREE(enumContext); hypervFreeObject(priv, head); + + /* Bull - Unlock mutex */ + pthread_mutex_unlock(&priv->mutex); return result; } @@ -403,8 +1100,13 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain, virBuffer query = VIR_BUFFER_INITIALIZER; Msvm_ConcreteJob *concreteJob = NULL; bool completed = false; - + bool locked; /* Bull */ + virUUIDFormat(domain->uuid, uuid_string); + + /* Bull - Lock mutex */ + pthread_mutex_lock(&priv->mutex); + locked = true; if (virAsprintf(&selector, "Name=%s&CreationClassName=Msvm_ComputerSystem", uuid_string) < 0 || @@ -456,6 +1158,11 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain, "InstanceID", "RequestStateChange"); goto cleanup; } + + /* Bull - Unlock mutex */ + /* 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. */ @@ -527,6 +1234,9 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain, VIR_FREE(instanceID); hypervFreeObject(priv, (hypervObject *)concreteJob); + /* Bull - Unlock mutex */ + if (locked == true) pthread_mutex_unlock(&priv->mutex); + return result; } @@ -676,5 +1386,32 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain, } +/* Bull */ +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..9a4f920 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -24,11 +24,76 @@ #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" +/* Bull */ +#define EPR_PARAM 0 +#define SIMPLE_PARAM 1 +#define EMBEDDED_PARAM 2 + + +/* Bull */ + +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 +hypervCreateXmlStruct(const char *methodName,const char *classURI,WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod); + +const char * +hypervGetPropType(const char * className, const char *attrName); + +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); + +int +hypervInvokeMethod(hypervPrivate *priv, invokeXmlParam *parameters, int nbParameters,const char* methodName, const char* providerURI, const char *selector); typedef struct _hypervObject hypervObject; @@ -53,7 +118,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 +179,15 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain, Msvm_ComputerSystem **computerSystem); +/* Bull */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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..dcaf090 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -68,7 +68,8 @@ class Class: header += "\n" header += "#define %s_RESOURCE_URI \\\n" % name_upper - if self.name.startswith("Win32_"): + #Bull + 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 +114,8 @@ class Class: % (self.name.replace("_", ""), self.name) source += "{\n" - if self.name.startswith("Win32_"): + #Bull + 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 +151,34 @@ class Class: return source - + #Bull + def generate_tab_classes(self): + tab_class = " {(\"%s" % self.name + tab_class += "\"),cimTypes_%s" % self.name + tab_class += "}" + + return tab_class + + #Bull + 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 +210,16 @@ class Property: return " SER_NS_%s(%s_RESOURCE_URI, \"%s\", 1),\n" \ % (Property.typemap[self.type], class_name.upper(), self.name) - + #Bull + def generate_type_tab(self): + tab_class = " {(\"%s" % self.name + tab_class += "\"),(\"%s" % self.type + #Adrien + #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 +268,20 @@ def parse_class(block): return Class(name=name, properties=properties) - +#Bull +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: @@ -253,6 +296,9 @@ def main(): classes_typedef = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.typedef")) 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")) + + #Bull + classes_test_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes_attr.generated.h")) # parse input file number = 0 @@ -294,6 +340,10 @@ def main(): classes_typedef.write(notice) classes_header.write(notice) classes_source.write(notice) + + #Bull + classes_test_header.write(notice) + classes_test_header.write(print_type_header()) names = classes_by_name.keys() names.sort() @@ -304,8 +354,17 @@ def main(): classes_typedef.write(classes_by_name[name].generate_classes_typedef()) classes_header.write(classes_by_name[name].generate_classes_header()) classes_source.write(classes_by_name[name].generate_classes_source()) - - + + #Bull + 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); -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list