Add a generator script to generate the structs and serialization
information for OpenWSMAN.
openwsman.h collects workarounds for problems in OpenWSMAN <= 2.2.6.
There are also disabled sections that would use ws_serializer_free_mem
but can't because it's broken in OpenWSMAN <= 2.2.6. Patches to fix
this have been posted upstream.
---
po/POTFILES.in | 1 +
src/Makefile.am | 25 ++-
src/hyperv/.gitignore | 1 +
src/hyperv/hyperv_private.h | 7 +
src/hyperv/hyperv_wmi.c | 684 +++++++++++++++++++++++++++++++++
src/hyperv/hyperv_wmi.h | 121 ++++++
src/hyperv/hyperv_wmi_classes.c | 37 ++
src/hyperv/hyperv_wmi_classes.h | 94 +++++
src/hyperv/hyperv_wmi_generator.input | 294 ++++++++++++++
src/hyperv/hyperv_wmi_generator.py | 309 +++++++++++++++
src/hyperv/openwsman.h | 47 +++
11 files changed, 1619 insertions(+), 1 deletions(-)
create mode 100644 src/hyperv/.gitignore
create mode 100644 src/hyperv/hyperv_wmi.c
create mode 100644 src/hyperv/hyperv_wmi.h
create mode 100644 src/hyperv/hyperv_wmi_classes.c
create mode 100644 src/hyperv/hyperv_wmi_classes.h
create mode 100644 src/hyperv/hyperv_wmi_generator.input
create mode 100755 src/hyperv/hyperv_wmi_generator.py
create mode 100644 src/hyperv/openwsman.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b3344b3..848d581 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -29,6 +29,7 @@ src/esx/esx_vi_methods.c
src/esx/esx_vi_types.c
src/fdstream.c
src/hyperv/hyperv_driver.c
+src/hyperv/hyperv_wmi.c
src/interface/netcf_driver.c
src/internal.h
src/libvirt.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 49da107..9971a90 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -387,7 +387,23 @@ HYPERV_DRIVER_SOURCES = \
hyperv/hyperv_storage_driver.c hyperv/hyperv_storage_driver.h \
hyperv/hyperv_device_monitor.c hyperv/hyperv_device_monitor.h \
hyperv/hyperv_secret_driver.c hyperv/hyperv_secret_driver.h \
- hyperv/hyperv_nwfilter_driver.c hyperv/hyperv_nwfilter_driver.h
+ hyperv/hyperv_nwfilter_driver.c hyperv/hyperv_nwfilter_driver.h \
+ hyperv/hyperv_wmi.c hyperv/hyperv_wmi.h \
+ hyperv/hyperv_wmi_classes.c hyperv/hyperv_wmi_classes.h \
+ 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
+
+HYPERV_DRIVER_EXTRA_DIST = \
+ hyperv/hyperv_wmi_generator.input \
+ hyperv/hyperv_wmi_generator.py \
+ $(HYPERV_DRIVER_GENERATED)
+
NETWORK_DRIVER_SOURCES = \
network/bridge_driver.h network/bridge_driver.c
@@ -819,6 +835,12 @@ libvirt_driver_esx_la_DEPENDENCIES = $(ESX_DRIVER_GENERATED)
endif
+BUILT_SOURCES += $(HYPERV_DRIVER_GENERATED)
+
+$(HYPERV_DRIVER_GENERATED): $(srcdir)/hyperv/hyperv_wmi_generator.input \
+ $(srcdir)/hyperv/hyperv_wmi_generator.py
+ $(AM_V_GEN)srcdir=$(srcdir) $(srcdir)/hyperv/hyperv_wmi_generator.py
+
if WITH_HYPERV
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_hyperv.la
@@ -1029,6 +1051,7 @@ EXTRA_DIST += \
$(ESX_DRIVER_SOURCES) \
$(ESX_DRIVER_EXTRA_DIST) \
$(HYPERV_DRIVER_SOURCES) \
+ $(HYPERV_DRIVER_EXTRA_DIST) \
$(NETWORK_DRIVER_SOURCES) \
$(INTERFACE_DRIVER_SOURCES) \
$(STORAGE_DRIVER_SOURCES) \
diff --git a/src/hyperv/.gitignore b/src/hyperv/.gitignore
new file mode 100644
index 0000000..29e1d48
--- /dev/null
+++ b/src/hyperv/.gitignore
@@ -0,0 +1 @@
+*.generated.*
diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h
index 17bdd60..0d5370e 100644
--- a/src/hyperv/hyperv_private.h
+++ b/src/hyperv/hyperv_private.h
@@ -26,9 +26,16 @@
# include "internal.h"
# include "virterror_internal.h"
+# include "openwsman.h"
# define HYPERV_ERROR(code, ...) \
virReportErrorHelper(VIR_FROM_HYPERV, code, __FILE__, __FUNCTION__, \
__LINE__, __VA_ARGS__)
+typedef struct _hypervPrivate hypervPrivate;
+
+struct _hypervPrivate {
+ WsManClient *client;
+};
+
#endif /* __HYPERV_PRIVATE_H__ */
diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c
new file mode 100644
index 0000000..dcfc3f9
--- /dev/null
+++ b/src/hyperv/hyperv_wmi.c
@@ -0,0 +1,684 @@
+
+/*
+ * hyperv_wmi.h: general WMI over WSMAN related functions and structures for
+ * managing Microsoft Hyper-V hosts
+ *
+ * Copyright (C) 2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009 Michael Sievers <msievers83(a)googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "logging.h"
+#include "memory.h"
+#include "util.h"
+#include "uuid.h"
+#include "buf.h"
+#include "hyperv_private.h"
+#include "hyperv_wmi.h"
+
+#define ROOT_CIMV2 \
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
+
+#define ROOT_VIRTUALIZATION \
+ "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
+
+#define VIR_FROM_THIS VIR_FROM_HYPERV
+
+
+
+int
+hyperyVerifyResponse(WsManClient *client, WsXmlDocH response,
+ const char *detail)
+{
+ int lastError = wsmc_get_last_error(client);
+ int responseCode = wsmc_get_response_code(client);
+ WsManFault *fault;
+
+ if (lastError != WS_LASTERR_OK) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Transport error during %s: %s (%d)"),
+ detail, wsman_transport_get_last_error_string(lastError),
+ lastError);
+ return -1;
+ }
+
+ if (responseCode != 200 && responseCode != 400 && responseCode !=
500) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected HTTP response during %s: %d"),
+ detail, responseCode);
+ return -1;
+ }
+
+ if (response == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Empty response during %s"), detail);
+ return -1;
+ }
+
+ if (wsmc_check_for_fault(response)) {
+ fault = wsmc_fault_new();
+
+ if (fault == NULL) {
+ virReportOOMError();
+ return -1;
+ }
+
+ wsmc_get_fault_data(response, fault);
+
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("SOAP fault during %s: code '%s', subcode
'%s', "
+ "reason '%s', detail '%s'"),
+ detail, NULLSTR(fault->code), NULLSTR(fault->subcode),
+ NULLSTR(fault->reason), NULLSTR(fault->fault_detail));
+
+ wsmc_fault_destroy(fault);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Object
+ */
+
+int
+hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root,
+ XmlSerializerInfo *serializerInfo, const char *resourceUri,
+ const char *className, hypervObject **list)
+{
+ int result = -1;
+ WsSerializerContextH serializerContext;
+ client_opt_t *options = NULL;
+ char *query_string = NULL;
+ filter_t *filter = NULL;
+ WsXmlDocH response = NULL;
+ char *enumContext = NULL;
+ hypervObject *head = NULL;
+ hypervObject *tail = NULL;
+ WsXmlNodeH node = NULL;
+ XML_TYPE_PTR data = NULL;
+ hypervObject *object;
+
+ if (list == NULL || *list != NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
argument"));
+ return -1;
+ }
+
+ if (virBufferError(query)) {
+ virReportOOMError();
+ return -1;
+ }
+
+ serializerContext = wsmc_get_serialization_context(priv->client);
+
+ options = wsmc_options_init();
+
+ if (options == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not initialize options"));
+ goto cleanup;
+ }
+
+ query_string = virBufferContentAndReset(query);
+ filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string);
+
+ if (filter == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not create filter"));
+ goto cleanup;
+ }
+
+ response = wsmc_action_enumerate(priv->client, root, options, filter);
+
+ if (hyperyVerifyResponse(priv->client, response, "enumeration") < 0)
{
+ goto cleanup;
+ }
+
+ enumContext = wsmc_get_enum_context(response);
+
+ ws_xml_destroy_doc(response);
+ response = NULL;
+
+ while (enumContext != NULL && *enumContext != '\0' ) {
+ response = wsmc_action_pull(priv->client, resourceUri, options,
+ filter, enumContext);
+
+ if (hyperyVerifyResponse(priv->client, response, "pull") < 0) {
+ goto cleanup;
+ }
+
+ node = ws_xml_get_soap_body(response);
+
+ if (node == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup SOAP body"));
+ goto cleanup;
+ }
+
+ node = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_PULL_RESP);
+
+ if (node == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response"));
+ goto cleanup;
+ }
+
+ node = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_ITEMS);
+
+ if (node == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not lookup pull response items"));
+ goto cleanup;
+ }
+
+ if (ws_xml_get_child(node, 0, resourceUri, className) == NULL) {
+ break;
+ }
+
+ data = ws_deserialize(serializerContext, node, serializerInfo,
+ className, resourceUri, NULL, 0, 0);
+
+ if (data == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not deserialize pull response item"));
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC(object) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ object->serializerInfo = serializerInfo;
+ object->data = data;
+
+ data = NULL;
+
+ if (head == NULL) {
+ head = object;
+ } else {
+ tail->next = object;
+ }
+
+ tail = object;
+
+ VIR_FREE(enumContext);
+ enumContext = wsmc_get_enum_context(response);
+
+ ws_xml_destroy_doc(response);
+ response = NULL;
+ }
+
+ *list = head;
+ head = NULL;
+
+ result = 0;
+
+ cleanup:
+ if (options != NULL) {
+ wsmc_options_destroy(options);
+ }
+
+ if (filter != NULL) {
+ filter_destroy(filter);
+ }
+
+ if (data != NULL) {
+#if 0
+ /* 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) {
+ VIR_ERROR(_("Could not free deserialized data"));
+ }
+#endif
+ }
+
+ VIR_FREE(query_string);
+ ws_xml_destroy_doc(response);
+ VIR_FREE(enumContext);
+ hypervFreeObject(priv, head);
+
+ return result;
+}
+
+void
+hypervFreeObject(hypervPrivate *priv ATTRIBUTE_UNUSED, hypervObject *object)
+{
+ hypervObject *next;
+#if 0
+ WsSerializerContextH serializerContext;
+#endif
+
+ if (object == NULL) {
+ return;
+ }
+
+#if 0
+ serializerContext = wsmc_get_serialization_context(priv->client);
+#endif
+
+ while (object != NULL) {
+ next = object->next;
+
+#if 0
+ /* FIXME: ws_serializer_free_mem is broken in openwsman <= 2.2.6,
+ * but this is not that critical, because openwsman keeps
+ * track of all allocations of the deserializer and frees
+ * 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) {
+ VIR_ERROR(_("Could not free deserialized data"));
+ }
+#endif
+
+ VIR_FREE(object);
+
+ object = next;
+ }
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * CIM/Msvm_ReturnCode
+ */
+
+const char *
+hypervReturnCodeToString(int returnCode)
+{
+ switch (returnCode) {
+ case CIM_RETURNCODE_COMPLETED_WITH_NO_ERROR:
+ return _("Completed with no error");
+
+ case CIM_RETURNCODE_NOT_SUPPORTED:
+ return _("Not supported");
+
+ case CIM_RETURNCODE_UNKNOWN_ERROR:
+ return _("Unknown error");
+
+ case CIM_RETURNCODE_CANNOT_COMPLETE_WITHIN_TIMEOUT_PERIOD:
+ return _("Cannot complete within timeout period");
+
+ case CIM_RETURNCODE_FAILED:
+ return _("Failed");
+
+ case CIM_RETURNCODE_INVALID_PARAMETER:
+ return _("Invalid parameter");
+
+ case CIM_RETURNCODE_IN_USE:
+ return _("In use");
+
+ case CIM_RETURNCODE_TRANSITION_STARTED:
+ return _("Transition started");
+
+ case CIM_RETURNCODE_INVALID_STATE_TRANSITION:
+ return _("Invalid state transition");
+
+ case CIM_RETURNCODE_TIMEOUT_PARAMETER_NOT_SUPPORTED:
+ return _("Timeout parameter not supported");
+
+ case CIM_RETURNCODE_BUSY:
+ return _("Busy");
+
+ case MSVM_RETURNCODE_FAILED:
+ return _("Failed");
+
+ case MSVM_RETURNCODE_ACCESS_DENIED:
+ return _("Access denied");
+
+ case MSVM_RETURNCODE_NOT_SUPPORTED:
+ return _("Not supported");
+
+ case MSVM_RETURNCODE_STATUS_IS_UNKNOWN:
+ return _("Status is unknown");
+
+ case MSVM_RETURNCODE_TIMEOUT:
+ return _("Timeout");
+
+ case MSVM_RETURNCODE_INVALID_PARAMETER:
+ return _("Invalid parameter");
+
+ case MSVM_RETURNCODE_SYSTEM_IS_IN_USE:
+ return _("System is in use");
+
+ case MSVM_RETURNCODE_INVALID_STATE_FOR_THIS_OPERATION:
+ return _("Invalid state for this operation");
+
+ case MSVM_RETURNCODE_INCORRECT_DATA_TYPE:
+ return _("Incorrect data type");
+
+ case MSVM_RETURNCODE_SYSTEM_IS_NOT_AVAILABLE:
+ return _("System is not available");
+
+ case MSVM_RETURNCODE_OUT_OF_MEMORY:
+ return _("Out of memory");
+
+ default:
+ return _("Unknown return code");
+ }
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_ComputerSystem
+ */
+
+int
+hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
+ int requestedState)
+{
+ int result = -1;
+ hypervPrivate *priv = domain->conn->privateData;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ WsXmlDocH response = NULL;
+ client_opt_t *options = NULL;
+ char *selector = NULL;
+ char *properties = NULL;
+ char *returnValue = NULL;
+ int returnCode;
+ char *instanceID = NULL;
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+ Msvm_ConcreteJob *concreteJob = NULL;
+ bool completed = false;
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ if (virAsprintf(&selector,
"Name=%s&CreationClassName=Msvm_ComputerSystem",
+ uuid_string) < 0 ||
+ virAsprintf(&properties, "RequestedState=%d", requestedState) <
0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ options = wsmc_options_init();
+
+ if (options == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not initialize options"));
+ goto cleanup;
+ }
+
+ wsmc_add_selectors_from_str(options, selector);
+ wsmc_add_prop_from_str(options, properties);
+
+ /* Invoke method */
+ response = wsmc_action_invoke(priv->client, MSVM_COMPUTERSYSTEM_RESOURCE_URI,
+ options, "RequestStateChange", NULL);
+
+ if (hyperyVerifyResponse(priv->client, response, "invocation") < 0)
{
+ goto cleanup;
+ }
+
+ /* Check return value */
+ returnValue = ws_xml_get_xpath_value(response, (char
*)"/s:Envelope/s:Body/p:RequestStateChange_OUTPUT/p:ReturnValue");
+
+ if (returnValue == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "ReturnValue", "RequestStateChange");
+ goto cleanup;
+ }
+
+ if (virStrToLong_i(returnValue, NULL, 10, &returnCode) < 0) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse return code from '%s'"),
returnValue);
+ goto cleanup;
+ }
+
+ if (returnCode == CIM_RETURNCODE_TRANSITION_STARTED) {
+ /* Get concrete job object */
+ instanceID = ws_xml_get_xpath_value(response, (char
*)"/s:Envelope/s:Body/p:RequestStateChange_OUTPUT/p:Job/a:ReferenceParameters/w:SelectorSet/w:Selector[@Name='InstanceID']");
+
+ if (instanceID == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "InstanceID", "RequestStateChange");
+ goto cleanup;
+ }
+
+ /* FIXME: Poll every 100ms until the job completes or fails. There
+ * seems to be no other way than polling. */
+ while (!completed) {
+ virBufferAddLit(&query, MSVM_CONCRETEJOB_WQL_SELECT);
+ virBufferAsprintf(&query, "where InstanceID =
\"%s\"", instanceID);
+
+ if (hypervGetMsvmConcreteJobList(priv, &query, &concreteJob) < 0)
{
+ goto cleanup;
+ }
+
+ if (concreteJob == NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not lookup %s for %s invocation"),
+ "Msvm_ConcreteJob",
"RequestStateChange");
+ goto cleanup;
+ }
+
+ switch (concreteJob->data->JobState) {
+ case MSVM_CONCRETEJOB_JOBSTATE_NEW:
+ case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
+ case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
+ case MSVM_CONCRETEJOB_JOBSTATE_SHUTTING_DOWN:
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+ concreteJob = NULL;
+
+ usleep(100 * 1000);
+ continue;
+
+ case MSVM_CONCRETEJOB_JOBSTATE_COMPLETED:
+ completed = true;
+ break;
+
+ case MSVM_CONCRETEJOB_JOBSTATE_TERMINATED:
+ case MSVM_CONCRETEJOB_JOBSTATE_KILLED:
+ case MSVM_CONCRETEJOB_JOBSTATE_EXCEPTION:
+ case MSVM_CONCRETEJOB_JOBSTATE_SERVICE:
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Concrete job for %s invocation is in error
state"),
+ "RequestStateChange");
+ goto cleanup;
+
+ default:
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Concrete job for %s invocation is in unknown
state"),
+ "RequestStateChange");
+ goto cleanup;
+ }
+ }
+ } else if (returnCode != CIM_RETURNCODE_COMPLETED_WITH_NO_ERROR) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Invocation of %s returned an error: %s (%d)"),
+ "RequestStateChange",
hypervReturnCodeToString(returnCode),
+ returnCode);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (options != NULL) {
+ wsmc_options_destroy(options);
+ }
+
+ ws_xml_destroy_doc(response);
+ VIR_FREE(selector);
+ VIR_FREE(properties);
+ VIR_FREE(returnValue);
+ VIR_FREE(instanceID);
+ hypervFreeObject(priv, (hypervObject *)concreteJob);
+
+ return result;
+}
+
+int
+hypervMsvmComputerSystemEnabledStateToDomainState
+ (Msvm_ComputerSystem *computerSystem)
+{
+ switch (computerSystem->data->EnabledState) {
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
+ return VIR_DOMAIN_NOSTATE;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED:
+ return VIR_DOMAIN_RUNNING;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_DISABLED:
+ return VIR_DOMAIN_SHUTOFF;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED:
+ return VIR_DOMAIN_PAUSED;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED:
+ return VIR_DOMAIN_SHUTOFF;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_STARTING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SNAPSHOTTING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SAVING:
+ return VIR_DOMAIN_RUNNING;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_STOPPING:
+ return VIR_DOMAIN_SHUTDOWN;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_RESUMING:
+ return VIR_DOMAIN_RUNNING;
+
+ default:
+ return VIR_DOMAIN_NOSTATE;
+ }
+}
+
+bool
+hypervIsMsvmComputerSystemActive(Msvm_ComputerSystem *computerSystem,
+ bool *in_transition)
+{
+ if (in_transition != NULL) {
+ *in_transition = false;
+ }
+
+ switch (computerSystem->data->EnabledState) {
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
+ return false;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED:
+ return true;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_DISABLED:
+ return false;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED:
+ return true;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED:
+ return false;
+
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_STARTING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SNAPSHOTTING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SAVING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_STOPPING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSING:
+ case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_RESUMING:
+ if (in_transition != NULL) {
+ *in_transition = true;
+ }
+
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+int
+hypervMsvmComputerSystemToDomain(virConnectPtr conn,
+ Msvm_ComputerSystem *computerSystem,
+ virDomainPtr *domain)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+
+ if (domain == NULL || *domain != NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
argument"));
+ return -1;
+ }
+
+ if (virUUIDParse(computerSystem->data->Name, uuid) < 0) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse UUID from string '%s'"),
+ computerSystem->data->Name);
+ return -1;
+ }
+
+ *domain = virGetDomain(conn, computerSystem->data->ElementName, uuid);
+
+ if (*domain == NULL) {
+ return -1;
+ }
+
+ if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
+ (*domain)->id = computerSystem->data->ProcessID;
+ } else {
+ (*domain)->id = -1;
+ }
+
+ return 0;
+}
+
+int
+hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
+ Msvm_ComputerSystem **computerSystem)
+{
+ hypervPrivate *priv = domain->conn->privateData;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+ virBuffer query = VIR_BUFFER_INITIALIZER;
+
+ if (computerSystem == NULL || *computerSystem != NULL) {
+ HYPERV_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid
argument"));
+ return -1;
+ }
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+ virBufferAddLit(&query, "where ");
+ virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_VIRTUAL);
+ virBufferAsprintf(&query, "and Name = \"%s\"", uuid_string);
+
+ if (hypervGetMsvmComputerSystemList(priv, &query, computerSystem) < 0) {
+ return -1;
+ }
+
+ if (*computerSystem == NULL) {
+ HYPERV_ERROR(VIR_ERR_NO_DOMAIN,
+ _("No domain with UUID %s"), uuid_string);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+#include "hyperv_wmi.generated.c"
diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h
new file mode 100644
index 0000000..fae6d4f
--- /dev/null
+++ b/src/hyperv/hyperv_wmi.h
@@ -0,0 +1,121 @@
+
+/*
+ * hyperv_wmi.h: general WMI over WSMAN related functions and structures for
+ * managing Microsoft Hyper-V hosts
+ *
+ * Copyright (C) 2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009 Michael Sievers <msievers83(a)googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __HYPERV_WMI_H__
+# define __HYPERV_WMI_H__
+
+# include "buf.h"
+# include "hyperv_private.h"
+# include "hyperv_wmi_classes.h"
+# include "openwsman.h"
+
+
+
+typedef struct _hypervObject hypervObject;
+
+int hyperyVerifyResponse(WsManClient *client, WsXmlDocH response,
+ const char *detail);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Object
+ */
+
+struct _hypervObject {
+ XmlSerializerInfo *serializerInfo;
+ XML_TYPE_PTR data;
+ hypervObject *next;
+};
+
+int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query,
+ const char *root, XmlSerializerInfo *serializerInfo,
+ const char *resourceUri, const char *className,
+ hypervObject **list);
+
+void hypervFreeObject(hypervPrivate *priv, hypervObject *object);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * CIM/Msvm_ReturnCode
+ */
+
+enum _CIM_ReturnCode {
+ CIM_RETURNCODE_COMPLETED_WITH_NO_ERROR = 0,
+ CIM_RETURNCODE_NOT_SUPPORTED = 1,
+ CIM_RETURNCODE_UNKNOWN_ERROR = 2,
+ CIM_RETURNCODE_CANNOT_COMPLETE_WITHIN_TIMEOUT_PERIOD = 3,
+ CIM_RETURNCODE_FAILED = 4,
+ CIM_RETURNCODE_INVALID_PARAMETER = 5,
+ CIM_RETURNCODE_IN_USE = 6,
+ CIM_RETURNCODE_TRANSITION_STARTED = 4096,
+ CIM_RETURNCODE_INVALID_STATE_TRANSITION = 4097,
+ CIM_RETURNCODE_TIMEOUT_PARAMETER_NOT_SUPPORTED = 4098,
+ CIM_RETURNCODE_BUSY = 4099,
+};
+
+enum _Msvm_ReturnCode {
+ MSVM_RETURNCODE_FAILED = 32768,
+ MSVM_RETURNCODE_ACCESS_DENIED = 32769,
+ MSVM_RETURNCODE_NOT_SUPPORTED = 32770,
+ MSVM_RETURNCODE_STATUS_IS_UNKNOWN = 32771,
+ MSVM_RETURNCODE_TIMEOUT = 32772,
+ MSVM_RETURNCODE_INVALID_PARAMETER = 32773,
+ MSVM_RETURNCODE_SYSTEM_IS_IN_USE = 32774,
+ MSVM_RETURNCODE_INVALID_STATE_FOR_THIS_OPERATION = 32775,
+ MSVM_RETURNCODE_INCORRECT_DATA_TYPE = 32776,
+ MSVM_RETURNCODE_SYSTEM_IS_NOT_AVAILABLE = 32777,
+ MSVM_RETURNCODE_OUT_OF_MEMORY = 32778,
+};
+
+const char *hypervReturnCodeToString(int returnCode);
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_ComputerSystem
+ */
+
+int hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
+ int requestedState);
+
+int hypervMsvmComputerSystemEnabledStateToDomainState
+ (Msvm_ComputerSystem *computerSystem);
+
+bool hypervIsMsvmComputerSystemActive(Msvm_ComputerSystem *computerSystem,
+ bool *in_transition);
+
+int hypervMsvmComputerSystemToDomain(virConnectPtr conn,
+ Msvm_ComputerSystem *computerSystem,
+ virDomainPtr *domain);
+
+int hypervMsvmComputerSystemFromDomain(virDomainPtr domain,
+ Msvm_ComputerSystem **computerSystem);
+
+
+
+# include "hyperv_wmi.generated.h"
+
+#endif /* __HYPERV_WMI_H__ */
diff --git a/src/hyperv/hyperv_wmi_classes.c b/src/hyperv/hyperv_wmi_classes.c
new file mode 100644
index 0000000..ed5e314
--- /dev/null
+++ b/src/hyperv/hyperv_wmi_classes.c
@@ -0,0 +1,37 @@
+
+/*
+ * hyperv_wmi_classes.c: WMI classes for managing Microsoft Hyper-V hosts
+ *
+ * Copyright (C) 2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009 Michael Sievers <msievers83(a)googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#include "hyperv_wmi_classes.h"
+
+SER_TYPEINFO_BOOL;
+SER_TYPEINFO_STRING;
+SER_TYPEINFO_INT8;
+SER_TYPEINFO_INT16;
+SER_TYPEINFO_INT32;
+SER_TYPEINFO_UINT8;
+SER_TYPEINFO_UINT16;
+SER_TYPEINFO_UINT32;
+
+#include "hyperv_wmi_classes.generated.c"
diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
new file mode 100644
index 0000000..5c97ca6
--- /dev/null
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -0,0 +1,94 @@
+
+/*
+ * hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
+ *
+ * Copyright (C) 2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009 Michael Sievers <msievers83(a)googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __HYPERV_WMI_CLASSES_H__
+# define __HYPERV_WMI_CLASSES_H__
+
+# include "openwsman.h"
+
+# include "hyperv_wmi_classes.generated.typedef"
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_ComputerSystem
+ */
+
+# define MSVM_COMPUTERSYSTEM_WQL_VIRTUAL \
+ "Description = \"Microsoft Virtual Machine\" "
+
+# define MSVM_COMPUTERSYSTEM_WQL_PHYSICAL \
+ "Description = \"Microsoft Hosting Computer System\" "
+
+# define MSVM_COMPUTERSYSTEM_WQL_ACTIVE \
+ "(EnabledState != 0 and EnabledState != 3 and EnabledState != 32769) "
+
+# define MSVM_COMPUTERSYSTEM_WQL_INACTIVE \
+ "(EnabledState = 0 or EnabledState = 3 or EnabledState = 32769) "
+
+enum _Msvm_ComputerSystem_EnabledState {
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN = 0, /* inactive */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED = 2, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_DISABLED = 3, /* inactive */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSED = 32768, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED = 32769, /* inactive */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_STARTING = 32770, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SNAPSHOTTING = 32771, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SAVING = 32773, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_STOPPING = 32774, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_PAUSING = 32776, /* active */
+ MSVM_COMPUTERSYSTEM_ENABLEDSTATE_RESUMING = 32777 /* active */
+};
+
+enum _Msvm_ComputerSystem_RequestedState {
+ MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED = 2,
+ MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED = 3,
+ MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_REBOOT = 10,
+ MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_PAUSED = 32768,
+ MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_SUSPENDED = 32769,
+};
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Msvm_ConcreteJob
+ */
+
+enum _Msvm_ConcreteJob_JobState {
+ MSVM_CONCRETEJOB_JOBSTATE_NEW = 2,
+ MSVM_CONCRETEJOB_JOBSTATE_STARTING = 3,
+ MSVM_CONCRETEJOB_JOBSTATE_RUNNING = 4,
+ MSVM_CONCRETEJOB_JOBSTATE_SUSPENDED = 5,
+ MSVM_CONCRETEJOB_JOBSTATE_SHUTTING_DOWN = 6,
+ MSVM_CONCRETEJOB_JOBSTATE_COMPLETED = 7,
+ MSVM_CONCRETEJOB_JOBSTATE_TERMINATED = 8,
+ MSVM_CONCRETEJOB_JOBSTATE_KILLED = 9,
+ MSVM_CONCRETEJOB_JOBSTATE_EXCEPTION = 10,
+ MSVM_CONCRETEJOB_JOBSTATE_SERVICE = 11,
+};
+
+
+
+# include "hyperv_wmi_classes.generated.h"
+
+#endif /* __HYPERV_WMI_CLASSES_H__ */
diff --git a/src/hyperv/hyperv_wmi_generator.input
b/src/hyperv/hyperv_wmi_generator.input
new file mode 100644
index 0000000..da874ac
--- /dev/null
+++ b/src/hyperv/hyperv_wmi_generator.input
@@ -0,0 +1,294 @@
+#
+# Definitions of WMI classes used as input for the hyperv_wmi_generator.py
+# script.
+#
+# This format is line-based, so end-of-line is important.
+#
+#
+# Class definition:
+#
+# class <name>
+# <type> <name>
+# ...
+# end
+#
+# Allowed values for <type> are: boolean, string, datetime, int8, int16,
+# int32, int64, uint8, uint16, uint32 and uint64
+#
+# The property <name> can be followed by [] to define a dynamic array.
+#
+
+
+class Msvm_ComputerSystem
+ 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 PrimaryOwnerName
+ string PrimaryOwnerContact
+ string Roles[]
+ string NameFormat
+ string OtherIdentifyingInfo[]
+ string IdentifyingDescriptions[]
+ uint16 Dedicated[]
+ string OtherDedicatedDescriptions[]
+ uint16 ResetCapability
+ uint16 PowerManagementCapabilities[]
+ uint64 OnTimeInMilliseconds
+ datetime TimeOfLastConfigurationChange
+ uint32 ProcessID
+ uint16 AssignedNumaNodeList[]
+end
+
+
+class Msvm_ConcreteJob
+ string Caption
+ string Description
+ string ElementName
+ datetime InstallDate
+ uint16 OperationalStatus[]
+ string StatusDescriptions[]
+ string Status
+ uint16 HealthState
+ string JobStatus
+ datetime TimeSubmitted
+ datetime ScheduledStartTime
+ datetime StartTime
+ datetime ElapsedTime
+ uint32 JobRunTimes
+ uint8 RunMonth
+ int8 RunDay
+ int8 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
+ string InstanceID
+ string Name
+ uint16 JobState
+ datetime TimeOfLastStateChange
+ datetime TimeBeforeRemoval
+ boolean Cancellable
+end
+
+
+class Msvm_MemorySettingData
+ string Caption
+ string Description
+ string InstanceID
+ string ElementName
+ uint16 ResourceType
+ string OtherResourceType
+ string ResourceSubType
+ string PoolID
+ uint16 ConsumerVisibility
+ string HostResource[]
+ string AllocationUnits
+ uint64 VirtualQuantity
+ uint64 Reservation
+ uint64 Limit
+ uint32 Weight
+ boolean AutomaticAllocation
+ boolean AutomaticDeallocation
+ string Parent
+ string Connection[]
+ string Address
+ uint16 MappingBehavior
+ boolean IsVirtualized
+ string DeviceID
+ string DeviceIDFormat
+ boolean DynamicMemoryEnabled
+# uint32 TargetMemoryBuffer # Available only on Windows Server 2008 R2 SP1
+end
+
+
+class Msvm_ProcessorSettingData
+ string Caption
+ string Description
+ string InstanceID
+ string ElementName
+ uint16 ResourceType
+ string OtherResourceType
+ string ResourceSubType
+ string PoolID
+ uint16 ConsumerVisibility
+ string HostResource[]
+ string AllocationUnits
+ uint64 VirtualQuantity
+ uint64 Reservation
+ uint64 Limit
+ uint32 Weight
+ boolean AutomaticAllocation
+ boolean AutomaticDeallocation
+ string Parent
+ string Connection[]
+ string Address
+ uint16 MappingBehavior
+ boolean IsVirtualized
+ string DeviceID
+ string DeviceIDFormat
+ uint16 ProcessorsPerSocket
+ uint16 SocketCount
+ boolean ThreadsEnabled
+ boolean LimitCPUID
+ boolean LimitProcessorFeatures
+end
+
+
+class Msvm_VirtualSystemSettingData
+ string Caption
+ string Description
+ string ElementName
+ string InstanceID
+ string SystemName
+ uint16 SettingType
+ uint16 VirtualSystemType
+ string OtherVirtualSystemType
+ boolean AutoActivate
+ datetime CreationTime
+ string Notes
+ string BIOSGUID
+ string BIOSSerialNumber
+ string BaseBoardSerialNumber
+ string ChassisSerialNumber
+ string ChassisAssetTag
+ boolean BIOSNumLock
+ uint16 BootOrder[]
+ string Parent
+ uint16 NumaNodeList[]
+ boolean NumaNodesAreRequired
+end
+
+
+class Win32_ComputerSystem
+ uint16 AdminPasswordStatus
+ boolean AutomaticManagedPagefile
+ boolean AutomaticResetBootOption
+ boolean AutomaticResetCapability
+ uint16 BootOptionOnLimit
+ uint16 BootOptionOnWatchDog
+ boolean BootROMSupported
+ string BootupState
+ string Caption
+ uint16 ChassisBootupState
+ string CreationClassName
+ int16 CurrentTimeZone
+ boolean DaylightInEffect
+ string Description
+ string DNSHostName
+ string Domain
+ uint16 DomainRole
+ boolean EnableDaylightSavingsTime
+ uint16 FrontPanelResetStatus
+ boolean InfraredSupported
+# string InitialLoadInfo # MSDN documents it, but it's not there
+ datetime InstallDate
+ uint16 KeyboardPasswordStatus
+ string LastLoadInfo
+ string Manufacturer
+ string Model
+ string Name
+ string NameFormat
+ boolean NetworkServerModeEnabled
+ uint32 NumberOfLogicalProcessors
+ uint32 NumberOfProcessors
+ uint8 OEMLogoBitmap[]
+ string OEMStringArray[]
+ boolean PartOfDomain
+ int64 PauseAfterReset
+ uint16 PCSystemType
+ uint16 PowerManagementCapabilities[]
+ boolean PowerManagementSupported
+ uint16 PowerOnPasswordStatus
+ uint16 PowerState
+ uint16 PowerSupplyState
+ string PrimaryOwnerContact
+ string PrimaryOwnerName
+ uint16 ResetCapability
+ int16 ResetCount
+ int16 ResetLimit
+ string Roles[]
+ string Status
+ string SupportContactDescription[]
+ uint16 SystemStartupDelay
+ string SystemStartupOptions[]
+ uint8 SystemStartupSetting
+ string SystemType
+ uint16 ThermalState
+ uint64 TotalPhysicalMemory
+ string UserName
+ uint16 WakeUpType
+ string Workgroup
+end
+
+
+class Win32_Processor
+ uint16 AddressWidth
+ uint16 Architecture
+ uint16 Availability
+ string Caption
+ uint32 ConfigManagerErrorCode
+ boolean ConfigManagerUserConfig
+ uint16 CpuStatus
+ string CreationClassName
+ uint32 CurrentClockSpeed
+ uint16 CurrentVoltage
+ uint16 DataWidth
+ string Description
+ string DeviceID
+ boolean ErrorCleared
+ string ErrorDescription
+ uint32 ExtClock
+ uint16 Family
+ datetime InstallDate
+ uint32 L2CacheSize
+ uint32 L2CacheSpeed
+ uint32 L3CacheSize
+ uint32 L3CacheSpeed
+ uint32 LastErrorCode
+ uint16 Level
+ uint16 LoadPercentage
+ string Manufacturer
+ uint32 MaxClockSpeed
+ string Name
+ uint32 NumberOfCores
+ uint32 NumberOfLogicalProcessors
+ string OtherFamilyDescription
+ string PNPDeviceID
+ uint16 PowerManagementCapabilities[]
+ boolean PowerManagementSupported
+ string ProcessorId
+ uint16 ProcessorType
+ uint16 Revision
+ string Role
+ string SocketDesignation
+ string Status
+ uint16 StatusInfo
+ string Stepping
+ string SystemCreationClassName
+ string SystemName
+ string UniqueId
+ uint16 UpgradeMethod
+ string Version
+ uint32 VoltageCaps
+end
diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py
new file mode 100755
index 0000000..077c3a0
--- /dev/null
+++ b/src/hyperv/hyperv_wmi_generator.py
@@ -0,0 +1,309 @@
+#!/usr/bin/env python
+
+#
+# hyperv_wmi_generator.py: generates most of the WMI type mapping code
+#
+# Copyright (C) 2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+import sys
+import os
+import os.path
+
+
+
+separator = "/* " + ("* " * 37) + "*\n"
+
+
+
+class Class:
+ def __init__(self, name, properties):
+ self.name = name
+ self.properties = properties
+
+
+ def generate_header(self):
+ 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 += "\n"
+ header += "\n"
+
+ return header
+
+
+ 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)
+
+ 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
+
+ if self.name.startswith("Win32_"):
+ 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 += "#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
+
+ for property in self.properties:
+ header += property.generate_classes_header()
+
+ 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
+
+
+ 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_"):
+ 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):
+ name_upper = self.name.upper()
+
+ source = separator
+ source += " * %s\n" % self.name
+ source += " */\n"
+ source += "\n"
+ source += "SER_START_ITEMS(%s_Data)\n" % self.name
+
+ for property in self.properties:
+ source += property.generate_classes_source(self.name)
+
+ source += "SER_END_ITEMS(%s_Data);\n" % self.name
+ source += "\n"
+ source += "\n"
+ source += "\n"
+
+ return source
+
+
+class Property:
+ typemap = {"boolean" : "BOOL",
+ "string" : "STR",
+ "datetime" : "STR",
+ "int8" : "INT8",
+ "int16" : "INT16",
+ "int32" : "INT32",
+ "int64" : "INT64",
+ "uint8" : "UINT8",
+ "uint16" : "UINT16",
+ "uint32" : "UINT32",
+ "uint64" : "UINT64"}
+
+
+ def __init__(self, type, name, is_array):
+ if type not in Property.typemap:
+ report_error("unhandled property type %s" % type)
+
+ self.type = type
+ self.name = name
+ self.is_array = is_array
+
+
+ def generate_classes_header(self):
+ if self.is_array:
+ return " XML_TYPE_DYN_ARRAY %s;\n" % self.name
+ else:
+ return " XML_TYPE_%s %s;\n" \
+ % (Property.typemap[self.type], self.name)
+
+
+ def generate_classes_source(self, class_name):
+ if self.is_array:
+ return " SER_NS_DYN_ARRAY(%s_RESOURCE_URI, \"%s\", 0, 0,
%s),\n" \
+ % (class_name.upper(), self.name, self.type)
+ else:
+ return " SER_NS_%s(%s_RESOURCE_URI, \"%s\", 1),\n" \
+ % (Property.typemap[self.type], class_name.upper(), self.name)
+
+
+
+def open_and_print(filename):
+ if filename.startswith("./"):
+ print " GEN " + filename[2:]
+ else:
+ print " GEN " + filename
+
+ return open(filename, "wb")
+
+
+
+def report_error(message):
+ print "error: " + message
+ sys.exit(1)
+
+
+
+def parse_class(block):
+ # expected format: class <name>
+ header_items = block[0][1].split()
+
+ if len(header_items) != 2:
+ report_error("line %d: invalid block header" % (number))
+
+ assert header_items[0] == "class"
+
+ name = header_items[1]
+
+ properties = []
+
+ for line in block[1:]:
+ # expected format: <type> <name>
+ items = line[1].split()
+
+ if len(items) != 2:
+ report_error("line %d: invalid property" % line[0])
+
+ if items[1].endswith("[]"):
+ items[1] = items[1][:-2]
+ is_array = True
+ else:
+ is_array = False
+
+ properties.append(Property(type=items[0], name=items[1],
+ is_array=is_array))
+
+ return Class(name=name, properties=properties)
+
+
+
+def main():
+ if "srcdir" in os.environ:
+ input_filename = os.path.join(os.environ["srcdir"],
"hyperv/hyperv_wmi_generator.input")
+ output_dirname = os.path.join(os.environ["srcdir"],
"hyperv")
+ else:
+ 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():
+ number += 1
+
+ if "#" in line:
+ line = line[:line.index("#")]
+
+ line = line.lstrip().rstrip()
+
+ if len(line) < 1:
+ continue
+
+ if line.startswith("class"):
+ if block is not None:
+ report_error("line %d: nested block found" % (number))
+ else:
+ block = []
+
+ if block is not None:
+ if line == "end":
+ if block[0][1].startswith("class"):
+ cls = parse_class(block)
+ classes_by_name[cls.name] = cls
+
+ block = None
+ else:
+ block.append((number, line))
+
+ # write output files
+ header.write("/* Generated by hyperv_wmi_generator.py */\n\n\n\n")
+ source.write("/* Generated by hyperv_wmi_generator.py */\n\n\n\n")
+ classes_typedef.write("/* Generated by hyperv_wmi_generator.py
*/\n\n\n\n")
+ classes_header.write("/* Generated by hyperv_wmi_generator.py */\n\n\n\n")
+ classes_source.write("/* Generated by hyperv_wmi_generator.py */\n\n\n\n")
+
+ names = 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())
+
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/hyperv/openwsman.h b/src/hyperv/openwsman.h
new file mode 100644
index 0000000..8bc0604
--- /dev/null
+++ b/src/hyperv/openwsman.h
@@ -0,0 +1,47 @@
+
+/*
+ * openwsman.h: workarounds for bugs in openwsman
+ *
+ * Copyright (C) 2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __OPENWSMAN_H__
+# define __OPENWSMAN_H__
+
+/* Workaround openwsman <= 2.2.6 unconditionally defining optarg. Just pretend
+ * that u/os.h was already included. Need to explicitly include time.h because
+ * wsman-xml-serializer.h needs it and u/os.h would have included it. */
+# include <time.h>
+# define _LIBU_OS_H_
+# include <wsman-api.h>
+
+/* wsman-xml-serializer.h in openwsman <= 2.2.6 is missing this defines */
+# ifndef SER_NS_INT8
+# define SER_NS_INT8(ns, n, x) SER_NS_INT8_FLAGS(ns, n, x, 0)
+# endif
+# ifndef SER_NS_INT16
+# define SER_NS_INT16(ns, n, x) SER_NS_INT16_FLAGS(ns, n, x, 0)
+# endif
+# ifndef SER_NS_INT32
+# define SER_NS_INT32(ns, n, x) SER_NS_INT32_FLAGS(ns, n, x, 0)
+# endif
+# ifndef SER_NS_INT64
+# define SER_NS_INT64(ns, n, x) SER_NS_INT64_FLAGS(ns, n, x, 0)
+# endif
+
+#endif /* __OPENWSMAN_H__ */
--
1.7.4.1