1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-22 17:34:18 +03:00

hyperv: Add OpenWSMAN based client for the Hyper-V WMI API

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.
This commit is contained in:
Matthias Bolte 2011-07-13 17:05:19 +02:00
parent 4d6e6f4aa9
commit e224b6f8fb
11 changed files with 1629 additions and 1 deletions

1
.gitignore vendored
View File

@ -54,6 +54,7 @@
/proxy/
/python/generator.py.stamp
/sc_*
/src/hyperv/*.generated.*
/src/libvirt_iohelper
/src/locking/qemu-sanlock.conf
/src/remote/*_client_bodies.h

View File

@ -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

View File

@ -411,7 +411,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
@ -845,6 +861,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) $(PYTHON) $(srcdir)/hyperv/hyperv_wmi_generator.py
if WITH_HYPERV
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_hyperv.la
@ -1058,6 +1080,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) \

View File

@ -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__ */

688
src/hyperv/hyperv_wmi.c Normal file
View File

@ -0,0 +1,688 @@
/*
* hyperv_wmi.h: general WMI over WSMAN related functions and structures for
* managing Microsoft Hyper-V hosts
*
* Copyright (C) 2011 Matthias Bolte <matthias.bolte@googlemail.com>
* Copyright (C) 2009 Michael Sievers <msievers83@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 WS_SERIALIZER_FREE_MEM_WORKS 0
#define ROOT_CIMV2 \
"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
#define ROOT_VIRTUALIZATION \
"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
#define VIR_FROM_THIS VIR_FROM_HYPERV
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;
}
/* Check the HTTP response code and report an error if it's not 200 (OK),
* 400 (Bad Request) or 500 (Internal Server Error) */
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 WS_SERIALIZER_FREE_MEM_WORKS
/* 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 WS_SERIALIZER_FREE_MEM_WORKS
WsSerializerContextH serializerContext;
#endif
if (object == NULL) {
return;
}
#if WS_SERIALIZER_FREE_MEM_WORKS
serializerContext = wsmc_get_serialization_context(priv->client);
#endif
while (object != NULL) {
next = object->next;
#if WS_SERIALIZER_FREE_MEM_WORKS
/* 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: /* managed save */
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: /* managed save */
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"

121
src/hyperv/hyperv_wmi.h Normal file
View File

@ -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@googlemail.com>
* Copyright (C) 2009 Michael Sievers <msievers83@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__ */

View File

@ -0,0 +1,37 @@
/*
* hyperv_wmi_classes.c: WMI classes for managing Microsoft Hyper-V hosts
*
* Copyright (C) 2011 Matthias Bolte <matthias.bolte@googlemail.com>
* Copyright (C) 2009 Michael Sievers <msievers83@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"

View File

@ -0,0 +1,94 @@
/*
* hyperv_wmi_classes.h: WMI classes for managing Microsoft Hyper-V hosts
*
* Copyright (C) 2011 Matthias Bolte <matthias.bolte@googlemail.com>
* Copyright (C) 2009 Michael Sievers <msievers83@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__ */

View File

@ -0,0 +1,298 @@
#
# 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.
#
#
# Based on MSDN Hyper-V WMI Classes:
# http://msdn.microsoft.com/en-us/library/cc136986%28v=vs.85%29.aspx
#
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

View File

@ -0,0 +1,311 @@
#!/usr/bin/env python
#
# hyperv_wmi_generator.py: generates most of the WMI type mapping code
#
# Copyright (C) 2011 Matthias Bolte <matthias.bolte@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
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.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()

47
src/hyperv/openwsman.h Normal file
View File

@ -0,0 +1,47 @@
/*
* openwsman.h: workarounds for bugs in openwsman
*
* Copyright (C) 2011 Matthias Bolte <matthias.bolte@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__ */