diff --git a/virttest/libvirt_version.py b/virttest/libvirt_version.py new file mode 100644 index 0000000000..f022782a5a --- /dev/null +++ b/virttest/libvirt_version.py @@ -0,0 +1,52 @@ +""" +Shared code for tests that need to get the libvirt version +""" + +import re +import logging + +from avocado.utils import process + +LIBVIRT_LIB_VERSION = 0 + + +def version_compare(major, minor, update): + """ + Determine/use the current libvirt library version on the system + and compare input major, minor, and update values against it. + If the running version is greater than or equal to the input + params version, then return True; otherwise, return False + + This is designed to handle upstream version comparisons for + test adjustments and/or comparisons as a result of upstream + fixes or changes that could impact test results. + + :param major: Major version to compare against + :param minor: Minor version to compare against + :param update: Update value to compare against + :return: True if running version is greater than or + equal to the input libvirt version + """ + global LIBVIRT_LIB_VERSION + + if LIBVIRT_LIB_VERSION == 0: + try: + regex = r'[Uu]sing\s*[Ll]ibrary:\s*[Ll]ibvirt\s*' + regex += r'(\d+)\.(\d+)\.(\d+)' + lines = process.run("virsh version").stdout_text.splitlines() + for line in lines: + mobj = re.search(regex, line) + if bool(mobj): + LIBVIRT_LIB_VERSION = int(mobj.group(1)) * 1000000 + \ + int(mobj.group(2)) * 1000 + \ + int(mobj.group(3)) + break + except (ValueError, TypeError, AttributeError): + logging.warning("Error determining libvirt version") + return False + + compare_version = major * 1000000 + minor * 1000 + update + + if LIBVIRT_LIB_VERSION >= compare_version: + return True + return False diff --git a/virttest/utils_misc.py b/virttest/utils_misc.py index afd57e6fc8..ff72f71b7c 100644 --- a/virttest/utils_misc.py +++ b/virttest/utils_misc.py @@ -72,6 +72,7 @@ from virttest import utils_selinux from virttest import utils_disk from virttest import logging_manager +from virttest import libvirt_version from virttest.staging import utils_koji from virttest.staging import service from virttest.xml_utils import XMLTreeFile @@ -4035,7 +4036,8 @@ def setup_remote(self): def get_model_features(model_name): """ - /usr/share/libvirt/cpu_map.xml defines all CPU models. + libvirt-4.5.0 :/usr/share/libvirt/cpu_map.xml defines all CPU models. + libvirt-5.0.0 :/usr/share/libvirt/cpu_map/ defines all CPU models. One CPU model is a set of features. This function is to get features of one specific model. @@ -4045,26 +4047,37 @@ def get_model_features(model_name): """ features = [] conf = "/usr/share/libvirt/cpu_map.xml" + conf_dir = "/usr/share/libvirt/cpu_map/" try: - output = open(conf, 'r').read() - root = ET.fromstring(output) - # Find model - for model_n in root.findall('arch/model'): - if model_n.get('name') == model_name: - model_node = model_n - for feature in model_n.findall('feature'): - features.append(feature.get('name')) - break - # Handle nested model - nested_model = model_node.find('model') - if nested_model is not None: - nested_model_name = nested_model.get('name') - for model_n in root.findall('arch/model'): - if model_n.get('name') == nested_model_name: - for feature in model_n.findall('feature'): - features.append(feature.get('name')) - break + if not libvirt_version.version_compare(5, 0, 0): + with open(conf, 'r') as output: + root = ET.fromstring(output.read()) + while True: + # Find model in file /usr/share/libvirt/cpu_map.xml + for model_n in root.findall('arch/model'): + if model_n.get('name') == model_name: + model_node = model_n + for feature in model_n.findall('feature'): + features.append(feature.get('name')) + break + # Handle nested model + if model_node.find('model') is not None: + model_name = model_node.find('model').get('name') + continue + else: + break + + else: + # Find model in dir /usr/share/libvirt/cpu_map + filelist = os.listdir(conf_dir) + for file_name in filelist: + if model_name in file_name: + with open(os.path.join(conf_dir, file_name), "r") as output: + model = ET.fromstring(output.read()) + for feature in model.findall("model/feature"): + features.append(feature.get('name')) + break except ET.ParseError as error: logging.warn("Configuration file %s has wrong xml format" % conf) raise