def test_qtree(self):
        """ Correct workflow """
        reference_nodes = [
            qemu_qtree.QtreeDisk, qemu_qtree.QtreeBus, qemu_qtree.QtreeDev,
            qemu_qtree.QtreeDev, qemu_qtree.QtreeDev, qemu_qtree.QtreeDisk,
            qemu_qtree.QtreeBus, qemu_qtree.QtreeDev, qemu_qtree.QtreeBus,
            qemu_qtree.QtreeDev, qemu_qtree.QtreeDev, qemu_qtree.QtreeBus
        ]

        info = qtree_header
        info = combine(info, dev_ide_disk, 1)
        info = combine(info, dev_usb_disk, 1)
        info = combine(info, dev_dummy_mmio, 1)
        info += "\n"

        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(info)
        nodes = qtree.get_nodes()

        self.assertEqual(len(nodes), len(reference_nodes),
                         ("Number of parsed "
                          "nodes is not equal to the number of qtree nodes. "
                          "%s != %s" % (len(nodes), len(reference_nodes))))

        for i in xrange(len(nodes)):
            self.assertTrue(isinstance(nodes[i], reference_nodes[i]),
                            ("Node %d should be class %s but is %s instead" %
                             (i, reference_nodes[i], type(reference_nodes))))

        tree = qtree.get_qtree()
        self.assertTrue(isinstance(tree.str_qtree(), six.string_types),
                        "qtree.str_qtree() returns nonstring output.")

        self.assertTrue(isinstance(str(tree), six.string_types),
                        "str(qtree) returns nonstring output.")
Exemple #2
0
 def verify_qtree(params, info_qtree, info_block, qdev):
     """
     Verifies that params, info qtree, info block and /proc/scsi/ matches
     :param params: Dictionary with the test parameters
     :type params: virttest.utils_params.Params
     :param info_qtree: Output of "info qtree" monitor command
     :type info_qtree: string
     :param info_block: Output of "info block" monitor command
     :type info_block: dict of dicts
     :param qdev: qcontainer representation
     :type qdev: virttest.qemu_devices.qcontainer.DevContainer
     """
     err = 0
     qtree = qemu_qtree.QtreeContainer()
     qtree.parse_info_qtree(info_qtree)
     disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
     (tmp1, tmp2) = disks.parse_info_block(info_block)
     err += tmp1 + tmp2
     err += disks.generate_params()
     err += disks.check_disk_params(params)
     if err:
         logging.error("info qtree:\n%s", info_qtree)
         logging.error("info block:\n%s", info_block)
         logging.error(qdev.str_bus_long())
         test.fail("%s errors occurred while verifying"
                   " qtree vs. params" % err)
Exemple #3
0
    def verify_num_queues():
        """ Verify the number of queues. """
        error_context.context("Verify num_queues from monitor.", test.log.info)
        qtree = qemu_qtree.QtreeContainer()
        try:
            qtree.parse_info_qtree(vm.monitor.info('qtree'))
        except AttributeError:
            test.cancel("Monitor deson't supoort qtree skip this test")
        error_msg = "Number of queues mismatch: expect %s report from monitor: %s(%s)"
        scsi_bus_addr = ""
        qtree_num_queues_full = ""
        qtree_num_queues = ""
        for node in qtree.get_nodes():
            type = node.qtree['type']
            if isinstance(node, qemu_qtree.QtreeDev) and (
                    type == "virtio-scsi-device"):
                qtree_num_queues_full = node.qtree["num_queues"]
                qtree_num_queues = re.search(
                    "[0-9]+", qtree_num_queues_full).group()
            elif (isinstance(node, qemu_qtree.QtreeDev)) and (
                    type == "virtio-scsi-pci"):
                scsi_bus_addr = node.qtree['addr']

        if qtree_num_queues != num_queues:
            error_msg = error_msg % (
                num_queues, qtree_num_queues, qtree_num_queues_full)
            test.fail(error_msg)
        if not scsi_bus_addr:
            test.error("Didn't find addr from qtree. Please check the log.")
Exemple #4
0
 def _check_property(vm, ioeventfd_opt):
     """
     Check the value of ioeventfd by sending "info qtree" in QMP.
     """
     ioevent_qtree_val = 'true' if 'on' in ioeventfd_opt else 'false'
     logging.info('Execute info qtree in QMP monitor.')
     qtree = qemu_qtree.QtreeContainer()
     qtree.parse_info_qtree(vm.monitor.info('qtree'))
     for node in qtree.get_nodes():
         if isinstance(node, qemu_qtree.QtreeDev) and (
                 node.qtree.get('id', None) == dev_id):
             if node.qtree.get('ioeventfd', None) is None:
                 test.fail('The qtree device %s has no property ioeventfd.'
                           % dev_id)
             elif node.qtree['ioeventfd'] == ioevent_qtree_val:
                 logging.info(
                     'The \"%s\" matches with qtree device \"%s\"(%s).' %
                     (ioeventfd_opt, dev_id, ioevent_qtree_val))
                 break
             else:
                 test.fail(
                     'The \"%s\" mismatches with qtree device \"%s\"(%s).' %
                     (ioeventfd_opt, dev_id, ioevent_qtree_val))
     else:
         test.error('No such \"%s\" qtree device.' % dev_id)
Exemple #5
0
 def get_vectors_fqtree():
     """
     Get device vectors from qemu info qtree.
     """
     device_type = params["device_type"]
     qtree = qemu_qtree.QtreeContainer()
     qtree.parse_info_qtree(vm.monitor.info('qtree'))
     for node in qtree.get_nodes():
         if (isinstance(node, qemu_qtree.QtreeDev)
                 and node.qtree['type'] == device_type):
             vectors = node.qtree["vectors"].split()[0]
             return vectors
    def get_rotational_rate_in_qtree():
        """ get_rotational_rate_in_qtree """

        error_context.context("Get rotational_rate from monitor.", logging.info)
        qtree = qemu_qtree.QtreeContainer()
        try:
            qtree.parse_info_qtree(vm.monitor.info('qtree'))
        except AttributeError:
            test.cancel("Monitor doesn't support qtree skip this test")
        for node in qtree.get_nodes():
            type = node.qtree['type']
            if isinstance(node, qemu_qtree.QtreeDev) and (type == "scsi-hd"):
                return node.qtree["rotation_rate"].split("(")[0].strip()
    def setUp(self):
        # Get rid of logging errors
        def dumm(*args, **kvargs):
            pass
        self.god = mock.mock_god(ut=self)
        self.god.stub_with(qemu_qtree.logging, 'error', dumm)

        info = qtree_header
        info = combine(info, dev_ide_disk, 1)
        info = combine(info, dev_usb_disk, 1)
        info = combine(info, dev_dummy_mmio, 1)
        info += "\n"

        self.no_disks = 2

        self.qtree = qemu_qtree.QtreeContainer()
        self.qtree.parse_info_qtree(info)

        self.disks = qemu_qtree.QtreeDisksContainer(self.qtree.get_nodes())
Exemple #8
0
 def verify_virtio_mode_qtree():
     """
     Verify that virtio mode setting in qtree are correct.
     """
     device_type = params["device_type"]
     qtree = qemu_qtree.QtreeContainer()
     try:
         qtree.parse_info_qtree(vm.monitor.info('qtree'))
     except AttributeError:
         test.cancel("Monitor deson't supoort qtree, skip this test")
     for node in qtree.get_nodes():
         if (isinstance(node, qemu_qtree.QtreeDev)
                 and node.qtree['type'] == device_type):
             disable_modern = node.qtree["disable-modern"]
             disable_legacy = node.qtree["disable-legacy"].strip('"')
     if (disable_modern != params["virtio_dev_disable_modern"]
             or disable_legacy != params["virtio_dev_disable_legacy"]):
         test.fail(
             "virtio mode in qtree is not correct, details are %s %s" %
             (disable_modern, disable_legacy))
 def check_attribute_in_qtree(dev_id, name, excepted_val):
     """Check if discard and write-zeroes attribute work."""
     error_context.context('Check if %s attribute works.' % name,
                           logging.info)
     qtree = qemu_qtree.QtreeContainer()
     qtree.parse_info_qtree(vm.monitor.info('qtree'))
     for node in qtree.get_nodes():
         if (isinstance(node, qemu_qtree.QtreeDev)
                 and node.qtree.get('id') == dev_id):
             _node = node.children[0].children[0]
             if _node.qtree.get('drive').endswith('_%s"' % dev_id):
                 if _node.qtree.get(name) is None:
                     test.fail('The qtree device %s has no property %s.' %
                               (dev_id, name))
                 elif _node.qtree.get(name) == excepted_val:
                     logging.info('The "%s" matches with qtree device "%s"'
                                  '(%s).' % (name, dev_id, excepted_val))
                     break
                 else:
                     test.fail('The "%s" mismatches with qtree device "%s"'
                               '(%s).' % (name, dev_id, excepted_val))
     else:
         test.error('No such "%s" qtree device.' % dev_id)
def run(test, params, env):
    """
    Qemu device options value check test:

    1) Boot up guest with setted option value
    2) Check the value is correct inside guest

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    error_context.context("Boot up guest.", logging.info)
    timeout = float(params.get("login_timeout", 240))
    vm = env.get_vm(params["main_vm"])
    parameter_value = params.get("parameter_value", "random")
    params_name = params["params_name"]
    parameter_prefix = params.get("parameter_prefix", "")
    check_cmds = params["check_cmds"]
    convert_str = params.get("convert_str")

    if params.get("start_vm") == "no":
        if parameter_value == "random":
            parameter_len = int(params.get("parameter_len", 4))
            random_ignore_str = params.get("ignore_str")
            func_generate_random_string = utils_misc.generate_random_string
            args = (parameter_len, )
            if random_ignore_str:
                args += ("ignore_str=%s" % random_ignore_str, )
            if convert_str:
                args += ("convert_str=%s" % convert_str, )
            parameter_value = func_generate_random_string(*args)

        params[params_name] = parameter_prefix + parameter_value
        logging.debug("Setup '%s' to '%s'" %
                      (params_name, params[params_name]))

        params["start_vm"] = "yes"
        env_process.preprocess_vm(test, params, env, vm.name)

    if convert_str:
        tmp_str = re.sub(r'\\\\', 'Abackslash', parameter_value)
        tmp_str = re.sub(r'\\', '', tmp_str)
        tmp_str = re.sub('Abackslash', r"\\", tmp_str)
        parameter_value_raw = tmp_str
    else:
        parameter_value_raw = parameter_value

    if params.get("check_in_qtree") == "yes":
        error_context.context("Check option in qtree", logging.info)
        qtree = qemu_qtree.QtreeContainer()
        try:
            qtree.parse_info_qtree(vm.monitor.info('qtree'))
            keyword = params['qtree_check_keyword']
            qtree_check_value = params['qtree_check_value']
            qtree_check_option = params['qtree_check_option']

            for qdev in qtree.get_nodes():
                if keyword not in qdev.qtree:
                    continue
                if qdev.qtree[keyword] != qtree_check_value:
                    continue

                qtree_value = None
                for node in qemu_qtree.traverse(qdev):
                    if qtree_check_option in node.qtree:
                        qtree_value = str(node.qtree.get(qtree_check_option))
                        break

                if qtree_value is not None:
                    break
            else:
                test.fail(
                    "Can not find property '%s' from info qtree where '%s' is "
                    "'%s'" % (qtree_check_option, keyword, qtree_check_value))

            qtree_value = re.findall('"?(.*)"?$', qtree_value)[0]
            if (qtree_value != parameter_value_raw
                    and parameter_value_raw not in qtree_value):
                test.fail(
                    "Value from info qtree is not match with the value from"
                    "command line: '%s' vs '%s'" %
                    (qtree_value, parameter_value_raw))
        except AttributeError:
            logging.debug("Monitor deson't support info qtree skip this test")

    session = vm.wait_for_login(timeout=timeout)

    failed_log = ""
    for check_cmd in check_cmds.split():
        check_cmd_params = params.object_params(check_cmd)
        cmd = check_cmd_params['cmd']
        cmd = utils_misc.set_winutils_letter(session, cmd)
        pattern = check_cmd_params['pattern'] % parameter_value_raw

        error_context.context("Check option with command %s" % cmd,
                              logging.info)
        _, output = session.cmd_status_output(cmd)
        if not re.findall(r'%s' % pattern, output):
            failed_log += ("Can not find option %s from guest."
                           " Guest output is '%s'" % (params_name, output))

    session.close()

    if failed_log:
        test.fail(failed_log)
Exemple #11
0
def run(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params. (Optional)
    4) Create partition on those disks.
    5) Get disk dev filenames in guest.
    6) Format those disks in guest.
    7) Copy file into / out of those disks.
    8) Compare the original file and the copied file using md5 or fc comand.
    9) Repeat steps 3-5 if needed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    def _do_post_cmd(session):
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    error_context.context("Parsing test configuration", logging.info)
    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    stg_params += _add_param("drive_cache", params.get("stg_drive_cache"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                       stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in range(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm is False:
                test.error("Incorrect cfg: stg_params %s looks "
                           "like range(..) but doesn't contain "
                           "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', 'images/%s')
    for i in range(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.items():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     astring.tabular_output(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    error_context.context("Start the guest with new disks", logging.info)
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        env_process.process_images(env_process.preprocess_image, test,
                                   vm_params)

    error_context.context("Start the guest with those disks", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    login_timeout = int(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=login_timeout)

    n_repeat = int(params.get("n_repeat", "1"))
    file_system = [_.strip() for _ in params["file_system"].split()]
    cmd_timeout = float(params.get("cmd_timeout", 360))
    black_list = params["black_list"].split()
    drive_letters = int(params.get("drive_letters", "26"))
    stg_image_size = params["stg_image_size"]
    dd_test = params.get("dd_test", "no")
    pre_command = params.get("pre_command", "")
    labeltype = params.get("labeltype", "gpt")
    iozone_target_num = int(params.get('iozone_target_num', '5'))
    iozone_options = params.get('iozone_options')
    iozone_timeout = float(params.get('iozone_timeout', '7200'))

    have_qtree = True
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        have_qtree = False

    if (params.get("check_guest_proc_scsi") == "yes") and have_qtree:
        error_context.context("Verifying qtree vs. test params")
        err = 0
        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
        disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block())
        err += tmp1 + tmp2
        err += disks.generate_params()
        err += disks.check_disk_params(params)
        (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
            session.cmd_output('cat /proc/scsi/scsi'))
        err += tmp1 + tmp2

        if err:
            test.fail("%s errors occurred while verifying qtree vs."
                      " params" % err)
        if params.get('multi_disk_only_qtree') == 'yes':
            return
    try:
        err_msg = "Set disks num: %d" % stg_image_num
        err_msg += ", Get disks num in guest: %d"
        ostype = params["os_type"]
        if ostype == "windows":
            error_context.context(
                "Get windows disk index that to "
                "be formatted", logging.info)
            disks = utils_disk.get_windows_disks_index(session, stg_image_size)
            if len(disks) < stg_image_num:
                test.fail("Fail to list all the volumes"
                          ", %s" % err_msg % len(disks))
            if len(disks) > drive_letters:
                black_list.extend(utils_misc.get_winutils_vol(session))
                disks = random.sample(disks, drive_letters - len(black_list))
            error_context.context(
                "Clear readonly for all disks and online "
                "them in windows guest.", logging.info)
            if not utils_disk.update_windows_disk_attributes(session, disks):
                test.fail("Failed to update windows disk attributes.")
            dd_test = "no"
        else:
            error_context.context("Get linux disk that to be "
                                  "formatted", logging.info)
            disks = sorted(utils_disk.get_linux_disks(session).keys())
            if len(disks) < stg_image_num:
                test.fail("Fail to list all the volumes"
                          ", %s" % err_msg % len(disks))
    except Exception:
        _do_post_cmd(session)
        raise
    try:
        if iozone_options:
            iozone = generate_instance(params, session, 'iozone')
            random.shuffle(disks)
        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            for n, disk in enumerate(disks):
                error_context.context("Format disk in guest: '%s'" % disk,
                                      logging.info)
                # Random select one file system from file_system
                index = random.randint(0, (len(file_system) - 1))
                fstype = file_system[index].strip()
                partitions = utils_disk.configure_empty_disk(
                    session,
                    disk,
                    stg_image_size,
                    ostype,
                    fstype=fstype,
                    labeltype=labeltype)
                if not partitions:
                    test.fail("Fail to format disks.")
                cmd_list = params["cmd_list"]
                for partition in partitions:
                    orig_partition = partition
                    if "/" not in partition:
                        partition += ":"
                    else:
                        partition = partition.split("/")[-1]
                    error_context.context(
                        "Copy file into / out of partition:"
                        " %s..." % partition, logging.info)
                    for cmd_l in cmd_list.split():
                        cmd = params.get(cmd_l)
                        if cmd:
                            session.cmd(cmd % partition, timeout=cmd_timeout)
                    cmd = params["compare_command"]
                    key_word = params["check_result_key_word"]
                    output = session.cmd_output(cmd)
                    if iozone_options and n < iozone_target_num:
                        iozone.run(iozone_options.format(orig_partition),
                                   iozone_timeout)
                    if key_word not in output:
                        test.fail("Files on guest os root fs and disk differ")
                    if dd_test != "no":
                        error_context.context(
                            "dd test on partition: %s..." % partition,
                            logging.info)
                        status, output = session.cmd_status_output(
                            dd_test % (partition, partition),
                            timeout=cmd_timeout)
                        if status != 0:
                            test.fail("dd test fail: %s" % output)
                    # When multiple SCSI disks are simulated by scsi_debug,
                    # they could be viewed as multiple paths to the same
                    # storage device. So need umount partition before operate
                    # next disk, in order to avoid corrupting the filesystem
                    # (xfs integrity checks error).
                    if ostype == "linux" and "scsi_debug add_host" in pre_command:
                        status, output = session.cmd_status_output(
                            "umount /dev/%s" % partition, timeout=cmd_timeout)
                        if status != 0:
                            test.fail("Failed to umount partition '%s': %s" %
                                      (partition, output))
            need_reboot = params.get("need_reboot", "no")
            need_shutdown = params.get("need_shutdown", "no")
            if need_reboot == "yes":
                error_context.context("Rebooting guest ...", logging.info)
                session = vm.reboot(session=session, timeout=login_timeout)
            if need_shutdown == "yes":
                error_context.context("Shutting down guest ...", logging.info)
                vm.graceful_shutdown(timeout=login_timeout)
                if vm.is_alive():
                    test.fail("Fail to shut down guest.")
                error_context.context("Start the guest again.", logging.info)
                vm = env.get_vm(params["main_vm"])
                vm.create(params=params)
                session = vm.wait_for_login(timeout=login_timeout)
            error_context.context("Delete partitions in guest.", logging.info)
            for disk in disks:
                utils_disk.clean_partition(session, disk, ostype)
    finally:
        if iozone_options:
            iozone.clean()
        _do_post_cmd(session)
Exemple #12
0
def run(test, params, env):
    """
    Check physical resources assigned to KVM virtual machines:
    1) Log into the guest
    2) Verify whether cpu counts ,memory size, nics' model,
       count and drives' format & count, drive_serial, UUID
       reported by the guest OS matches what has been assigned
       to the VM (qemu command line)
    3) Verify all MAC addresses for guest NICs

    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """

    # Define a function for checking number of hard drivers & NICs
    def check_num(devices, info_cmd, check_str):
        f_fail = []
        expected_num = params.objects(devices).__len__()
        o = ""
        try:
            o = vm.monitor.human_monitor_cmd("info %s " % info_cmd)
        except qemu_monitor.MonitorError as e:
            fail_log = str(e) + "\n"
            fail_log += "info/query monitor command failed (%s)" % info_cmd
            f_fail.append(fail_log)
            logging.error(fail_log)

        ovmf_fd_num = o.count('%s.fd' % check_str)  # Exclude ovmf fd drive
        actual_num = o.count(check_str) - ovmf_fd_num
        if expected_num != actual_num:
            fail_log = "%s number mismatch:\n" % str(devices)
            fail_log += "    Assigned to VM: %d\n" % expected_num
            fail_log += "    Reported by OS: %d" % actual_num
            f_fail.append(fail_log)
            logging.error(fail_log)
        return f_fail

    # Define a function for checking hard drives & NICs' model
    def chk_fmt_model(device, fmt_model, info_cmd, regexp):
        f_fail = []
        devices = params.objects(device)
        for chk_device in devices:
            expected = params.object_params(chk_device).get(fmt_model)
            if not expected:
                expected = "rtl8139"
            o = ""
            try:
                o = vm.monitor.human_monitor_cmd("info %s" % info_cmd)
            except qemu_monitor.MonitorError as e:
                fail_log = str(e) + "\n"
                fail_log += "info/query monitor command failed (%s)" % info_cmd
                f_fail.append(fail_log)
                logging.error(fail_log)

            device_found = re.findall(regexp, o)
            logging.debug("Found devices: %s", device_found)
            found = False
            for fm in device_found:
                if expected in fm:
                    found = True

            if not found:
                fail_log = "%s model mismatch:\n" % str(device)
                fail_log += "    Assigned to VM: %s\n" % expected
                fail_log += "    Reported by OS: %s" % device_found
                f_fail.append(fail_log)
                logging.error(fail_log)
        return f_fail

    # Define a function to verify UUID & Serial number
    def verify_device(expect, name, verify_cmd):
        f_fail = []
        if verify_cmd:
            actual = session.cmd_output(verify_cmd)
            if not re.findall(expect, actual, re.I):
                fail_log = "%s mismatch:\n" % name
                fail_log += "    Assigned to VM: %s\n" % expect.upper()
                fail_log += "    Reported by OS: %s" % actual
                f_fail.append(fail_log)
                logging.error(fail_log)
        return f_fail

    def get_cpu_number(chk_type, chk_timeout):
        """
        Get cpu sockets/cores/threads number.

        :param chk_type: Should be one of 'sockets', 'cores', 'threads'.
        :param chk_timeout: timeout of running chk_cmd.

        :return: Actual number of guest cpu number.
        """
        chk_str = params["mem_chk_re_str"]
        chk_cmd = params.get("cpu_%s_chk_cmd" % chk_type)

        if chk_cmd is None:
            fail_log = "Unknown cpu number checking type: '%s'" % chk_type
            logging.error(fail_log)
            return -1

        s, output = session.cmd_status_output(chk_cmd, timeout=chk_timeout)
        num = re.findall(chk_str, output)
        if s != 0 or not num:
            fail_log = "Failed to get guest %s number, " % chk_type
            fail_log += "guest output: '%s'" % output
            logging.error(fail_log)
            return -2

        logging.info("CPU %s number: %d", chk_type.capitalize(), int(num[-1]))
        return int(num[-1])

    def check_cpu_number(chk_type, actual_n, expected_n):
        """
        Checking cpu sockets/cores/threads number.

        :param chk_type: Should be one of 'sockets', 'cores', 'threads'.
        :param actual_n: Actual number of guest cpu number.
        :param expected_n: Expected number of guest cpu number.

        :return: a list that contains fail report.
        """
        f_fail = []

        if actual_n == -1:
            fail_log = "Unknown cpu number checking type: '%s'" % chk_type
            logging.error(fail_log)
            f_fail.append(fail_log)
            return f_fail

        if actual_n == -2:
            fail_log = "Failed to get guest %s number." % chk_type
            logging.error(fail_log)
            f_fail.append(fail_log)
            return f_fail

        logging.info("CPU %s number check", chk_type.capitalize())

        if actual_n != expected_n:
            fail_log = "%s output mismatch:\n" % chk_type.capitalize()
            fail_log += "    Assigned to VM: '%s'\n" % expected_n
            fail_log += "    Reported by OS: '%s'" % actual_n
            f_fail.append(fail_log)
            logging.error(fail_log)
            return f_fail

        logging.debug("%s check pass. Expected: '%s', Actual: '%s'",
                      chk_type.capitalize(), expected_n, actual_n)
        return f_fail

    def verify_machine_type():
        f_fail = []
        cmd = params.get("check_machine_type_cmd")
        fail_log = ""

        if cmd is None:
            return f_fail

        status, actual_mtype = session.cmd_status_output(cmd)
        if status != 0:
            test.error("Failed to get machine type from vm")

        machine_type_cmd = "%s -M ?" % utils_misc.get_qemu_binary(params)
        machine_types = process.system_output(machine_type_cmd,
                                              ignore_status=True).decode()
        machine_types = machine_types.split(':')[-1]
        machine_type_map = {}
        for machine_type in machine_types.splitlines():
            if not machine_type:
                continue
            type_pair = re.findall(r"([\w\.-]+)\s+([^(]+).*", machine_type)
            if len(type_pair) == 1 and len(type_pair[0]) == 2:
                machine_type_map[type_pair[0][0]] = type_pair[0][1]
            else:
                logging.warn("Unexpect output from qemu-kvm -M "
                             "?: '%s'", machine_type)
        try:
            expect_mtype = machine_type_map[params['machine_type']].strip()
        except KeyError:
            logging.warn(
                "Can not find machine type '%s' from qemu-kvm -M ?"
                " output. Skip this test.", params['machine_type'])
            return f_fail

        if expect_mtype not in actual_mtype:
            fail_log += "    Assigned to VM: '%s' \n" % expect_mtype
            fail_log += "    Reported by OS: '%s'" % actual_mtype
            f_fail.append(fail_log)
            logging.error(fail_log)
        else:
            logging.info("MachineType check pass. Expected: %s, Actual: %s",
                         expect_mtype, actual_mtype)
        return f_fail

    if params.get("catch_serial_cmd") is not None:
        length = int(params.get("length", "20"))
        id_leng = random.randint(0, length)
        drive_serial = ""
        convert_str = "!\"#$%&\'()*+./:;<=>?@[\\]^`{|}~"
        drive_serial = utils_misc.generate_random_string(
            id_leng, ignore_str=",", convert_str=convert_str)

        params["drive_serial"] = drive_serial
        params["start_vm"] = "yes"

        vm = params["main_vm"]
        vm_params = params.object_params(vm)
        env_process.preprocess_vm(test, vm_params, env, vm)
        vm = env.get_vm(vm)
    else:
        vm = env.get_vm(params["main_vm"])

    vm.verify_alive()
    timeout = int(params.get("login_timeout", 360))
    chk_timeout = int(params.get("chk_timeout", 240))

    error_context.context("Login to the guest", logging.info)
    session = vm.wait_for_login(timeout=timeout)

    qtree = qemu_qtree.QtreeContainer()
    try:
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
    except AttributeError:  # monitor doesn't support info qtree
        qtree = None

    logging.info("Starting physical resources check test")
    logging.info("Values assigned to VM are the values we expect "
                 "to see reported by the Operating System")
    # Define a failure counter, as we want to check all physical
    # resources to know which checks passed and which ones failed
    n_fail = []

    # We will check HDs with the image name
    image_name = storage.get_image_filename(params, data_dir.get_data_dir())

    # Check cpu count
    error_context.context("CPU count check", logging.info)
    actual_cpu_nr = vm.get_cpu_count()
    cpu_cores_num = get_cpu_number("cores", chk_timeout)
    cpu_lp_num = get_cpu_number("logical_processors", chk_timeout)
    cpu_threads_num = get_cpu_number("threads", chk_timeout)
    cpu_sockets_num = get_cpu_number("sockets", chk_timeout)

    if ((params.get("os_type") == 'windows') and cpu_cores_num > 0
            and cpu_lp_num > 0 and cpu_sockets_num > 0):
        actual_cpu_nr = cpu_lp_num * cpu_sockets_num
        cpu_threads_num = cpu_lp_num / cpu_cores_num

    if vm.cpuinfo.smp != actual_cpu_nr:
        fail_log = "CPU count mismatch:\n"
        fail_log += "    Assigned to VM: %s \n" % vm.cpuinfo.smp
        fail_log += "    Reported by OS: %s" % actual_cpu_nr
        n_fail.append(fail_log)
        logging.error(fail_log)

    n_fail.extend(check_cpu_number("cores", cpu_cores_num, vm.cpuinfo.cores))

    n_fail.extend(
        check_cpu_number("threads", cpu_threads_num, vm.cpuinfo.threads))

    n_fail.extend(
        check_cpu_number("sockets", cpu_sockets_num, vm.cpuinfo.sockets))

    # Check the cpu vendor_id
    expected_vendor_id = params.get("cpu_model_vendor")
    cpu_vendor_id_chk_cmd = params.get("cpu_vendor_id_chk_cmd")
    if expected_vendor_id and cpu_vendor_id_chk_cmd:
        output = session.cmd_output(cpu_vendor_id_chk_cmd)

        if expected_vendor_id not in output:
            fail_log = "CPU vendor id check failed.\n"
            fail_log += "    Assigned to VM: '%s'\n" % expected_vendor_id
            fail_log += "    Reported by OS: '%s'" % output
            n_fail.append(fail_log)
            logging.error(fail_log)

    # Check memory size
    error_context.context("Memory size check", logging.info)
    expected_mem = int(params["mem"])
    actual_mem = vm.get_memory_size()
    if actual_mem != expected_mem:
        fail_log = "Memory size mismatch:\n"
        fail_log += "    Assigned to VM: %s\n" % expected_mem
        fail_log += "    Reported by OS: %s\n" % actual_mem
        n_fail.append(fail_log)
        logging.error(fail_log)

    error_context.context("Hard drive count check", logging.info)
    f_fail = check_num("images", "block", image_name)
    n_fail.extend(f_fail)

    error_context.context("NIC count check", logging.info)
    f_fail = check_num("nics", "network", "model=")
    n_fail.extend(f_fail)

    error_context.context("NICs model check", logging.info)
    f_fail = chk_fmt_model("nics", "nic_model", "network", "model=(.*),")
    n_fail.extend(f_fail)

    if qtree is not None:
        error_context.context("Images params check", logging.info)
        logging.debug("Found devices: %s", params.objects('images'))
        qdisks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        disk_errors = sum(qdisks.parse_info_block(vm.monitor.info_block()))
        disk_errors += qdisks.generate_params()
        disk_errors += qdisks.check_disk_params(params)
        if disk_errors:
            disk_errors = ("Images check failed with %s errors, "
                           "check the log for details" % disk_errors)
            logging.error(disk_errors)
            n_fail.append("\n".join(qdisks.errors))
    else:
        logging.info("Images check param skipped (qemu monitor doesn't "
                     "support 'info qtree')")

    error_context.context("Network card MAC check", logging.info)
    o = ""
    try:
        o = vm.monitor.human_monitor_cmd("info network")
    except qemu_monitor.MonitorError as e:
        fail_log = str(e) + "\n"
        fail_log += "info/query monitor command failed (network)"
        n_fail.append(fail_log)
        logging.error(fail_log)
    found_mac_addresses = re.findall(r"macaddr=(\S+)", o)
    logging.debug("Found MAC adresses: %s", found_mac_addresses)

    num_nics = len(params.objects("nics"))
    for nic_index in range(num_nics):
        mac = vm.get_mac_address(nic_index)
        if mac.lower() not in found_mac_addresses:
            fail_log = "MAC address mismatch:\n"
            fail_log += "    Assigned to VM (not found): %s" % mac
            n_fail.append(fail_log)
            logging.error(fail_log)

    error_context.context("UUID check", logging.info)
    if vm.get_uuid():
        f_fail = verify_device(vm.get_uuid(), "UUID",
                               params.get("catch_uuid_cmd"))
        n_fail.extend(f_fail)

    error_context.context("Hard Disk serial number check", logging.info)
    catch_serial_cmd = params.get("catch_serial_cmd")
    f_fail = verify_device(params.get("drive_serial"), "Serial",
                           catch_serial_cmd)
    n_fail.extend(f_fail)

    error_context.context("Machine Type Check", logging.info)
    f_fail = verify_machine_type()
    n_fail.extend(f_fail)

    if n_fail:
        session.close()
        test.fail("Physical resources check test "
                  "reported %s failures:\n%s" %
                  (len(n_fail), "\n".join(n_fail)))

    session.close()
Exemple #13
0
def run_multi_disk(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params.
    4) Format those disks.
    5) Copy file into / out of those disks.
    6) Compare the original file and the copied file using md5 or fc comand.
    7) Repeat steps 3-5 if needed.

    @param test: kvm test object
    @param params: Dictionary with the test parameters
    @param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                          stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in xrange(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm == False:
                raise error.TestError("Incorrect cfg: stg_params %s looks "
                                      "like range(..) but doesn't contain "
                                      "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', '%s')
    for i in xrange(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.iteritems():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     utils.matrix_to_string(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        for image_name in vm_params.objects("images"):
            image_params = vm_params.object_params(image_name)
            env_process.preprocess_image(test, image_params, image_name)

    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    images = params.get("images").split()
    n_repeat = int(params.get("n_repeat", "1"))
    image_num = len(images)
    file_system = params.get("file_system").split()
    fs_num = len(file_system)
    cmd_timeout = float(params.get("cmd_timeout", 360))
    re_str = params.get("re_str")
    black_list = params.get("black_list").split()

    error.context("verifying qtree vs. test params")
    err = 0
    qtree = qemu_qtree.QtreeContainer()
    qtree.parse_info_qtree(vm.monitor.info('qtree'))
    disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
    (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info('block'))
    err += tmp1 + tmp2
    err += disks.generate_params()
    err += disks.check_disk_params(params)
    (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
                                    session.cmd_output('cat /proc/scsi/scsi'))
    err += tmp1 + tmp2

    if err:
        raise error.TestFail("%s errors occurred while verifying qtree vs. "
                             "params" % err)
    if params.get('multi_disk_only_qtree') == 'yes':
        return

    try:
        if params.get("clean_cmd"):
            cmd = params.get("clean_cmd")
            session.cmd_status_output(cmd)
        if params.get("pre_cmd"):
            cmd = params.get("pre_cmd")
            error.context("creating partition on test disk")
            session.cmd(cmd, timeout=cmd_timeout)
        cmd = params.get("list_volume_command")
        output = session.cmd_output(cmd, timeout=cmd_timeout)
        disks = re.findall(re_str, output)
        disks = map(string.strip, disks)
        disks.sort()
        logging.debug("Volume list that meets regular expressions: '%s'", disks)
        if len(disks) < image_num:
            raise error.TestFail("Fail to list all the volumes!")

        if params.get("os_type") == "linux":
            df_output = session.cmd_output("df")
            li = re.findall("^/dev/(.*?)[ \d]", df_output, re.M)
            if li:
                black_list.extend(li)

        exclude_list = [d for d in disks if d in black_list]
        f = lambda d: logging.info("No need to check volume '%s'", d)
        map(f, exclude_list)

        disks = [d for d in disks if d not in exclude_list]

        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            for disk in disks:
                disk = disk.strip()

                logging.info("Format disk: %s...", disk)
                index = random.randint(0, fs_num - 1)

                # Random select one file system from file_system
                fs = file_system[index].strip()
                cmd = params.get("format_command") % (fs, disk)
                error.context("formatting test disk")
                session.cmd(cmd, timeout=cmd_timeout)
                if params.get("mount_command"):
                    cmd = params.get("mount_command") % (disk, disk, disk)
                    session.cmd(cmd, timeout=cmd_timeout)

            for disk in disks:
                disk = disk.strip()

                logging.info("Performing I/O on disk: %s...", disk)
                cmd_list = params.get("cmd_list").split()
                for cmd_l in cmd_list:
                    if params.get(cmd_l):
                        cmd = params.get(cmd_l) % disk
                        session.cmd(cmd, timeout=cmd_timeout)

                cmd = params.get("compare_command")
                output = session.cmd_output(cmd)
                key_word = params.get("check_result_key_word")
                if key_word and key_word in output:
                    logging.debug("Guest's virtual disk %s works fine", disk)
                elif key_word:
                    raise error.TestFail("Files on guest os root fs and disk "
                                         "differ")
                else:
                    raise error.TestError("Param check_result_key_word was not "
                                          "specified! Please check your config")

            if params.get("umount_command"):
                cmd = params.get("show_mount_cmd")
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    disk = disk.strip()
                    cmd = params.get("umount_command") % (disk, disk)
                    error.context("unmounting test disk")
                    session.cmd(cmd)
    finally:
        if params.get("post_cmd"):
            cmd = params.get("post_cmd")
            session.cmd(cmd)
        session.close()
 def test_bad_qtree(self):
     """ Incorrect qtree """
     qtree = qemu_qtree.QtreeContainer()
     info = combine(qtree_header, "Very_bad_line", 1)
     self.assertRaises(ValueError, qtree.parse_info_qtree, info)
Exemple #15
0
def run(test, params, env):
    """
    Qemu multiqueue test for virtio-scsi controller:

    1) Boot up a guest with virtio-scsi device which support multi-queue and
       the vcpu and images number of guest should match the multi-queue number
    2) Check the multi queue option from monitor
    3) Check device init status in guest
    4) Load I/O in all targets
    5) Check the interrupt queues in guest

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def proc_interrupts_results(results, irqs_pattern):
        results_dict = {}
        cpu_count = 0
        cpu_list = []
        for line in results.splitlines():
            line = line.strip()
            if re.match("CPU0", line):
                cpu_list = re.findall(r"CPU\d+", line)
                cpu_count = len(cpu_list)
                continue
            if cpu_count > 0:
                irq_key = re.split(":", line)[0]
                if re.findall(irqs_pattern, re.split(":", line)[-1]):
                    results_dict[irq_key] = {}
                    content = line[len(irq_key) + 1:].strip()
                    if len(re.split(r"\s+", content)) < cpu_count:
                        continue
                    count = 0
                    irq_des = ""
                    for irq_item in re.split(r"\s+", content):
                        if count < cpu_count:
                            if count == 0:
                                results_dict[irq_key]["count"] = []
                            results_dict[irq_key]["count"].append(irq_item)
                        else:
                            irq_des += " %s" % irq_item
                        count += 1
                    results_dict[irq_key]["irq_des"] = irq_des.strip()
        if not results_dict:
            test.error("Couldn't find virtio request interrupts from procfs")
        return results_dict, cpu_list

    timeout = float(params.get("login_timeout", 240))
    host_cpu_num = utils_cpu.online_cpus_count()
    while host_cpu_num:
        num_queues = str(host_cpu_num)
        host_cpu_num &= host_cpu_num - 1
    params['smp'] = num_queues
    params['num_queues'] = num_queues
    images_num = int(num_queues)
    extra_image_size = params.get("image_size_extra_images", "512M")
    system_image = params.get("images")
    system_image_drive_format = params.get("system_image_drive_format",
                                           "virtio")
    params["drive_format_%s" % system_image] = system_image_drive_format

    error_context.context("Boot up guest with block devcie with num_queues"
                          " is %s and smp is %s" % (num_queues, params['smp']),
                          logging.info)
    for vm in env.get_all_vms():
        if vm.is_alive():
            vm.destroy()
    for extra_image in range(images_num):
        image_tag = "stg%s" % extra_image
        params["images"] += " %s" % image_tag
        params["image_name_%s" % image_tag] = "images/%s" % image_tag
        params["image_size_%s" % image_tag] = extra_image_size
        params["force_create_image_%s" % image_tag] = "yes"
        image_params = params.object_params(image_tag)
        env_process.preprocess_image(test, image_params, image_tag)

    params["start_vm"] = "yes"
    vm = env.get_vm(params["main_vm"])
    env_process.preprocess_vm(test, params, env, vm.name)
    session = vm.wait_for_login(timeout=timeout)

    if params.get("os_type") == "windows":
        driver_name = params["driver_name"]
        wmi_check_cmd = params["wmi_check_cmd"]
        pattern = params["pattern"]
        session = utils_test.qemu.windrv_check_running_verifier(session, vm, test,
                                                                driver_name, timeout)
        wmi_check_cmd = utils_misc.set_winutils_letter(session, wmi_check_cmd)
        error_context.context("Run wmi check in guest.", logging.info)
        output = session.cmd_output(wmi_check_cmd)
        queue_num = re.findall(pattern, output, re.M)
        try:
            if not queue_num or queue_num[0] != num_queues:
                test.fail("The queue_num from guest is not match with expected.\n"
                          "queue_num from guest is %s, expected is %s"
                          % (queue_num, num_queues))
        finally:
            session.close()
            return
    error_context.context("Check irqbalance service status", logging.info)
    output = session.cmd_output("systemctl status irqbalance")
    if not re.findall("Active: active", output):
        session.cmd("systemctl start irqbalance")
        output = session.cmd_output("systemctl status irqbalance")
        output = utils_misc.strip_console_codes(output)
        if not re.findall("Active: active", output):
            test.cancel("Can not start irqbalance inside guest. "
                        "Skip this test.")

    error_context.context("Pin vcpus to host cpus", logging.info)
    host_numa_nodes = utils_misc.NumaInfo()
    vcpu_num = 0
    for numa_node_id in host_numa_nodes.nodes:
        numa_node = host_numa_nodes.nodes[numa_node_id]
        for _ in range(len(numa_node.cpus)):
            if vcpu_num >= len(vm.vcpu_threads):
                break
            vcpu_tid = vm.vcpu_threads[vcpu_num]
            logging.debug("pin vcpu thread(%s) to cpu"
                          "(%s)" % (vcpu_tid,
                                    numa_node.pin_cpu(vcpu_tid)))
            vcpu_num += 1

    error_context.context("Verify num_queues from monitor", logging.info)
    qtree = qemu_qtree.QtreeContainer()
    try:
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
    except AttributeError:
        test.cancel("Monitor deson't supoort qtree skip this test")
    error_msg = "Number of queues mismatch: expect %s"
    error_msg += " report from monitor: %s(%s)"
    scsi_bus_addr = ""
    qtree_num_queues_full = ""
    qtree_num_queues = ""
    for node in qtree.get_nodes():
        if isinstance(node, qemu_qtree.QtreeDev) and (
                node.qtree['type'] == "virtio-scsi-device"):
            qtree_num_queues_full = node.qtree["num_queues"]
            qtree_num_queues = re.search(
                "[0-9]+",
                qtree_num_queues_full).group()
        elif isinstance(node, qemu_qtree.QtreeDev) and node.qtree['type'] == "virtio-scsi-pci":
            scsi_bus_addr = node.qtree['addr']

    if qtree_num_queues != num_queues:
        error_msg = error_msg % (num_queues,
                                 qtree_num_queues,
                                 qtree_num_queues_full)
        test.fail(error_msg)
    if not scsi_bus_addr:
        test.error("Didn't find addr from qtree. Please check the log.")
    error_context.context("Check device init status in guest", logging.info)
    irq_check_cmd = params.get("irq_check_cmd", "cat /proc/interrupts")
    output = session.cmd_output(irq_check_cmd)
    irq_name = params.get("irq_regex")
    prev_irq_results, _ = proc_interrupts_results(output, irq_name)
    logging.debug('The info of interrupters before testing:')
    for irq_watch in prev_irq_results.keys():
        logging.debug('%s : %s %s' % (irq_watch, prev_irq_results[irq_watch]['count'],
                                      prev_irq_results[irq_watch]['irq_des']))

    error_context.context("Pin the interrupters to vcpus", logging.info)
    cpu_select = 1
    for irq_id in prev_irq_results.keys():
        bind_cpu_cmd = "echo %s > /proc/irq/%s/smp_affinity" % \
                       (hex(cpu_select).replace('0x', ''), irq_id)
        cpu_select = cpu_select << 1
        session.cmd(bind_cpu_cmd)

    error_context.context("Load I/O in all targets", logging.info)
    get_dev_cmd = params.get("get_dev_cmd", "ls /dev/[svh]d*")
    output = session.cmd_output(get_dev_cmd)
    system_dev = re.findall(r"/dev/[svh]d\w+(?=\d+)", output)[0]
    dd_timeout = int(re.findall(r"\d+", extra_image_size)[0])
    fill_cmd = ""
    count = 0
    for dev in re.split(r"\s+", output):
        if not dev:
            continue
        if not re.findall(system_dev, dev):
            fill_cmd += " dd of=%s if=/dev/urandom bs=1M " % dev
            fill_cmd += "count=%s oflag=direct &" % dd_timeout
            count += 1
    if count != images_num:
        test.error("Disks are not all show up in system. Output "
                   "from the check command: %s" % output)
    # As Bug 1177332 exists, mq is not supported completely.
    # So don't considering performance currently, dd_timeout is longer.
    dd_timeout = dd_timeout * images_num * 2
    session.cmd(fill_cmd, timeout=dd_timeout)

    dd_thread_num = count
    while dd_thread_num:
        time.sleep(5)
        dd_thread_num = session.cmd_output("pgrep -x dd", timeout=dd_timeout)

    error_context.context("Check the interrupt queues in guest", logging.info)
    output = session.cmd_output(irq_check_cmd)
    next_irq_results, cpu_list = proc_interrupts_results(output, irq_name)
    logging.debug('The info of interrupters after testing :')
    for irq_watch in next_irq_results.keys():
        logging.debug('%s : %s %s' % (irq_watch, next_irq_results[irq_watch]['count'],
                                      next_irq_results[irq_watch]['irq_des']))
    irq_bit_map = 0
    for irq_watch in next_irq_results.keys():
        for index, count in enumerate(next_irq_results[irq_watch]["count"]):
            if (int(count) - int(prev_irq_results[irq_watch]["count"][index])) > 0:
                irq_bit_map |= 2 ** index

    error_msg = ""
    cpu_not_used = []
    for index, cpu in enumerate(cpu_list):
        if 2 ** index & irq_bit_map != 2 ** index:
            cpu_not_used.append(cpu)

    if cpu_not_used:
        logging.debug("Interrupt info from procfs:\n%s" % output)
        error_msg = " ".join(cpu_not_used)
        if len(cpu_not_used) > 1:
            error_msg += " are"
        else:
            error_msg += " is"
        error_msg += " not used during test. Please check debug log for"
        error_msg += " more information."
        test.fail(error_msg)
Exemple #16
0
def run(test, params, env):
    """
    PCI Devices test
    1) prints out the setup to be used
    2) boots the defined VM
    3) verifies monitor "info qtree" vs. internal representation
    4) verifies guest "lspci" vs. info qtree (Linux only)
    :note: Only PCI device properties are checked

    :param test: VirtTest instance
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment
    """
    error_context.context("Creating early names representation")
    env_process.preprocess_vm(test, params, env, params["main_vm"])
    vm = env.get_vm(params["main_vm"])
    qdev = vm.make_create_command()  # parse params into qdev
    if isinstance(qdev, tuple):
        qdev = qdev[0]

    error_context.context("Getting main PCI bus info")

    error_context.context("Processing test params")
    test_params = params['test_setup']
    test_devices = params['test_devices']
    test_device_type = params['test_device_type']
    if not params.get('pci_controllers'):
        params['pci_controllers'] = ''
    _lasts = [PCIBusInfo(qdev.get_by_properties({'aobject': 'pci.0'})[0])]
    _lasts[0].first = 7  # first 6 slots might be already occupied on pci.0
    _lasts[0].last -= 1  # last port is usually used by the VM
    use_buses = []
    names = {}
    logging.info("Test setup")
    for line in test_params.split('\\n'):
        _idx = 0
        out = ""
        for device in line.split('->'):
            device = device.strip()
            if device:
                if device == 'devices':
                    use_buses.append(_lasts[_idx])
                    out += "->(test_devices)"
                    break
                idx = names.get(device, 0) + 1
                name = "test_pci_%s%d" % (device, idx)
                names[device] = idx
                params, bus = add_bus(qdev, params, device, name, _lasts[_idx])
                # we inserted a device, increase the upper bus first idx
                _lasts[_idx].first += 1
                out += "->%s" % (name)
                _idx += 1
                if len(_lasts) > _idx:
                    _lasts = _lasts[:_idx]
                _lasts.append(bus)
            else:
                _idx += 1
                out += " " * (len(_lasts[_idx].name) + 2)
        logging.info(out)

    add_devices = {
        'first': add_devices_first,
        'all': add_devices_all
    }.get(test_devices, add_devices_random)
    add_device = {
        'uhci': add_device_usb_uhci,
        'ehci': add_device_usb_ehci,
        'xhci': add_device_usb_xhci,
        'virtio_disk': add_virtio_disk,
    }.get(test_device_type, add_device_random)
    name_idxs = {}
    for bus in use_buses:
        params, name_idxs = add_devices(params, name_idxs, bus, add_device)
    params['start_vm'] = 'yes'
    env_process.process(test, params, env, env_process.preprocess_image,
                        env_process.preprocess_vm)
    vm = env.get_vm(params["main_vm"])

    # PCI devices are initialized by firmware, which might require some time
    # to setup. Wait 5s before getting the qtree.
    time.sleep(5)
    qtree = qemu_qtree.QtreeContainer()

    error_context.context("Verify qtree vs. qemu devices", logging.info)
    _info_qtree = vm.monitor.info('qtree', False)
    qtree.parse_info_qtree(_info_qtree)
    info_qdev = process_qdev(vm.devices)
    info_qtree = process_qtree(qtree)
    errors = ""
    err = verify_qdev_vs_qtree(info_qdev, info_qtree)
    if err:
        logging.error(_info_qtree)
        logging.error(qtree.get_qtree().str_qtree())
        logging.error(vm.devices.str_bus_long())
        logging.error(err)
        errors += "qdev vs. qtree, "

    error_context.context("Verify VM booted properly.", logging.info)
    session = vm.wait_for_login()

    error_context.context("Verify lspci vs. qtree", logging.info)
    if params.get('lspci_cmd'):
        _info_lspci = session.cmd_output(params['lspci_cmd'])
        info_lspci = process_lspci(_info_lspci)
        err = verify_lspci(info_lspci, info_qtree[2])
        if err:
            logging.error(_info_lspci)
            logging.error(_info_qtree)
            logging.error(err)
            errors += "qtree vs. lspci, "

    error_context.context("Results")
    if errors:
        test.fail("Errors occurred while comparing %s. Please check"
                  " the log for details." % errors[:-2])
Exemple #17
0
def run(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params. (Optional)
    4) Create partition on those disks.
    5) Get disk dev filenames in guest.
    6) Format those disks in guest.
    7) Copy file into / out of those disks.
    8) Compare the original file and the copied file using md5 or fc comand.
    9) Repeat steps 3-5 if needed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    def _do_post_cmd(session):
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    def _get_disk_index(session, image_size, disk_indexs):
        list_disk_cmd = "echo list disk > disk && "
        list_disk_cmd += "echo exit >> disk && diskpart /s disk"
        disks = session.cmd_output(list_disk_cmd)
        size_type = image_size[-1] + "B"
        disk_size = ""

        if size_type == "MB":
            disk_size = image_size[:-1] + " MB"
        elif size_type == "GB" and int(image_size[:-1]) < 8:
            disk_size = str(int(image_size[:-1]) * 1024) + " MB"
        else:
            disk_size = image_size[:-1] + " GB"

        regex_str = 'Disk (\d+).*?%s.*?%s' % (disk_size, disk_size)
        for disk in disks.splitlines():
            if disk.startswith("  Disk"):
                o = re.findall(regex_str, disk, re.I | re.M)
                if o:
                    disk_indexs.append(o[0])

    error.context("Parsing test configuration", logging.info)
    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    stg_params += _add_param("drive_cache", params.get("stg_drive_cache"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                       stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in xrange(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm is False:
                raise error.TestError("Incorrect cfg: stg_params %s looks "
                                      "like range(..) but doesn't contain "
                                      "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', 'images/%s')
    for i in xrange(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.iteritems():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     utils.matrix_to_string(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    error.context("Start the guest with new disks", logging.info)
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        env_process.process_images(env_process.preprocess_image, test,
                                   vm_params)

    error.context("Start the guest with those disks", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    n_repeat = int(params.get("n_repeat", "1"))
    file_system = [_.strip() for _ in params.get("file_system").split()]
    cmd_timeout = float(params.get("cmd_timeout", 360))
    re_str = params["re_str"]
    black_list = params["black_list"].split()
    os_type = params["os_type"]
    stg_image_size = params.get("stg_image_size")
    disk_indexs = []

    have_qtree = True
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        have_qtree = False

    if (params.get("check_guest_proc_scsi") == "yes") and have_qtree:
        error.context("Verifying qtree vs. test params")
        err = 0
        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
        disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block())
        err += tmp1 + tmp2
        err += disks.generate_params()
        err += disks.check_disk_params(params)
        (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
            session.cmd_output('cat /proc/scsi/scsi'))
        err += tmp1 + tmp2

        if err:
            raise error.TestFail("%s errors occurred while verifying"
                                 " qtree vs. params" % err)
        if params.get('multi_disk_only_qtree') == 'yes':
            return

    try:
        cmd = params.get("clean_cmd")
        if cmd:
            session.cmd_status_output(cmd)

        if params.get("os_type") == "windows":
            error.context("Create partition on those disks", logging.info)
            # Get the disk index
            _get_disk_index(session, stg_image_size, disk_indexs)

            # Random select one file system from file_system
            index = random.randint(0, (len(file_system) - 1))
            fs_type = file_system[index].strip()
            for i in xrange(stg_image_num):
                utils_misc.format_windows_disk(session, disk_indexs[i], None,
                                               None, fs_type)

        error.context("Get disks dev filenames in guest", logging.info)
        cmd = params["list_volume_command"]
        s, output = session.cmd_status_output(cmd, timeout=cmd_timeout)
        if s != 0:
            raise error.TestFail("List volume command failed with cmd '%s'.\n"
                                 "Output is: %s\n" % (cmd, output))

        output = session.cmd_output(cmd, timeout=cmd_timeout)
        disks = re.findall(re_str, output)
        disks = map(string.strip, disks)
        disks.sort()
        logging.debug("Volume list that meet regular expressions: %s",
                      " ".join(disks))

        images = params.get("images").split()
        if len(disks) < len(images):
            logging.debug("disks: %s , images: %s", len(disks), len(images))
            raise error.TestFail("Fail to list all the volumes!")

        if params.get("os_type") == "linux":
            output = session.cmd_output("mount")
            li = re.findall(r"^/dev/(%s)\d*" % re_str, output, re.M)
            if li:
                black_list.extend(li)
        else:
            black_list.extend(utils_misc.get_winutils_vol(session))
        disks = set(disks)
        black_list = set(black_list)
        logging.info("No need to check volume '%s'", (disks & black_list))
        disks = disks - black_list
    except Exception:
        _do_post_cmd(session)
        raise

    try:
        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            error.context("Format those disks in guest", logging.info)
            for disk in disks:
                disk = disk.strip()
                error.context("Preparing disk: %s..." % disk)

                # Random select one file system from file_system
                index = random.randint(0, (len(file_system) - 1))
                fs = file_system[index].strip()
                cmd = params["format_command"] % (fs, disk)
                error.context("formatting test disk")
                session.cmd(cmd, timeout=cmd_timeout)
                cmd = params.get("mount_command")
                if cmd:
                    cmd = cmd % (disk, disk, disk)
                    session.cmd(cmd)

            error.context("Cope file into / out of those disks", logging.info)
            for disk in disks:
                disk = disk.strip()

                error.context("Performing I/O on disk: %s..." % disk)
                cmd_list = params["cmd_list"].split()
                for cmd_l in cmd_list:
                    cmd = params.get(cmd_l)
                    if cmd:
                        session.cmd(cmd % disk, timeout=cmd_timeout)

                cmd = params["compare_command"]
                key_word = params["check_result_key_word"]
                output = session.cmd_output(cmd)
                if key_word not in output:
                    raise error.TestFail("Files on guest os root fs and disk "
                                         "differ")

            if params.get("umount_command"):
                cmd = params.get("show_mount_cmd")
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    disk = disk.strip()
                    error.context("Unmounting disk: %s..." % disk)
                    cmd = params.get("umount_command") % (disk, disk)
                    session.cmd(cmd)
    finally:
        cmd = params.get("show_mount_cmd")
        if cmd:
            try:
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    error.context("Unmounting disk: %s..." % disk)
                    cmd = params["umount_command"] % (disk, disk)
                    session.cmd(cmd)
            except Exception, err:
                logging.warn("Get error when cleanup, '%s'", err)

        _do_post_cmd(session)
        session.close()
Exemple #18
0
def run(test, params, env):
    """
    Test hotplug of block devices.

    1) Boot up guest with/without block device(s).
    2) Hoplug block device and verify
    3) Do read/write data on hotplug block.
    4) Unplug block device and verify

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def find_image(image_name):
        """
        Find the path of the iamge.
        """
        image_params = params.object_params(image_name)
        o = storage.get_image_filename(image_params, data_dir.get_data_dir())
        return o

    def find_disk(vm, cmd):
        """
        Find all disks in guest.
        """
        if params.get("os_type") == "linux":
            pattern = params.get("get_disk_pattern", "^/dev/vd[a-z]*$")
        elif params.get("os_type") == "windows":
            pattern = r"^\d+"
            cmd = params.get("get_disk_index", "wmic diskdrive get index")
        else:
            test.cancel("Unsupported OS type '%s'" % params.get("os_type"))

        session = vm.wait_for_login(timeout=timeout)
        output = session.cmd_output_safe(cmd)
        disks = re.findall(pattern, output, re.M)
        session.close()
        return disks

    def get_new_disk(disk1, disk2):
        """
        Get the different disk between disk1 and disk2.
        """
        disk = list(set(disk2).difference(set(disk1)))
        return disk

    def unplug_device(vm, get_disk_cmd, device):
        """
        Unplug device
        """
        disks_before_unplug = find_disk(vm, get_disk_cmd)
        device.unplug(vm.monitor)
        device.verify_unplug("", vm.monitor)
        unplug_status = utils_misc.wait_for(
            lambda: len(
                get_new_disk(find_disk(vm, get_disk_cmd), disks_before_unplug))
            != 0, pause)
        return unplug_status

    img_list = params.get("images").split()
    img_format_type = params.get("img_format_type", "qcow2")
    pci_type = params.get("pci_type", "virtio-blk-pci")
    #sometimes, ppc can't get new plugged disk in 5s, so time to 10s
    pause = float(params.get("virtio_block_pause", 10.0))
    blk_num = int(params.get("blk_num", 1))
    repeat_times = int(params.get("repeat_times", 3))
    timeout = int(params.get("login_timeout", 360))
    disk_op_timeout = int(params.get("disk_op_timeout", 360))
    get_disk_cmd = params.get("get_disk_cmd")
    context_msg = "Running sub test '%s' %s"
    disk_index = params.objects("disk_index")
    disk_letter = params.objects("disk_letter")

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    for iteration in range(repeat_times):
        device_list = []
        controller_list = []
        controller_device_dict = {}
        error_context.context(
            "Hotplug block device (iteration %d)" % iteration, logging.info)

        sub_type = params.get("sub_type_before_plug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "before hotplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)

        for num in range(blk_num):
            device = qdevices.QDevice(pci_type)
            if params.get("need_plug") == "yes":
                disks_before_plug = find_disk(vm, get_disk_cmd)

                if params.get("need_controller", "no") == "yes":
                    controller_model = params.get("controller_model")
                    controller = qdevices.QDevice(
                        controller_model,
                        params={"id": "hotadded_scsi%s" % num})
                    bus_extra_param = params.get("bus_extra_params_%s" %
                                                 img_list[num + 1])
                    if bus_extra_param:
                        for item in bus_extra_param.split():
                            key, value = item.split("=", 1)
                            qdevice_params = {key: value}
                            controller.params.update(qdevice_params)
                    controller.hotplug(vm.monitor)
                    ver_out = controller.verify_hotplug("", vm.monitor)
                    if not ver_out:
                        err = "%s is not in qtree after hotplug" % controller_model
                        test.fail(err)
                    else:
                        controller_list.append(controller)

                drive = qdevices.QRHDrive("block%d" % num)
                drive.set_param("file", find_image(img_list[num + 1]))
                drive.set_param("format", img_format_type)
                drive_id = drive.get_param("id")
                drive.hotplug(vm.monitor)

                device.set_param("drive", drive_id)
                device.set_param("id", "block%d" % num)
                if params.get("need_controller", "no") == "yes" and bool(
                        random.randrange(2)):
                    device.set_param("bus", controller.get_param("id") + '.0')
                blk_extra_param = params.get("blk_extra_params_%s" %
                                             img_list[num + 1])
                if blk_extra_param:
                    for item in blk_extra_param.split():
                        key, value = item.split("=", 1)
                        device.set_param(key, value)
                device.hotplug(vm.monitor)
                ver_out = device.verify_hotplug("", vm.monitor)
                if not ver_out:
                    err = "%s is not in qtree after hotplug" % pci_type
                    test.fail(err)
                plug_status = utils_misc.wait_for(
                    lambda: len(
                        get_new_disk(disks_before_plug,
                                     find_disk(vm, get_disk_cmd))) != 0, pause)
                if plug_status:
                    disks_after_plug = find_disk(vm, get_disk_cmd)
                    new_disks = get_new_disk(disks_before_plug,
                                             disks_after_plug)
                else:
                    test.fail("Can't get new disks")
                if params.get("need_controller", "no") == "yes":
                    info_qtree = vm.monitor.info('qtree', False)
                    qtree = qemu_qtree.QtreeContainer()
                    qtree.parse_info_qtree(info_qtree)
                    for node in qtree.get_nodes():
                        if node.qtree.get("id") == device.get_param("id"):
                            try:
                                controller_id = node.parent.qtree.get(
                                    "id").split(".")[0]
                            except AttributeError:
                                test.fail("can't get parent of:\n%s" % node)
                            controller_device_dict.setdefault(
                                controller_id, []).append(device)
                            break
                    else:
                        test.fail("Can't find device '%s' in qtree" %
                                  device.get_param("id"))
            else:
                if params.get("drive_format") in pci_type:
                    get_disk_cmd += " | egrep -v '^/dev/[hsv]da[0-9]*$'"

                device.set_param("id", img_list[num + 1])
                new_disks = find_disk(vm, get_disk_cmd)

            device_list.append(device)
            if not new_disks:
                test.fail("Cannot find new disk after hotplug.")

            if params.get("need_plug") == "yes":
                disk = new_disks[0]
            else:
                disk = new_disks[num]

            session = vm.wait_for_login(timeout=timeout)
            if params.get("os_type") == "windows":
                if iteration == 0:
                    error_context.context("Format disk", logging.info)
                    utils_misc.format_windows_disk(session,
                                                   disk_index[num],
                                                   mountpoint=disk_letter[num])
            error_context.context("Check block device after hotplug.",
                                  logging.info)
            if params.get("disk_op_cmd"):
                if params.get("os_type") == "linux":
                    test_cmd = params.get("disk_op_cmd") % (disk, disk)
                elif params.get("os_type") == "windows":
                    test_cmd = params.get("disk_op_cmd") % (disk_letter[num],
                                                            disk_letter[num])
                    test_cmd = utils_misc.set_winutils_letter(
                        session, test_cmd)
                else:
                    test.cancel("Unsupported OS type '%s'" %
                                params.get("os_type"))

                status, output = session.cmd_status_output(
                    test_cmd, timeout=disk_op_timeout)
                if status:
                    test.fail("Check for block device failed "
                              "after hotplug, Output: %r" % output)
            session.close()

        sub_type = params.get("sub_type_after_plug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "after hotplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)
            if sub_type == "shutdown" and vm.is_dead():
                return

        sub_type = params.get("sub_type_before_unplug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "before unplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)

        error_context.context("Unplug block device (iteration %d)" % iteration,
                              logging.info)
        for controller in controller_list:
            controller_id = controller.get_param("id")
            for device in controller_device_dict.get(controller_id, []):
                unplug_status = unplug_device(vm, get_disk_cmd, device)
                if not unplug_status:
                    test.fail("Failed to unplug disks '%s'" %
                              device.get_param("id"))
                device_list.remove(device)
            controller.unplug(vm.monitor)
        for device in device_list:
            unplug_status = unplug_device(vm, get_disk_cmd, device)
            if not unplug_status:
                test.fail("Failed to unplug disks '%s'" %
                          device.get_param("id"))

        sub_type = params.get("sub_type_after_unplug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "after unplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)
        params["drive_serial"] = drive_serial
        params["start_vm"] = "yes"

        vm = params["main_vm"]
        vm_params = params.object_params(vm)
        env_process.preprocess_vm(test, vm_params, env, vm)
        vm = env.get_vm(vm)
    else:
        vm = env.get_vm(params["main_vm"])

    vm.verify_alive()
    timeout = int(params.get("login_timeout", 360))
    chk_timeout = int(params.get("chk_timeout", 240))
    session = vm.wait_for_login(timeout=timeout)
    qtree = qemu_qtree.QtreeContainer()
    try:
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
    except AttributeError:  # monitor doesn't support info qtree
        qtree = None

    logging.info("Starting physical resources check test")
    logging.info("Values assigned to VM are the values we expect "
                 "to see reported by the Operating System")
    # Define a failure counter, as we want to check all physical
    # resources to know which checks passed and which ones failed
    n_fail = []

    # We will check HDs with the image name
    image_name = storage.get_image_filename(params, data_dir.get_data_dir())
Exemple #20
0
def run(test, params, env):
    """
    Qemu multiqueue test for virtio-scsi controller:

    1) Boot up a guest with virtio-scsi device which support multi-queue and
       the vcpu and images number of guest should match the multi-queue number
    2) Check the multi queue option from monitor
    3) Check device init status in guest
    4) Load I/O in all targets
    5) Check the interrupt queues in guest

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def proc_interrupts_results(results):
        results_dict = {}
        cpu_count = 0
        cpu_list = []
        for line in results.splitlines():
            line = line.strip()
            if re.match("CPU0", line):
                cpu_list = re.findall("CPU\d+", line)
                cpu_count = len(cpu_list)
                continue
            if cpu_count > 0:
                irq_key = re.split(":", line)[0]
                results_dict[irq_key] = {}
                content = line[len(irq_key) + 1:].strip()
                if len(re.split("\s+", content)) < cpu_count:
                    continue
                count = 0
                irq_des = ""
                for irq_item in re.split("\s+", content):
                    if count < cpu_count:
                        if count == 0:
                            results_dict[irq_key]["count"] = []
                        results_dict[irq_key]["count"].append(irq_item)
                    else:
                        irq_des += " %s" % irq_item
                    count += 1
                results_dict[irq_key]["irq_des"] = irq_des.strip()
        return results_dict, cpu_list

    timeout = float(params.get("login_timeout", 240))
    host_cpu_num = local_host.LocalHost().get_num_cpu()
    while host_cpu_num:
        num_queues = str(host_cpu_num)
        host_cpu_num &= host_cpu_num - 1
    params['smp'] = num_queues
    params['num_queues'] = num_queues
    images_num = int(num_queues)
    extra_image_size = params.get("image_size_extra_images", "512M")
    system_image = params.get("images")
    system_image_drive_format = params.get("system_image_drive_format", "ide")
    params["drive_format_%s" % system_image] = system_image_drive_format
    dev_type = params.get("dev_type", "i440FX-pcihost")

    error.context("Boot up guest with block devcie with num_queues"
                  " is %s and smp is %s" % (num_queues, params['smp']),
                  logging.info)
    for vm in env.get_all_vms():
        if vm.is_alive():
            vm.destroy()
    for extra_image in range(images_num):
        image_tag = "stg%s" % extra_image
        params["images"] += " %s" % image_tag
        params["image_name_%s" % image_tag] = "images/%s" % image_tag
        params["image_size_%s" % image_tag] = extra_image_size
        params["force_create_image_%s" % image_tag] = "yes"
        image_params = params.object_params(image_tag)
        env_process.preprocess_image(test, image_params, image_tag)

    params["start_vm"] = "yes"
    vm = env.get_vm(params["main_vm"])
    env_process.preprocess_vm(test, params, env, vm.name)
    session = vm.wait_for_login(timeout=timeout)

    error.context("Check irqbalance service status", logging.info)
    output = session.cmd_output("systemctl status irqbalance")
    if not re.findall("Active: active", output):
        session.cmd("systemctl start irqbalance")
        output = session.cmd_output("systemctl status irqbalance")
        output = utils_misc.strip_console_codes(output)
        if not re.findall("Active: active", output):
            raise error.TestNAError("Can not start irqbalance inside guest. "
                                    "Skip this test.")

    error.context("Pin vcpus to host cpus", logging.info)
    host_numa_nodes = utils_misc.NumaInfo()
    vcpu_num = 0
    for numa_node_id in host_numa_nodes.nodes:
        numa_node = host_numa_nodes.nodes[numa_node_id]
        for _ in range(len(numa_node.cpus)):
            if vcpu_num >= len(vm.vcpu_threads):
                break
            vcpu_tid = vm.vcpu_threads[vcpu_num]
            logging.debug("pin vcpu thread(%s) to cpu"
                          "(%s)" % (vcpu_tid,
                                    numa_node.pin_cpu(vcpu_tid)))
            vcpu_num += 1

    error.context("Verify num_queues from monitor", logging.info)
    qtree = qemu_qtree.QtreeContainer()
    try:
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
    except AttributeError:
        raise error.TestNAError("Monitor deson't supoort qtree "
                                "skip this test")
    error_msg = "Number of queues mismatch: expect %s"
    error_msg += " report from monitor: %s(%s)"
    scsi_bus_addr = ""
    for qdev in qtree.get_qtree().get_children():
        if qdev.qtree["type"] == dev_type:
            for pci_bus in qdev.get_children():
                for pcic in pci_bus.get_children():
                    if pcic.qtree["class_name"] == "SCSI controller":
                        qtree_queues = pcic.qtree["num_queues"].split("(")[0]
                        if qtree_queues.strip() != num_queues.strip():
                            error_msg = error_msg % (num_queues,
                                                     qtree_queues,
                                                     pcic.qtree["num_queues"])
                            raise error.TestFail(error_msg)
                    if pcic.qtree["class_name"] == "SCSI controller":
                        scsi_bus_addr = pcic.qtree['addr']
                        break

    if not scsi_bus_addr:
        raise error.TestError("Didn't find addr from qtree. Please check "
                              "the log.")
    error.context("Check device init status in guest", logging.info)
    init_check_cmd = params.get("init_check_cmd", "dmesg | grep irq")
    output = session.cmd_output(init_check_cmd)
    irqs_pattern = params.get("irqs_pattern", "%s:\s+irq\s+(\d+)")
    irqs_pattern = irqs_pattern % scsi_bus_addr
    irqs_watch = re.findall(irqs_pattern, output)
    # As there are several interrupts count for virtio device:
    # config, control, event and request. And the each queue have
    # a request count. So the totally count for virtio device should
    # equal to queus number plus three.
    if len(irqs_watch) != 3 + int(num_queues):
        raise error.TestFail("Failed to check the interrupt ids from dmesg")
    irq_check_cmd = params.get("irq_check_cmd", "cat /proc/interrupts")
    output = session.cmd_output(irq_check_cmd)
    irq_results, _ = proc_interrupts_results(output)
    for irq_watch in irqs_watch:
        if irq_watch not in irq_results:
            raise error.TestFail("Can't find irq %s from procfs" % irq_watch)

    error.context("Load I/O in all targets", logging.info)
    get_dev_cmd = params.get("get_dev_cmd", "ls /dev/[svh]d*")
    output = session.cmd_output(get_dev_cmd)
    system_dev = re.findall("[svh]d(\w+)\d+", output)[0]
    dd_timeout = int(re.findall("\d+", extra_image_size)[0])
    fill_cmd = ""
    count = 0
    for dev in re.split("\s+", output):
        if not dev:
            continue
        if not re.findall("[svh]d%s" % system_dev, dev):
            fill_cmd += " dd of=%s if=/dev/urandom bs=1M " % dev
            fill_cmd += "count=%s &&" % dd_timeout
            count += 1
    if count != images_num:
        raise error.TestError("Disks are not all show up in system. Output "
                              "from the check command: %s" % output)
    fill_cmd = fill_cmd.rstrip("&&")
    session.cmd(fill_cmd, timeout=dd_timeout)

    error.context("Check the interrupt queues in guest", logging.info)
    output = session.cmd_output(irq_check_cmd)
    irq_results, cpu_list = proc_interrupts_results(output)
    irq_bit_map = 0
    for irq_watch in irqs_watch:
        if "request" in irq_results[irq_watch]["irq_des"]:
            for index, count in enumerate(irq_results[irq_watch]["count"]):
                if int(count) > 0:
                    irq_bit_map |= 2 ** index

    cpu_count = 0
    error_msg = ""
    cpu_not_used = []
    for index, cpu in enumerate(cpu_list):
        if 2 ** index & irq_bit_map != 2 ** index:
            cpu_not_used.append(cpu)

    if cpu_not_used:
        logging.debug("Interrupt info from procfs:\n%s" % output)
        error_msg = " ".join(cpu_not_used)
        if len(cpu_not_used) > 1:
            error_msg += " are"
        else:
            error_msg += " is"
        error_msg += " not used during test. Please check debug log for"
        error_msg += " more information."
        raise error.TestFail(error_msg)