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")
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)
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))
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))
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()
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()
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()
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)
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)
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.")
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)
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()