mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 19:32:19 +00:00
hyperv: add support for Hyper-V 2012 and newer
This patch reworks the Hyper-V driver structs and the code generator to provide seamless support for both Hyper-V 2008 and 2012 or newer. This does not implement any new libvirt APIs, it just adapts existing 2008-only driver to also handle 2012 and newer by sharing as much driver code as possible (currently it's all of it :-)). This is needed to set the foundation before we can move forward with implementing the rest of the driver APIs. With the 2012 release, Microsoft introduced "v2" version of Msvm_* WMI classes. Those are largely the same as "v1" (used in 2008) but have some new properties as well as need different wsman request URIs. To accomodate those differences, most of work went into the code generator so that it's "aware" of possibility of multiple versions of the same WMI class and produce C code accordingly. To accomplish this the following changes were made: * the abstract hypervObject struct's data member was changed to a union that has "common", "v1" and "v2" members. Those are structs that represent WMI classes that we get back from wsman response. The "common" struct has members that are present in both "v1" and "v2" which the driver API callbacks can use to read the data from in version-independent manner (if version-specific member needs to be accessed the driver can check priv->wmiVersion and read from "v1" or "v2" as needed). Those structs are guaranteed to be memory aligned by the code generator (see the align_property_members implementation that takes care of that) * the generator produces *_WmiInfo for each WMI class "family" that holds an array of hypervWmiClassInfoPtr each providing information as to which request URI to use for each "version" of given WMI class as well as XmlSerializerInfo struct needed to unserilize WS-MAN responsed into the data structs. The driver uses those to make proper WS-MAN request depending on which version it's connected to. * the generator no longer produces "helper" functions such as hypervGetMsvmComputerSystemList as those were originally just simple wrappers around hypervEnumAndPull, instead those were hand-written now (to keep driver changes minimal). The reason is that we'll have more code coming implementing missing libvirt APIs and surely code patterns will emerge that would warrant more useful "utility" functions like that. * a hypervInitConnection was added to the driver which "detects" Hyper-V version by testing simple wsman request using v2 then falling back to v1, obviously if both fail, the we're erroring out. To express how the above translates in code: void hypervImplementSomeLibvirtApi(virConnectPtr conn, ...) { hypervPrivate *priv = conn->privateData; virBuffer query = VIR_BUFFER_INITIALIZER; hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER; Msvm_ComputerSystem *list = NULL; /* typed hypervObject instance */ /* the WmiInfo struct has the data needed for wsman request and * response handling for both v1 and v2 */ wqlQuery.info = Msvm_ComputerSystem_WmiInfo; wqlQuery.query = &query; virBufferAddLit(&query, "select * from Msvm_ComputerSystem"); if (hypervEnumAndPull(priv, &wqlQuery, (hypervObject **) &list) < 0) { goto cleanup; } if (list == NULL) { /* none found */ goto cleanup; } /* works with v1 and v2 */ char *vmName = list->data.common->Name; /* access property that is in v2 only */ if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) char *foo = list->data.v2->V2Property; else char *foo = list->data.v1->V1Property; cleanup: hypervFreeObject(priv, (hypervObject *)list); }
This commit is contained in:
parent
87f2bd3c0c
commit
3372f8fb5b
@ -912,8 +912,6 @@ HYPERV_DRIVER_SOURCES = \
|
|||||||
hyperv/openwsman.h
|
hyperv/openwsman.h
|
||||||
|
|
||||||
HYPERV_DRIVER_GENERATED = \
|
HYPERV_DRIVER_GENERATED = \
|
||||||
hyperv/hyperv_wmi.generated.c \
|
|
||||||
hyperv/hyperv_wmi.generated.h \
|
|
||||||
hyperv/hyperv_wmi_classes.generated.c \
|
hyperv/hyperv_wmi_classes.generated.c \
|
||||||
hyperv/hyperv_wmi_classes.generated.h \
|
hyperv/hyperv_wmi_classes.generated.h \
|
||||||
hyperv/hyperv_wmi_classes.generated.typedef
|
hyperv/hyperv_wmi_classes.generated.typedef
|
||||||
|
@ -55,7 +55,67 @@ hypervFreePrivate(hypervPrivate **priv)
|
|||||||
VIR_FREE(*priv);
|
VIR_FREE(*priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervInitConnection(virConnectPtr conn, hypervPrivate *priv,
|
||||||
|
char *username, char *password)
|
||||||
|
{
|
||||||
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
||||||
|
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
|
||||||
|
hypervObject *computerSystem = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
/* Initialize the openwsman connection */
|
||||||
|
priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman",
|
||||||
|
priv->parsedUri->transport, username, password);
|
||||||
|
|
||||||
|
if (priv->client == NULL) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Could not create openwsman client"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wsmc_transport_init(priv->client, NULL) != 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Could not initialize openwsman transport"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Currently only basic authentication is supported */
|
||||||
|
wsman_transport_set_auth_method(priv->client, "basic");
|
||||||
|
|
||||||
|
wqlQuery.info = Msvm_ComputerSystem_WmiInfo;
|
||||||
|
wqlQuery.query = &query;
|
||||||
|
|
||||||
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
||||||
|
virBufferAddLit(&query, "WHERE ");
|
||||||
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);
|
||||||
|
|
||||||
|
/* try query using V2 namespace (for Hyper-V 2012+) */
|
||||||
|
priv->wmiVersion = HYPERV_WMI_VERSION_V2;
|
||||||
|
|
||||||
|
if (hypervEnumAndPull(priv, &wqlQuery, &computerSystem) < 0) {
|
||||||
|
/* rebuild query because hypervEnumAndPull consumes it */
|
||||||
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
||||||
|
virBufferAddLit(&query, "WHERE ");
|
||||||
|
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);
|
||||||
|
|
||||||
|
/* fall back to V1 namespace (for Hyper-V 2008) */
|
||||||
|
priv->wmiVersion = HYPERV_WMI_VERSION_V1;
|
||||||
|
|
||||||
|
if (hypervEnumAndPull(priv, &wqlQuery, &computerSystem) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("%s is not a Hyper-V server"), conn->uri->server);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
hypervFreeObject(priv, computerSystem);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static virDrvOpenStatus
|
static virDrvOpenStatus
|
||||||
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
||||||
@ -67,8 +127,6 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
|||||||
hypervPrivate *priv = NULL;
|
hypervPrivate *priv = NULL;
|
||||||
char *username = NULL;
|
char *username = NULL;
|
||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
virBuffer query = VIR_BUFFER_INITIALIZER;
|
|
||||||
Msvm_ComputerSystem *computerSystem = NULL;
|
|
||||||
|
|
||||||
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
||||||
|
|
||||||
@ -147,41 +205,9 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the openwsman connection */
|
|
||||||
priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman",
|
|
||||||
priv->parsedUri->transport, username, password);
|
|
||||||
|
|
||||||
if (priv->client == NULL) {
|
if (hypervInitConnection(conn, priv, username, password) < 0)
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("Could not create openwsman client"));
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (wsmc_transport_init(priv->client, NULL) != 0) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
||||||
_("Could not initialize openwsman transport"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Currently only basic authentication is supported */
|
|
||||||
wsman_transport_set_auth_method(priv->client, "basic");
|
|
||||||
|
|
||||||
/* Check if the connection can be established and if the server has the
|
|
||||||
* Hyper-V role installed. If the call to hypervGetMsvmComputerSystemList
|
|
||||||
* succeeds than the connection has been established. If the returned list
|
|
||||||
* is empty than the server isn't a Hyper-V server. */
|
|
||||||
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
|
|
||||||
virBufferAddLit(&query, "where ");
|
|
||||||
virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);
|
|
||||||
|
|
||||||
if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (computerSystem == NULL) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("%s is not a Hyper-V server"), conn->uri->server);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->privateData = priv;
|
conn->privateData = priv;
|
||||||
priv = NULL;
|
priv = NULL;
|
||||||
@ -191,7 +217,6 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
|||||||
hypervFreePrivate(&priv);
|
hypervFreePrivate(&priv);
|
||||||
VIR_FREE(username);
|
VIR_FREE(username);
|
||||||
VIR_FREE(password);
|
VIR_FREE(password);
|
||||||
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -240,7 +265,7 @@ hypervConnectGetHostname(virConnectPtr conn)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ignore_value(VIR_STRDUP(hostname, computerSystem->data->DNSHostName));
|
ignore_value(VIR_STRDUP(hostname, computerSystem->data.common->DNSHostName));
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
hypervFreeObject(priv, (hypervObject *)computerSystem);
|
||||||
@ -282,7 +307,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|||||||
"{Win32_ComputerSystem.Name=\"%s\"} "
|
"{Win32_ComputerSystem.Name=\"%s\"} "
|
||||||
"where AssocClass = Win32_ComputerSystemProcessor "
|
"where AssocClass = Win32_ComputerSystemProcessor "
|
||||||
"ResultClass = Win32_Processor",
|
"ResultClass = Win32_Processor",
|
||||||
computerSystem->data->Name);
|
computerSystem->data.common->Name);
|
||||||
|
|
||||||
if (hypervGetWin32ProcessorList(priv, &query, &processorList) < 0)
|
if (hypervGetWin32ProcessorList(priv, &query, &processorList) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -295,7 +320,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Strip the string to fit more relevant information in 32 chars */
|
/* Strip the string to fit more relevant information in 32 chars */
|
||||||
tmp = processorList->data->Name;
|
tmp = processorList->data.common->Name;
|
||||||
|
|
||||||
while (*tmp != '\0') {
|
while (*tmp != '\0') {
|
||||||
if (STRPREFIX(tmp, " ")) {
|
if (STRPREFIX(tmp, " ")) {
|
||||||
@ -313,16 +338,16 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fill struct */
|
/* Fill struct */
|
||||||
if (virStrncpy(info->model, processorList->data->Name,
|
if (virStrncpy(info->model, processorList->data.common->Name,
|
||||||
sizeof(info->model) - 1, sizeof(info->model)) == NULL) {
|
sizeof(info->model) - 1, sizeof(info->model)) == NULL) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("CPU model %s too long for destination"),
|
_("CPU model %s too long for destination"),
|
||||||
processorList->data->Name);
|
processorList->data.common->Name);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->memory = computerSystem->data->TotalPhysicalMemory / 1024; /* byte to kilobyte */
|
info->memory = computerSystem->data.common->TotalPhysicalMemory / 1024; /* byte to kilobyte */
|
||||||
info->mhz = processorList->data->MaxClockSpeed;
|
info->mhz = processorList->data.common->MaxClockSpeed;
|
||||||
info->nodes = 1;
|
info->nodes = 1;
|
||||||
info->sockets = 0;
|
info->sockets = 0;
|
||||||
|
|
||||||
@ -331,8 +356,8 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|||||||
++info->sockets;
|
++info->sockets;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->cores = processorList->data->NumberOfCores;
|
info->cores = processorList->data.common->NumberOfCores;
|
||||||
info->threads = info->cores / processorList->data->NumberOfLogicalProcessors;
|
info->threads = info->cores / processorList->data.common->NumberOfLogicalProcessors;
|
||||||
info->cpus = info->sockets * info->cores;
|
info->cpus = info->sockets * info->cores;
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
@ -372,7 +397,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids)
|
|||||||
|
|
||||||
for (computerSystem = computerSystemList; computerSystem != NULL;
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
||||||
computerSystem = computerSystem->next) {
|
computerSystem = computerSystem->next) {
|
||||||
ids[count++] = computerSystem->data->ProcessID;
|
ids[count++] = computerSystem->data.common->ProcessID;
|
||||||
|
|
||||||
if (count >= maxids)
|
if (count >= maxids)
|
||||||
break;
|
break;
|
||||||
@ -532,7 +557,7 @@ hypervDomainSuspend(virDomainPtr domain)
|
|||||||
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (computerSystem->data->EnabledState !=
|
if (computerSystem->data.common->EnabledState !=
|
||||||
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
_("Domain is not active"));
|
_("Domain is not active"));
|
||||||
@ -560,7 +585,7 @@ hypervDomainResume(virDomainPtr domain)
|
|||||||
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (computerSystem->data->EnabledState !=
|
if (computerSystem->data.common->EnabledState !=
|
||||||
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED) {
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED) {
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
_("Domain is not paused"));
|
_("Domain is not paused"));
|
||||||
@ -666,7 +691,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not lookup %s for domain %s"),
|
_("Could not lookup %s for domain %s"),
|
||||||
"Msvm_VirtualSystemSettingData",
|
"Msvm_VirtualSystemSettingData",
|
||||||
computerSystem->data->ElementName);
|
computerSystem->data.common->ElementName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,7 +701,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||||||
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
||||||
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
||||||
"ResultClass = Msvm_ProcessorSettingData",
|
"ResultClass = Msvm_ProcessorSettingData",
|
||||||
virtualSystemSettingData->data->InstanceID);
|
virtualSystemSettingData->data.common->InstanceID);
|
||||||
|
|
||||||
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
||||||
&processorSettingData) < 0) {
|
&processorSettingData) < 0) {
|
||||||
@ -687,7 +712,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not lookup %s for domain %s"),
|
_("Could not lookup %s for domain %s"),
|
||||||
"Msvm_ProcessorSettingData",
|
"Msvm_ProcessorSettingData",
|
||||||
computerSystem->data->ElementName);
|
computerSystem->data.common->ElementName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,7 +722,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||||||
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
||||||
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
||||||
"ResultClass = Msvm_MemorySettingData",
|
"ResultClass = Msvm_MemorySettingData",
|
||||||
virtualSystemSettingData->data->InstanceID);
|
virtualSystemSettingData->data.common->InstanceID);
|
||||||
|
|
||||||
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
||||||
&memorySettingData) < 0) {
|
&memorySettingData) < 0) {
|
||||||
@ -709,15 +734,15 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not lookup %s for domain %s"),
|
_("Could not lookup %s for domain %s"),
|
||||||
"Msvm_MemorySettingData",
|
"Msvm_MemorySettingData",
|
||||||
computerSystem->data->ElementName);
|
computerSystem->data.common->ElementName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill struct */
|
/* Fill struct */
|
||||||
info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
|
||||||
info->maxMem = memorySettingData->data->Limit * 1024; /* megabyte to kilobyte */
|
info->maxMem = memorySettingData->data.common->Limit * 1024; /* megabyte to kilobyte */
|
||||||
info->memory = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
info->memory = memorySettingData->data.common->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
||||||
info->nrVirtCpu = processorSettingData->data->VirtualQuantity;
|
info->nrVirtCpu = processorSettingData->data.common->VirtualQuantity;
|
||||||
info->cpuTime = 0;
|
info->cpuTime = 0;
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
@ -803,7 +828,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not lookup %s for domain %s"),
|
_("Could not lookup %s for domain %s"),
|
||||||
"Msvm_VirtualSystemSettingData",
|
"Msvm_VirtualSystemSettingData",
|
||||||
computerSystem->data->ElementName);
|
computerSystem->data.common->ElementName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +838,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
||||||
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
||||||
"ResultClass = Msvm_ProcessorSettingData",
|
"ResultClass = Msvm_ProcessorSettingData",
|
||||||
virtualSystemSettingData->data->InstanceID);
|
virtualSystemSettingData->data.common->InstanceID);
|
||||||
|
|
||||||
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
|
||||||
&processorSettingData) < 0) {
|
&processorSettingData) < 0) {
|
||||||
@ -824,7 +849,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not lookup %s for domain %s"),
|
_("Could not lookup %s for domain %s"),
|
||||||
"Msvm_ProcessorSettingData",
|
"Msvm_ProcessorSettingData",
|
||||||
computerSystem->data->ElementName);
|
computerSystem->data.common->ElementName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,7 +859,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
|
||||||
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
||||||
"ResultClass = Msvm_MemorySettingData",
|
"ResultClass = Msvm_MemorySettingData",
|
||||||
virtualSystemSettingData->data->InstanceID);
|
virtualSystemSettingData->data.common->InstanceID);
|
||||||
|
|
||||||
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
if (hypervGetMsvmMemorySettingDataList(priv, &query,
|
||||||
&memorySettingData) < 0) {
|
&memorySettingData) < 0) {
|
||||||
@ -846,7 +871,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not lookup %s for domain %s"),
|
_("Could not lookup %s for domain %s"),
|
||||||
"Msvm_MemorySettingData",
|
"Msvm_MemorySettingData",
|
||||||
computerSystem->data->ElementName);
|
computerSystem->data.common->ElementName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,34 +879,34 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
|
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
|
||||||
|
|
||||||
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
|
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
|
||||||
def->id = computerSystem->data->ProcessID;
|
def->id = computerSystem->data.common->ProcessID;
|
||||||
} else {
|
} else {
|
||||||
def->id = -1;
|
def->id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virUUIDParse(computerSystem->data->Name, def->uuid) < 0) {
|
if (virUUIDParse(computerSystem->data.common->Name, def->uuid) < 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not parse UUID from string '%s'"),
|
_("Could not parse UUID from string '%s'"),
|
||||||
computerSystem->data->Name);
|
computerSystem->data.common->Name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_STRDUP(def->name, computerSystem->data->ElementName) < 0)
|
if (VIR_STRDUP(def->name, computerSystem->data.common->ElementName) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (VIR_STRDUP(def->description, virtualSystemSettingData->data->Notes) < 0)
|
if (VIR_STRDUP(def->description, virtualSystemSettingData->data.common->Notes) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
virDomainDefSetMemoryTotal(def, memorySettingData->data->Limit * 1024); /* megabyte to kilobyte */
|
virDomainDefSetMemoryTotal(def, memorySettingData->data.common->Limit * 1024); /* megabyte to kilobyte */
|
||||||
def->mem.cur_balloon = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
def->mem.cur_balloon = memorySettingData->data.common->VirtualQuantity * 1024; /* megabyte to kilobyte */
|
||||||
|
|
||||||
if (virDomainDefSetVcpusMax(def,
|
if (virDomainDefSetVcpusMax(def,
|
||||||
processorSettingData->data->VirtualQuantity,
|
processorSettingData->data.common->VirtualQuantity,
|
||||||
NULL) < 0)
|
NULL) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (virDomainDefSetVcpus(def,
|
if (virDomainDefSetVcpus(def,
|
||||||
processorSettingData->data->VirtualQuantity) < 0)
|
processorSettingData->data.common->VirtualQuantity) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
|
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
|
||||||
@ -930,7 +955,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn
|
|||||||
|
|
||||||
for (computerSystem = computerSystemList; computerSystem != NULL;
|
for (computerSystem = computerSystemList; computerSystem != NULL;
|
||||||
computerSystem = computerSystem->next) {
|
computerSystem = computerSystem->next) {
|
||||||
if (VIR_STRDUP(names[count], computerSystem->data->ElementName) < 0)
|
if (VIR_STRDUP(names[count], computerSystem->data.common->ElementName) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
@ -1154,7 +1179,7 @@ hypervDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
|
|||||||
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
result = computerSystem->data->EnabledState ==
|
result = computerSystem->data.common->EnabledState ==
|
||||||
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -1177,7 +1202,7 @@ hypervDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
|
|||||||
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (computerSystem->data->EnabledState !=
|
if (computerSystem->data.common->EnabledState !=
|
||||||
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
|
||||||
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
_("Domain has no managed save image"));
|
_("Domain has no managed save image"));
|
||||||
@ -1280,7 +1305,7 @@ hypervConnectListAllDomains(virConnectPtr conn,
|
|||||||
|
|
||||||
/* managed save filter */
|
/* managed save filter */
|
||||||
if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
|
if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
|
||||||
bool mansave = computerSystem->data->EnabledState ==
|
bool mansave = computerSystem->data.common->EnabledState ==
|
||||||
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED;
|
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED;
|
||||||
|
|
||||||
if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
|
if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
|
||||||
|
@ -36,15 +36,56 @@
|
|||||||
|
|
||||||
#define WS_SERIALIZER_FREE_MEM_WORKS 0
|
#define WS_SERIALIZER_FREE_MEM_WORKS 0
|
||||||
|
|
||||||
#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/*"
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_HYPERV
|
#define VIR_FROM_THIS VIR_FROM_HYPERV
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervGetWmiClassInfo(hypervPrivate *priv, hypervWmiClassInfoListPtr list,
|
||||||
|
hypervWmiClassInfoPtr *info)
|
||||||
|
{
|
||||||
|
const char *version = "v2";
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (list->count == 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("The WMI class info list is empty"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if there's just one WMI class and isn't versioned, assume "shared" */
|
||||||
|
if (list->count == 1 && list->objs[0]->version == NULL) {
|
||||||
|
*info = list->objs[0];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->wmiVersion == HYPERV_WMI_VERSION_V1)
|
||||||
|
version = "v1";
|
||||||
|
|
||||||
|
for (i = 0; i < list->count; i++) {
|
||||||
|
if (STRCASEEQ(list->objs[i]->version, version)) {
|
||||||
|
*info = list->objs[i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Could not match WMI class info for version %s"),
|
||||||
|
version);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervGetWmiClassList(hypervPrivate *priv, hypervWmiClassInfoListPtr wmiInfo,
|
||||||
|
virBufferPtr query, hypervObject **wmiClass)
|
||||||
|
{
|
||||||
|
hypervWqlQuery wqlQuery = HYPERV_WQL_QUERY_INITIALIZER;
|
||||||
|
|
||||||
|
wqlQuery.info = wmiInfo;
|
||||||
|
wqlQuery.query = query;
|
||||||
|
|
||||||
|
return hypervEnumAndPull(priv, &wqlQuery, wmiClass);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
|
hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
|
||||||
@ -106,16 +147,16 @@ hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
|
|||||||
* Object
|
* Object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This function guarantees that query is freed, even on failure */
|
/* This function guarantees that wqlQuery->query is reset, even on failure */
|
||||||
int
|
int
|
||||||
hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
hypervEnumAndPull(hypervPrivate *priv, hypervWqlQueryPtr wqlQuery,
|
||||||
XmlSerializerInfo *serializerInfo, const char *resourceUri,
|
hypervObject **list)
|
||||||
const char *className, hypervObject **list)
|
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
WsSerializerContextH serializerContext;
|
WsSerializerContextH serializerContext;
|
||||||
client_opt_t *options = NULL;
|
client_opt_t *options = NULL;
|
||||||
char *query_string = NULL;
|
char *query_string = NULL;
|
||||||
|
hypervWmiClassInfoPtr wmiInfo = NULL;
|
||||||
filter_t *filter = NULL;
|
filter_t *filter = NULL;
|
||||||
WsXmlDocH response = NULL;
|
WsXmlDocH response = NULL;
|
||||||
char *enumContext = NULL;
|
char *enumContext = NULL;
|
||||||
@ -125,11 +166,12 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
XML_TYPE_PTR data = NULL;
|
XML_TYPE_PTR data = NULL;
|
||||||
hypervObject *object;
|
hypervObject *object;
|
||||||
|
|
||||||
if (virBufferCheckError(query) < 0) {
|
if (virBufferCheckError(wqlQuery->query) < 0) {
|
||||||
virBufferFreeAndReset(query);
|
virBufferFreeAndReset(wqlQuery->query);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
query_string = virBufferContentAndReset(query);
|
|
||||||
|
query_string = virBufferContentAndReset(wqlQuery->query);
|
||||||
|
|
||||||
if (list == NULL || *list != NULL) {
|
if (list == NULL || *list != NULL) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
|
||||||
@ -137,6 +179,9 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hypervGetWmiClassInfo(priv, wqlQuery->info, &wmiInfo) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
serializerContext = wsmc_get_serialization_context(priv->client);
|
serializerContext = wsmc_get_serialization_context(priv->client);
|
||||||
|
|
||||||
options = wsmc_options_init();
|
options = wsmc_options_init();
|
||||||
@ -155,7 +200,8 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
response = wsmc_action_enumerate(priv->client, root, options, filter);
|
response = wsmc_action_enumerate(priv->client, wmiInfo->rootUri, options,
|
||||||
|
filter);
|
||||||
|
|
||||||
if (hypervVerifyResponse(priv->client, response, "enumeration") < 0)
|
if (hypervVerifyResponse(priv->client, response, "enumeration") < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -166,7 +212,7 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
response = NULL;
|
response = NULL;
|
||||||
|
|
||||||
while (enumContext != NULL && *enumContext != '\0') {
|
while (enumContext != NULL && *enumContext != '\0') {
|
||||||
response = wsmc_action_pull(priv->client, resourceUri, options,
|
response = wsmc_action_pull(priv->client, wmiInfo->resourceUri, options,
|
||||||
filter, enumContext);
|
filter, enumContext);
|
||||||
|
|
||||||
if (hypervVerifyResponse(priv->client, response, "pull") < 0)
|
if (hypervVerifyResponse(priv->client, response, "pull") < 0)
|
||||||
@ -196,11 +242,12 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws_xml_get_child(node, 0, resourceUri, className) == NULL)
|
if (ws_xml_get_child(node, 0, wmiInfo->resourceUri,
|
||||||
|
wmiInfo->name) == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
data = ws_deserialize(serializerContext, node, serializerInfo,
|
data = ws_deserialize(serializerContext, node, wmiInfo->serializerInfo,
|
||||||
className, resourceUri, NULL, 0, 0);
|
wmiInfo->name, wmiInfo->resourceUri, NULL, 0, 0);
|
||||||
|
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
@ -211,8 +258,8 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
if (VIR_ALLOC(object) < 0)
|
if (VIR_ALLOC(object) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
object->serializerInfo = serializerInfo;
|
object->info = wmiInfo;
|
||||||
object->data = data;
|
object->data.common = data;
|
||||||
|
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
||||||
@ -248,7 +295,7 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
|
|||||||
/* FIXME: ws_serializer_free_mem is broken in openwsman <= 2.2.6,
|
/* FIXME: ws_serializer_free_mem is broken in openwsman <= 2.2.6,
|
||||||
* see hypervFreeObject for a detailed explanation. */
|
* see hypervFreeObject for a detailed explanation. */
|
||||||
if (ws_serializer_free_mem(serializerContext, data,
|
if (ws_serializer_free_mem(serializerContext, data,
|
||||||
serializerInfo) < 0) {
|
wmiInfo->serializerInfo) < 0) {
|
||||||
VIR_ERROR(_("Could not free deserialized data"));
|
VIR_ERROR(_("Could not free deserialized data"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -287,8 +334,8 @@ hypervFreeObject(hypervPrivate *priv ATTRIBUTE_UNUSED, hypervObject *object)
|
|||||||
* them in wsmc_release. So this doesn't result in a real
|
* them in wsmc_release. So this doesn't result in a real
|
||||||
* memory leak, but just in piling up unused memory until
|
* memory leak, but just in piling up unused memory until
|
||||||
* the connection is closed. */
|
* the connection is closed. */
|
||||||
if (ws_serializer_free_mem(serializerContext, object->data,
|
if (ws_serializer_free_mem(serializerContext, object->data.common,
|
||||||
object->serializerInfo) < 0) {
|
object->info->serializerInfo) < 0) {
|
||||||
VIR_ERROR(_("Could not free deserialized data"));
|
VIR_ERROR(_("Could not free deserialized data"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -381,6 +428,70 @@ hypervReturnCodeToString(int returnCode)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Generic "Get WMI class list" helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetMsvmComputerSystemList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Msvm_ComputerSystem **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Msvm_ComputerSystem_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetMsvmConcreteJobList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Msvm_ConcreteJob **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Msvm_ConcreteJob_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetWin32ComputerSystemList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Win32_ComputerSystem **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Win32_ComputerSystem_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetWin32ProcessorList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Win32_Processor **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Win32_Processor_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetMsvmVirtualSystemSettingDataList(hypervPrivate *priv,
|
||||||
|
virBufferPtr query,
|
||||||
|
Msvm_VirtualSystemSettingData **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Msvm_VirtualSystemSettingData_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetMsvmProcessorSettingDataList(hypervPrivate *priv,
|
||||||
|
virBufferPtr query,
|
||||||
|
Msvm_ProcessorSettingData **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Msvm_ProcessorSettingData_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Msvm_MemorySettingData **list)
|
||||||
|
{
|
||||||
|
return hypervGetWmiClassList(priv, Msvm_MemorySettingData_WmiInfo, query,
|
||||||
|
(hypervObject **) list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* Msvm_ComputerSystem
|
* Msvm_ComputerSystem
|
||||||
*/
|
*/
|
||||||
@ -402,6 +513,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
|
|||||||
virBuffer query = VIR_BUFFER_INITIALIZER;
|
virBuffer query = VIR_BUFFER_INITIALIZER;
|
||||||
Msvm_ConcreteJob *concreteJob = NULL;
|
Msvm_ConcreteJob *concreteJob = NULL;
|
||||||
bool completed = false;
|
bool completed = false;
|
||||||
|
const char *resourceUri = MSVM_COMPUTERSYSTEM_V2_RESOURCE_URI;
|
||||||
|
|
||||||
virUUIDFormat(domain->uuid, uuid_string);
|
virUUIDFormat(domain->uuid, uuid_string);
|
||||||
|
|
||||||
@ -410,6 +522,9 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
|
|||||||
virAsprintf(&properties, "RequestedState=%d", requestedState) < 0)
|
virAsprintf(&properties, "RequestedState=%d", requestedState) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (priv->wmiVersion == HYPERV_WMI_VERSION_V1)
|
||||||
|
resourceUri = MSVM_COMPUTERSYSTEM_V1_RESOURCE_URI;
|
||||||
|
|
||||||
options = wsmc_options_init();
|
options = wsmc_options_init();
|
||||||
|
|
||||||
if (options == NULL) {
|
if (options == NULL) {
|
||||||
@ -422,7 +537,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
|
|||||||
wsmc_add_prop_from_str(options, properties);
|
wsmc_add_prop_from_str(options, properties);
|
||||||
|
|
||||||
/* Invoke method */
|
/* Invoke method */
|
||||||
response = wsmc_action_invoke(priv->client, MSVM_COMPUTERSYSTEM_RESOURCE_URI,
|
response = wsmc_action_invoke(priv->client, resourceUri,
|
||||||
options, "RequestStateChange", NULL);
|
options, "RequestStateChange", NULL);
|
||||||
|
|
||||||
if (hypervVerifyResponse(priv->client, response, "invocation") < 0)
|
if (hypervVerifyResponse(priv->client, response, "invocation") < 0)
|
||||||
@ -471,7 +586,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (concreteJob->data->JobState) {
|
switch (concreteJob->data.common->JobState) {
|
||||||
case MSVM_CONCRETEJOB_JOBSTATE_NEW:
|
case MSVM_CONCRETEJOB_JOBSTATE_NEW:
|
||||||
case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
|
case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
|
||||||
case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
|
case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
|
||||||
@ -530,7 +645,7 @@ int
|
|||||||
hypervMsvmComputerSystemEnabledStateToDomainState
|
hypervMsvmComputerSystemEnabledStateToDomainState
|
||||||
(Msvm_ComputerSystem *computerSystem)
|
(Msvm_ComputerSystem *computerSystem)
|
||||||
{
|
{
|
||||||
switch (computerSystem->data->EnabledState) {
|
switch (computerSystem->data.common->EnabledState) {
|
||||||
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
|
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
|
||||||
return VIR_DOMAIN_NOSTATE;
|
return VIR_DOMAIN_NOSTATE;
|
||||||
|
|
||||||
@ -570,7 +685,7 @@ hypervIsMsvmComputerSystemActive(Msvm_ComputerSystem *computerSystem,
|
|||||||
if (in_transition != NULL)
|
if (in_transition != NULL)
|
||||||
*in_transition = false;
|
*in_transition = false;
|
||||||
|
|
||||||
switch (computerSystem->data->EnabledState) {
|
switch (computerSystem->data.common->EnabledState) {
|
||||||
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
|
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -615,17 +730,17 @@ hypervMsvmComputerSystemToDomain(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virUUIDParse(computerSystem->data->Name, uuid) < 0) {
|
if (virUUIDParse(computerSystem->data.common->Name, uuid) < 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not parse UUID from string '%s'"),
|
_("Could not parse UUID from string '%s'"),
|
||||||
computerSystem->data->Name);
|
computerSystem->data.common->Name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL))
|
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL))
|
||||||
id = computerSystem->data->ProcessID;
|
id = computerSystem->data.common->ProcessID;
|
||||||
|
|
||||||
*domain = virGetDomain(conn, computerSystem->data->ElementName, uuid, id);
|
*domain = virGetDomain(conn, computerSystem->data.common->ElementName, uuid, id);
|
||||||
|
|
||||||
return *domain ? 0 : -1;
|
return *domain ? 0 : -1;
|
||||||
}
|
}
|
||||||
@ -661,7 +776,3 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "hyperv_wmi.generated.c"
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _hypervObject hypervObject;
|
# define HYPERV_WQL_QUERY_INITIALIZER { NULL, NULL }
|
||||||
|
|
||||||
int hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
|
int hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
|
||||||
const char *detail);
|
const char *detail);
|
||||||
@ -41,8 +41,9 @@ int hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* Object
|
* Object
|
||||||
*/
|
*/
|
||||||
typedef struct _hypervObjectUnified hypervObjectUnified;
|
|
||||||
struct _hypervObjectUnified {
|
typedef struct _hypervObject hypervObject;
|
||||||
|
struct _hypervObject {
|
||||||
/* Unserialized data from wsman response. The member called "common" has
|
/* Unserialized data from wsman response. The member called "common" has
|
||||||
* properties that are the same type and name for all "versions" of given
|
* properties that are the same type and name for all "versions" of given
|
||||||
* WMI class. This means that calling code does not have to make any
|
* WMI class. This means that calling code does not have to make any
|
||||||
@ -57,18 +58,17 @@ struct _hypervObjectUnified {
|
|||||||
} data;
|
} data;
|
||||||
/* The info used to make wsman request */
|
/* The info used to make wsman request */
|
||||||
hypervWmiClassInfoPtr info;
|
hypervWmiClassInfoPtr info;
|
||||||
hypervObjectUnified *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _hypervObject {
|
|
||||||
XmlSerializerInfo *serializerInfo;
|
|
||||||
XML_TYPE_PTR data;
|
|
||||||
hypervObject *next;
|
hypervObject *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query,
|
typedef struct _hypervWqlQuery hypervWqlQuery;
|
||||||
const char *root, XmlSerializerInfo *serializerInfo,
|
typedef hypervWqlQuery *hypervWqlQueryPtr;
|
||||||
const char *resourceUri, const char *className,
|
struct _hypervWqlQuery {
|
||||||
|
virBufferPtr query;
|
||||||
|
hypervWmiClassInfoListPtr info;
|
||||||
|
};
|
||||||
|
|
||||||
|
int hypervEnumAndPull(hypervPrivate *priv, hypervWqlQueryPtr wqlQuery,
|
||||||
hypervObject **list);
|
hypervObject **list);
|
||||||
|
|
||||||
void hypervFreeObject(hypervPrivate *priv, hypervObject *object);
|
void hypervFreeObject(hypervPrivate *priv, hypervObject *object);
|
||||||
@ -111,6 +111,35 @@ const char *hypervReturnCodeToString(int returnCode);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Generic "Get WMI class list" helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
int hypervGetMsvmComputerSystemList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Msvm_ComputerSystem **list);
|
||||||
|
|
||||||
|
int hypervGetMsvmConcreteJobList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Msvm_ConcreteJob **list);
|
||||||
|
|
||||||
|
int hypervGetWin32ComputerSystemList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Win32_ComputerSystem **list);
|
||||||
|
|
||||||
|
int hypervGetWin32ProcessorList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Win32_Processor **list);
|
||||||
|
|
||||||
|
int hypervGetMsvmVirtualSystemSettingDataList(hypervPrivate *priv,
|
||||||
|
virBufferPtr query,
|
||||||
|
Msvm_VirtualSystemSettingData **list);
|
||||||
|
|
||||||
|
int hypervGetMsvmProcessorSettingDataList(hypervPrivate *priv,
|
||||||
|
virBufferPtr query,
|
||||||
|
Msvm_ProcessorSettingData **list);
|
||||||
|
|
||||||
|
int hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, virBufferPtr query,
|
||||||
|
Msvm_MemorySettingData **list);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* Msvm_ComputerSystem
|
* Msvm_ComputerSystem
|
||||||
*/
|
*/
|
||||||
@ -131,8 +160,4 @@ int hypervMsvmComputerSystemToDomain(virConnectPtr conn,
|
|||||||
int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
|
int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
|
||||||
Msvm_ComputerSystem **computerSystem);
|
Msvm_ComputerSystem **computerSystem);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# include "hyperv_wmi.generated.h"
|
|
||||||
|
|
||||||
#endif /* __HYPERV_WMI_H__ */
|
#endif /* __HYPERV_WMI_H__ */
|
||||||
|
@ -27,6 +27,15 @@
|
|||||||
|
|
||||||
# include "hyperv_wmi_classes.generated.typedef"
|
# include "hyperv_wmi_classes.generated.typedef"
|
||||||
|
|
||||||
|
# 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/*"
|
||||||
|
|
||||||
|
# define ROOT_VIRTUALIZATION_V2 \
|
||||||
|
"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/v2/*"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
@ -56,6 +56,55 @@ class Msvm_ComputerSystem
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class v2/Msvm_ComputerSystem
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
string ElementName
|
||||||
|
datetime InstallDate
|
||||||
|
uint16 OperationalStatus[]
|
||||||
|
string StatusDescriptions[]
|
||||||
|
string Status
|
||||||
|
uint16 HealthState
|
||||||
|
uint16 CommunicationStatus
|
||||||
|
uint16 DetailedStatus
|
||||||
|
uint16 OperatingStatus
|
||||||
|
uint16 PrimaryStatus
|
||||||
|
uint16 EnabledState
|
||||||
|
string OtherEnabledState
|
||||||
|
uint16 RequestedState
|
||||||
|
uint16 EnabledDefault
|
||||||
|
datetime TimeOfLastStateChange
|
||||||
|
uint16 AvailableRequestedStates[]
|
||||||
|
uint16 TransitioningToState
|
||||||
|
string CreationClassName
|
||||||
|
string Name
|
||||||
|
string PrimaryOwnerName
|
||||||
|
string PrimaryOwnerContact
|
||||||
|
string Roles[]
|
||||||
|
string NameFormat
|
||||||
|
string OtherIdentifyingInfo[]
|
||||||
|
string IdentifyingDescriptions[]
|
||||||
|
uint16 Dedicated[]
|
||||||
|
string OtherDedicatedDescriptions[]
|
||||||
|
uint16 ResetCapability
|
||||||
|
uint16 PowerManagementCapabilities[]
|
||||||
|
uint64 OnTimeInMilliseconds
|
||||||
|
uint32 ProcessID
|
||||||
|
datetime TimeOfLastConfigurationChange
|
||||||
|
uint16 NumberOfNumaNodes
|
||||||
|
uint16 ReplicationState
|
||||||
|
uint16 ReplicationHealth
|
||||||
|
uint16 ReplicationMode
|
||||||
|
uint16 FailedOverReplicationType
|
||||||
|
uint16 LastReplicationType
|
||||||
|
datetime LastApplicationConsistentReplicationTime
|
||||||
|
datetime LastReplicationTime
|
||||||
|
datetime LastSuccessfulBackupTime
|
||||||
|
uint16 EnhancedSessionModeState
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
class Msvm_ConcreteJob
|
class Msvm_ConcreteJob
|
||||||
string Caption
|
string Caption
|
||||||
string Description
|
string Description
|
||||||
@ -96,6 +145,51 @@ class Msvm_ConcreteJob
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class v2/Msvm_ConcreteJob
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
string ElementName
|
||||||
|
datetime InstallDate
|
||||||
|
string Name
|
||||||
|
uint16 OperationalStatus[]
|
||||||
|
string StatusDescriptions[]
|
||||||
|
string Status
|
||||||
|
uint16 HealthState
|
||||||
|
uint16 CommunicationStatus
|
||||||
|
uint16 DetailedStatus
|
||||||
|
uint16 OperatingStatus
|
||||||
|
uint16 PrimaryStatus
|
||||||
|
string JobStatus
|
||||||
|
datetime TimeSubmitted
|
||||||
|
datetime ScheduledStartTime
|
||||||
|
datetime StartTime
|
||||||
|
datetime ElapsedTime
|
||||||
|
uint32 JobRunTimes
|
||||||
|
uint8 RunMonth
|
||||||
|
sint8 RunDay
|
||||||
|
sint8 RunDayOfWeek
|
||||||
|
datetime RunStartInterval
|
||||||
|
uint16 LocalOrUtcTime
|
||||||
|
datetime UntilTime
|
||||||
|
string Notify
|
||||||
|
string Owner
|
||||||
|
uint32 Priority
|
||||||
|
uint16 PercentComplete
|
||||||
|
boolean DeleteOnCompletion
|
||||||
|
uint16 ErrorCode
|
||||||
|
string ErrorDescription
|
||||||
|
string ErrorSummaryDescription
|
||||||
|
uint16 RecoveryAction
|
||||||
|
string OtherRecoveryAction
|
||||||
|
uint16 JobState
|
||||||
|
datetime TimeOfLastStateChange
|
||||||
|
datetime TimeBeforeRemoval
|
||||||
|
boolean Cancellable
|
||||||
|
uint16 JobType
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
class Msvm_MemorySettingData
|
class Msvm_MemorySettingData
|
||||||
string Caption
|
string Caption
|
||||||
string Description
|
string Description
|
||||||
@ -126,6 +220,38 @@ class Msvm_MemorySettingData
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class v2/Msvm_MemorySettingData
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
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 AddressOnParent
|
||||||
|
string VirtualQuantityUnits
|
||||||
|
boolean DynamicMemoryEnabled
|
||||||
|
uint32 TargetMemoryBuffer
|
||||||
|
boolean IsVirtualized
|
||||||
|
boolean SwapFilesInUse
|
||||||
|
uint64 MaxMemoryBlocksPerNumaNode
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
class Msvm_ProcessorSettingData
|
class Msvm_ProcessorSettingData
|
||||||
string Caption
|
string Caption
|
||||||
string Description
|
string Description
|
||||||
@ -159,6 +285,37 @@ class Msvm_ProcessorSettingData
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class v2/Msvm_ProcessorSettingData
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
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 AddressOnParent
|
||||||
|
string VirtualQuantityUnits
|
||||||
|
boolean LimitCPUID
|
||||||
|
boolean LimitProcessorFeatures
|
||||||
|
uint64 MaxProcessorsPerNumaNode
|
||||||
|
uint64 MaxNumaNodesPerSocket
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
class Msvm_VirtualSystemSettingData
|
class Msvm_VirtualSystemSettingData
|
||||||
string Caption
|
string Caption
|
||||||
string Description
|
string Description
|
||||||
@ -184,6 +341,55 @@ class Msvm_VirtualSystemSettingData
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class v2/Msvm_VirtualSystemSettingData
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
string ElementName
|
||||||
|
string VirtualSystemIdentifier
|
||||||
|
string VirtualSystemType
|
||||||
|
string Notes[]
|
||||||
|
datetime CreationTime
|
||||||
|
string ConfigurationID
|
||||||
|
string ConfigurationDataRoot
|
||||||
|
string ConfigurationFile
|
||||||
|
string SnapshotDataRoot
|
||||||
|
string SuspendDataRoot
|
||||||
|
string SwapFileDataRoot
|
||||||
|
string LogDataRoot
|
||||||
|
uint16 AutomaticStartupAction
|
||||||
|
datetime AutomaticStartupActionDelay
|
||||||
|
uint16 AutomaticStartupActionSequenceNumber
|
||||||
|
uint16 AutomaticShutdownAction
|
||||||
|
uint16 AutomaticRecoveryAction
|
||||||
|
string RecoveryFile
|
||||||
|
string BIOSGUID
|
||||||
|
string BIOSSerialNumber
|
||||||
|
string BaseBoardSerialNumber
|
||||||
|
string ChassisSerialNumber
|
||||||
|
string ChassisAssetTag
|
||||||
|
boolean BIOSNumLock
|
||||||
|
uint16 BootOrder[]
|
||||||
|
string Parent
|
||||||
|
boolean IsSaved
|
||||||
|
string AdditionalRecoveryInformation
|
||||||
|
boolean AllowFullSCSICommandSet
|
||||||
|
uint32 DebugChannelId
|
||||||
|
uint16 DebugPortEnabled
|
||||||
|
uint32 DebugPort
|
||||||
|
string Version
|
||||||
|
boolean IncrementalBackupEnabled
|
||||||
|
boolean VirtualNumaEnabled
|
||||||
|
boolean AllowReducedFcRedundancy
|
||||||
|
string VirtualSystemSubType
|
||||||
|
string BootSourceOrder[]
|
||||||
|
boolean PauseAfterBootFailure
|
||||||
|
uint16 NetworkBootPreferredProtocol
|
||||||
|
boolean SecureBootEnabled
|
||||||
|
uint64 LowMmioGapSize
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
class Win32_ComputerSystem
|
class Win32_ComputerSystem
|
||||||
uint16 AdminPasswordStatus
|
uint16 AdminPasswordStatus
|
||||||
boolean AutomaticManagedPagefile
|
boolean AutomaticManagedPagefile
|
||||||
@ -607,39 +813,6 @@ class Msvm_VirtualSystemGlobalSettingData
|
|||||||
end
|
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_ResourceAllocationSettingData
|
class Msvm_ResourceAllocationSettingData
|
||||||
string Caption
|
string Caption
|
||||||
string Description
|
string Description
|
||||||
|
@ -24,140 +24,324 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
separator = "/*" + ("*" * 50) + "*\n"
|
||||||
|
wmi_version_separator = "/"
|
||||||
|
wmi_classes_by_name = {}
|
||||||
|
|
||||||
|
class WmiClass:
|
||||||
|
"""Represents WMI class and provides methods to generate C code.
|
||||||
|
|
||||||
separator = "/* " + ("* " * 37) + "*\n"
|
This class holds one or more instances of WmiClassVersion because with the
|
||||||
|
Windows 2012 release, Microsoft introduced "v2" version of Msvm_* family of
|
||||||
|
classes that need different URI for making wsman requests and also have
|
||||||
|
some additional/changed properties (though many of the properies are the
|
||||||
|
same as in "v1". Therefore, this class makes sure that C code is generated
|
||||||
|
for each of them while avoiding name conflics, identifies common members,
|
||||||
|
and defined *_WmiInfo structs holding info about each version so the driver
|
||||||
|
code can make the right choices based on which Hyper-V host it's connected
|
||||||
|
to.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name, versions = []):
|
||||||
|
|
||||||
class Class:
|
|
||||||
def __init__(self, name, properties):
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.properties = properties
|
self.versions = versions
|
||||||
|
self.common = None
|
||||||
|
|
||||||
|
|
||||||
def generate_header(self):
|
def prepare(self):
|
||||||
name_upper = self.name.upper()
|
"""Prepares the class for code generation
|
||||||
|
|
||||||
header = separator
|
Makes sure that "versioned" classes are sorted by version, identifies
|
||||||
header += " * %s\n" % self.name
|
common properies and ensures that they are aligned by name and
|
||||||
header += " */\n"
|
type in each version
|
||||||
header += "\n"
|
"""
|
||||||
header += "int hypervGet%sList(hypervPrivate *priv, virBufferPtr query, %s **list);\n" \
|
# sort vesioned classes by version in case input file did not have them
|
||||||
% (self.name.replace("_", ""), self.name)
|
# in order
|
||||||
header += "\n"
|
self.versions = sorted(self.versions, key=lambda cls: cls.version)
|
||||||
header += "\n"
|
|
||||||
header += "\n"
|
|
||||||
|
|
||||||
return header
|
# if there's more than one verion make sure first one has name suffixed
|
||||||
|
# because we'll generate "common" memeber and will be the "base" name
|
||||||
|
if len(self.versions) > 1:
|
||||||
|
first = self.versions[0]
|
||||||
|
if first.version == None:
|
||||||
|
first.version = "v1"
|
||||||
|
first.name = "%s_%s" % (first.name, first.version)
|
||||||
|
|
||||||
|
# finally, identify common members in all versions and make sure they
|
||||||
def generate_classes_typedef(self):
|
# are in the same order - to ensure C struct member alignment
|
||||||
typedef = "typedef struct _%s_Data %s_Data;\n" % (self.name, self.name)
|
self._align_property_members()
|
||||||
typedef += "typedef struct _%s %s;\n" % (self.name, self.name)
|
|
||||||
|
|
||||||
return typedef
|
|
||||||
|
|
||||||
|
|
||||||
def generate_classes_header(self):
|
def generate_classes_header(self):
|
||||||
|
"""Generate C header code and return it as string
|
||||||
|
|
||||||
|
Declares:
|
||||||
|
<class_name>_Data - used as one of hypervObject->data members
|
||||||
|
<class_name>_TypeInfo - used as wsman XmlSerializerInfo
|
||||||
|
<class_name> - "inherits" hypervObject struct
|
||||||
|
"""
|
||||||
|
|
||||||
name_upper = self.name.upper()
|
name_upper = self.name.upper()
|
||||||
|
|
||||||
header = separator
|
header = separator
|
||||||
header += " * %s\n" % self.name
|
header += " * %s\n" % self.name
|
||||||
header += " */\n"
|
header += " */\n"
|
||||||
header += "\n"
|
|
||||||
header += "#define %s_RESOURCE_URI \\\n" % name_upper
|
|
||||||
|
|
||||||
if self.name.startswith("Win32_") or self.name.startswith("CIM_"):
|
|
||||||
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
|
|
||||||
|
|
||||||
header += "\n"
|
header += "\n"
|
||||||
header += "#define %s_CLASSNAME \\\n" % name_upper
|
header += "#define %s_CLASSNAME \\\n" % name_upper
|
||||||
header += " \"%s\"\n" % self.name
|
header += " \"%s\"\n" % self.name
|
||||||
header += "\n"
|
header += "\n"
|
||||||
header += "#define %s_WQL_SELECT \\\n" % name_upper
|
header += "#define %s_WQL_SELECT \\\n" % name_upper
|
||||||
header += " \"select * from %s \"\n" % self.name
|
header += " \"SELECT * FROM %s \"\n" % self.name
|
||||||
header += "\n"
|
header += "\n"
|
||||||
header += "struct _%s_Data {\n" % self.name
|
header += "extern hypervWmiClassInfoListPtr %s_WmiInfo;\n\n" % self.name
|
||||||
|
|
||||||
for property in self.properties:
|
header += self._declare_data_structs()
|
||||||
header += property.generate_classes_header()
|
header += self._declare_hypervObject_struct()
|
||||||
|
|
||||||
header += "};\n"
|
|
||||||
header += "\n"
|
|
||||||
header += "SER_DECLARE_TYPE(%s_Data);\n" % self.name
|
|
||||||
header += "\n"
|
|
||||||
header += "struct _%s {\n" % self.name
|
|
||||||
header += " XmlSerializerInfo *serializerInfo;\n"
|
|
||||||
header += " %s_Data *data;\n" % self.name
|
|
||||||
header += " %s *next;\n" % self.name
|
|
||||||
header += "};\n"
|
|
||||||
header += "\n"
|
|
||||||
header += "\n"
|
|
||||||
header += "\n"
|
|
||||||
|
|
||||||
return header
|
return header
|
||||||
|
|
||||||
|
|
||||||
def generate_source(self):
|
|
||||||
name_upper = self.name.upper()
|
|
||||||
|
|
||||||
source = separator
|
|
||||||
source += " * %s\n" % self.name
|
|
||||||
source += " */\n"
|
|
||||||
source += "\n"
|
|
||||||
source += "int\n"
|
|
||||||
source += "hypervGet%sList(hypervPrivate *priv, virBufferPtr query, %s **list)\n" \
|
|
||||||
% (self.name.replace("_", ""), self.name)
|
|
||||||
source += "{\n"
|
|
||||||
|
|
||||||
if self.name.startswith("Win32_") or self.name.startswith("CIM_"):
|
|
||||||
source += " return hypervEnumAndPull(priv, query, ROOT_CIMV2,\n"
|
|
||||||
else:
|
|
||||||
source += " return hypervEnumAndPull(priv, query, ROOT_VIRTUALIZATION,\n"
|
|
||||||
|
|
||||||
source += " %s_Data_TypeInfo,\n" % self.name
|
|
||||||
source += " %s_RESOURCE_URI,\n" % name_upper
|
|
||||||
source += " %s_CLASSNAME,\n" % name_upper
|
|
||||||
source += " (hypervObject **)list);\n"
|
|
||||||
source += "}\n"
|
|
||||||
source += "\n"
|
|
||||||
source += "\n"
|
|
||||||
source += "\n"
|
|
||||||
|
|
||||||
return source
|
|
||||||
|
|
||||||
|
|
||||||
def generate_classes_source(self):
|
def generate_classes_source(self):
|
||||||
name_upper = self.name.upper()
|
"""Returns a C code string defining wsman data structs
|
||||||
|
|
||||||
|
Defines:
|
||||||
|
<class_name>_Data structs
|
||||||
|
<class_name>_WmiInfo - list holding metadata (e.g. request URIs) for
|
||||||
|
each known version of WMI class.
|
||||||
|
"""
|
||||||
|
|
||||||
source = separator
|
source = separator
|
||||||
source += " * %s\n" % self.name
|
source += " * %s\n" % self.name
|
||||||
source += " */\n"
|
source += " */\n"
|
||||||
source += "\n"
|
|
||||||
source += "SER_START_ITEMS(%s_Data)\n" % self.name
|
|
||||||
|
|
||||||
for property in self.properties:
|
for cls in self.versions:
|
||||||
source += property.generate_classes_source(self.name)
|
source += "SER_START_ITEMS(%s_Data)\n" % cls.name
|
||||||
|
|
||||||
source += "SER_END_ITEMS(%s_Data);\n" % self.name
|
for property in cls.properties:
|
||||||
source += "\n"
|
source += property.generate_classes_source(cls.name)
|
||||||
source += "\n"
|
|
||||||
source += "\n"
|
source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
|
||||||
|
|
||||||
|
|
||||||
|
source += self._define_WmiInfo_struct()
|
||||||
|
source += "\n\n"
|
||||||
|
|
||||||
return source
|
return source
|
||||||
|
|
||||||
|
|
||||||
|
def generate_classes_typedef(self):
|
||||||
|
"""Returns C string for typdefs"""
|
||||||
|
|
||||||
|
typedef = "typedef struct _%s %s;\n" % (self.name, self.name)
|
||||||
|
|
||||||
|
if self.common is not None:
|
||||||
|
typedef += "typedef struct _%s_Data %s_Data;\n" % (self.name, self.name)
|
||||||
|
|
||||||
|
for cls in self.versions:
|
||||||
|
typedef += "typedef struct _%s_Data %s_Data;\n" % (cls.name, cls.name)
|
||||||
|
|
||||||
|
return typedef
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _declare_data_structs(self):
|
||||||
|
"""Returns string C code declaring data structs.
|
||||||
|
|
||||||
|
The *_Data structs are members of hypervObject data union. Each one has
|
||||||
|
corresponding *_TypeInfo that is used for wsman unserialization of
|
||||||
|
response XML into the *_Data structs. If there's a "common" member, it
|
||||||
|
won't have corresponding *_TypeInfo becuase this is a special case only
|
||||||
|
used to provide a common "view" of v1, v2 etc members
|
||||||
|
"""
|
||||||
|
|
||||||
|
header = ""
|
||||||
|
if self.common is not None:
|
||||||
|
header += "struct _%s_Data {\n" % self.name
|
||||||
|
for property in self.common:
|
||||||
|
header += property.generate_classes_header()
|
||||||
|
header += "};\n\n"
|
||||||
|
|
||||||
|
# Declare actual data struct for each versions
|
||||||
|
for cls in self.versions:
|
||||||
|
header += "#define %s_RESOURCE_URI \\\n" % cls.name.upper()
|
||||||
|
header += " \"%s\"\n" % cls.uri_info.resourceUri
|
||||||
|
header += "\n"
|
||||||
|
header += "struct _%s_Data {\n" % cls.name
|
||||||
|
for property in cls.properties:
|
||||||
|
header += property.generate_classes_header()
|
||||||
|
header += "};\n\n"
|
||||||
|
header += "SER_DECLARE_TYPE(%s_Data);\n" % cls.name
|
||||||
|
|
||||||
|
return header
|
||||||
|
|
||||||
|
|
||||||
|
def _declare_hypervObject_struct(self):
|
||||||
|
"""Return string for C code declaring hypervObject instance"""
|
||||||
|
|
||||||
|
header = "\n/* must match hypervObject */\n"
|
||||||
|
header += "struct _%s {\n" % self.name
|
||||||
|
header += " union {\n"
|
||||||
|
|
||||||
|
# if there's common use it as "common" else first and only version is
|
||||||
|
# the "common" member
|
||||||
|
if self.common is not None:
|
||||||
|
header += " %s_Data *common;\n" % self.name
|
||||||
|
else:
|
||||||
|
header += " %s_Data *common;\n" % self.versions[0].name
|
||||||
|
|
||||||
|
for cls in self.versions:
|
||||||
|
header += " %s_Data *%s;\n" % (cls.name, cls.version)
|
||||||
|
|
||||||
|
header += " } data;\n"
|
||||||
|
header += " hypervWmiClassInfoPtr info;\n"
|
||||||
|
header += " %s *next;\n" % self.name
|
||||||
|
header += "};\n"
|
||||||
|
|
||||||
|
header += "\n\n\n"
|
||||||
|
|
||||||
|
return header
|
||||||
|
|
||||||
|
|
||||||
|
def _define_WmiInfo_struct(self):
|
||||||
|
"""Return string for C code defining *_WmiInfo struct
|
||||||
|
|
||||||
|
Those structs hold info with meta-data needed to make wsman requests for
|
||||||
|
each version of WMI class
|
||||||
|
"""
|
||||||
|
|
||||||
|
source = "hypervWmiClassInfoListPtr %s_WmiInfo = &(hypervWmiClassInfoList) {\n" % self.name
|
||||||
|
source += " .count = %d,\n" % len(self.versions)
|
||||||
|
source += " .objs = (hypervWmiClassInfoPtr []) {\n"
|
||||||
|
|
||||||
|
for cls in self.versions:
|
||||||
|
source += " &(hypervWmiClassInfo) {\n"
|
||||||
|
source += " .name = %s_CLASSNAME,\n" % self.name.upper()
|
||||||
|
if cls.version is not None:
|
||||||
|
source += " .version = \"%s\",\n" % cls.version
|
||||||
|
else:
|
||||||
|
source += " .version = NULL,\n"
|
||||||
|
source += " .rootUri = %s,\n" % cls.uri_info.rootUri
|
||||||
|
source += " .resourceUri = %s_RESOURCE_URI,\n" % cls.name.upper()
|
||||||
|
source += " .serializerInfo = %s_Data_TypeInfo\n" % cls.name
|
||||||
|
source += " },\n"
|
||||||
|
|
||||||
|
source += " }\n"
|
||||||
|
source += "};\n"
|
||||||
|
|
||||||
|
return source
|
||||||
|
|
||||||
|
|
||||||
|
def _align_property_members(self):
|
||||||
|
"""Identifies common properties in all class versions.
|
||||||
|
|
||||||
|
Makes sure that properties in all versions are ordered with common
|
||||||
|
members first and that they are in the same order. This makes the
|
||||||
|
generated C structs memory aligned and safe to access via the "common"
|
||||||
|
struct that "shares" members with v1, v2 etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
num_classes = len(self.versions)
|
||||||
|
common = {}
|
||||||
|
property_info = {}
|
||||||
|
|
||||||
|
if num_classes < 2:
|
||||||
|
return
|
||||||
|
|
||||||
|
# count property occurences in all class versions
|
||||||
|
for cls in self.versions:
|
||||||
|
for prop in cls.properties:
|
||||||
|
# consdered same if matches by name AND type
|
||||||
|
key = "%s_%s" % (prop.name, prop.type)
|
||||||
|
|
||||||
|
if key in property_info:
|
||||||
|
property_info[key][1] += 1
|
||||||
|
else:
|
||||||
|
property_info[key] = [prop, 1]
|
||||||
|
|
||||||
|
# isolate those that are common for all and keep track of their postions
|
||||||
|
pos = 0
|
||||||
|
for key in property_info:
|
||||||
|
info = property_info[key]
|
||||||
|
# exists in all class versions
|
||||||
|
if info[1] == num_classes:
|
||||||
|
common[info[0].name] = [info[0], pos]
|
||||||
|
pos += 1
|
||||||
|
|
||||||
|
# alter each versions's property list so that common members are first
|
||||||
|
# and in the same order as in the common dictionary
|
||||||
|
total = len(common)
|
||||||
|
for cls in self.versions:
|
||||||
|
index = 0
|
||||||
|
count = len(cls.properties)
|
||||||
|
|
||||||
|
while index < count:
|
||||||
|
prop = cls.properties[index]
|
||||||
|
|
||||||
|
# it's a "common" property
|
||||||
|
if prop.name in common:
|
||||||
|
pos = common[prop.name][1]
|
||||||
|
|
||||||
|
# move to the same position as in "common" dictionary
|
||||||
|
if index != pos:
|
||||||
|
tmp = cls.properties[pos]
|
||||||
|
cls.properties[pos] = prop
|
||||||
|
cls.properties[index] = tmp
|
||||||
|
else:
|
||||||
|
index += 1
|
||||||
|
else:
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
# finally, get common properties as list sorted by position in dictionary
|
||||||
|
tmp = sorted(common.values(), key=lambda x: x[1])
|
||||||
|
self.common = []
|
||||||
|
for x in tmp:
|
||||||
|
self.common.append(x[0])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ClassUriInfo:
|
||||||
|
"""Prepares URI information needed for wsman requests."""
|
||||||
|
|
||||||
|
def __init__(self, wmi_name, version):
|
||||||
|
self.rootUri = "ROOT_CIMV2"
|
||||||
|
self.resourceUri = None
|
||||||
|
baseUri = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2"
|
||||||
|
|
||||||
|
if wmi_name.startswith("Msvm_"):
|
||||||
|
baseUri = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization"
|
||||||
|
self.rootUri = "ROOT_VIRTUALIZATION"
|
||||||
|
|
||||||
|
if version == "v2":
|
||||||
|
baseUri += "/v2"
|
||||||
|
self.rootUri = "ROOT_VIRTUALIZATION_V2"
|
||||||
|
|
||||||
|
self.resourceUri = "%s/%s" % (baseUri, wmi_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class WmiClassVersion:
|
||||||
|
"""Represents specific version of WMI class."""
|
||||||
|
|
||||||
|
def __init__(self, name, version, properties, uri_info):
|
||||||
|
self.name = name
|
||||||
|
self.version = version
|
||||||
|
self.properties = properties
|
||||||
|
self.uri_info = uri_info
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Property:
|
class Property:
|
||||||
typemap = {"boolean" : "BOOL",
|
typemap = {"boolean" : "BOOL",
|
||||||
"string" : "STR",
|
"string" : "STR",
|
||||||
"datetime" : "STR",
|
"datetime" : "STR",
|
||||||
"int8" : "INT8",
|
"int8" : "INT8",
|
||||||
|
"sint8" : "INT8",
|
||||||
"int16" : "INT16",
|
"int16" : "INT16",
|
||||||
|
"sint16" : "INT16",
|
||||||
"int32" : "INT32",
|
"int32" : "INT32",
|
||||||
|
"sint32" : "INT32",
|
||||||
"int64" : "INT64",
|
"int64" : "INT64",
|
||||||
|
"sint64" : "INT64",
|
||||||
"uint8" : "UINT8",
|
"uint8" : "UINT8",
|
||||||
"uint16" : "UINT16",
|
"uint16" : "UINT16",
|
||||||
"uint32" : "UINT32",
|
"uint32" : "UINT32",
|
||||||
@ -217,8 +401,15 @@ def parse_class(block):
|
|||||||
assert header_items[0] == "class"
|
assert header_items[0] == "class"
|
||||||
|
|
||||||
name = header_items[1]
|
name = header_items[1]
|
||||||
|
|
||||||
properties = []
|
properties = []
|
||||||
|
version = None
|
||||||
|
wmi_name = name
|
||||||
|
ns_separator = name.find(wmi_version_separator)
|
||||||
|
|
||||||
|
if ns_separator != -1:
|
||||||
|
version = name[:ns_separator]
|
||||||
|
wmi_name = name[ns_separator + 1:]
|
||||||
|
name = "%s_%s" % (wmi_name, version)
|
||||||
|
|
||||||
for line in block[1:]:
|
for line in block[1:]:
|
||||||
# expected format: <type> <name>
|
# expected format: <type> <name>
|
||||||
@ -236,7 +427,13 @@ def parse_class(block):
|
|||||||
properties.append(Property(type=items[0], name=items[1],
|
properties.append(Property(type=items[0], name=items[1],
|
||||||
is_array=is_array))
|
is_array=is_array))
|
||||||
|
|
||||||
return Class(name=name, properties=properties)
|
cls = WmiClassVersion(name=name, version=version, properties=properties,
|
||||||
|
uri_info=ClassUriInfo(wmi_name, version))
|
||||||
|
|
||||||
|
if wmi_name in wmi_classes_by_name:
|
||||||
|
wmi_classes_by_name[wmi_name].versions.append(cls)
|
||||||
|
else:
|
||||||
|
wmi_classes_by_name[wmi_name] = WmiClass(wmi_name, [cls])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -248,15 +445,12 @@ def main():
|
|||||||
input_filename = os.path.join(os.getcwd(), "hyperv_wmi_generator.input")
|
input_filename = os.path.join(os.getcwd(), "hyperv_wmi_generator.input")
|
||||||
output_dirname = os.getcwd()
|
output_dirname = os.getcwd()
|
||||||
|
|
||||||
header = open_and_print(os.path.join(output_dirname, "hyperv_wmi.generated.h"))
|
|
||||||
source = open_and_print(os.path.join(output_dirname, "hyperv_wmi.generated.c"))
|
|
||||||
classes_typedef = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.typedef"))
|
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_header = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.h"))
|
||||||
classes_source = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.c"))
|
classes_source = open_and_print(os.path.join(output_dirname, "hyperv_wmi_classes.generated.c"))
|
||||||
|
|
||||||
# parse input file
|
# parse input file
|
||||||
number = 0
|
number = 0
|
||||||
classes_by_name = {}
|
|
||||||
block = None
|
block = None
|
||||||
|
|
||||||
for line in file(input_filename, "rb").readlines():
|
for line in file(input_filename, "rb").readlines():
|
||||||
@ -279,8 +473,7 @@ def main():
|
|||||||
if block is not None:
|
if block is not None:
|
||||||
if line == "end":
|
if line == "end":
|
||||||
if block[0][1].startswith("class"):
|
if block[0][1].startswith("class"):
|
||||||
cls = parse_class(block)
|
parse_class(block)
|
||||||
classes_by_name[cls.name] = cls
|
|
||||||
|
|
||||||
block = None
|
block = None
|
||||||
else:
|
else:
|
||||||
@ -289,21 +482,20 @@ def main():
|
|||||||
# write output files
|
# write output files
|
||||||
notice = "/* Generated by hyperv_wmi_generator.py */\n\n\n\n"
|
notice = "/* Generated by hyperv_wmi_generator.py */\n\n\n\n"
|
||||||
|
|
||||||
header.write(notice)
|
|
||||||
source.write(notice)
|
|
||||||
classes_typedef.write(notice)
|
classes_typedef.write(notice)
|
||||||
classes_header.write(notice)
|
classes_header.write(notice)
|
||||||
classes_source.write(notice)
|
classes_source.write(notice)
|
||||||
|
|
||||||
names = classes_by_name.keys()
|
names = wmi_classes_by_name.keys()
|
||||||
names.sort()
|
names.sort()
|
||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
header.write(classes_by_name[name].generate_header())
|
cls = wmi_classes_by_name[name]
|
||||||
source.write(classes_by_name[name].generate_source())
|
cls.prepare()
|
||||||
classes_typedef.write(classes_by_name[name].generate_classes_typedef())
|
|
||||||
classes_header.write(classes_by_name[name].generate_classes_header())
|
classes_typedef.write(cls.generate_classes_typedef())
|
||||||
classes_source.write(classes_by_name[name].generate_classes_source())
|
classes_header.write(cls.generate_classes_header())
|
||||||
|
classes_source.write(cls.generate_classes_source())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user