def hotplug_path_disk(vm, path_dev):
     """Hotplug passthrough disk."""
     error_context.context("Hotplug passthrough device", logging.info)
     vm.params["image_name_stg0"] = path_dev
     plug = BlockDevicesPlug(vm)
     plug.hotplug_devs_serial()
     return plug[0]
 def operation_hotplug():
     """
     relevant operation:
     unplug throttle group
     plug throttle group
     add disk into exist throttle group
     add disk into plugged throttle group
     """
     opts = json.loads(params.get("throttle_group_parameters_group2", "{}"))
     tgm.delete_throttle_group("group2")
     tgm.add_throttle_group("group2", opts)
     plug = BlockDevicesPlug(vm)
     plug.hotplug_devs_serial("stg3")
     plug.hotplug_devs_serial("stg4")
Esempio n. 3
0
def run(test, params, env):
    """
    Test hot plug and unplug NVMe device.

    Steps:
        1. Install guest with local filesystem.
        2. Hot plug NVMe device to guest.
        3. Check if the NVMe device exists in qemu side.
        4. Check if the NVMe has been successfully added to guest.
        5. Run fio in the hot plugged NVMe device in guest.
        6. Unplug the NVMe device.
        7. Check if the NVMe device still exists.
        8. Check if the NVMe has been successfully removed from guest.
        9. Reboot guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    unattended_install.run(test, params, env)

    if params.get('remove_options'):
        for option in params.get('remove_options').split():
            del params[option]
    params['cdroms'] = params.get('default_cdroms')

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

    plug = BlockDevicesPlug(vm)
    plug.hotplug_devs_serial()
    target = '/dev/%s' % plug[0]
    os_type = params['os_type']
    data_img_size = params.get('image_size_%s' % params.get('data_img_tag'))
    if os_type == 'windows':
        utils_disk.update_windows_disk_attributes(session, plug[0])
        drive_letter = utils_disk.configure_empty_disk(session, plug[0],
                                                       data_img_size,
                                                       os_type)[0]
        target = r'%s\:\\%s' % (drive_letter, params.get('fio_filename'))
    fio = generate_instance(params, vm, 'fio')
    for option in params['fio_options'].split(';'):
        fio.run('--filename=%s %s' % (target, option))
    plug.unplug_devs_serial()
    vm.reboot(session)
Esempio n. 4
0
 def hotplug_unplug_block_repeatedly(times):
     """Hot plug then unplug block devices repeatedly."""
     vm_pid = vm.get_pid()
     plug = BlockDevicesPlug(vm)
     info = ('The number of AIO file descriptors is %s '
             'after %s block device.')
     for i in range(times):
         logging.info('Iteration %d: Hot plug then unplug '
                      'block device.', i)
         plug.hotplug_devs_serial()
         orig_fds_num = _get_aio_fds_num(vm_pid)
         logging.info(info, orig_fds_num, 'hot plugging')
         plug.unplug_devs_serial()
         new_fds_num = _get_aio_fds_num(vm_pid)
         logging.info(info, new_fds_num, 'unplugging')
         if new_fds_num != orig_fds_num:
             test.fail('The the number of AIO descriptors is '
                       'changed, from %s to %s.' %
                       (orig_fds_num, new_fds_num))
Esempio n. 5
0
def run(test, params, env):
    """
    Test plug cdrom device.
      Scenario "with_hotplug":
        1) Start VM with virtio-scsi-pci (system disk).
        2) For windows, Check whether vioscsi.sys verifier enabled in guest.
        3) Hot plug a virtio-scsi cdrom via qmp.
        4) Check in qmp monitor.
        5) Check in VM, the cdrom show in system computer.
        6) For linux, check guest kernel logs.
        7) Reboot then shutdown guest.

      Scenario "with_unplug":
        1) Boot a guest with virtio-scsi CD-ROM normally.
        2) Check block in QMP.
        3) Delete the virtio-scsi CD-ROM by qmp.
        4) Reboot then shutdown guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _shutdown_vm(session):
        """Shutdown vm."""
        shutdown_command = params["shutdown_cmd"]
        error_context.context("Shutting down VM by \"%s\"." % shutdown_command,
                              logging.info)
        session.sendline(shutdown_command)
        if not vm.wait_for_shutdown():
            test.fail("Failed to shutdown vm.")

    def _reboot_vm(session):
        """Reboot vm."""
        reboot_cmd = params["reboot_cmd"]
        error_context.context("Rebooting VM by \"%s\"." % reboot_cmd,
                              logging.info)
        session.sendline(reboot_cmd)
        return vm.wait_for_login(timeout=360)

    def _check_cdrom_info_by_qmp(items):
        """Check the cdrom device info by qmp."""
        error_context.context(
            'Check if the info \"%s\" are match with the output of query-block.'
            % str(items), logging.info)
        blocks = vm.monitor.info_block()
        for key, val in items.items():
            if (key == 'device'
                    and val == dev_id) or blocks[dev_id][key] == val:
                continue
            test.fail('No such \"%s: %s\" in the output of query-block.' %
                      (key, val))

    def _check_cdrom_info_by_guest():
        """Check cdrom info inside guest."""
        logging.info('Check if the file \"%s\" is in the cdrom.' % iso_name)
        cmd_map = {
            'linux': 'mount /dev/sr{0} /mnt && ls /mnt && umount /mnt',
            'windows': 'dir {0}:\\'
        }
        if is_windows:
            output = session.cmd(
                "wmic logicaldisk where (Description='CD-ROM Disc') get DeviceID"
            )
            letters = re.findall(r'(\w):', output, re.M)
            if not letters:
                test.error('No available CD-ROM devices: %s' % output)
        for index in range(len(cdroms)):
            if iso_name in session.cmd(cmd_map[os_type].format(
                    letters[index] if is_windows else index)).lower():
                break
        else:
            test.fail('No such the file \"%s\" in cdrom.' % iso_name)

    def _check_cdrom_info(items):
        _check_cdrom_info_by_qmp(items)
        _check_cdrom_info_by_guest()

    os_type = params['os_type']
    cdroms = params['cdroms'].split()
    is_windows = os_type == 'windows'
    action = HOTPLUG if params.get('do_hotplug', 'no') == 'yes' else UNPLUG

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=360)

    if is_windows:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, params['driver_name'], 300)

    plug = BlockDevicesPlug(vm)
    for cdrom in cdroms:
        cdrom_params = params.object_params(cdrom)
        items_checked = ast.literal_eval(cdrom_params.get('items_checked'))
        dev_id = items_checked['device']
        iso_name = cdrom_params.get('iso_name')
        if action == UNPLUG:
            _check_cdrom_info(items_checked)
        getattr(plug, '%s_devs_serial' % action)(cdrom)
        if action == HOTPLUG:
            _check_cdrom_info(items_checked)

    _shutdown_vm(_reboot_vm(session))
Esempio n. 6
0
def run(test, params, env):
    """
    Test to resize block device then unplug it.

    Steps:
        1) Boot the guest with a data disk.
        2) For Windows: Check whether viostor.sys verifier enabled in
           guest.
        3) Resize the data disk, e.g, enlarge to 10GB; shrink to 1GB.
        4) Check the data disk in guest whether is enlarge or shrink
           to the excepted size.
        5) Reboot guest.
        6) Unplug the data disk.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _change_vm_power():
        """ Change the vm power. """
        method, command = params['command_opts'].split(',')
        logging.info('Sending command(%s): %s' % (method, command))
        if method == 'shell':
            power_session = vm.wait_for_login()
            power_session.sendline(command)
        else:
            getattr(vm.monitor, command)()
        if shutdown_vm:
            if not utils_misc.wait_for(
                    lambda: vm.monitor.get_event("SHUTDOWN"), 600):
                raise test.fail("Not received SHUTDOWN QMP event.")

    def _check_vm_status(timeout=600):
        """ Check the status of vm. """
        action = 'shutdown' if shutdown_vm else 'login'
        if not getattr(vm, 'wait_for_%s' % action)(timeout=timeout):
            test.fail('Failed to %s vm.' % action)

    def _block_resize(dev):
        """ Resize the block size. """
        resize_size = int(
            float(
                normalize_data_size(
                    re.search(r'(\d+\.?(\d+)?\w)',
                              params['resize_size']).group(1), "B")))
        size = str(data_image_size +
                   resize_size) if resize_op == ENLARGE else str(
                       data_image_size - resize_size)
        logging.info("Start to %s image '%s' to %sB." %
                     (resize_op, data_image, size))
        if vm.check_capability(Flags.BLOCKDEV):
            args = (None, size, dev)
        else:
            args = (dev, size)
        vm.monitor.block_resize(*args)
        return size

    def _check_img_size(size):
        """ Check the size of image after resize. """
        img = qemu_storage.QemuImg(data_image_params, data_dir.get_data_dir(),
                                   data_image)
        if json.loads(img.info(True, 'json'))['virtual-size'] != int(size):
            test.fail('The virtual size is not equal to %sB after %s.' %
                      (size, resize_op))

    shutdown_vm = params.get('shutdown_vm', 'no') == 'yes'
    reboot = params.get('reboot_vm', 'no') == 'yes'
    data_image = params.get("images").split()[-1]
    data_image_params = params.object_params(data_image)
    data_image_size = int(
        float(normalize_data_size(data_image_params.get("image_size"), "B")))
    data_image_filename = storage.get_image_filename(data_image_params,
                                                     data_dir.get_data_dir())
    resize_op = SHRINK if '-' in params['resize_size'] else ENLARGE
    is_windows = params['os_type'] == 'windows'

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login()
    plug = BlockDevicesPlug(vm)

    if is_windows:
        utils_test.qemu.windrv_check_running_verifier(session, vm, test,
                                                      params['driver_name'],
                                                      300)
    _check_img_size(_block_resize(vm.get_block({'file': data_image_filename})))

    if reboot:
        _change_vm_power()
        _check_vm_status()
    plug.unplug_devs_serial()
Esempio n. 7
0
def run(test, params, env):
    """
    Test hotplug of block devices.

    1) Boot up guest with virtio-blk or virtio-scsi system disk.
    2) Hoplug a virtio-blk or virtio-scsi data disk by qmp.
    3) Do read/write data on hotplug block.
    4) Unplug block device during serving block io, then verify devices.
    5) repeat step2~step4 100 times.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _check_iozone_status():
        ck_session = vm.wait_for_login(timeout=360)
        if not utils_misc.wait_for(lambda: check_cmd[os_type].split(
        )[-1].lower() in ck_session.cmd_output(check_cmd[os_type]).lower(),
                                   180,
                                   step=3.0):
            test.fail("Iozone is not alive!")
        ck_session.close()

    def _run_iozone_background():
        logging.info("Start iozone under background.")
        thread = utils_misc.InterruptedThread(
            iozone.run, (params['iozone_options'].format(mount_point),
                         float(params['iozone_timeout'])))
        thread.start()
        _check_iozone_status()
        return thread

    check_cmd = {
        'linux': 'pgrep -lx iozone',
        'windows': 'TASKLIST /FI "IMAGENAME eq IOZONE.EXE'
    }
    os_type = params['os_type']
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=360)

    iozone = generate_instance(params, vm, 'iozone')
    plug = BlockDevicesPlug(vm)
    need_format = True
    try:
        for i in range(int(params['repeat_time'])):
            logging.info('Start to run testing.(iteration: %d).', (i + 1))
            plug.hotplug_devs_serial()
            if need_format:
                if os_type == 'windows':
                    utils_disk.update_windows_disk_attributes(session, plug[0])
                mount_point = utils_disk.configure_empty_disk(
                    session, plug[0], params['image_size_stg0'], os_type)[0]
                if os_type == 'windows':
                    need_format = False
            iozone_thread = _run_iozone_background()
            time.sleep(float(params['sleep_time']))
            _check_iozone_status()
            plug.unplug_devs_serial()
            iozone_thread.join(suppress_exception=True)
    finally:
        iozone.clean(force=True)
        session.close()
Esempio n. 8
0
def run(test, params, env):
    """
    Boot vm with virtio device:virtio-blk-pci, virtio-scsi-pci, virtio-net-pci
    and use aer=on for virtio devices.

    1) Boot guest with virtio-blk-pci, virtio-scsi-pci, virtio-net-pci device,
       and use aer=on,ats=on for virtio devices.
    2) check if aer and ats capabilitie in guest os

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def get_pci_addr_by_devid(dev_id):
        """
        Get pci address by device id.
        """
        def _get_device_by_devid(devices, dev_id):
            """
            Get device info with device id from 'info pci' output.
            """
            device_found = {}
            for dev in devices:
                if dev['qdev_id'] == dev_id:
                    device_found = dev
                    break
                elif dev['class_info'].get('desc') == 'PCI bridge':
                    pci_bridge_devices = dev['pci_bridge'].get('devices')
                    if not pci_bridge_devices:
                        continue
                    device_found = _get_device_by_devid(
                        pci_bridge_devices, dev_id)
                    if device_found:
                        break
            return device_found

        dev_addr = ''
        dev_addr_fmt = '%02d:%02d.%d'
        pci_info = vm.monitor.info('pci', debug=False)
        device = _get_device_by_devid(pci_info[0]['devices'], dev_id)
        if device:
            dev_addr = dev_addr_fmt % (device['bus'], device['slot'],
                                       device['function'])
        return dev_addr

    def check_dev_cap_in_guest(dev_id, capbilities):
        """
        Check the specified device's capabilities in guest os

        :params dev_id: device id in qemu command line
        :params capbilities: the capabilities list that expected to be found
        :return True if get all the capabilities, else False
        """

        dev_addr = get_pci_addr_by_devid(dev_id)
        for cap in capbilities:
            check_cmd = "lspci -vvv -s %s | grep '%s'" % (dev_addr, cap)
            if session.cmd_status(check_cmd) != 0:
                logging.error("Failed to get capability '%s' for device %s",
                              cap, dev_id)
                return False
        return True

    if params.object_params('qmpmonitor1').get('monitor_type') == 'human':
        test.cancel("Please run test with qmp monitor")

    vm = env.get_vm(params["main_vm"])
    session = vm.wait_for_login()
    capabilities = params['capabilities'].split(',')
    images = params.objects('images')

    dev_ids = []
    blk_image = images[1]
    blk_dev = vm.devices.get_by_qid(blk_image)[0]
    blk_dev_id = blk_dev.params['id']
    dev_ids.append(blk_dev_id)

    scsi_dev = vm.devices.get_by_params({'driver': 'virtio-scsi-pci'})[0]
    scsi_dev_id = scsi_dev.params['id']
    dev_ids.append(scsi_dev_id)

    nic_id = vm.virtnet[0].device_id
    nic_dev = vm.devices.get_by_qid(nic_id)[0]
    nic_dev_id = nic_dev.params['id']
    dev_ids.append(nic_dev_id)

    try:
        for dev_id in dev_ids:
            if not check_dev_cap_in_guest(dev_id, capabilities):
                test.fail('Check capabilities %s for device %s failed' %
                          (capabilities, dev_id))

        plug = BlockDevicesPlug(vm)
        for img in params.get("hotplug_images", "").split():
            plug.unplug_devs_serial(img)
            plug.hotplug_devs_serial(img)
            blk_dev = vm.devices.get_by_qid(img)[0]
            blk_dev_id = blk_dev.params['id']
            if not check_dev_cap_in_guest(blk_dev_id, capabilities):
                test.fail('Check capabilities %s for device %s failed' %
                          (capabilities, blk_dev_id))
    finally:
        session.close()
Esempio n. 9
0
def utils_test(test, params, env, vm, session):
    """
    :param test:
    :param params:
    :param env:
    :param vm:
    :param session:
    :return:
    """
    logging.info(test, params, env, vm, session)
    tgm = ThrottleGroupManager(vm)

    logging.info("query_throttle_group group1")
    tgm.get_throttle_group_props("group1")

    logging.info("query_throttle_group group4")
    tgm.get_throttle_group_props("group4")
    # stg2 nonexist
    tgm.get_throttle_group_props("stg2")
    # group5 nonexist
    logging.info("delete_throttle_group group5")
    tgm.delete_throttle_group("group5")

    logging.info("query_throttle_group group3")
    tgm.get_throttle_group_props("group3")

    # add group3 failed
    logging.info("add_throttle_group group3")
    try:
        tgm.add_throttle_group("group3", {"iopsx-total": 50})
    except Exception as err:
        logging.error(err)

    # add group3 succeed
    tgm.add_throttle_group("group3", {"iops-total": 50})
    out = tgm.get_throttle_group_props("group3")
    logging.info(out)

    logging.info("get_throttle_group group3")
    dev = tgm.get_throttle_group("group3")

    plug = BlockDevicesPlug(vm)

    # hotplug stg7
    logging.info("stg7 hot-plug")
    plug.hotplug_devs_serial("stg7")
    logging.info(vm.devices.str_bus_short())

    # hotplug stg6
    logging.info("stg6 hot-plug")
    plug.hotplug_devs_serial("stg6")
    logging.info(vm.devices.str_bus_short())

    logging.info("change stg6 from group3 to group1")
    tgm.change_throttle_group("stg6", "group1")
    logging.info("change stg3 from group1 to group2")
    tgm.change_throttle_group("stg3", "group2")
    logging.info(vm.devices.str_bus_short())
    logging.info("change stg3 from group2 to group1")
    tgm.change_throttle_group("stg3", "group1")
    logging.info(vm.devices.str_bus_short())
    vm.monitor.info("block")

    logging.info("stg6 hot-unplug")
    plug.unplug_devs_serial("stg6")
    logging.info(vm.devices.str_bus_short())

    logging.info("update throttle group")
    tgm.update_throttle_group("group3", {"bps-total": 150})
    out = tgm.get_throttle_group_props("group3")
    logging.info(out)
    logging.info(dev.raw_limits)

    logging.info("throttle group hot-unplug")
    tgm.delete_throttle_group("group3")
    logging.info(vm.devices.str_bus_short())
    tgm.get_throttle_group("group3")
    logging.info("==================")

    # image hotplug-unplug
    logging.info("unplug stg1 ")
    plug.unplug_devs_serial("stg1")
    logging.info(vm.devices.str_bus_short())

    logging.info("plug stg1")
    plug.hotplug_devs_serial("stg1")
    logging.info(vm.devices.str_bus_short())

    logging.info("unplug stg1")
    plug.unplug_devs_serial("stg1")
    logging.info(vm.devices.str_bus_short())

    logging.info("==================")
    logging.info("plug stg5 belong to no group")
    plug.hotplug_devs_serial("stg5")
    logging.info(vm.devices.str_bus_short())

    logging.info("unplug stg5")
    plug.unplug_devs_serial("stg5")
    logging.info(vm.devices.str_bus_short())
    logging.info("sleep 3...")
    time.sleep(3)

    logging.info("test simple_hotplug ...")
    image_name = "stg1"
    image_params = params.object_params(image_name)
    # include blockdevs and devices
    stg_a_devs = vm.devices.images_define_by_params(image_name, image_params,
                                                    'disk')
    for dev in stg_a_devs:
        vm.devices.simple_hotplug(dev, vm.monitor)

    image_name = "stg5"
    image_params = params.object_params(image_name)
    stg_b_devs = vm.devices.images_define_by_params(image_name, image_params,
                                                    'disk')
    for dev in stg_b_devs:
        vm.devices.simple_hotplug(dev, vm.monitor)
    logging.info(vm.devices.str_bus_short())
    time.sleep(3)

    logging.info("test simple_unplug ...")
    vm.devices.simple_unplug(stg_a_devs[-1], vm.monitor)
    vm.devices.simple_unplug(stg_b_devs[-1], vm.monitor)
    logging.info(vm.devices.str_bus_short())
    time.sleep(3)
Esempio n. 10
0
def run(test, params, env):
    """
    Test the virtio scsi block device with virtio-scsi-pci.hotplug=on
    or off.
      Steps:
        1. Start VM with virtio-scsi-pci(system disk).
        2. Check whether vioscsi.sys verifier enabled in windows guest.
        3. Hotplug a virtio-scsi disk with virtio-scsi-pci.hotplug=off
           via qmp.
        4. Check the new disk in guest.
        5. Rescan the scsi bus in the guest and recheck the disk.
        6. Retest the step 3-4 with hotplug=on specified and then
           hot-unplug it.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def list_all_disks(session):
        """List all disks inside guest."""
        if is_linux:
            return utils_misc.list_linux_guest_disks(session)
        return set(session.cmd('wmic diskdrive get index').split()[1:])

    def _get_scsi_host_id(session):
        logging.info("Get the scsi host id which is hot plugged.")
        output = session.cmd("dmesg | grep \"scsi host\" | "
                             "awk 'END{print}' | awk '{print $4}'")
        return re.search(r'(\d+)', output).group(1)

    def _rescan_hba_controller_linux(session):
        session.cmd('echo "- - -" > /sys/class/scsi_host/host%s/scan' %
                    _get_scsi_host_id(session))

    def _rescan_hba_controller_windows(session):
        session.cmd(
            'echo rescan > {0} && echo exit >> {0} && diskpart / {0} '
            '&& del /f {0}'.format('diskpart_script'), 300)

    def rescan_hba_controller(session):
        """Rescan the scsi hba controller."""
        error_context.context("Rescan the scsi hba controller.", logging.info)
        if is_linux:
            _rescan_hba_controller_linux(session)
        else:
            _rescan_hba_controller_windows(session)

    is_linux = params['os_type'] == 'linux'
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=360)

    if not is_linux:
        session = qemu.windrv_check_running_verifier(session, vm, test,
                                                     params['driver_name'],
                                                     360)

    orig_disks = list_all_disks(session)
    plug = BlockDevicesPlug(vm)
    plug.hotplug_devs_serial(interval=int(params['hotplug_interval']))
    if params['need_rescan_hba'] == 'yes':
        if utils_misc.wait_for(
                lambda: bool(list_all_disks(session) - orig_disks), 30,
                step=3):
            logging.debug('The all disks: %s.', list_all_disks(session))
            test.fail('Found a new disk with virtio-scsi-pci.hotplug=off '
                      'before rescan scsi hba controller.')
        rescan_hba_controller(session)
    plug.unplug_devs_serial()
def run(test, params, env):
    """
    Test hotplug of block devices.

    1) Boot up a guest with a system disk and a data disk.
    2) Do IO stress test on data disk.
    3) Unplug data disk during io stress.
    4) Reboot guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _check_stress_status():
        """ Check the status of stress. """
        ck_session = vm.wait_for_login(timeout=360)
        proc_name = check_cmd[os_type].split()[-1]
        cmd = check_cmd[os_type]
        if not utils_misc.wait_for(lambda: proc_name.lower() in ck_session.
                                   cmd_output(cmd).lower(),
                                   180,
                                   step=3.0):
            test.fail("%s is not alive!" % proc_name)
        ck_session.close()

    def _get_data_disk():
        """ Get the data disk. """
        extra_params = params["blk_extra_params_%s" %
                              params['images'].split()[-1]]
        if windows:
            return sorted(
                session.cmd('wmic diskdrive get index').split()[1:])[-1]
        drive_id = re.search(r"(serial|wwn)=(\w+)", extra_params,
                             re.M).group(2)
        return utils_misc.get_linux_drive_path(session, drive_id)

    def _run_stress_background():
        """ Run stress under background. """
        logging.info("Start io stress under background.")
        thread = utils_misc.InterruptedThread(target[os_type]['name'],
                                              (target[os_type]['args'], ))
        thread.start()
        _check_stress_status()
        return thread

    check_cmd = {
        'linux': 'pgrep -lx dd',
        'windows': 'TASKLIST /FI "IMAGENAME eq IOZONE.EXE'
    }
    os_type = params['os_type']
    args = params['stress_args']
    windows = os_type == 'windows'
    target = {}
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=360)
    disk = _get_data_disk()
    if windows:
        iozone = generate_instance(params, vm, 'iozone')
        utils_disk.update_windows_disk_attributes(session, disk)
        disk_letter = utils_disk.configure_empty_disk(
            session, disk, params['image_size_stg0'], os_type)[0]
        target[os_type] = {
            'name': iozone.run,
            'args': args.format(disk_letter)
        }
    else:
        target[os_type] = {'name': session.cmd, 'args': args.format(disk)}

    stress_thread = _run_stress_background()
    time.sleep(float(params['sleep_time']))
    _check_stress_status()
    BlockDevicesPlug(vm).unplug_devs_serial()
    stress_thread.join(suppress_exception=True)
    session.close()
    vm.monitor.system_reset()
    logging.info('Login guest after reboot.')
    session = vm.wait_for_login(timeout=360)
Esempio n. 12
0
def run(test, params, env):
    """
    This tests the disk hotplug/unplug functionality.
    1) prepares multiple disks to be hotplugged
    2) hotplugs them
    3) verifies that they are in qtree/guest system/...
    4) stop I/O stress_cmd
    5) unplugs them
    6) continue I/O stress_cmd
    7) verifies they are not in qtree/guest system/...
    8) repeats $repeat_times

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    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)

    def _create_params_matrix():
        matrix = {}
        stg_image_name = params['stg_image_name']
        if not stg_image_name[0] == "/":
            stg_image_name = "%s/%s" % (data_dir.get_data_dir(),
                                        stg_image_name)
        matrix['stg_image_name'] = stg_image_name
        stg_params = params.get('stg_params', '').split(' ')
        for i in range(len(stg_params)):
            if not stg_params[i].strip():
                continue
            if stg_params[i][-1] == '\\':
                stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                           stg_params.pop(i + 1))
            if not stg_params[i].strip():
                continue
            (cmd, parm) = stg_params[i].split(':', 1)
            # ',' separated list of values
            parm = parm.split(',')
            for j in range(len(parm)):
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
            matrix[cmd] = parm
        return matrix

    def configure_images_params(params):
        params_matrix = _create_params_matrix()
        _formats = params_matrix.pop('fmt', [params.get('drive_format')])
        formats = _formats[:]
        usb_port_occupied = 0
        usb_max_port = params.get('usb_max_port', 6)
        set_drive_bus = params.get('set_drive_bus', 'yes') == 'yes'
        no_disks = int(params['stg_image_num'])
        i = 0
        while i < no_disks:
            # Set the format
            if len(formats) < 1:
                if i == 0:
                    test.error("Fail to add any disks, probably bad"
                               " configuration.")
                logging.warn(
                    "Can't create desired number '%s' of disk types "
                    "'%s'. Using '%d' no disks.", no_disks, _formats, i)
                break
            name = 'stg%d' % i
            args = {
                'name': name,
                'filename': params_matrix['stg_image_name'] % i
            }
            fmt = random.choice(formats)
            drive_bus = None
            if set_drive_bus and fmt != 'virtio':
                drive_bus = str(i)
            if fmt == 'virtio_scsi':
                args['fmt'] = 'scsi-hd'
                args['scsi_hba'] = 'virtio-scsi-pci'
            elif fmt == 'lsi_scsi':
                args['fmt'] = 'scsi-hd'
                args['scsi_hba'] = 'lsi53c895a'
            elif fmt == 'spapr_vscsi':
                args['fmt'] = 'scsi-hd'
                args['scsi_hba'] = 'spapr-vscsi'
            elif fmt == 'usb2':
                usb_port_occupied += 1
                if usb_port_occupied > int(usb_max_port):
                    continue
                args['fmt'] = fmt
            else:
                args['fmt'] = fmt
            args['drive_bus'] = drive_bus
            # Other params
            for key, value in params_matrix.items():
                args[key] = random.choice(value)
            env_process.preprocess_image(
                test,
                convert_params(params, args).object_params(name), name)
            i += 1

    def _postprocess_images():
        # remove and check the images
        _disks = []
        for disk in params['images'].split(' '):
            if disk.startswith("stg"):
                env_process.postprocess_image(test, params.object_params(disk),
                                              disk)
            else:
                _disks.append(disk)
            params['images'] = " ".join(_disks)

    def verify_qtree_unsupported(params, info_qtree, info_block, qdev):
        return logging.warn("info qtree not supported. Can't verify qtree vs. "
                            "guest disks.")

    def enable_driver_verifier(driver, timeout=300):
        return utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, driver, timeout)

    def _initial_win_drives():
        size = params['stg_image_size']
        disks = utils_disk.get_windows_disks_index(session, size)
        if not utils_disk.update_windows_disk_attributes(session, disks):
            test.fail("Failed to update windows disk attributes.")
        for disk in disks[1:24]:
            yield utils_disk.configure_empty_windows_disk(session, disk,
                                                          size)[0]

    def run_stress_iozone():
        error_context.context("Run iozone stress after hotplug", logging.info)
        iozone = generate_instance(params, vm, 'iozone')
        try:
            iozone_cmd_option = params['iozone_cmd_option']
            iozone_timeout = float(params['iozone_timeout'])
            for letter in _initial_win_drives():
                iozone.run(iozone_cmd_option.format(letter), iozone_timeout)
        finally:
            iozone.clean()

    def run_stress_dd():
        error_context.context("Run dd stress after hotplug", logging.info)
        output = session.cmd_output(
            params.get("get_dev_cmd", "ls /dev/[svh]d*"))
        system_dev = re.findall(r"/dev/[svh]d\w+(?=\d+)", output)[0]
        for dev in re.split(r"\s+", output):
            if not dev:
                continue
            if not re.findall(system_dev, dev):
                session.cmd(params['dd_cmd'].format(dev),
                            int(params['dd_timeout']))

    Monitor.CONNECT_TIMEOUT = params.get_numeric('connect_timeout', 60)
    BlockDevicesPlug.ACQUIRE_LOCK_TIMEOUT = params.get_numeric(
        'acquire_lock_timeout', 20)
    BlockDevicesPlug.VERIFY_UNPLUG_TIMEOUT = params.get_numeric(
        'verify_unplug_timeout', 60)

    configure_images_params(params)
    params['start_vm'] = 'yes'
    env_process.preprocess_vm(test, params, env, params["main_vm"])
    vm = env.get_vm(params['main_vm'])
    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    is_windows = params['os_type'] == 'windows'
    if is_windows:
        session = enable_driver_verifier(params['driver_name'])
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        verify_qtree = verify_qtree_unsupported

    # Modprobe the module if specified in config file
    module = params.get("modprobe_module")
    if module:
        session.cmd("modprobe %s" % module)

    stress_cmd = params.get('stress_cmd')
    if stress_cmd:
        funcatexit.register(env, params.get('type'), stop_stresser, vm,
                            params.get('stress_kill_cmd'))
        stress_session = vm.wait_for_login(timeout=10)
        for _ in range(int(params.get('no_stress_cmds', 1))):
            stress_session.sendline(stress_cmd)

    rp_times = int(params.get("repeat_times", 1))
    queues = params.get("multi_disk_type") == "parallel"
    timeout = params.get_numeric('plug_timeout', 300)
    if queues:  # parallel
        hotplug, unplug = 'hotplug_devs_threaded', 'unplug_devs_threaded'
    else:  # serial
        hotplug, unplug = 'hotplug_devs_serial', 'unplug_devs_serial'

    context_msg = "Running sub test '%s' %s"
    plug = BlockDevicesPlug(vm)
    for iteration in range(rp_times):
        error_context.context(
            "Hotplugging/unplugging devices, 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)

        error_context.context("Hotplug the devices", logging.debug)
        getattr(plug, hotplug)(timeout=timeout)
        time.sleep(float(params.get('wait_after_hotplug', 0)))

        error_context.context("Verify disks after hotplug", logging.debug)
        info_qtree = vm.monitor.info('qtree', False)
        info_block = vm.monitor.info_block(False)
        vm.verify_alive()
        verify_qtree(params, info_qtree, info_block, vm.devices)

        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)
        run_stress_iozone() if is_windows else run_stress_dd()
        sub_type = params.get("sub_type_before_unplug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "before hotunplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)

        error_context.context("Unplug and remove the devices", logging.debug)
        if stress_cmd:
            session.cmd(params["stress_stop_cmd"])
        getattr(plug, unplug)(timeout=timeout)
        if stress_cmd:
            session.cmd(params["stress_cont_cmd"])
        _postprocess_images()

        error_context.context("Verify disks after unplug", logging.debug)
        time.sleep(float(params.get('wait_after_unplug', 0)))
        info_qtree = vm.monitor.info('qtree', False)
        info_block = vm.monitor.info_block(False)
        vm.verify_alive()
        verify_qtree(params, info_qtree, info_block, vm.devices)

        sub_type = params.get("sub_type_after_unplug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "after hotunplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)
        configure_images_params(params)

    # Check for various KVM failures
    error_context.context("Validating VM after all disk hotplug/unplugs",
                          logging.debug)
    vm.verify_alive()
    out = session.cmd_output('dmesg')
    if "I/O error" in out:
        logging.warn(out)
        test.error("I/O error messages occured in dmesg, "
                   "check the log for details.")
Esempio n. 13
0
def run(test, params, env):
    """
    Test multi disk with multifunction on and off.

    1) Boot guest with system disk(multifunction=on)
    2) Hotplug 7 disks with addr 0x0.0x1~0x0.0x7
    3) hotplug 1 disk with multifunction=on (addr 0x0)
    4) Check disks in guest
    5) Run dd/iozone test on all data disks
    6) Reboot guest, check disks in guest
    7) Unplug disk8, and remove disk 1-7
    8) Hotplug disk8 with multifunction=off

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def get_image_device(qdev, img_name):
        """
        Get the image device(virtio-blk-pci/virtio-scsi-pci)
        :param qdev: DevContainer object
        :param img_name: The image name
        """
        dev = qdev.get(img_name)
        devs = [dev]
        if params['drive_format'].startswith('scsi'):
            devs.append(
                qdev.get_by_properties(
                    {'aid': dev.get_param('bus').split('.')[0]})[0])
        return devs

    image = params.objects('images')[0]
    vm_name = params['main_vm']
    set_addr(image, 0, 0,
             params)  # Add multifunction=on option before start vm
    params['start_vm'] = 'yes'
    env_process.preprocess_vm(test, params, env, vm_name)
    vm = env.get_vm(vm_name)
    qdev = vm.devices
    windows = params["os_type"] == 'windows'
    disk_op_cmd = params.get("disk_op_cmd")
    session = vm.wait_for_login()

    q35 = params['machine_type'] == 'q35'
    dev_slot = 0 if q35 else 9
    parent_bus = 'pcie_extra_root_port_0' if q35 else 'pci.0'
    image_size = '1G'
    # Generate the data disk devices to be plugged
    for i in range(1, 9):
        stg = 'stg%s' % i
        vm.params['images'] += ' %s' % stg
        vm.params['image_name_%s' % stg] = 'images/%s' % stg
        vm.params['image_size_%s' % stg] = image_size
        vm.params['remove_image_%s' % stg] = 'yes'
        vm.params['force_create_image_%s' % stg] = 'yes'
        vm.params['boot_drive_%s' % stg] = 'no'
        # Specify the address of the device, plug them into same slot
        set_addr(stg, dev_slot, i, vm.params)
        if params['drive_format'].startswith('scsi'):
            # Create oen new scsi bus for each block device
            vm.params['drive_bus_%s' % stg] = i
    # To create those image files
    env_process.process_images(env_process.preprocess_image, test, vm.params)

    plug = BlockDevicesPlug(vm)
    parent_bus_obj = qdev.get_buses({'aobject': parent_bus})[0]
    plug.hotplug_devs_serial(bus=parent_bus_obj)

    # Run io test on all the plugged disks
    io_test(session, disk_op_cmd, plug, windows, image_size)

    # Reboot the guest and check if all the disks still exist
    disks_before_reboot = block_hotplug.find_all_disks(session, windows)
    session = vm.reboot(session)
    block_hotplug.wait_plug_disks(session, 'check', disks_before_reboot, 0,
                                  windows, test)
    session.close()

    # Unplug the disk on function 7 and 0, and check if all the disks been removed
    images = vm.params.objects('images')
    unplug_dev = images[-1]
    unplug_timeout = params['unplug_timeout']
    try:
        plug.unplug_devs_serial(images=unplug_dev, timeout=unplug_timeout)
    except exceptions.TestError as e:
        if 'Actual: 8 disks. Expected: ' not in str(e):
            raise
    else:
        test.fail('All the plugged disks should be removed when'
                  ' the device at function 0 is removed.')

    # replug disk 2-7
    rest_dev = images[1:-1]
    # Remove them from DevContainer first, they are unplugged by qemu
    # but still in DevContainer
    for img in rest_dev:
        devs_rm = get_image_device(qdev, img)
        list(map(lambda x: qdev.remove(x, recursive=False), devs_rm))
    plug._create_devices(rest_dev, {'aobject': parent_bus})
    for img, devs in plug._hotplugged_devs.items():
        if img not in rest_dev:
            continue
        for dev in devs:
            args = (dev, vm.monitor)
            if isinstance(dev, QDevice):
                pci_device = qdev.is_pci_device(dev['driver'])
                if pci_device:
                    args += (parent_bus_obj, )
                elif not dev['driver'].startswith('scsi'):
                    continue
            elif not isinstance(dev, QDrive):
                continue
            try:
                plug._hotplug_atomic(*args)
            except NotImplementedError:
                # Insert might fail for file node 1-7 not been removed
                # from vm.devices, which can be ignored
                pass

    # Replug disk 8 on slot 0 with multifunction='off'
    set_addr(images[-1], dev_slot, 0, vm.params, multifunction='off')
    plug._create_devices(unplug_dev.split(), {'aobject': parent_bus})
    for img, devs in plug._hotplugged_devs.items():
        for dev in devs:
            if (img == images[-1] and isinstance(dev, QDevice)
                    and qdev.is_pci_device(dev['driver'])):
                dev['addr'] = hex(dev_slot)  # for pci bus addr might be reset
                try:
                    parent_bus_obj.prepare_hotplug(dev)
                    dev.hotplug(vm.monitor, vm.devices.qemu_version)
                except QMPCmdError as e:
                    if 'single function' not in str(e):
                        raise
                else:
                    test.fail(
                        'It should fail to hotplug a single function device'
                        ' to the address where multifunction already on.')
                break
            else:
                plug._hotplug_atomic(dev, vm.monitor)
def run(test, params, env):
    """
    Hotplug many disks with multifunction on.

    1) Boot guest with system disk(multifunction=on)
    2) Hotplug disks with addr 0x0.0x1~0xn.0x7
    3) Check disks in guest
    4) Run iozone test on all data disks for Windows guest

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

    def generate_image(dev_slots, plug, params, qdev, image_size, pcie, test):
        """
        Generate the data disk devices to be plugged

        :param dev_slots: All the slots to be plugged
        :param plug: BlockDevicesPlug
        :param params: vm.params
        :param qdev: DevContainer
        :param image_size: The image size to be specified
        :param pcie: if itis pcie bus
        """
        disks = []
        for slot in dev_slots:
            scsi_bus = 1
            parent_bus = 'pcie_extra_root_port_%s' % slot if pcie else 'pci.0'
            images = []
            for i in range(1, 9):
                stg = 'stg%s%s' % (slot, i)
                images.append(stg)
                params['images'] += ' %s' % stg
                params['image_name_%s' % stg] = 'images/%s' % stg
                params['image_size_%s' % stg] = image_size
                params['remove_image_%s' % stg] = 'yes'
                params['force_create_image_%s' % stg] = 'no'
                params['create_image_%s' % stg] = 'yes'
                params['boot_drive_%s' % stg] = 'no'
                # Specify the address of the device, plug them into same slot
                addr = 0 if pcie else slot
                set_addr(stg, addr, i, params)
                if params['drive_format'].startswith('scsi'):
                    # Create oen new scsi bus for each block device
                    params['drive_bus_%s' % stg] = scsi_bus
                    scsi_bus += 1
            env_process.process_images(env_process.preprocess_image, test, params)
            parent_bus_obj = qdev.get_buses({'aobject': parent_bus})[0]
            plug._hotplug_devs(images, vm.monitor, bus=parent_bus_obj)
            disks.extend(plug)
        return disks

    image_size = '500M'
    vm_name = params['main_vm']
    env_process.preprocess_vm(test, params, env, vm_name)
    vm = env.get_vm(vm_name)
    qdev = vm.devices
    windows = params["os_type"] == 'windows'
    disk_op_cmd = params.get("disk_op_cmd")
    session = vm.wait_for_login()
    pcie = params['machine_type'] == 'q35'
    dev_slots = range(0, 3) if pcie else (7, 10)

    plug = BlockDevicesPlug(vm)
    disks = generate_image(
        dev_slots, plug, vm.params, qdev, image_size, pcie, test)
    if windows:
        io_test(session, disk_op_cmd, disks, windows, image_size)
Esempio n. 15
0
def run(test, params, env):
    """
    Test to hot plug with block resize.
    Steps:
        1) Boot the guest with system disk.
        2) Hotplug a virtio disk via qmp.
        3) For Windows: check whether viostor.sys verifier enabled in
           guest.
        4) block_resize data disk, e.g, enlarge to 10GB; shrink to 1GB.
        5) Check the disk using qemu-img check on host and do io test
           in guest.
        6) Reboot or shutdown guest by qmp and shell.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _change_vm_power():
        """ Change the vm power. """
        method, command = params['command_opts'].split(',')
        logging.info('Sending command(%s): %s' % (method, command))
        if method == 'shell':
            power_session = vm.wait_for_login(timeout=360)
            power_session.sendline(command)
        else:
            getattr(vm.monitor, command)()
        if shutdown_vm:
            if not utils_misc.wait_for(
                    lambda: vm.monitor.get_event("SHUTDOWN"), 600):
                raise test.fail("Not received SHUTDOWN QMP event.")

    def _check_vm_status(timeout=600):
        """ Check the status of vm. """
        action = 'shutdown' if shutdown_vm else 'login'
        if not getattr(vm, 'wait_for_%s' % action)(timeout=timeout):
            test.fail('Failed to %s vm.' % action)

    def _block_resize(dev):
        """ Resize the block size. """
        resize_size = int(
            float(
                normalize_data_size(
                    re.search(r'(\d+\.?(\d+)?\w)',
                              params['resize_size']).group(1), "B")))
        size = str(data_image_size +
                   resize_size) if resize_op == ENLARGE else str(
                       data_image_size - resize_size)
        logging.info("Start to %s %s to %sB." % (resize_op, plug[0], size))
        vm.monitor.block_resize(dev, size)
        return size

    def _check_img_size(size):
        """ Check the size of image after resize. """
        img = qemu_storage.QemuImg(data_image_params, data_dir.get_data_dir(),
                                   data_image)
        if json.loads(img.info(True, 'json'))['virtual-size'] != int(size):
            test.fail('The virtual size is not equal to %sB after %s.' %
                      (size, resize_op))

    shutdown_vm = params.get('shutdown_vm', 'no') == 'yes'
    reboot = params.get('reboot_vm', 'no') == 'yes'
    data_image = params.get("images").split()[-1]
    data_image_params = params.object_params(data_image)
    data_image_size = int(
        float(normalize_data_size(data_image_params.get("image_size"), "B")))
    data_image_filename = storage.get_image_filename(data_image_params,
                                                     data_dir.get_data_dir())
    resize_op = SHRINK if '-' in params['resize_size'] else ENLARGE
    os_type = params['os_type']
    is_windows = os_type == 'windows'

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=360)

    if is_windows:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, params['driver_name'], 300)
    plug = BlockDevicesPlug(vm)
    plug.hotplug_devs_serial()
    block_size = _block_resize(vm.get_block({'file': data_image_filename}))
    _check_img_size(block_size)

    iozone = generate_instance(params, vm, 'iozone')
    try:
        if is_windows:
            if not utils_disk.update_windows_disk_attributes(session, plug[:]):
                test.fail('Failed to clear readonly and online on %s.' %
                          plug[:])
        mount_point = utils_disk.configure_empty_disk(session, plug[0],
                                                      block_size + 'B',
                                                      os_type)[0]
        iozone_size = str(int(float(normalize_data_size(block_size)))) + 'M'
        iozone.run(params['iozone_options'].format(mount_point, iozone_size),
                   float(params['iozone_timeout']))
    finally:
        iozone.clean()
        if shutdown_vm or reboot:
            _change_vm_power()
            _check_vm_status()
 def unplug_path_disk(vm):
     """Unplug passthrough disk."""
     error_context.context("Unplug passthrouth device", logging.info)
     plug = BlockDevicesPlug(vm)
     plug.unplug_devs_serial()