def check_support_device(dev): if is_qmp_monitor: devices_supported = vm.monitor.human_monitor_cmd("%s ?" % cmd_type) else: devices_supported = vm.monitor.send_args_cmd("%s ?" % cmd_type) # Check if the device is support in qemu is_support = utils_test.find_substring(devices_supported, dev) if not is_support: raise error.TestError("%s doesn't support device: %s" % (cmd_type, dev))
def run_sr_iov_hotplug(test, params, env): """ Test hotplug of sr-iov devices. (Elements between [] are configurable test parameters) 1) Set up sr-iov test environment in host. 2) Start VM. 3) PCI add one/multi sr-io deivce with (or without) repeat 4) Compare output of monitor command 'info pci'. 5) Compare output of guest command [reference_cmd]. 6) Verify whether pci_model is shown in [pci_find_cmd]. 7) Check whether the newly added PCI device works fine. 8) Delete the device, verify whether could remove the sr-iov device. @param test: KVM test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ def pci_add_iov(pci_num): pci_add_cmd = ("pci_add pci_addr=auto host host=%s,if=%s" % (pa_pci_ids[pci_num], pci_model)) if params.get("hotplug_params"): assign_param = params.get("hotplug_params").split() for param in assign_param: value = params.get(param) if value: pci_add_cmd += ",%s=%s" % (param, value) return pci_add(pci_add_cmd) def pci_add(pci_add_cmd): error.context("Adding pci device with command 'pci_add'") add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info.append(['', add_output]) if not "OK domain" in add_output: raise error.TestFail("Add PCI device failed. " "Monitor command is: %s, Output: %r" % (pci_add_cmd, add_output)) return vm.monitor.info("pci") def check_support_device(dev): if is_qmp_monitor: devices_supported = vm.monitor.human_monitor_cmd("%s ?" % cmd_type) else: devices_supported = vm.monitor.send_args_cmd("%s ?" % cmd_type) # Check if the device is support in qemu is_support = utils_test.find_substring(devices_supported, dev) if not is_support: raise error.TestError("%s doesn't support device: %s" % (cmd_type, dev)) def device_add_iov(pci_num): device_id = "%s" % pci_model + "-" + utils_misc.generate_random_id() pci_info.append([device_id]) check_support_device("pci-assign") pci_add_cmd = ("device_add id=%s,driver=pci-assign,host=%s" % (pci_info[pci_num][0], pa_pci_ids[pci_num])) if params.get("hotplug_params"): assign_param = params.get("hotplug_params").split() for param in assign_param: value = params.get(param) if value: pci_add_cmd += ",%s=%s" % (param, value) return device_add(pci_num, pci_add_cmd) def device_add(pci_num, pci_add_cmd): error.context("Adding pci device with command 'device_add'") if is_qmp_monitor: add_output = vm.monitor.send_args_cmd(pci_add_cmd) else: add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info[pci_num].append(add_output) after_add = vm.monitor.info("pci") if pci_info[pci_num][0] not in after_add: logging.debug("Print info pci after add the block: %s" % after_add) raise error.TestFail("Add device failed. Monitor command is: %s" ". Output: %r" % (pci_add_cmd, add_output)) return after_add # Hot add a pci device def add_device(pci_num): reference_cmd = params.get("reference_cmd") find_pci_cmd = params.get("find_pci_cmd") info_pci_ref = vm.monitor.info("pci") reference = session.cmd_output(reference_cmd) try: # get function for adding device. add_fuction = local_functions["%s_iov" % cmd_type] except Exception: raise error.TestError( "No function for adding sr-iov dev with '%s'" % cmd_type) after_add = None if add_fuction: # Do add pci device. after_add = add_fuction(pci_num) try: # Define a helper function to compare the output def _new_shown(): o = session.cmd_output(reference_cmd) return o != reference # Define a helper function to catch PCI device string def _find_pci(): o = session.cmd_output(find_pci_cmd) if re.search(match_string, o, re.IGNORECASE): return True else: return False error.context("Start checking new added device") # Compare the output of 'info pci' if after_add == info_pci_ref: raise error.TestFail("No new PCI device shown after executing " "monitor command: 'info pci'") secs = int(params.get("wait_secs_for_hook_up")) if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3): raise error.TestFail( "No new device shown in output of command " "executed inside the guest: %s" % reference_cmd) if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3): raise error.TestFail( "New add sr-iov device not found in guest. " "Command was: %s" % find_pci_cmd) # Test the newly added device try: session.cmd(params.get("pci_test_cmd") % (pci_num + 1)) except aexpect.ShellError, e: raise error.TestFail( "Check for sr-iov device failed after PCI " "hotplug. Output: %r" % e.output) except Exception: pci_del(pci_num, ignore_failure=True) raise # Hot delete a pci device def pci_del(pci_num, ignore_failure=False): def _device_removed(): after_del = vm.monitor.info("pci") return after_del != before_del before_del = vm.monitor.info("pci") if cmd_type == "pci_add": slot_id = "0" + pci_info[pci_num][1].split(",")[2].split()[1] cmd = "pci_del pci_addr=%s" % slot_id vm.monitor.send_args_cmd(cmd, convert=False) elif cmd_type == "device_add": cmd = "device_del id=%s" % pci_info[pci_num][0] vm.monitor.send_args_cmd(cmd) if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1) and not ignore_failure): raise error.TestFail("Failed to hot remove PCI device: %s. " "Monitor command: %s" % (pci_model, cmd)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) test_timeout = int(params.get("test_timeout", 360)) # Test if it is nic or block pci_num_range = int(params.get("pci_num", 1)) rp_times = int(params.get("repeat_times", 1)) pci_model = params.get("pci_model", "pci-assign") # Need udpate match_string if you use a card other than 82576 match_string = params.get("match_string", "82576") if vm.pci_assignable is not None: pa_pci_ids = vm.pci_assignable.request_devs(pci_num_range) # Modprobe the module if specified in config file module = params.get("modprobe_module") if module: error.context("modprobe the module %s" % module, logging.info) session.cmd("modprobe %s" % module) # check monitor type qemu_binary = params.get("qemu_binary", "/usr/bin/qemu-kvm") qemu_binary = utils_misc.get_path(test.bindir, qemu_binary) is_qmp_monitor = (utils_misc.qemu_has_option("qmp", qemu_binary) and params.get("monitor_type") == "qmp") # Probe qemu to verify what is the supported syntax for PCI hotplug if is_qmp_monitor: cmd_o = vm.monitor.info("commands") else: cmd_o = vm.monitor.send_args_cmd("help") cmd_type = utils_test.find_substring(str(cmd_o), "device_add", "pci_add") if not cmd_o: raise error.TestError("Unknow version of qemu") local_functions = locals() for j in range(rp_times): # pci_info is a list of list. # each element 'i' has 4 members: # pci_info[i][0] == device id, only used for device_add # pci_info[i][1] == output of device add command pci_info = [] for pci_num in xrange(pci_num_range): msg = "Start hot-adding %sth pci device, repeat %d" % (pci_num + 1, j + 1) error.context(msg, logging.info) add_device(pci_num) for pci_num in xrange(pci_num_range): msg = "start hot-deleting %sth pci device repeat %d" % (pci_num + 1, j + 1) error.context(msg, logging.info) pci_del(-(pci_num + 1))
def run_sr_iov_hotplug_negative(test, params, env): """ KVM sr-iov hotplug negatvie test: 1) Boot up VM. 2) Try to remove sr-iov device driver module (optional) 3) Hotplug sr-iov device to VM with negative parameters 4) Verify that qemu could handle the negative parameters check hotplug error message (optional) @param test: qemu test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ def make_pci_add_cmd(pa_pci_id, pci_addr="auto"): pci_add_cmd = ("pci_add pci_addr=%s host host=%s,if=%s" % (pci_addr, pa_pci_id, pci_model)) if params.get("hotplug_params"): assign_param = params.get("hotplug_params").split() for param in assign_param: value = params.get(param) if value: pci_add_cmd += ",%s=%s" % (param, value) return pci_add_cmd def make_device_add_cmd(pa_pci_id, pci_addr=None): device_id = "%s" % pci_model + "-" + utils_misc.generate_random_id() pci_add_cmd = ("device_add id=%s,driver=pci-assign,host=%s" % (device_id, pa_pci_id)) if pci_addr is not None: pci_add_cmd += ",addr=%s" % pci_addr if params.get("hotplug_params"): assign_param = params.get("hotplug_params").split() for param in assign_param: value = params.get(param) if value: pci_add_cmd += ",%s=%s" % (param, value) return pci_add_cmd neg_msg = params.get("negative_msg") vm = env.get_vm(params["main_vm"]) vm.verify_alive() rp_times = int(params.get("repeat_times", 1)) pci_model = params.get("pci_model", "pci-assign") pci_addr = params.get("pci_addr") modprobe_cmd = params.get("modprobe_cmd") if modprobe_cmd: #negative test, both guest and host should still work well. msg = "Try to remove sr-iov module in host." error.context(msg, logging.info) utils.system(modprobe_cmd) if vm.pci_assignable is not None: pa_pci_ids = vm.pci_assignable.request_devs(1) # Probe qemu to verify what is the supported syntax for PCI hotplug if vm.monitor.protocol == 'qmp': cmd_output = vm.monitor.info("commands") else: cmd_output = vm.monitor.send_args_cmd("help") if not cmd_output: raise error.TestError("Unknow version of qemu") cmd_type = utils_test.find_substring(str(cmd_output), "pci_add", "device_add") for j in range(rp_times): if cmd_type == "pci_add": pci_add_cmd = make_pci_add_cmd(pa_pci_ids[0], pci_addr) elif cmd_type == "device_add": pci_add_cmd = make_device_add_cmd(pa_pci_ids[0], pci_addr) try: msg = "Adding pci device with command '%s'" % pci_add_cmd error.context(msg, logging.info) case_fail = False add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) case_fail = True except Exception, e: if neg_msg: msg = "Check negative hotplug error message" error.context(msg, logging.info) if neg_msg not in str(e): msg = "Could not find '%s' in error msg '%s'" % (neg_msg, e) raise error.TestFail(msg) logging.debug("Could not boot up vm, %s" % e) if case_fail: raise error.TestFail("Did not raise exception during hotpluging")
def run_pci_hotplug(test, params, env): """ Test hotplug of PCI devices. (Elements between [] are configurable test parameters) 1) PCI add one/multi device (NIC / block) with(or without) repeat 2) Compare output of monitor command 'info pci'. 3) Compare output of guest command [reference_cmd]. 4) Verify whether pci_model is shown in [pci_find_cmd]. 5) Check whether the newly added PCI device works fine. 6) PCI delete the device, verify whether could remove the PCI device. 7) reboot VM after guest wakeup form S3/S4 status (Optional Step). :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ # Select an image file def find_image(pci_num): image_params = params.object_params("%s" % img_list[pci_num + 1]) o = storage.get_image_filename(image_params, data_dir.get_data_dir()) return o def pci_add_nic(pci_num): pci_add_cmd = "pci_add pci_addr=auto nic model=%s" % pci_model return pci_add(pci_add_cmd) def pci_add_block(pci_num): image_filename = find_image(pci_num) pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" % (image_filename, pci_model)) return pci_add(pci_add_cmd) def pci_add(pci_add_cmd): error.context("Adding pci device with command 'pci_add'") add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info.append(['', '', add_output, pci_model]) if not "OK domain" in add_output: raise error.TestFail("Add PCI device failed. " "Monitor command is: %s, Output: %r" % (pci_add_cmd, add_output)) return vm.monitor.info("pci") def is_supported_device(dev): # Probe qemu to verify what is the supported syntax for PCI hotplug cmd_output = vm.monitor.human_monitor_cmd("?") if len(re.findall("\ndevice_add", cmd_output)) > 0: cmd_type = "device_add" elif len(re.findall("\npci_add", cmd_output)) > 0: cmd_type = "pci_add" else: raise error.TestError("Unknow version of qemu") # Probe qemu for a list of supported devices probe_output = vm.monitor.human_monitor_cmd("%s ?" % cmd_type) devices_supported = [j.strip('"') for j in re.findall('\"[a-z|0-9|\-|\_|\,|\.]*\"', probe_output, re.MULTILINE)] logging.debug("QEMU reported the following supported devices for " "PCI hotplug: %s", devices_supported) return (dev in devices_supported) def verify_supported_device(dev): if not is_supported_device(dev): raise error.TestError("%s doesn't support device: %s" % (cmd_type, dev)) def device_add_nic(pci_num, queues=1): device_id = pci_type + "-" + utils_misc.generate_random_id() pci_info.append([device_id, device_id]) pci_model = params.get("pci_model") if pci_model == "virtio": pci_model = "virtio-net-pci" verify_supported_device(pci_model) pci_add_cmd = "device_add id=%s,driver=%s" % (pci_info[pci_num][1], pci_model) if queues > 1 and "virtio" in pci_model: pci_add_cmd += ",mq=on" return device_add(pci_num, pci_add_cmd) def device_add_block(pci_num): device_id = pci_type + "-" + utils_misc.generate_random_id() pci_info.append([device_id, device_id]) image_format = params.get("image_format_%s" % img_list[pci_num + 1]) if not image_format: image_format = params.get("image_format", "qcow2") image_filename = find_image(pci_num) pci_model = params.get("pci_model") controller_model = None if pci_model == "virtio": pci_model = "virtio-blk-pci" if pci_model == "scsi": pci_model = "scsi-disk" controller_model = "lsi53c895a" verify_supported_device(controller_model) controller_id = "controller-" + device_id controller_add_cmd = ("device_add %s,id=%s" % (controller_model, controller_id)) error.context("Adding SCSI controller.") vm.monitor.send_args_cmd(controller_add_cmd) verify_supported_device(pci_model) if drive_cmd_type == "drive_add": driver_add_cmd = ("%s auto file=%s,if=none,format=%s,id=%s" % (drive_cmd_type, image_filename, image_format, pci_info[pci_num][0])) elif drive_cmd_type == "__com.redhat_drive_add": driver_add_cmd = ("%s file=%s,format=%s,id=%s" % (drive_cmd_type, image_filename, image_format, pci_info[pci_num][0])) # add driver. error.context("Adding driver.") vm.monitor.send_args_cmd(driver_add_cmd, convert=False) pci_add_cmd = ("device_add id=%s,driver=%s,drive=%s" % (pci_info[pci_num][1], pci_model, pci_info[pci_num][0])) return device_add(pci_num, pci_add_cmd) def device_add(pci_num, pci_add_cmd): error.context("Adding pci device with command 'device_add'") if vm.monitor.protocol == 'qmp': add_output = vm.monitor.send_args_cmd(pci_add_cmd) else: add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info[pci_num].append(add_output) pci_info[pci_num].append(pci_model) after_add = vm.monitor.info("pci") if pci_info[pci_num][1] not in after_add: logging.error("Could not find matched id in monitor:" " %s" % pci_info[pci_num][1]) raise error.TestFail("Add device failed. Monitor command is: %s" ". Output: %r" % (pci_add_cmd, add_output)) return after_add # Hot add a pci device def add_device(pci_num, queues=1): info_pci_ref = vm.monitor.info("pci") reference = session.cmd_output(reference_cmd) try: # get function for adding device. add_fuction = local_functions["%s_%s" % (cmd_type, pci_type)] except Exception: raise error.TestError("No function for adding '%s' dev with '%s'" % (pci_type, cmd_type)) after_add = None if add_fuction: # Do add pci device. after_add = add_fuction(pci_num, queues) try: # Define a helper function to compare the output def _new_shown(): o = session.cmd_output(reference_cmd) return o != reference # Define a helper function to catch PCI device string def _find_pci(): output = session.cmd_output(params.get("find_pci_cmd")) output = map(string.strip, output.splitlines()) ref = map(string.strip, reference.splitlines()) output = [_ for _ in output if _ not in ref] output = "\n".join(output) if re.search(params.get("match_string"), output, re.I): return True return False error.context("Start checking new added device") # Compare the output of 'info pci' if after_add == info_pci_ref: raise error.TestFail("No new PCI device shown after executing " "monitor command: 'info pci'") secs = int(params.get("wait_secs_for_hook_up")) if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3): raise error.TestFail("No new device shown in output of command " "executed inside the guest: %s" % reference_cmd) if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3): raise error.TestFail("PCI %s %s device not found in guest. " "Command was: %s" % (pci_model, pci_type, params.get("find_pci_cmd"))) # Test the newly added device try: session.cmd(params.get("pci_test_cmd") % (pci_num + 1)) except aexpect.ShellError, e: raise error.TestFail("Check for %s device failed after PCI " "hotplug. Output: %r" % (pci_type, e.output)) except Exception: pci_del(pci_num, ignore_failure=True) raise # Hot delete a pci device def pci_del(pci_num, ignore_failure=False): def _device_removed(): after_del = vm.monitor.info("pci") return after_del != before_del before_del = vm.monitor.info("pci") if cmd_type == "pci_add": slot_id = int(pci_info[pci_num][2].split(",")[2].split()[1]) cmd = "pci_del pci_addr=%s" % hex(slot_id) vm.monitor.send_args_cmd(cmd, convert=False) elif cmd_type == "device_add": cmd = "device_del id=%s" % pci_info[pci_num][1] vm.monitor.send_args_cmd(cmd) if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1) and not ignore_failure): raise error.TestFail("Failed to hot remove PCI device: %s. " "Monitor command: %s" % (pci_info[pci_num][3], cmd)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) test_timeout = int(params.get("hotplug_timeout", 360)) reference_cmd = params["reference_cmd"] # Test if it is nic or block pci_type = params["pci_type"] pci_model = params["pci_model"] # Modprobe the module if specified in config file module = params.get("modprobe_module") if module: session.cmd("modprobe %s" % module) # check monitor type qemu_binary = params.get("qemu_binary", "/usr/libexec/qemu-kvm") qemu_binary = utils_misc.get_path(test.bindir, qemu_binary) # Probe qemu to verify what is the supported syntax for PCI hotplug if vm.monitor.protocol == 'qmp': cmd_output = vm.monitor.info("commands") else: cmd_output = vm.monitor.human_monitor_cmd("help", debug=False) cmd_type = utils_test.find_substring(str(cmd_output), "device_add", "pci_add") if not cmd_output: raise error.TestError("Could find a suitable method for hotplugging" " device in this version of qemu") # Determine syntax of drive hotplug # __com.redhat_drive_add == qemu-kvm-0.12 on RHEL 6 # drive_add == qemu-kvm-0.13 onwards drive_cmd_type = utils_test.find_substring(str(cmd_output), "__com.redhat_drive_add", "drive_add") if not drive_cmd_type: raise error.TestError("Could find a suitable method for hotplugging" " drive in this version of qemu") local_functions = locals() pci_num_range = int(params.get("pci_num")) queues = int(params.get("queues")) rp_times = int(params.get("repeat_times")) img_list = params.get("images").split() context_msg = "Running sub test '%s' %s" for j in range(rp_times): # pci_info is a list of list. # each element 'i' has 4 members: # pci_info[i][0] == device drive id, only used for device_add # pci_info[i][1] == device id, only used for device_add # pci_info[i][2] == output of device add command # pci_info[i][3] == device module name. pci_info = [] for pci_num in xrange(pci_num_range): sub_type = params.get("sub_type_before_plug") if sub_type: error.context(context_msg % (sub_type, "before hotplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) error.context("Start hot-adding pci device, repeat %d" % j) add_device(pci_num, queues) sub_type = params.get("sub_type_after_plug") if sub_type: error.context(context_msg % (sub_type, "after hotplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) for pci_num in xrange(pci_num_range): sub_type = params.get("sub_type_before_unplug") if sub_type: error.context(context_msg % (sub_type, "before hotunplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) error.context("start hot-deleting pci device, repeat %d" % j) pci_del(-(pci_num + 1)) sub_type = params.get("sub_type_after_unplug") if sub_type: error.context(context_msg % (sub_type, "after hotunplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) if params.get("reboot_vm", "no") == "yes": vm.reboot()
def run_pci_hotplug(test, params, env): """ Test hotplug of PCI devices. (Elements between [] are configurable test parameters) 1) PCI add one/multi device (NIC / block) with(or without) repeat 2) Compare output of monitor command 'info pci'. 3) Compare output of guest command [reference_cmd]. 4) Verify whether pci_model is shown in [pci_find_cmd]. 5) Check whether the newly added PCI device works fine. 6) PCI delete the device, verify whether could remove the PCI device. @param test: QEMU test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ # Select an image file def find_image(pci_num): image_params = params.object_params("%s" % img_list[pci_num + 1]) o = storage.get_image_filename(image_params, data_dir.get_data_dir()) return o def pci_add_nic(pci_num): pci_add_cmd = "pci_add pci_addr=auto nic model=%s" % pci_model return pci_add(pci_add_cmd) def pci_add_block(pci_num): image_filename = find_image(pci_num) pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" % (image_filename, pci_model)) return pci_add(pci_add_cmd) def pci_add(pci_add_cmd): error.context("Adding pci device with command 'pci_add'") add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info.append(['', '' , add_output, pci_model]) if not "OK domain" in add_output: raise error.TestFail("Add PCI device failed. " "Monitor command is: %s, Output: %r" % (pci_add_cmd, add_output)) return vm.monitor.info("pci") def is_supported_device(dev): # Probe qemu to verify what is the supported syntax for PCI hotplug cmd_output = vm.monitor.human_monitor_cmd("?") if len(re.findall("\ndevice_add", cmd_output)) > 0: cmd_type = "device_add" elif len(re.findall("\npci_add", cmd_output)) > 0: cmd_type = "pci_add" else: raise error.TestError("Unknow version of qemu") # Probe qemu for a list of supported devices probe_output = vm.monitor.human_monitor_cmd("%s ?" % cmd_type) devices_supported = [j.strip('"') for j in re.findall('\"[a-z|0-9|\-|\_|\,|\.]*\"', probe_output, re.MULTILINE)] logging.debug("QEMU reported the following supported devices for " "PCI hotplug: %s", devices_supported) return (dev in devices_supported) def verify_supported_device(dev): if not is_supported_device(dev): raise error.TestError("%s doesn't support device: %s" % (cmd_type, dev)) def device_add_nic(pci_num, queues=1): device_id = pci_type + "-" + utils_misc.generate_random_id() pci_info.append([device_id, device_id]) pci_model = params.get("pci_model") if pci_model == "virtio": pci_model = "virtio-net-pci" verify_supported_device(pci_model) pci_add_cmd = "device_add id=%s,driver=%s" % (pci_info[pci_num][1], pci_model) if queues > 1 and "virtio" in pci_model: pci_add_cmd += ",mq=on" return device_add(pci_num, pci_add_cmd) def device_add_block(pci_num): device_id = pci_type + "-" + utils_misc.generate_random_id() pci_info.append([device_id, device_id]) image_format = params.get("image_format_%s" % img_list[pci_num+1]) if not image_format: image_format = params.get("image_format", "qcow2") image_filename = find_image(pci_num) pci_model = params.get("pci_model") controller_model = None if pci_model == "virtio": pci_model = "virtio-blk-pci" if pci_model == "scsi": pci_model = "scsi-disk" controller_model = "lsi53c895a" verify_supported_device(controller_model) controller_id = "controller-" + device_id controller_add_cmd = ("device_add %s,id=%s" % (controller_model, controller_id)) error.context("Adding SCSI controller.") vm.monitor.send_args_cmd(controller_add_cmd) verify_supported_device(pci_model) if drive_cmd_type == "drive_add": driver_add_cmd = ("%s auto file=%s,if=none,format=%s,id=%s" % (drive_cmd_type, image_filename, image_format, pci_info[pci_num][0])) elif drive_cmd_type == "__com.redhat_drive_add": driver_add_cmd = ("%s file=%s,format=%s,id=%s" % (drive_cmd_type, image_filename, image_format, pci_info[pci_num][0])) # add driver. error.context("Adding driver.") vm.monitor.send_args_cmd(driver_add_cmd, convert=False) pci_add_cmd = ("device_add id=%s,driver=%s,drive=%s" % (pci_info[pci_num][1], pci_model, pci_info[pci_num][0])) return device_add(pci_num, pci_add_cmd) def device_add(pci_num, pci_add_cmd): error.context("Adding pci device with command 'device_add'") if vm.monitor.protocol == 'qmp': add_output = vm.monitor.send_args_cmd(pci_add_cmd) else: add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info[pci_num].append(add_output) pci_info[pci_num].append(pci_model) after_add = vm.monitor.info("pci") if pci_info[pci_num][1] not in after_add: logging.error("Could not find matched id in monitor:" " %s" % pci_info[pci_num][1]) raise error.TestFail("Add device failed. Monitor command is: %s" ". Output: %r" % (pci_add_cmd, add_output)) return after_add # Hot add a pci device def add_device(pci_num, queues=1): info_pci_ref = vm.monitor.info("pci") reference = session.cmd_output(reference_cmd) try: # get function for adding device. add_fuction = local_functions["%s_%s" % (cmd_type, pci_type)] except Exception: raise error.TestError("No function for adding '%s' dev with '%s'" % (pci_type, cmd_type)) after_add = None if add_fuction: # Do add pci device. after_add = add_fuction(pci_num, queues) try: # Define a helper function to compare the output def _new_shown(): o = session.cmd_output(reference_cmd) return o != reference # Define a helper function to catch PCI device string def _find_pci(): output = session.cmd_output(params.get("find_pci_cmd")) output = map(string.strip, output.splitlines()) ref = map(string.strip, reference.splitlines()) output = [_ for _ in output if _ not in ref] output = "\n".join(output) if re.search(params.get("match_string"), output, re.I): return True return False error.context("Start checking new added device") # Compare the output of 'info pci' if after_add == info_pci_ref: raise error.TestFail("No new PCI device shown after executing " "monitor command: 'info pci'") secs = int(params.get("wait_secs_for_hook_up")) if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3): raise error.TestFail("No new device shown in output of command " "executed inside the guest: %s" % reference_cmd) if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3): raise error.TestFail("PCI %s %s device not found in guest. " "Command was: %s" % (pci_model, pci_type, params.get("find_pci_cmd"))) # Test the newly added device try: session.cmd(params.get("pci_test_cmd") % (pci_num+1)) except aexpect.ShellError, e: raise error.TestFail("Check for %s device failed after PCI " "hotplug. Output: %r" % (pci_type, e.output)) except Exception: pci_del(pci_num, ignore_failure=True) raise # Hot delete a pci device def pci_del(pci_num, ignore_failure=False): def _device_removed(): after_del = vm.monitor.info("pci") return after_del != before_del before_del = vm.monitor.info("pci") if cmd_type == "pci_add": slot_id = int(pci_info[pci_num][2].split(",")[2].split()[1]) cmd = "pci_del pci_addr=%s" % hex(slot_id) vm.monitor.send_args_cmd(cmd, convert=False) elif cmd_type == "device_add": cmd = "device_del id=%s" % pci_info[pci_num][1] vm.monitor.send_args_cmd(cmd) if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1) and not ignore_failure): raise error.TestFail("Failed to hot remove PCI device: %s. " "Monitor command: %s" % (pci_info[pci_num][3], cmd)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) test_timeout = int(params.get("hotplug_timeout", 360)) reference_cmd = params["reference_cmd"] # Test if it is nic or block pci_type = params["pci_type"] pci_model = params["pci_model"] # Modprobe the module if specified in config file module = params.get("modprobe_module") if module: session.cmd("modprobe %s" % module) # check monitor type qemu_binary = params.get("qemu_binary", "/usr/libexec/qemu-kvm") qemu_binary = utils_misc.get_path(test.bindir, qemu_binary) # Probe qemu to verify what is the supported syntax for PCI hotplug if vm.monitor.protocol == 'qmp': cmd_output = vm.monitor.info("commands") else: cmd_output = vm.monitor.human_monitor_cmd("help", debug=False) cmd_type = utils_test.find_substring(str(cmd_output), "device_add", "pci_add") if not cmd_output: raise error.TestError("Could find a suitable method for hotplugging" " device in this version of qemu") # Determine syntax of drive hotplug # __com.redhat_drive_add == qemu-kvm-0.12 on RHEL 6 # drive_add == qemu-kvm-0.13 onwards drive_cmd_type = utils_test.find_substring(str(cmd_output), "__com.redhat_drive_add", "drive_add") if not drive_cmd_type: raise error.TestError("Could find a suitable method for hotplugging" " drive in this version of qemu") local_functions = locals() pci_num_range = int(params.get("pci_num")) queues = int(params.get("queues")) rp_times = int(params.get("repeat_times")) img_list = params.get("images").split() context_msg = "Running sub test '%s' %s" for j in range(rp_times): # pci_info is a list of list. # each element 'i' has 4 members: # pci_info[i][0] == device drive id, only used for device_add # pci_info[i][1] == device id, only used for device_add # pci_info[i][2] == output of device add command # pci_info[i][3] == device module name. pci_info = [] for pci_num in xrange(pci_num_range): sub_type = params.get("sub_type_before_plug") if sub_type: error.context(context_msg % (sub_type, "before hotplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) error.context("Start hot-adding pci device, repeat %d" % j) add_device(pci_num, queues) sub_type = params.get("sub_type_after_plug") if sub_type: error.context(context_msg % (sub_type, "after hotplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) for pci_num in xrange(pci_num_range): sub_type = params.get("sub_type_before_unplug") if sub_type: error.context(context_msg % (sub_type, "before hotunplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type) error.context("start hot-deleting pci device, repeat %d" % j) pci_del(-(pci_num + 1)) sub_type = params.get("sub_type_after_unplug") if sub_type: error.context(context_msg % (sub_type, "after hotunplug"), logging.info) utils_test.run_virt_sub_test(test, params, env, sub_type)
def run_sr_iov_hotplug(test, params, env): """ Test hotplug of sr-iov devices. (Elements between [] are configurable test parameters) 1) Set up sr-iov test environment in host. 2) Start VM. 3) PCI add one/multi sr-io deivce with (or without) repeat 4) Compare output of monitor command 'info pci'. 5) Compare output of guest command [reference_cmd]. 6) Verify whether pci_model is shown in [pci_find_cmd]. 7) Check whether the newly added PCI device works fine. 8) Delete the device, verify whether could remove the sr-iov device. @param test: KVM test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ def pci_add_iov(pci_num): pci_add_cmd = ("pci_add pci_addr=auto host host=%s,if=%s" % (pa_pci_ids[pci_num], pci_model)) if params.get("hotplug_params"): assign_param = params.get("hotplug_params").split() for param in assign_param: value = params.get(param) if value: pci_add_cmd += ",%s=%s" % (param, value) return pci_add(pci_add_cmd) def pci_add(pci_add_cmd): error.context("Adding pci device with command 'pci_add'") add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info.append(['' , add_output]) if not "OK domain" in add_output: raise error.TestFail("Add PCI device failed. " "Monitor command is: %s, Output: %r" % (pci_add_cmd, add_output)) return vm.monitor.info("pci") def check_support_device(dev): if is_qmp_monitor: devices_supported = vm.monitor.human_monitor_cmd("%s ?" % cmd_type) else: devices_supported = vm.monitor.send_args_cmd("%s ?" % cmd_type) # Check if the device is support in qemu is_support = utils_test.find_substring(devices_supported, dev) if not is_support: raise error.TestError("%s doesn't support device: %s" % (cmd_type, dev)) def device_add_iov(pci_num): device_id = "%s" % pci_model + "-" + utils_misc.generate_random_id() pci_info.append([device_id]) check_support_device("pci-assign") pci_add_cmd = ("device_add id=%s,driver=pci-assign,host=%s" % (pci_info[pci_num][0], pa_pci_ids[pci_num])) if params.get("hotplug_params"): assign_param = params.get("hotplug_params").split() for param in assign_param: value = params.get(param) if value: pci_add_cmd += ",%s=%s" % (param, value) return device_add(pci_num, pci_add_cmd) def device_add(pci_num, pci_add_cmd): error.context("Adding pci device with command 'device_add'") if is_qmp_monitor: add_output = vm.monitor.send_args_cmd(pci_add_cmd) else: add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False) pci_info[pci_num].append(add_output) after_add = vm.monitor.info("pci") if pci_info[pci_num][0] not in after_add: logging.debug("Print info pci after add the block: %s" % after_add) raise error.TestFail("Add device failed. Monitor command is: %s" ". Output: %r" % (pci_add_cmd, add_output)) return after_add # Hot add a pci device def add_device(pci_num): reference_cmd = params.get("reference_cmd") find_pci_cmd = params.get("find_pci_cmd") info_pci_ref = vm.monitor.info("pci") reference = session.cmd_output(reference_cmd) try: # get function for adding device. add_fuction = local_functions["%s_iov" % cmd_type] except Exception: raise error.TestError("No function for adding sr-iov dev with '%s'" % cmd_type) after_add = None if add_fuction: # Do add pci device. after_add = add_fuction(pci_num) try: # Define a helper function to compare the output def _new_shown(): o = session.cmd_output(reference_cmd) return o != reference # Define a helper function to catch PCI device string def _find_pci(): o = session.cmd_output(find_pci_cmd) if re.search(match_string, o, re.IGNORECASE): return True else: return False error.context("Start checking new added device") # Compare the output of 'info pci' if after_add == info_pci_ref: raise error.TestFail("No new PCI device shown after executing " "monitor command: 'info pci'") secs = int(params.get("wait_secs_for_hook_up")) if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3): raise error.TestFail("No new device shown in output of command " "executed inside the guest: %s" % reference_cmd) if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3): raise error.TestFail("New add sr-iov device not found in guest. " "Command was: %s" % find_pci_cmd) # Test the newly added device try: session.cmd(params.get("pci_test_cmd") % (pci_num+1)) except aexpect.ShellError, e: raise error.TestFail("Check for sr-iov device failed after PCI " "hotplug. Output: %r" % e.output) except Exception: pci_del(pci_num, ignore_failure=True) raise # Hot delete a pci device def pci_del(pci_num, ignore_failure=False): def _device_removed(): after_del = vm.monitor.info("pci") return after_del != before_del before_del = vm.monitor.info("pci") if cmd_type == "pci_add": slot_id = "0" + pci_info[pci_num][1].split(",")[2].split()[1] cmd = "pci_del pci_addr=%s" % slot_id vm.monitor.send_args_cmd(cmd, convert=False) elif cmd_type == "device_add": cmd = "device_del id=%s" % pci_info[pci_num][0] vm.monitor.send_args_cmd(cmd) if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1) and not ignore_failure): raise error.TestFail("Failed to hot remove PCI device: %s. " "Monitor command: %s" % (pci_model, cmd)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) test_timeout = int(params.get("test_timeout", 360)) # Test if it is nic or block pci_num_range = int(params.get("pci_num", 1)) rp_times = int(params.get("repeat_times", 1)) pci_model = params.get("pci_model", "pci-assign") # Need udpate match_string if you use a card other than 82576 match_string = params.get("match_string", "82576") if vm.pci_assignable is not None: pa_pci_ids = vm.pci_assignable.request_devs(pci_num_range) # Modprobe the module if specified in config file module = params.get("modprobe_module") if module: error.context("modprobe the module %s" %module, logging.info) session.cmd("modprobe %s" % module) # check monitor type qemu_binary = params.get("qemu_binary", "/usr/bin/qemu-kvm") qemu_binary = utils_misc.get_path(test.bindir, qemu_binary) is_qmp_monitor = (utils_misc.qemu_has_option("qmp", qemu_binary) and params.get("monitor_type") == "qmp") # Probe qemu to verify what is the supported syntax for PCI hotplug if is_qmp_monitor: cmd_o = vm.monitor.info("commands") else: cmd_o = vm.monitor.send_args_cmd("help") cmd_type = utils_test.find_substring(str(cmd_o), "device_add", "pci_add") if not cmd_o: raise error.TestError("Unknow version of qemu") local_functions = locals() for j in range(rp_times): # pci_info is a list of list. # each element 'i' has 4 members: # pci_info[i][0] == device id, only used for device_add # pci_info[i][1] == output of device add command pci_info = [] for pci_num in xrange(pci_num_range): msg = "Start hot-adding %sth pci device, repeat %d" % (pci_num + 1, j + 1) error.context(msg, logging.info) add_device(pci_num) for pci_num in xrange(pci_num_range): msg = "start hot-deleting %sth pci device repeat %d" % (pci_num + 1, j + 1) error.context(msg, logging.info) pci_del(-(pci_num + 1))
def run_pci_hotunplug(test, params, env): """ Test hot unplug of PCI devices. 1) Set up test environment in host if test sr-iov. 2) Start VM. 3) Get the device id that want to unplug. 4) Delete the device, verify whether could remove the PCI device. :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def find_pci(): output = vm.monitor.info("qtree") devices = re.findall(match_string, output) return devices # Hot delete a pci device def pci_del(device, ignore_failure=False): def _device_removed(): after_del = vm.monitor.info("pci") return after_del != before_del before_del = vm.monitor.info("pci") if cmd_type == "device_del": cmd = "device_del id=%s" % device vm.monitor.send_args_cmd(cmd) else: raise error.TestFail("device_del command is not supported") if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1) and not ignore_failure): raise error.TestFail("Failed to hot remove PCI device: %s. " "Monitor command: %s" % (pci_model, cmd)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) test_timeout = int(params.get("test_timeout", 360)) # Test if it is nic or block pci_num = int(params.get("unplug_pci_num", 1)) pci_model = params.get("pci_model", "pci-assign") # Need udpate match_string if you use a card other than 82576 match_string = params.get("match_string", "dev: %s, id \"(.*)\"") match_string = match_string % pci_model # Modprobe the module if specified in config file module = params.get("modprobe_module") if module: error.context("modprobe the module %s" % module, logging.info) session.cmd("modprobe %s" % module) # check monitor type is_qmp_monitor = (utils_misc.qemu_has_option("qmp") and params.get("monitor_type") == "qmp") # Probe qemu to verify what is the supported syntax for PCI hotplug if is_qmp_monitor: cmd_o = vm.monitor.info("commands") else: cmd_o = vm.monitor.send_args_cmd("help") if not cmd_o: raise error.TestError("Unknow version of qemu") cmd_type = utils_test.find_substring(str(cmd_o), "device_del") devices = find_pci() if devices: for device in devices[:pci_num]: # (lmr) I think here is the place where pci_info should go pci_info = [] error.context("Hot unplug device %s" % device, logging.info) pci_del(device)