hyperv: remove support for multiple API versions from the WMI generator

All Msvm_* classes are assumed to be V2, now.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Matt Coleman <matt@datto.com>
This commit is contained in:
Matt Coleman 2020-11-09 03:43:09 -05:00 committed by Daniel P. Berrangé
parent b920556979
commit 0e43ccb838
6 changed files with 122 additions and 335 deletions

View File

@ -25,57 +25,22 @@ import os
import os.path import os.path
separator = "/*" + ("*" * 50) + "*\n" separator = "/*" + ("*" * 50) + "*\n"
wmi_version_separator = "/"
wmi_classes_by_name = {} wmi_classes_by_name = {}
class WmiClass: class WmiClass:
"""Represents WMI class and provides methods to generate C code. """Represents WMI class and provides methods to generate C code."""
This class holds one or more instances of WmiClassVersion because with the def __init__(self, name, properties, uri_info):
Windows 2012 release, Microsoft introduced "v2" version of Msvm_* family of
classes that need different URI for making wsman requests and also have
some additional/changed properties (though many of the properties are the
same as in "v1". Therefore, this class makes sure that C code is generated
for each of them while avoiding name conflicts, identifies common members,
and defined *_WmiInfo structs holding info about each version so the driver
code can make the right choices based on which Hyper-V host it's connected
to.
"""
def __init__(self, name, versions=None):
self.name = name self.name = name
self.versions = versions if versions else list() self.properties = properties
self.common = None self.uri_info = uri_info
def prepare(self):
"""Prepares the class for code generation
Makes sure that "versioned" classes are sorted by version, identifies
common properties and ensures that they are aligned by name and
type in each version
"""
# sort versioned classes by version in case input file did not have them
# in order
self.versions = sorted(self.versions, key=lambda cls: cls.version or "")
# if there's more than one version make sure first one has name suffixed
# because we'll generate "common" member and will be the "base" name
if len(self.versions) > 1:
first = self.versions[0]
if first.version is None:
first.version = "v1"
first.name = "%s_%s" % (first.name, first.version)
# finally, identify common members in all versions and make sure they
# are in the same order - to ensure C struct member alignment
self._align_property_members()
def generate_classes_header(self): def generate_classes_header(self):
"""Generate C header code and return it as string """Generate C header code and return it as string
Declares: Declares:
<class_name>_Data - used as one of hypervObject->data members <class_name>_Data - used as hypervObject->data
<class_name>_TypeInfo - used as wsman XmlSerializerInfo <class_name>_TypeInfo - used as wsman XmlSerializerInfo
<class_name> - "inherits" hypervObject struct <class_name> - "inherits" hypervObject struct
""" """
@ -103,30 +68,28 @@ class WmiClass:
"""Returns a C code string defining wsman data structs """Returns a C code string defining wsman data structs
Defines: Defines:
<class_name>_Data structs <class_name>_Data struct
<class_name>_WmiInfo - list holding metadata (e.g. request URIs) for <class_name>_WmiInfo - list holding metadata (e.g. request URIs) for the WMI class
each known version of WMI class.
""" """
source = separator source = separator
source += " * %s\n" % self.name source += " * %s\n" % self.name
source += " */\n" source += " */\n"
for cls in self.versions: source += "SER_START_ITEMS(%s_Data)\n" % self.name
source += "SER_START_ITEMS(%s_Data)\n" % cls.name
for property in cls.properties: for property in self.properties:
source += property.generate_classes_source(cls.name) source += property.generate_classes_source(self.name)
source += "SER_END_ITEMS(%s_Data);\n\n" % cls.name source += "SER_END_ITEMS(%s_Data);\n\n" % self.name
# also generate typemap data while we're here # also generate typemap data while we're here
source += "hypervCimType %s_Typemap[] = {\n" % cls.name source += "hypervCimType %s_Typemap[] = {\n" % self.name
for property in cls.properties: for property in self.properties:
source += property.generate_typemap() source += property.generate_typemap()
source += ' { "", "", 0 },\n' # null terminated source += ' { "", "", 0 },\n' # null terminated
source += '};\n\n' source += '};\n\n'
source += self._define_WmiInfo_struct() source += self._define_WmiInfo_struct()
source += "\n\n" source += "\n\n"
@ -134,45 +97,29 @@ class WmiClass:
return source return source
def generate_classes_typedef(self): def generate_classes_typedef(self):
"""Returns C string for typdefs""" """Returns C string for typedefs"""
typedef = "typedef struct _%s %s;\n" % (self.name, self.name) typedef = "typedef struct _%s %s;\n" % (self.name, self.name)
typedef += "typedef struct _%s_Data %s_Data;\n" % (self.name, self.name)
if self.common is not None:
typedef += "typedef struct _%s_Data %s_Data;\n" % (self.name, self.name)
for cls in self.versions:
typedef += "typedef struct _%s_Data %s_Data;\n" % (cls.name, cls.name)
return typedef return typedef
def _declare_data_structs(self): def _declare_data_structs(self):
"""Returns string C code declaring data structs. """Returns string C code declaring data structs.
The *_Data structs are members of hypervObject data union. Each one has The *_Data structs are used as hypervObject->data. Each one has
corresponding *_TypeInfo that is used for wsman unserialization of corresponding *_TypeInfo that is used for wsman unserialization of
response XML into the *_Data structs. If there's a "common" member, it response XML into the *_Data structs.
won't have corresponding *_TypeInfo because this is a special case only
used to provide a common "view" of v1, v2 etc members
""" """
header = "" header = "#define %s_RESOURCE_URI \\\n" % self.name.upper()
if self.common is not None: header += " \"%s\"\n" % self.uri_info.resourceUri
header += "struct _%s_Data {\n" % self.name header += "\n"
for property in self.common: header += "struct _%s_Data {\n" % self.name
header += property.generate_classes_header() for property in self.properties:
header += "};\n\n" header += property.generate_classes_header()
header += "};\n\n"
# Declare actual data struct for each versions header += "SER_DECLARE_TYPE(%s_Data);\n" % self.name
for cls in self.versions:
header += "#define %s_RESOURCE_URI \\\n" % cls.name.upper()
header += " \"%s\"\n" % cls.uri_info.resourceUri
header += "\n"
header += "struct _%s_Data {\n" % cls.name
for property in cls.properties:
header += property.generate_classes_header()
header += "};\n\n"
header += "SER_DECLARE_TYPE(%s_Data);\n" % cls.name
return header return header
@ -181,19 +128,7 @@ class WmiClass:
header = "\n/* must match hypervObject */\n" header = "\n/* must match hypervObject */\n"
header += "struct _%s {\n" % self.name header += "struct _%s {\n" % self.name
header += " union {\n" header += " %s_Data *data;\n" % self.name
# if there's common use it as "common" else first and only version is
# the "common" member
if self.common is not None:
header += " %s_Data *common;\n" % self.name
else:
header += " %s_Data *common;\n" % self.versions[0].name
for cls in self.versions:
header += " %s_Data *%s;\n" % (cls.name, cls.version)
header += " } data;\n"
header += " hypervWmiClassInfoPtr info;\n" header += " hypervWmiClassInfoPtr info;\n"
header += " %s *next;\n" % self.name header += " %s *next;\n" % self.name
header += "};\n" header += "};\n"
@ -205,127 +140,41 @@ class WmiClass:
def _define_WmiInfo_struct(self): def _define_WmiInfo_struct(self):
"""Return string for C code defining *_WmiInfo struct """Return string for C code defining *_WmiInfo struct
Those structs hold info with meta-data needed to make wsman requests for This struct holds info with meta-data needed to make wsman requests for the WMI class.
each version of WMI class
""" """
source = "hypervWmiClassInfoListPtr %s_WmiInfo = &(hypervWmiClassInfoList) {\n" % self.name source = "hypervWmiClassInfoListPtr %s_WmiInfo = &(hypervWmiClassInfoList) {\n" % self.name
source += " .count = %d,\n" % len(self.versions) source += " .count = 1,\n"
source += " .objs = (hypervWmiClassInfoPtr []) {\n" source += " .objs = (hypervWmiClassInfoPtr []) {\n"
for cls in self.versions: source += " &(hypervWmiClassInfo) {\n"
source += " &(hypervWmiClassInfo) {\n" source += " .name = %s_CLASSNAME,\n" % self.name.upper()
source += " .name = %s_CLASSNAME,\n" % self.name.upper() source += " .rootUri = %s,\n" % self.uri_info.rootUri
if cls.version is not None: source += " .resourceUri = %s_RESOURCE_URI,\n" % self.name.upper()
source += " .version = \"%s\",\n" % cls.version source += " .serializerInfo = %s_Data_TypeInfo,\n" % self.name
else: source += " .propertyInfo = %s_Typemap\n" % self.name
source += " .version = NULL,\n" source += " },\n"
source += " .rootUri = %s,\n" % cls.uri_info.rootUri
source += " .resourceUri = %s_RESOURCE_URI,\n" % cls.name.upper()
source += " .serializerInfo = %s_Data_TypeInfo,\n" % cls.name
source += " .propertyInfo = %s_Typemap\n" % cls.name
source += " },\n"
source += " }\n" source += " }\n"
source += "};\n" source += "};\n"
return source return source
def _align_property_members(self):
"""Identifies common properties in all class versions.
Makes sure that properties in all versions are ordered with common
members first and that they are in the same order. This makes the
generated C structs memory aligned and safe to access via the "common"
struct that "shares" members with v1, v2 etc.
"""
num_classes = len(self.versions)
common = {}
property_info = {}
if num_classes < 2:
return
# count property occurrences in all class versions
for cls in self.versions:
for prop in cls.properties:
# consdered same if matches by name AND type
key = "%s_%s_%s" % (prop.name, prop.type, prop.is_array)
if key in property_info:
property_info[key][1] += 1
else:
property_info[key] = [prop, 1]
# isolate those that are common for all and keep track of their positions
pos = 0
for key in sorted(property_info):
info = property_info[key]
# exists in all class versions
if info[1] == num_classes:
common[info[0].name] = [info[0], pos]
pos += 1
# alter each version's property list so that common members are first
# and in the same order as in the common dictionary
for cls in self.versions:
index = 0
count = len(cls.properties)
while index < count:
prop = cls.properties[index]
# it's a "common" property
if prop.name in common:
pos = common[prop.name][1]
# move to the same position as in "common" dictionary
if index != pos:
tmp = cls.properties[pos]
cls.properties[pos] = prop
cls.properties[index] = tmp
else:
index += 1
else:
index += 1
# finally, get common properties as list sorted by position in dictionary
tmp = sorted(common.values(), key=lambda x: x[1])
self.common = []
for x in tmp:
self.common.append(x[0])
class ClassUriInfo: class ClassUriInfo:
"""Prepares URI information needed for wsman requests.""" """Prepares URI information needed for wsman requests."""
def __init__(self, wmi_name, version): def __init__(self, wmi_name):
self.rootUri = "ROOT_CIMV2"
self.resourceUri = None
baseUri = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2"
if wmi_name.startswith("Msvm_"): if wmi_name.startswith("Msvm_"):
baseUri = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization" self.rootUri = "ROOT_VIRTUALIZATION_V2"
self.rootUri = "ROOT_VIRTUALIZATION" baseUri = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/v2"
else:
if version == "v2": self.rootUri = "ROOT_CIMV2"
baseUri += "/v2" baseUri = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2"
self.rootUri = "ROOT_VIRTUALIZATION_V2"
self.resourceUri = "%s/%s" % (baseUri, wmi_name) self.resourceUri = "%s/%s" % (baseUri, wmi_name)
class WmiClassVersion:
"""Represents specific version of WMI class."""
def __init__(self, name, version, properties, uri_info):
self.name = name
self.version = version
self.properties = properties
self.uri_info = uri_info
class Property: class Property:
typemap = { typemap = {
"boolean": "BOOL", "boolean": "BOOL",
@ -391,15 +240,11 @@ def parse_class(block, number):
assert header_items[0] == "class" assert header_items[0] == "class"
name = header_items[1] name = header_items[1]
properties = []
version = None
wmi_name = name
ns_separator = name.find(wmi_version_separator)
if ns_separator != -1: if name in wmi_classes_by_name:
version = name[:ns_separator] report_error("class '%s' has already been defined" % name)
wmi_name = name[ns_separator + 1:]
name = "%s_%s" % (wmi_name, version) properties = []
for line in block[1:]: for line in block[1:]:
# expected format: <type> <name> # expected format: <type> <name>
@ -414,16 +259,9 @@ def parse_class(block, number):
else: else:
is_array = False is_array = False
properties.append(Property(type=items[0], name=items[1], properties.append(Property(type=items[0], name=items[1], is_array=is_array))
is_array=is_array))
cls = WmiClassVersion(name=name, version=version, properties=properties, wmi_classes_by_name[name] = WmiClass(name, properties, ClassUriInfo(name))
uri_info=ClassUriInfo(wmi_name, version))
if wmi_name in wmi_classes_by_name:
wmi_classes_by_name[wmi_name].versions.append(cls)
else:
wmi_classes_by_name[wmi_name] = WmiClass(wmi_name, [cls])
def main(): def main():
@ -478,7 +316,6 @@ def main():
for name in names: for name in names:
cls = wmi_classes_by_name[name] cls = wmi_classes_by_name[name]
cls.prepare()
classes_typedef.write(cls.generate_classes_typedef()) classes_typedef.write(cls.generate_classes_typedef())
classes_header.write(cls.generate_classes_header()) classes_header.write(cls.generate_classes_header())

View File

@ -192,7 +192,7 @@ hypervRequestStateChange(virDomainPtr domain, int state)
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup; goto cleanup;
if (computerSystem->data.common->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) { if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not active")); virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not active"));
goto cleanup; goto cleanup;
} }
@ -239,10 +239,10 @@ hypervLookupHostSystemBiosUuid(hypervPrivate *priv, unsigned char *uuid)
if (hypervGetWmiClass(Win32_ComputerSystemProduct, &computerSystem) < 0) if (hypervGetWmiClass(Win32_ComputerSystemProduct, &computerSystem) < 0)
goto cleanup; goto cleanup;
if (virUUIDParse(computerSystem->data.common->UUID, uuid) < 0) { if (virUUIDParse(computerSystem->data->UUID, uuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not parse UUID from string '%s'"), _("Could not parse UUID from string '%s'"),
computerSystem->data.common->UUID); computerSystem->data->UUID);
goto cleanup; goto cleanup;
} }
result = 0; result = 0;
@ -443,11 +443,10 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version)
goto cleanup; goto cleanup;
} }
if (hypervParseVersionString(os->data.common->Version, if (hypervParseVersionString(os->data->Version, &major, &minor, &micro) < 0) {
&major, &minor, &micro) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not parse version from '%s'"), _("Could not parse version from '%s'"),
os->data.common->Version); os->data->Version);
goto cleanup; goto cleanup;
} }
@ -471,7 +470,7 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version)
if (major > 99 || minor > 99 || micro > 999999) { if (major > 99 || minor > 99 || micro > 999999) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not produce packed version number from '%s'"), _("Could not produce packed version number from '%s'"),
os->data.common->Version); os->data->Version);
goto cleanup; goto cleanup;
} }
@ -496,7 +495,7 @@ hypervConnectGetHostname(virConnectPtr conn)
if (hypervGetPhysicalSystemList(priv, &computerSystem) < 0) if (hypervGetPhysicalSystemList(priv, &computerSystem) < 0)
goto cleanup; goto cleanup;
hostname = g_strdup(computerSystem->data.common->DNSHostName); hostname = g_strdup(computerSystem->data->DNSHostName);
cleanup: cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)computerSystem);
@ -537,7 +536,7 @@ hypervConnectGetMaxVcpus(virConnectPtr conn, const char *type G_GNUC_UNUSED)
goto cleanup; goto cleanup;
} }
result = processorSettingData->data.common->VirtualQuantity; result = processorSettingData->data->VirtualQuantity;
cleanup: cleanup:
hypervFreeObject(priv, (hypervObject *)processorSettingData); hypervFreeObject(priv, (hypervObject *)processorSettingData);
@ -561,13 +560,12 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
if (hypervGetPhysicalSystemList(priv, &computerSystem) < 0) if (hypervGetPhysicalSystemList(priv, &computerSystem) < 0)
goto cleanup; goto cleanup;
if (hypervGetProcessorsByName(priv, computerSystem->data.common->Name, if (hypervGetProcessorsByName(priv, computerSystem->data->Name, &processorList) < 0) {
&processorList) < 0) {
goto cleanup; goto cleanup;
} }
/* Strip the string to fit more relevant information in 32 chars */ /* Strip the string to fit more relevant information in 32 chars */
tmp = processorList->data.common->Name; tmp = processorList->data->Name;
while (*tmp != '\0') { while (*tmp != '\0') {
if (STRPREFIX(tmp, " ")) { if (STRPREFIX(tmp, " ")) {
@ -589,15 +587,15 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
} }
/* Fill struct */ /* Fill struct */
if (virStrcpyStatic(info->model, processorList->data.common->Name) < 0) { if (virStrcpyStatic(info->model, processorList->data->Name) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("CPU model %s too long for destination"), _("CPU model %s too long for destination"),
processorList->data.common->Name); processorList->data->Name);
goto cleanup; goto cleanup;
} }
info->memory = computerSystem->data.common->TotalPhysicalMemory / 1024; /* byte to kilobyte */ info->memory = computerSystem->data->TotalPhysicalMemory / 1024; /* byte to kilobyte */
info->mhz = processorList->data.common->MaxClockSpeed; info->mhz = processorList->data->MaxClockSpeed;
info->nodes = 1; info->nodes = 1;
info->sockets = 0; info->sockets = 0;
@ -606,8 +604,8 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
++info->sockets; ++info->sockets;
} }
info->cores = processorList->data.common->NumberOfCores; info->cores = processorList->data->NumberOfCores;
info->threads = processorList->data.common->NumberOfLogicalProcessors / info->cores; info->threads = processorList->data->NumberOfLogicalProcessors / info->cores;
info->cpus = info->sockets * info->cores; info->cpus = info->sockets * info->cores;
result = 0; result = 0;
@ -637,7 +635,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids)
for (computerSystem = computerSystemList; computerSystem != NULL; for (computerSystem = computerSystemList; computerSystem != NULL;
computerSystem = computerSystem->next) { computerSystem = computerSystem->next) {
ids[count++] = computerSystem->data.common->ProcessID; ids[count++] = computerSystem->data->ProcessID;
if (count >= maxids) if (count >= maxids)
break; break;
@ -755,7 +753,7 @@ hypervDomainResume(virDomainPtr domain)
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
return -1; return -1;
if (computerSystem->data.common->EnabledState != MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_QUIESCE) { if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_QUIESCE) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s", virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("Domain is not paused")); _("Domain is not paused"));
goto cleanup; goto cleanup;
@ -810,7 +808,7 @@ hypervDomainShutdownFlags(virDomainPtr domain, unsigned int flags)
selector = g_strdup_printf("CreationClassName=\"Msvm_ShutdownComponent\"&DeviceID=\"%s\"&" selector = g_strdup_printf("CreationClassName=\"Msvm_ShutdownComponent\"&DeviceID=\"%s\"&"
"SystemCreationClassName=\"Msvm_ComputerSystem\"&SystemName=\"%s\"", "SystemCreationClassName=\"Msvm_ComputerSystem\"&SystemName=\"%s\"",
shutdown->data.common->DeviceID, uuid); shutdown->data->DeviceID, uuid);
params = hypervCreateInvokeParamsList("InitiateShutdown", selector, params = hypervCreateInvokeParamsList("InitiateShutdown", selector,
Msvm_ShutdownComponent_WmiInfo); Msvm_ShutdownComponent_WmiInfo);
@ -931,20 +929,20 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
goto cleanup; goto cleanup;
if (hypervGetProcessorSD(priv, if (hypervGetProcessorSD(priv,
virtualSystemSettingData->data.common->InstanceID, virtualSystemSettingData->data->InstanceID,
&processorSettingData) < 0) &processorSettingData) < 0)
goto cleanup; goto cleanup;
if (hypervGetMemorySD(priv, if (hypervGetMemorySD(priv,
virtualSystemSettingData->data.common->InstanceID, virtualSystemSettingData->data->InstanceID,
&memorySettingData) < 0) &memorySettingData) < 0)
goto cleanup; goto cleanup;
/* Fill struct */ /* Fill struct */
info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem); info->state = hypervMsvmComputerSystemEnabledStateToDomainState(computerSystem);
info->maxMem = memorySettingData->data.common->Limit * 1024; /* megabyte to kilobyte */ info->maxMem = memorySettingData->data->Limit * 1024; /* megabyte to kilobyte */
info->memory = memorySettingData->data.common->VirtualQuantity * 1024; /* megabyte to kilobyte */ info->memory = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */
info->nrVirtCpu = processorSettingData->data.common->VirtualQuantity; info->nrVirtCpu = processorSettingData->data->VirtualQuantity;
info->cpuTime = 0; info->cpuTime = 0;
result = 0; result = 0;
@ -1014,12 +1012,12 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
goto cleanup; goto cleanup;
if (hypervGetProcessorSD(priv, if (hypervGetProcessorSD(priv,
virtualSystemSettingData->data.common->InstanceID, virtualSystemSettingData->data->InstanceID,
&processorSettingData) < 0) &processorSettingData) < 0)
goto cleanup; goto cleanup;
if (hypervGetMemorySD(priv, if (hypervGetMemorySD(priv,
virtualSystemSettingData->data.common->InstanceID, virtualSystemSettingData->data->InstanceID,
&memorySettingData) < 0) &memorySettingData) < 0)
goto cleanup; goto cleanup;
@ -1027,27 +1025,27 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
def->virtType = VIR_DOMAIN_VIRT_HYPERV; def->virtType = VIR_DOMAIN_VIRT_HYPERV;
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) { if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
def->id = computerSystem->data.common->ProcessID; def->id = computerSystem->data->ProcessID;
} else { } else {
def->id = -1; def->id = -1;
} }
if (virUUIDParse(computerSystem->data.common->Name, def->uuid) < 0) { if (virUUIDParse(computerSystem->data->Name, def->uuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not parse UUID from string '%s'"), _("Could not parse UUID from string '%s'"),
computerSystem->data.common->Name); computerSystem->data->Name);
return NULL; return NULL;
} }
def->name = g_strdup(computerSystem->data.common->ElementName); def->name = g_strdup(computerSystem->data->ElementName);
if (virtualSystemSettingData->data.v2->Notes.data) { if (virtualSystemSettingData->data->Notes.data) {
char **notes = (char **)virtualSystemSettingData->data.v2->Notes.data; char **notes = (char **)virtualSystemSettingData->data->Notes.data;
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
size_t i = 0; size_t i = 0;
/* in practice Notes has 1 element */ /* in practice Notes has 1 element */
for (i = 0; i < virtualSystemSettingData->data.v2->Notes.count; i++) { for (i = 0; i < virtualSystemSettingData->data->Notes.count; i++) {
/* but if there's more than 1, separate by double new line */ /* but if there's more than 1, separate by double new line */
if (virBufferUse(&buf) > 0) if (virBufferUse(&buf) > 0)
virBufferAddLit(&buf, "\n\n"); virBufferAddLit(&buf, "\n\n");
@ -1060,17 +1058,14 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
} }
/* mebibytes to kibibytes */ /* mebibytes to kibibytes */
def->mem.max_memory = memorySettingData->data.common->Limit * 1024; def->mem.max_memory = memorySettingData->data->Limit * 1024;
def->mem.cur_balloon = memorySettingData->data.common->VirtualQuantity * 1024; def->mem.cur_balloon = memorySettingData->data->VirtualQuantity * 1024;
virDomainDefSetMemoryTotal(def, memorySettingData->data.common->VirtualQuantity * 1024); virDomainDefSetMemoryTotal(def, memorySettingData->data->VirtualQuantity * 1024);
if (virDomainDefSetVcpusMax(def, if (virDomainDefSetVcpusMax(def, processorSettingData->data->VirtualQuantity, NULL) < 0)
processorSettingData->data.common->VirtualQuantity,
NULL) < 0)
goto cleanup; goto cleanup;
if (virDomainDefSetVcpus(def, if (virDomainDefSetVcpus(def, processorSettingData->data->VirtualQuantity) < 0)
processorSettingData->data.common->VirtualQuantity) < 0)
goto cleanup; goto cleanup;
def->os.type = VIR_DOMAIN_OSTYPE_HVM; def->os.type = VIR_DOMAIN_OSTYPE_HVM;
@ -1110,7 +1105,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn
for (computerSystem = computerSystemList; computerSystem != NULL; for (computerSystem = computerSystemList; computerSystem != NULL;
computerSystem = computerSystem->next) { computerSystem = computerSystem->next) {
names[count] = g_strdup(computerSystem->data.common->ElementName); names[count] = g_strdup(computerSystem->data->ElementName);
++count; ++count;
@ -1208,7 +1203,7 @@ hypervDomainGetAutostart(virDomainPtr domain, int *autostart)
if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, &vssd) < 0) if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, &vssd) < 0)
goto cleanup; goto cleanup;
*autostart = vssd->data.v2->AutomaticStartupAction == 4; *autostart = vssd->data->AutomaticStartupAction == 4;
result = 0; result = 0;
cleanup: cleanup:
@ -1246,8 +1241,7 @@ hypervDomainSetAutostart(virDomainPtr domain, int autostart)
autostart ? "4" : "2") < 0) autostart ? "4" : "2") < 0)
goto cleanup; goto cleanup;
if (hypervSetEmbeddedProperty(autostartParam, "InstanceID", if (hypervSetEmbeddedProperty(autostartParam, "InstanceID", vssd->data->InstanceID) < 0)
vssd->data.common->InstanceID) < 0)
goto cleanup; goto cleanup;
if (hypervAddEmbeddedParam(params, "SystemSettings", if (hypervAddEmbeddedParam(params, "SystemSettings",
@ -1284,7 +1278,7 @@ hypervNodeGetFreeMemory(virConnectPtr conn)
return 0; return 0;
} }
freeMemoryBytes = operatingSystem->data.common->FreePhysicalMemory * 1024; freeMemoryBytes = operatingSystem->data->FreePhysicalMemory * 1024;
hypervFreeObject(priv, (hypervObject *)operatingSystem); hypervFreeObject(priv, (hypervObject *)operatingSystem);
@ -1409,8 +1403,7 @@ hypervDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup; goto cleanup;
result = computerSystem->data.common->EnabledState == result = computerSystem->data->EnabledState == MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED ? 1 : 0;
cleanup: cleanup:
hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)computerSystem);
@ -1431,8 +1424,7 @@ hypervDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
goto cleanup; goto cleanup;
if (computerSystem->data.common->EnabledState != if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s", virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("Domain has no managed save image")); _("Domain has no managed save image"));
goto cleanup; goto cleanup;
@ -1530,7 +1522,7 @@ hypervConnectListAllDomains(virConnectPtr conn,
/* managed save filter */ /* managed save filter */
if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) { if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE)) {
bool mansave = computerSystem->data.common->EnabledState == bool mansave = computerSystem->data->EnabledState ==
MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED; MSVM_COMPUTERSYSTEM_ENABLEDSTATE_SUSPENDED;
if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) || if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && mansave) ||
@ -1628,7 +1620,7 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
selector = g_strdup_printf("CreationClassName=Msvm_Keyboard&DeviceID=%s&" selector = g_strdup_printf("CreationClassName=Msvm_Keyboard&DeviceID=%s&"
"SystemCreationClassName=Msvm_ComputerSystem&" "SystemCreationClassName=Msvm_ComputerSystem&"
"SystemName=%s", keyboard->data.common->DeviceID, uuid_string); "SystemName=%s", keyboard->data->DeviceID, uuid_string);
/* press the keys */ /* press the keys */
for (i = 0; i < nkeycodes; i++) { for (i = 0; i < nkeycodes; i++) {
@ -1701,7 +1693,7 @@ hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, &vssd) < 0) if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, &vssd) < 0)
goto cleanup; goto cleanup;
if (hypervGetMemorySD(priv, vssd->data.common->InstanceID, &memsd) < 0) if (hypervGetMemorySD(priv, vssd->data->InstanceID, &memsd) < 0)
goto cleanup; goto cleanup;
params = hypervCreateInvokeParamsList("ModifyResourceSettings", params = hypervCreateInvokeParamsList("ModifyResourceSettings",
@ -1718,10 +1710,8 @@ hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) < 0) if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) < 0)
goto cleanup; goto cleanup;
if (hypervSetEmbeddedProperty(memResource, "InstanceID", if (hypervSetEmbeddedProperty(memResource, "InstanceID", memsd->data->InstanceID) < 0)
memsd->data.common->InstanceID) < 0) {
goto cleanup; goto cleanup;
}
if (hypervAddEmbeddedParam(params, "ResourceSettings", if (hypervAddEmbeddedParam(params, "ResourceSettings",
&memResource, Msvm_MemorySettingData_WmiInfo) < 0) { &memResource, Msvm_MemorySettingData_WmiInfo) < 0) {

View File

@ -50,31 +50,8 @@ VIR_LOG_INIT("hyperv.hyperv_wmi");
static int static int
hypervGetWmiClassInfo(hypervWmiClassInfoListPtr list, hypervWmiClassInfoPtr *info) hypervGetWmiClassInfo(hypervWmiClassInfoListPtr list, hypervWmiClassInfoPtr *info)
{ {
size_t i; *info = list->objs[0];
return 0;
if (list->count == 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("The WMI class info list is empty"));
return -1;
}
/* if there's just one WMI class and isn't versioned, assume "shared" */
if (list->count == 1 && list->objs[0]->version == NULL) {
*info = list->objs[0];
return 0;
}
for (i = 0; i < list->count; i++) {
if (STRCASEEQ(list->objs[i]->version, "v2")) {
*info = list->objs[i];
return 0;
}
}
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not match WMI class info for version v2"));
return -1;
} }
@ -911,7 +888,7 @@ hypervInvokeMethod(hypervPrivate *priv,
if (hypervGetWmiClass(Msvm_ConcreteJob, &job) < 0 || !job) if (hypervGetWmiClass(Msvm_ConcreteJob, &job) < 0 || !job)
goto cleanup; goto cleanup;
jobState = job->data.common->JobState; jobState = job->data->JobState;
switch (jobState) { switch (jobState) {
case MSVM_CONCRETEJOB_JOBSTATE_NEW: case MSVM_CONCRETEJOB_JOBSTATE_NEW:
case MSVM_CONCRETEJOB_JOBSTATE_STARTING: case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
@ -1078,7 +1055,7 @@ hypervEnumAndPull(hypervPrivate *priv, hypervWqlQueryPtr wqlQuery,
object = g_new0(hypervObject, 1); object = g_new0(hypervObject, 1);
object->info = wmiInfo; object->info = wmiInfo;
object->data.common = data; object->data = data;
data = NULL; data = NULL;
@ -1139,7 +1116,7 @@ hypervFreeObject(hypervPrivate *priv G_GNUC_UNUSED, hypervObject *object)
while (object != NULL) { while (object != NULL) {
next = object->next; next = object->next;
if (ws_serializer_free_mem(serializerContext, object->data.common, if (ws_serializer_free_mem(serializerContext, object->data,
object->info->serializerInfo) < 0) { object->info->serializerInfo) < 0) {
VIR_ERROR(_("Could not free deserialized data")); VIR_ERROR(_("Could not free deserialized data"));
} }
@ -1270,7 +1247,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
wsmc_add_prop_from_str(options, properties); wsmc_add_prop_from_str(options, properties);
/* Invoke method */ /* Invoke method */
response = wsmc_action_invoke(priv->client, MSVM_COMPUTERSYSTEM_V2_RESOURCE_URI, response = wsmc_action_invoke(priv->client, MSVM_COMPUTERSYSTEM_RESOURCE_URI,
options, "RequestStateChange", NULL); options, "RequestStateChange", NULL);
if (hypervVerifyResponse(priv->client, response, "invocation") < 0) if (hypervVerifyResponse(priv->client, response, "invocation") < 0)
@ -1320,7 +1297,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain,
goto cleanup; goto cleanup;
} }
switch (concreteJob->data.common->JobState) { switch (concreteJob->data->JobState) {
case MSVM_CONCRETEJOB_JOBSTATE_NEW: case MSVM_CONCRETEJOB_JOBSTATE_NEW:
case MSVM_CONCRETEJOB_JOBSTATE_STARTING: case MSVM_CONCRETEJOB_JOBSTATE_STARTING:
case MSVM_CONCRETEJOB_JOBSTATE_RUNNING: case MSVM_CONCRETEJOB_JOBSTATE_RUNNING:
@ -1380,7 +1357,7 @@ int
hypervMsvmComputerSystemEnabledStateToDomainState hypervMsvmComputerSystemEnabledStateToDomainState
(Msvm_ComputerSystem *computerSystem) (Msvm_ComputerSystem *computerSystem)
{ {
switch (computerSystem->data.common->EnabledState) { switch (computerSystem->data->EnabledState) {
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN: case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
return VIR_DOMAIN_NOSTATE; return VIR_DOMAIN_NOSTATE;
@ -1421,7 +1398,7 @@ hypervIsMsvmComputerSystemActive(Msvm_ComputerSystem *computerSystem,
if (in_transition != NULL) if (in_transition != NULL)
*in_transition = false; *in_transition = false;
switch (computerSystem->data.common->EnabledState) { switch (computerSystem->data->EnabledState) {
case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN: case MSVM_COMPUTERSYSTEM_ENABLEDSTATE_UNKNOWN:
return false; return false;
@ -1467,17 +1444,17 @@ hypervMsvmComputerSystemToDomain(virConnectPtr conn,
return -1; return -1;
} }
if (virUUIDParse(computerSystem->data.common->Name, uuid) < 0) { if (virUUIDParse(computerSystem->data->Name, uuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not parse UUID from string '%s'"), _("Could not parse UUID from string '%s'"),
computerSystem->data.common->Name); computerSystem->data->Name);
return -1; return -1;
} }
if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) if (hypervIsMsvmComputerSystemActive(computerSystem, NULL))
id = computerSystem->data.common->ProcessID; id = computerSystem->data->ProcessID;
*domain = virGetDomain(conn, computerSystem->data.common->ElementName, uuid, id); *domain = virGetDomain(conn, computerSystem->data->ElementName, uuid, id);
return *domain ? 0 : -1; return *domain ? 0 : -1;
} }

View File

@ -47,20 +47,8 @@ int hypervVerifyResponse(WsManClient *client, WsXmlDocH response,
typedef struct _hypervObject hypervObject; typedef struct _hypervObject hypervObject;
struct _hypervObject { struct _hypervObject {
/* Unserialized data from wsman response. The member called "common" has XML_TYPE_PTR data; /* Unserialized data from wsman response */
* properties that are the same type and name for all "versions" of given hypervWmiClassInfoPtr info; /* The info used to make wsman request */
* WMI class. This means that calling code does not have to make any
* conditional checks based on which version was returned as long as it
* only needs to read common values. The alignment of structs is ensured
* by the generator.
*/
union {
XML_TYPE_PTR common;
XML_TYPE_PTR v1;
XML_TYPE_PTR v2;
} data;
/* The info used to make wsman request */
hypervWmiClassInfoPtr info;
hypervObject *next; hypervObject *next;
}; };

View File

@ -32,9 +32,6 @@
#define ROOT_CIMV2 \ #define ROOT_CIMV2 \
"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*" "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
#define ROOT_VIRTUALIZATION \
"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/*"
#define ROOT_VIRTUALIZATION_V2 \ #define ROOT_VIRTUALIZATION_V2 \
"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/v2/*" "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/v2/*"
@ -121,8 +118,6 @@ typedef hypervWmiClassInfo *hypervWmiClassInfoPtr;
struct _hypervWmiClassInfo { struct _hypervWmiClassInfo {
/* The WMI class name */ /* The WMI class name */
const char *name; const char *name;
/* The version of the WMI class as in "v1" or "v2" */
const char *version;
/* The URI for wsman enumerate request */ /* The URI for wsman enumerate request */
const char *rootUri; const char *rootUri;
/* The namespace URI for XML serialization */ /* The namespace URI for XML serialization */

View File

@ -23,7 +23,7 @@
# #
class v2/Msvm_ComputerSystem class Msvm_ComputerSystem
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -72,7 +72,7 @@ class v2/Msvm_ComputerSystem
end end
class v2/Msvm_ConcreteJob class Msvm_ConcreteJob
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -117,7 +117,7 @@ class v2/Msvm_ConcreteJob
end end
class v2/Msvm_MemorySettingData class Msvm_MemorySettingData
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -149,7 +149,7 @@ class v2/Msvm_MemorySettingData
end end
class v2/Msvm_ProcessorSettingData class Msvm_ProcessorSettingData
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -180,7 +180,7 @@ class v2/Msvm_ProcessorSettingData
end end
class v2/Msvm_VirtualSystemSettingData class Msvm_VirtualSystemSettingData
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -569,7 +569,7 @@ class Win32_OperatingSystem
end end
class v2/Msvm_VirtualSystemManagementService class Msvm_VirtualSystemManagementService
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -601,7 +601,7 @@ class v2/Msvm_VirtualSystemManagementService
end end
class v2/Msvm_Keyboard class Msvm_Keyboard
string InstanceID string InstanceID
string Caption string Caption
string Description string Description
@ -648,7 +648,7 @@ class v2/Msvm_Keyboard
end end
class v2/Msvm_ShutdownComponent class Msvm_ShutdownComponent
string InstanceID string InstanceID
string Caption string Caption
string Description string Description