hyperv/openwsman.h
HYPERV_DRIVER_GENERATED = \
- hyperv/hyperv_wmi.generated.c \
- hyperv/hyperv_wmi.generated.h \
hyperv/hyperv_wmi_classes.generated.c \
hyperv/hyperv_wmi_classes.generated.h \
hyperv/hyperv_wmi_classes.generated.typedef
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
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
hypervPrivate *priv = NULL;
char *username = NULL;
char *password = NULL;
- virBuffer query = VIR_BUFFER_INITIALIZER;
- Msvm_ComputerSystem *computerSystem = NULL;
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
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) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not create openwsman client"));
+ if (hypervInitConnection(conn, priv, username, password) < 0)
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;
priv = NULL;
hypervFreePrivate(&priv);
VIR_FREE(username);
VIR_FREE(password);
- hypervFreeObject(priv, (hypervObject *)computerSystem);
return result;
}
goto cleanup;
}
- ignore_value(VIR_STRDUP(hostname, computerSystem->data->DNSHostName));
+ ignore_value(VIR_STRDUP(hostname, computerSystem->data.common->DNSHostName));
cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem);
"{Win32_ComputerSystem.Name=\"%s\"} "
"where AssocClass = Win32_ComputerSystemProcessor "
"ResultClass = Win32_Processor",
- computerSystem->data->Name);
+ computerSystem->data.common->Name);
if (hypervGetWin32ProcessorList(priv, &query, &processorList) < 0)
goto cleanup;
}
/* Strip the string to fit more relevant information in 32 chars */
- tmp = processorList->data->Name;
+ tmp = processorList->data.common->Name;
while (*tmp != '\0') {
if (STRPREFIX(tmp, " ")) {
}
/* 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) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("CPU model %s too long for destination"),
- processorList->data->Name);
+ processorList->data.common->Name);
goto cleanup;
}
- info->memory = computerSystem->data->TotalPhysicalMemory / 1024; /* byte to kilobyte */
- info->mhz = processorList->data->MaxClockSpeed;
+ info->memory = computerSystem->data.common->TotalPhysicalMemory / 1024; /* byte to kilobyte */
+ info->mhz = processorList->data.common->MaxClockSpeed;
info->nodes = 1;
info->sockets = 0;
++info->sockets;
}
- info->cores = processorList->data->NumberOfCores;
- info->threads = info->cores / processorList->data->NumberOfLogicalProcessors;
+ info->cores = processorList->data.common->NumberOfCores;
+ info->threads = info->cores / processorList->data.common->NumberOfLogicalProcessors;
info->cpus = info->sockets * info->cores;
result = 0;
for (computerSystem = computerSystemList; computerSystem != NULL;
computerSystem = computerSystem->next) {
- ids[count++] = computerSystem->data->ProcessID;
+ ids[count++] = computerSystem->data.common->ProcessID;
if (count >= maxids)
break;
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup;
- if (computerSystem->data->EnabledState !=
+ if (computerSystem->data.common->EnabledState !=
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("Domain is not active"));
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup;
- if (computerSystem->data->EnabledState !=
+ if (computerSystem->data.common->EnabledState !=
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("Domain is not paused"));
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not lookup %s for domain %s"),
"Msvm_VirtualSystemSettingData",
- computerSystem->data->ElementName);
+ computerSystem->data.common->ElementName);
goto cleanup;
}
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
"ResultClass = Msvm_ProcessorSettingData",
- virtualSystemSettingData->data->InstanceID);
+ virtualSystemSettingData->data.common->InstanceID);
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
&processorSettingData) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not lookup %s for domain %s"),
"Msvm_ProcessorSettingData",
- computerSystem->data->ElementName);
+ computerSystem->data.common->ElementName);
goto cleanup;
}
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
"ResultClass = Msvm_MemorySettingData",
- virtualSystemSettingData->data->InstanceID);
+ virtualSystemSettingData->data.common->InstanceID);
if (hypervGetMsvmMemorySettingDataList(priv, &query,
&memorySettingData) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not lookup %s for domain %s"),
"Msvm_MemorySettingData",
- computerSystem->data->ElementName);
+ computerSystem->data.common->ElementName);
goto cleanup;
}
/* Fill struct */
info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
- info->maxMem = memorySettingData->data->Limit * 1024; /* megabyte to kilobyte */
- info->memory = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
- info->nrVirtCpu = processorSettingData->data->VirtualQuantity;
+ info->maxMem = memorySettingData->data.common->Limit * 1024; /* megabyte to kilobyte */
+ info->memory = memorySettingData->data.common->VirtualQuantity * 1024; /* megabyte to kilobyte */
+ info->nrVirtCpu = processorSettingData->data.common->VirtualQuantity;
info->cpuTime = 0;
result = 0;
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not lookup %s for domain %s"),
"Msvm_VirtualSystemSettingData",
- computerSystem->data->ElementName);
+ computerSystem->data.common->ElementName);
goto cleanup;
}
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
"ResultClass = Msvm_ProcessorSettingData",
- virtualSystemSettingData->data->InstanceID);
+ virtualSystemSettingData->data.common->InstanceID);
if (hypervGetMsvmProcessorSettingDataList(priv, &query,
&processorSettingData) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not lookup %s for domain %s"),
"Msvm_ProcessorSettingData",
- computerSystem->data->ElementName);
+ computerSystem->data.common->ElementName);
goto cleanup;
}
"{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
"where AssocClass = Msvm_VirtualSystemSettingDataComponent "
"ResultClass = Msvm_MemorySettingData",
- virtualSystemSettingData->data->InstanceID);
+ virtualSystemSettingData->data.common->InstanceID);
if (hypervGetMsvmMemorySettingDataList(priv, &query,
&memorySettingData) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not lookup %s for domain %s"),
"Msvm_MemorySettingData",
- computerSystem->data->ElementName);
+ computerSystem->data.common->ElementName);
goto cleanup;
}
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
- def->id = computerSystem->data->ProcessID;
+ def->id = computerSystem->data.common->ProcessID;
} else {
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,
_("Could not parse UUID from string '%s'"),
- computerSystem->data->Name);
+ computerSystem->data.common->Name);
return NULL;
}
- if (VIR_STRDUP(def->name, computerSystem->data->ElementName) < 0)
+ if (VIR_STRDUP(def->name, computerSystem->data.common->ElementName) < 0)
goto cleanup;
- if (VIR_STRDUP(def->description, virtualSystemSettingData->data->Notes) < 0)
+ if (VIR_STRDUP(def->description, virtualSystemSettingData->data.common->Notes) < 0)
goto cleanup;
- virDomainDefSetMemoryTotal(def, memorySettingData->data->Limit * 1024); /* megabyte to kilobyte */
- def->mem.cur_balloon = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
+ virDomainDefSetMemoryTotal(def, memorySettingData->data.common->Limit * 1024); /* megabyte to kilobyte */
+ def->mem.cur_balloon = memorySettingData->data.common->VirtualQuantity * 1024; /* megabyte to kilobyte */
if (virDomainDefSetVcpusMax(def,
- processorSettingData->data->VirtualQuantity,
+ processorSettingData->data.common->VirtualQuantity,
NULL) < 0)
goto cleanup;
if (virDomainDefSetVcpus(def,
- processorSettingData->data->VirtualQuantity) < 0)
+ processorSettingData->data.common->VirtualQuantity) < 0)
goto cleanup;
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
for (computerSystem = computerSystemList; computerSystem != NULL;
computerSystem = computerSystem->next) {
- if (VIR_STRDUP(names[count], computerSystem->data->ElementName) < 0)
+ if (VIR_STRDUP(names[count], computerSystem->data.common->ElementName) < 0)
goto cleanup;
++count;
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup;
- result = computerSystem->data->EnabledState ==
+ result = computerSystem->data.common->EnabledState ==
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
cleanup:
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup;
- if (computerSystem->data->EnabledState !=
+ if (computerSystem->data.common->EnabledState !=
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("Domain has no managed save image"));
/* managed save filter */
if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
- bool mansave = computerSystem->data->EnabledState ==
+ bool mansave = computerSystem->data.common->EnabledState ==
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED;
if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
#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/*"
-#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
hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
* Object
*/
-/* This function guarantees that query is freed, even on failure */
+/* This function guarantees that wqlQuery->query is reset, even on failure */
int
-hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
- XmlSerializerInfo *serializerInfo, const char *resourceUri,
- const char *className, hypervObject **list)
+hypervEnumAndPull(hypervPrivate *priv, hypervWqlQueryPtr wqlQuery,
+ hypervObject **list)
{
int result = -1;
WsSerializerContextH serializerContext;
client_opt_t *options = NULL;
char *query_string = NULL;
+ hypervWmiClassInfoPtr wmiInfo = NULL;
filter_t *filter = NULL;
WsXmlDocH response = NULL;
char *enumContext = NULL;
XML_TYPE_PTR data = NULL;
hypervObject *object;
- if (virBufferCheckError(query) < 0) {
- virBufferFreeAndReset(query);
+ if (virBufferCheckError(wqlQuery->query) < 0) {
+ virBufferFreeAndReset(wqlQuery->query);
return -1;
}
- query_string = virBufferContentAndReset(query);
+
+ query_string = virBufferContentAndReset(wqlQuery->query);
if (list == NULL || *list != NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
+ if (hypervGetWmiClassInfo(priv, wqlQuery->info, &wmiInfo) < 0)
+ goto cleanup;
+
serializerContext = wsmc_get_serialization_context(priv->client);
options = wsmc_options_init();
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)
goto cleanup;
response = NULL;
while (enumContext != NULL && *enumContext != '\0') {
- response = wsmc_action_pull(priv->client, resourceUri, options,
+ response = wsmc_action_pull(priv->client, wmiInfo->resourceUri, options,
filter, enumContext);
if (hypervVerifyResponse(priv->client, response, "pull") < 0)
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;
- data = ws_deserialize(serializerContext, node, serializerInfo,
- className, resourceUri, NULL, 0, 0);
+ data = ws_deserialize(serializerContext, node, wmiInfo->serializerInfo,
+ wmiInfo->name, wmiInfo->resourceUri, NULL, 0, 0);
if (data == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
if (VIR_ALLOC(object) < 0)
goto cleanup;
- object->serializerInfo = serializerInfo;
- object->data = data;
+ object->info = wmiInfo;
+ object->data.common = data;
data = NULL;
/* FIXME: ws_serializer_free_mem is broken in openwsman <= 2.2.6,
* see hypervFreeObject for a detailed explanation. */
if (ws_serializer_free_mem(serializerContext, data,
- serializerInfo) < 0) {
+ wmiInfo->serializerInfo) < 0) {
VIR_ERROR(_("Could not free deserialized data"));
}
#endif
* them in wsmc_release. So this doesn't result in a real
* memory leak, but just in piling up unused memory until
* the connection is closed. */
- if (ws_serializer_free_mem(serializerContext, object->data,
- object->serializerInfo) < 0) {
+ if (ws_serializer_free_mem(serializerContext, object->data.common,
+ object->info->serializerInfo) < 0) {
VIR_ERROR(_("Could not free deserialized data"));
}
#endif
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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
*/
virBuffer query = VIR_BUFFER_INITIALIZER;
Msvm_ConcreteJob *concreteJob = NULL;
bool completed = false;
+ const char *resourceUri = MSVM_COMPUTERSYSTEM_V2_RESOURCE_URI;
virUUIDFormat(domain->uuid, uuid_string);
virAsprintf(&properties, "RequestedState=%d", requestedState) < 0)
goto cleanup;
+ if (priv->wmiVersion == HYPERV_WMI_VERSION_V1)
+ resourceUri = MSVM_COMPUTERSYSTEM_V1_RESOURCE_URI;
+
options = wsmc_options_init();
if (options == NULL) {
wsmc_add_prop_from_str(options, properties);
/* Invoke method */
- response = wsmc_action_invoke(priv->client, MSVM_COMPUTERSYSTEM_RESOURCE_URI,
+ response = wsmc_action_invoke(priv->client, resourceUri,
options, "RequestStateChange", NULL);
if (hypervVerifyResponse(priv->client, response, "invocation") < 0)
goto cleanup;
}
- switch (concreteJob->data->JobState) {
+ switch (concreteJob->data.common->JobState) {
case MSVM_CONCRETEJOB_JOBSTATE_NEW:
case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
hypervMsvmComputerSystemEnabledStateToDomainState
(Msvm_ComputerSystem *computerSystem)
{
- switch (computerSystem->data->EnabledState) {
+ switch (computerSystem->data.common->EnabledState) {
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
return VIR_DOMAIN_NOSTATE;
if (in_transition != NULL)
*in_transition = false;
- switch (computerSystem->data->EnabledState) {
+ switch (computerSystem->data.common->EnabledState) {
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
return false;
return -1;
}
- if (virUUIDParse(computerSystem->data->Name, uuid) < 0) {
+ if (virUUIDParse(computerSystem->data.common->Name, uuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not parse UUID from string '%s'"),
- computerSystem->data->Name);
+ computerSystem->data.common->Name);
return -1;
}
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 0;
}
-
-
-
-#include "hyperv_wmi.generated.c"
-typedef struct _hypervObject hypervObject;
+# define HYPERV_WQL_QUERY_INITIALIZER { NULL, NULL }
int hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
const char *detail);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Object
*/
-typedef struct _hypervObjectUnified hypervObjectUnified;
-struct _hypervObjectUnified {
+
+typedef struct _hypervObject hypervObject;
+struct _hypervObject {
/* Unserialized data from wsman response. The member called "common" has
* 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
} data;
/* The info used to make wsman request */
hypervWmiClassInfoPtr info;
- hypervObjectUnified *next;
+ hypervObject *next;
};
-struct _hypervObject {
- XmlSerializerInfo *serializerInfo;
- XML_TYPE_PTR data;
- hypervObject *next;
+typedef struct _hypervWqlQuery hypervWqlQuery;
+typedef hypervWqlQuery *hypervWqlQueryPtr;
+struct _hypervWqlQuery {
+ virBufferPtr query;
+ hypervWmiClassInfoListPtr info;
};
-int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query,
- const char *root, XmlSerializerInfo *serializerInfo,
- const char *resourceUri, const char *className,
+int hypervEnumAndPull(hypervPrivate *priv, hypervWqlQueryPtr wqlQuery,
hypervObject **list);
void hypervFreeObject(hypervPrivate *priv, hypervObject *object);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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
*/
int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
Msvm_ComputerSystem **computerSystem);
-
-
-# include "hyperv_wmi.generated.h"
-
#endif /* __HYPERV_WMI_H__ */
# 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/*"
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
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
string Caption
string Description
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
string Caption
string Description
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
string Caption
string Description
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
string Caption
string Description
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
uint16 AdminPasswordStatus
boolean AutomaticManagedPagefile
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
string Caption
string Description
import os
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.
+
+ 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 = []):
+ self.name = name
+ self.versions = versions
+ self.common = None
-separator = "/* " + ("* " * 37) + "*\n"
+ def prepare(self):
+ """Prepares the class for code generation
+ Makes sure that "versioned" classes are sorted by version, identifies
+ common properies and ensures that they are aligned by name and
+ type in each version
+ """
+ # sort vesioned classes by version in case input file did not have them
+ # in order
+ self.versions = sorted(self.versions, key=lambda cls: cls.version)
+ # 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)
-class Class:
- def __init__(self, name, properties):
- self.name = name
- self.properties = properties
+ # finally, identify common members in all versions and make sure they
+ # are in the same order - to ensure C struct member alignment
+ self._align_property_members()
- def generate_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()
header = separator
header += " * %s\n" % self.name
header += " */\n"
header += "\n"
- header += "int hypervGet%sList(hypervPrivate *priv, virBufferPtr query, %s **list);\n" \
- % (self.name.replace("_", ""), self.name)
- header += "\n"
+ header += "#define %s_CLASSNAME \\\n" % name_upper
+ header += " \"%s\"\n" % self.name
header += "\n"
+ header += "#define %s_WQL_SELECT \\\n" % name_upper
+ header += " \"SELECT * FROM %s \"\n" % self.name
header += "\n"
+ header += "extern hypervWmiClassInfoListPtr %s_WmiInfo;\n\n" % self.name
+
+ header += self._declare_data_structs()
+ header += self._declare_hypervObject_struct()
return header
+ def generate_classes_source(self):
+ """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 += " * %s\n" % self.name
+ source += " */\n"
+
+ for cls in self.versions:
+ source += "SER_START_ITEMS(%s_Data)\n" % cls.name
+
+ for property in cls.properties:
+ source += property.generate_classes_source(cls.name)
+
+ source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name
+
+
+ source += self._define_WmiInfo_struct()
+ source += "\n\n"
+
+ return source
+
+
def generate_classes_typedef(self):
- typedef = "typedef struct _%s_Data %s_Data;\n" % (self.name, self.name)
- typedef += "typedef struct _%s %s;\n" % (self.name, self.name)
+ """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 generate_classes_header(self):
- name_upper = self.name.upper()
- header = separator
- header += " * %s\n" % self.name
- header += " */\n"
- header += "\n"
- header += "#define %s_RESOURCE_URI \\\n" % name_upper
+ def _declare_data_structs(self):
+ """Returns string C code declaring data structs.
- 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
+ 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 += "\n"
- header += "#define %s_CLASSNAME \\\n" % name_upper
- header += " \"%s\"\n" % self.name
- header += "\n"
- header += "#define %s_WQL_SELECT \\\n" % name_upper
- header += " \"select * from %s \"\n" % self.name
- header += "\n"
- header += "struct _%s_Data {\n" % self.name
+ 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"
- for property in self.properties:
- header += property.generate_classes_header()
+ # 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
- header += "};\n"
- header += "\n"
- header += "SER_DECLARE_TYPE(%s_Data);\n" % self.name
- header += "\n"
+ 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 += " XmlSerializerInfo *serializerInfo;\n"
- header += " %s_Data *data;\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"
- header += "\n"
- header += "\n"
+
+ header += "\n\n\n"
return header
- def generate_source(self):
- name_upper = self.name.upper()
+ def _define_WmiInfo_struct(self):
+ """Return string for C code defining *_WmiInfo struct
- 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"
+ 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 += " %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"
+ source += " }\n"
+ source += "};\n"
return source
- def generate_classes_source(self):
- name_upper = self.name.upper()
+ def _align_property_members(self):
+ """Identifies common properties in all class versions.
- source = separator
- source += " * %s\n" % self.name
- source += " */\n"
- source += "\n"
- source += "SER_START_ITEMS(%s_Data)\n" % self.name
+ 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.
+ """
- for property in self.properties:
- source += property.generate_classes_source(self.name)
+ num_classes = len(self.versions)
+ common = {}
+ property_info = {}
- source += "SER_END_ITEMS(%s_Data);\n" % self.name
- source += "\n"
- source += "\n"
- source += "\n"
+ 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
- return source
class Property:
"string" : "STR",
"datetime" : "STR",
"int8" : "INT8",
+ "sint8" : "INT8",
"int16" : "INT16",
+ "sint16" : "INT16",
"int32" : "INT32",
+ "sint32" : "INT32",
"int64" : "INT64",
+ "sint64" : "INT64",
"uint8" : "UINT8",
"uint16" : "UINT16",
"uint32" : "UINT32",
assert header_items[0] == "class"
name = header_items[1]
-
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:]:
# expected format: <type> <name>
properties.append(Property(type=items[0], name=items[1],
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])
input_filename = os.path.join(os.getcwd(), "hyperv_wmi_generator.input")
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_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"))
# parse input file
number = 0
- classes_by_name = {}
block = None
for line in file(input_filename, "rb").readlines():
if block is not None:
if line == "end":
if block[0][1].startswith("class"):
- cls = parse_class(block)
- classes_by_name[cls.name] = cls
+ parse_class(block)
block = None
else:
# write output files
notice = "/* Generated by hyperv_wmi_generator.py */\n\n\n\n"
- header.write(notice)
- source.write(notice)
classes_typedef.write(notice)
classes_header.write(notice)
classes_source.write(notice)
- names = classes_by_name.keys()
+ names = wmi_classes_by_name.keys()
names.sort()
for name in names:
- header.write(classes_by_name[name].generate_header())
- source.write(classes_by_name[name].generate_source())
- 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())
+ cls = wmi_classes_by_name[name]
+ cls.prepare()
+
+ classes_typedef.write(cls.generate_classes_typedef())
+ classes_header.write(cls.generate_classes_header())
+ classes_source.write(cls.generate_classes_source())