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:
parent
4d6e6f4aa9
commit
e224b6f8fb
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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
688
src/hyperv/hyperv_wmi.c
Normal 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
121
src/hyperv/hyperv_wmi.h
Normal 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__ */
|
37
src/hyperv/hyperv_wmi_classes.c
Normal file
37
src/hyperv/hyperv_wmi_classes.c
Normal 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"
|
94
src/hyperv/hyperv_wmi_classes.h
Normal file
94
src/hyperv/hyperv_wmi_classes.h
Normal 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__ */
|
298
src/hyperv/hyperv_wmi_generator.input
Normal file
298
src/hyperv/hyperv_wmi_generator.input
Normal 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
|
311
src/hyperv/hyperv_wmi_generator.py
Executable file
311
src/hyperv/hyperv_wmi_generator.py
Executable 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
47
src/hyperv/openwsman.h
Normal 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__ */
|
Loading…
Reference in New Issue
Block a user