Ejemplo n.º 1
0
    def get_match_cdrom(session, serial_num):
        """
        Find the cdrom in guest which is corresponding with the CML
        according to the serial number.

        :param session: VM session.
        :param serial num: serial number of the cdrom.
        :return match_cdrom: the cdrom in guest which is corresponding
                             with the CML according to the serial number.
        """
        error.context("Get matching cdrom in guest", logging.info)
        show_serial_num = "ls -l /dev/disk/by-id"
        serial_num_output = session.cmd_output(show_serial_num)
        if serial_num_output:
            serial_cdrom = ""
            for line in serial_num_output.splitlines():
                if utils_misc.find_substring(str(line), str(serial_num)):
                    serial_cdrom = line.split(" ")[-1].split("/")[-1]
                    break
            if not serial_cdrom:
                qtree_info = vm.monitor.info("qtree")
                raise error.TestFail("Could not find the device whose "
                                     "serial number %s is same in Qemu"
                                     " CML.\n Qtree info: %s" %
                                     (qtree_info, serial_num))

        show_cdrom_cmd = "ls -l /dev/cdrom*"
        dev_cdrom_output = session.cmd_output(show_cdrom_cmd)
        if dev_cdrom_output:
            for line in dev_cdrom_output.splitlines():
                if utils_misc.find_substring(str(line), str(serial_cdrom)):
                    match_cdrom = line.split(" ")[-3]
                    return match_cdrom
            raise error.TestFail("Could not find the corresponding cdrom"
                                 "in guest which is same in Qemu CML.")
Ejemplo n.º 2
0
    def get_match_cdrom(vm, session, serial_num):
        """
        Find the cdrom in guest which is corresponding with the CML
        according to the serial number.

        :param session: VM session.
        :param serial num: serial number of the cdrom.
        :return match_cdrom: the cdrom in guest which is corresponding
                             with the CML according to the serial number.
        """
        error.context("Get matching cdrom in guest", logging.info)
        show_serial_num = "ls -l /dev/disk/by-id"
        serial_num_output = session.cmd_output(show_serial_num)
        if serial_num_output:
            serial_cdrom = ""
            for line in serial_num_output.splitlines():
                if utils_misc.find_substring(str(line), str(serial_num)):
                    serial_cdrom = line.split(" ")[-1].split("/")[-1]
                    break
            if not serial_cdrom:
                qtree_info = vm.monitor.info("qtree")
                raise error.TestFail("Could not find the device whose "
                                     "serial number %s is same in Qemu"
                                     " CML.\n Qtree info: %s" %
                                     (serial_num, qtree_info))

        show_cdrom_cmd = "ls -l /dev/cdrom*"
        dev_cdrom_output = session.cmd_output(show_cdrom_cmd)
        if dev_cdrom_output:
            for line in dev_cdrom_output.splitlines():
                if utils_misc.find_substring(str(line), str(serial_cdrom)):
                    match_cdrom = line.split(" ")[-3]
                    return match_cdrom
            raise error.TestFail("Could not find the corresponding cdrom"
                                 "in guest which is same in Qemu CML.")
Ejemplo n.º 3
0
 def check_support_device(dev):
     if vm.monitor.protocol == 'qmp':
         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_misc.find_substring(devices_supported, dev)
     if not is_support:
         test.error("%s doesn't support device: %s" % (cmd_type, dev))
Ejemplo n.º 4
0
 def check_support_device(dev):
     if vm.monitor.protocol == "qmp":
         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_misc.find_substring(devices_supported, dev)
     if not is_support:
         raise error.TestError("%s doesn't support device: %s" % (cmd_type, dev))
Ejemplo n.º 5
0
def run(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) Disable the primary link(s) of guest.
    4) PCI add one/multi sr-io  deivce with (or without) repeat
    5) Compare output of monitor command 'info pci'.
    6) Compare output of guest command [reference_cmd].
    7) Verify whether pci_model is shown in [pci_find_cmd].
    8) Check whether the newly added PCI device works fine.
    9) Delete the device, verify whether could remove the sr-iov device.
    10) Re-enabling the primary link(s) of guest.

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

    def get_active_network_device(session, nic_filter):
        devnames = []
        cmd = "ifconfig -a"
        status, output = session.cmd_status_output(cmd)
        if status:
            msg = "Guest command '%s' fail with output: %s." % (cmd, output)
            raise error.TestError(msg)
        devnames = re.findall(nic_filter, output)
        return devnames

    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 vm.monitor.protocol == 'qmp':
            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_misc.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])
        driver  = params.get("device_driver", "pci-assign")
        check_support_device(driver)
        pci_add_cmd = ("device_add id=%s,driver=%s,host=%s" %
                       (pci_info[pci_num][0], driver, 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 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)
        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["reference_cmd"]
        find_pci_cmd = params["find_pci_cmd"]
        info_pci_ref = vm.monitor.info("pci")
        reference = session.cmd_output(reference_cmd)
        active_nics = get_active_network_device(session, nic_filter)
        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():
                output = session.cmd_output(reference_cmd)
                return output != reference

            # Define a helper function to make sure new nic could get ip.
            def _check_ip():
                post_nics = get_active_network_device(session, nic_filter)
                return (len(active_nics) <= len(post_nics) and
                        active_nics != post_nics)

            # Define a helper function to catch PCI device string
            def _find_pci():
                output = session.cmd_output(find_pci_cmd)
                if re.search(match_string, output, 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["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 device not found in guest. "
                                     "Command was: %s" % find_pci_cmd)

            # Test the newly added device
            if not utils_misc.wait_for(_check_ip, 30, 3, 3):
                ifconfig = session.cmd_output("ifconfig -a")
                raise error.TestFail("New hotpluged device could not get ip "
                                     "after 30s in guest. guest ifconfig "
                                     "output: \n%s" % ifconfig)
            try:
                session.cmd(params["pci_test_cmd"] % (pci_num + 1))
            except aexpect.ShellError, e:
                raise error.TestFail("Check 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_serial_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")
    nic_filter = params["nic_interface_filter"]
    devices = []
    device_type = params.get("hotplug_device_type", "vf")
    for i in xrange(pci_num_range):
        device = {}
        device["type"] = device_type
        device['mac'] = utils_net.generate_mac_address_simple()
        if params.get("device_name"):
            device["name"] = params.get("device_name")
        devices.append(device)
    device_driver = params.get("device_driver", "pci-assign")
    if vm.pci_assignable is None:
        vm.pci_assignable = test_setup.PciAssignable(
            driver=params.get("driver"),
            driver_option=params.get("driver_option"),
            host_set_flag=params.get("host_setup_flag"),
            kvm_params=params.get("kvm_default"),
            vf_filter_re=params.get("vf_filter_re"),
            pf_filter_re=params.get("pf_filter_re"),
            device_driver=device_driver)

    pa_pci_ids = vm.pci_assignable.request_devs(devices)
    # 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)

    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == 'qmp':
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")

    cmd_type = utils_misc.find_substring(str(cmd_o), "device_add", "pci_add")
    if not cmd_o:
        raise error.TestError("Unknow version of qemu")

    local_functions = locals()

    error.context("Disable the primary link(s) of guest", logging.info)
    for nic in vm.virtnet:
        vm.set_link(nic.device_id, up=False)

    try:
        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," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error.context(msg, logging.info)
                add_device(pci_num)
            sub_type = params.get("sub_type_after_plug")
            if sub_type:
                error.context("Running sub test '%s' after hotplug" % sub_type,
                              logging.info)
                utils_test.run_virt_sub_test(test, params, env, sub_type)
                if "guest_suspend" == sub_type:
                    # Hotpluged device have been released after guest suspend,
                    # so do not need unpluged step.
                    break
            for pci_num in xrange(pci_num_range):
                msg = "start hot-deleting %sth pci device," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error.context(msg, logging.info)
                pci_del(-(pci_num + 1))
    finally:
        error.context("Re-enabling the primary link(s) of guest", logging.info)
        for nic in vm.virtnet:
            vm.set_link(nic.device_id, up=True)
Ejemplo n.º 6
0
def run(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) Disable the primary link(s) of guest.
    4) PCI add one/multi sr-io  deivce with (or without) repeat
    5) Compare output of monitor command 'info pci'.
    6) Compare output of guest command [reference_cmd].
    7) Verify whether pci_model is shown in [pci_find_cmd].
    8) Check whether the newly added PCI device works fine.
    9) Delete the device, verify whether could remove the sr-iov device.
    10) Re-enabling the primary link(s) of guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def get_active_network_device(session, nic_filter):
        devnames = []
        cmd = "ifconfig -a"
        status, output = session.cmd_status_output(cmd)
        if status:
            msg = "Guest command '%s' fail with output: %s." % (cmd, output)
            raise error.TestError(msg)
        devnames = re.findall(nic_filter, output)
        return devnames

    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 "OK domain" not 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 vm.monitor.protocol == 'qmp':
            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_misc.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])
        driver = params.get("device_driver", "pci-assign")
        check_support_device(driver)
        pci_add_cmd = ("device_add id=%s,driver=%s,host=%s" %
                       (pci_info[pci_num][0], driver, 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 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)
        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][0] not in str(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["reference_cmd"]
        find_pci_cmd = params["find_pci_cmd"]
        info_pci_ref = vm.monitor.info("pci")
        reference = session.cmd_output(reference_cmd)
        active_nics = get_active_network_device(session, nic_filter)
        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():
                output = session.cmd_output(reference_cmd)
                return output != reference

            # Define a helper function to make sure new nic could get ip.
            def _check_ip():
                post_nics = get_active_network_device(session, nic_filter)
                return (len(active_nics) <= len(post_nics)
                        and active_nics != post_nics)

            # Define a helper function to catch PCI device string
            def _find_pci():
                output = session.cmd_output(find_pci_cmd)
                if re.search(match_string, output, 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["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 device not found in guest. "
                                     "Command was: %s" % find_pci_cmd)

            # Test the newly added device
            if not utils_misc.wait_for(_check_ip, 120, 3, 3):
                ifconfig = session.cmd_output("ifconfig -a")
                raise error.TestFail("New hotpluged device could not get ip "
                                     "after 120s in guest. guest ifconfig "
                                     "output: \n%s" % ifconfig)
            try:
                session.cmd(params["pci_test_cmd"] % (pci_num + 1))
            except aexpect.ShellError, e:
                raise error.TestFail("Check 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_serial_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")
    generate_mac = params.get("generate_mac", "yes")
    nic_filter = params["nic_interface_filter"]
    devices = []
    device_type = params.get("hotplug_device_type", "vf")
    for i in xrange(pci_num_range):
        device = {}
        device["type"] = device_type
        if generate_mac == "yes":
            device['mac'] = utils_net.generate_mac_address_simple()
        if params.get("device_name"):
            device["name"] = params.get("device_name")
        devices.append(device)
    device_driver = params.get("device_driver", "pci-assign")
    if vm.pci_assignable is None:
        vm.pci_assignable = test_setup.PciAssignable(
            driver=params.get("driver"),
            driver_option=params.get("driver_option"),
            host_set_flag=params.get("host_setup_flag"),
            kvm_params=params.get("kvm_default"),
            vf_filter_re=params.get("vf_filter_re"),
            pf_filter_re=params.get("pf_filter_re"),
            device_driver=device_driver)

    pa_pci_ids = vm.pci_assignable.request_devs(devices)
    # 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)

    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == 'qmp':
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")

    cmd_type = utils_misc.find_substring(str(cmd_o), "device_add", "pci_add")
    if not cmd_o:
        raise error.TestError("Unknown version of qemu")

    local_functions = locals()

    if params.get("enable_set_link" "yes") == "yes":
        error.context("Disable the primary link(s) of guest", logging.info)
        for nic in vm.virtnet:
            vm.set_link(nic.device_id, up=False)

    try:
        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," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error.context(msg, logging.info)
                add_device(pci_num)
            sub_type = params.get("sub_type_after_plug")
            if sub_type:
                error.context("Running sub test '%s' after hotplug" % sub_type,
                              logging.info)
                utils_test.run_virt_sub_test(test, params, env, sub_type)
                if "guest_suspend" == sub_type:
                    # Hotpluged device have been released after guest suspend,
                    # so do not need unpluged step.
                    break
            for pci_num in xrange(pci_num_range):
                msg = "start hot-deleting %sth pci device," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error.context(msg, logging.info)
                pci_del(-(pci_num + 1))
    finally:
        if params.get("enable_set_link", "yes") == "yes":
            error.context("Re-enabling the primary link(s) of guest",
                          logging.info)
            for nic in vm.virtnet:
                vm.set_link(nic.device_id, up=True)
Ejemplo n.º 7
0
def run(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_misc.find_substring(str(cmd_o), "device_del")

    devices = find_pci()
    context_msg = "Running sub test '%s' %s"
    sub_type = params.get("sub_type_before_unplug")
    if sub_type:
        error.context(context_msg % (sub_type, "before unplug"), logging.info)
        utils_test.run_virt_sub_test(test, params, env, sub_type)

    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)

    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)
Ejemplo n.º 8
0
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"
            if arch.ARCH == "ppc64":
                controller_model = "spapr-vscsi"
            else:
                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_misc.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_misc.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", 1))
    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()
Ejemplo n.º 9
0
def run(test, params, env):
    """
    Test hotplug of PCI devices and check the status in guest.
    1 Boot up a guest
    2 Hotplug virtio disk to the guest. Record the id and partition name of
      the disk in a list.
    3 Random choice a disk in the list. Unplug the disk and check the
      partition status.
    4 Hotpulg the disk back to guest with the same monitor cmdline and same
      id which is record in step 2.
    5 Check the partition status in guest. And confirm the disk with dd cmd
    6 Repeat step 3 to 5 for N times

    :param test:   KVM test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def prepare_image_params(params):
        pci_num = int(params['pci_num'])
        for i in xrange(pci_num):
            image_name = '%s_%s' % ('stg', i)
            params['images'] = ' '.join([params['images'], image_name])
            image_image_name = '%s_%s' % ('image_name', image_name)
            params[image_image_name] = '%s_%s' % ('storage', i)
            image_image_format = '%s_%s' % ('image_format', image_name)
            params[image_image_format] = params.get('image_format_extra',
                                                    'qcow2')
            image_image_size = '%s_%s' % ('image_size', image_name)
            params[image_image_size] = params.get('image_size_extra', '128K')
        return params

    def find_new_device(check_cmd, device_string, chk_timeout=5.0):
        end_time = time.time() + chk_timeout
        idx = ("wmic" in check_cmd and [0] or [-1])[0]
        while time.time() < end_time:
            new_line = session.cmd_output(check_cmd)
            for line in re.split("\n+", new_line.strip()):
                dev_name = re.split("\s+", line.strip())[idx]
                if dev_name not in device_string:
                    return dev_name
            time.sleep(0.1)
        return None

    def find_del_device(check_cmd, device_string, chk_timeout=5.0):
        end_time = time.time() + chk_timeout
        idx = ("wmic" in check_cmd and [0] or [-1])[0]
        while time.time() < end_time:
            new_line = session.cmd_output(check_cmd)
            for line in re.split("\n+", device_string.strip()):
                dev_name = re.split("\s+", line.strip())[idx]
                if dev_name not in new_line:
                    return dev_name
            time.sleep(0.1)
        return None

    # 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_block(pci_num, queues, pci_id):
        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):
        guest_devices = session.cmd_output(chk_cmd)
        error.context("Adding pci device with command 'pci_add'")
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        guest_device = find_new_device(chk_cmd, guest_devices)
        pci_info.append(['', '', add_output, pci_model, guest_device])
        if "OK domain" not 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("Unknown 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_block(pci_num, queues=1, pci_id=None):
        if pci_id is not None:
            device_id = pci_type + "-" + pci_id
        else:
            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"
            if arch.ARCH in ('ppc64', 'ppc64le'):
                controller_model = "spapr-vscsi"
            else:
                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, pci_id=pci_id)

    def device_add(pci_num, pci_add_cmd, pci_id=None):
        error.context("Adding pci device with command 'device_add'")
        guest_devices = session.cmd_output(chk_cmd)
        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)
        guest_device = find_new_device(chk_cmd, guest_devices)
        if pci_id is None:
            pci_info[pci_num].append(add_output)
            pci_info[pci_num].append(pci_model)
            pci_info[pci_num].append(guest_device)

        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][1] not in str(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, pci_id=None):
        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 " % pci_type +
                                  "with '%s'" % cmd_type)
        after_add = None
        if add_fuction:
            # Do add pci device.
            after_add = add_fuction(pci_num, queues, pci_id)

        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 " % (pci_model, pci_type) +
                                     "device not found in guest. Command " +
                                     "was: %s" % 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" % pci_type +
                                     "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 = 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))

    params = prepare_image_params(params)
    env_process.process_images(env_process.preprocess_image, test, params)
    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 = utils_misc.get_qemu_binary(params)
    # 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_misc.find_substring(str(cmd_output), "device_add",
                                         "pci_add")
    if not cmd_type:
        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_misc.find_substring(str(cmd_output),
                                               "__com.redhat_drive_add",
                                               "drive_add")
    if not drive_cmd_type:
        raise error.TestError("Unknown version of qemu")

    local_functions = locals()

    pci_num_range = int(params.get("pci_num"))
    rp_times = int(params.get("repeat_times"))
    img_list = params.get("images").split()
    chk_cmd = params.get("guest_check_cmd")
    mark_cmd = params.get("mark_cmd")
    offset = params.get("offset")
    confirm_cmd = params.get("confirm_cmd")

    pci_info = []
    # Add block device into guest
    for pci_num in xrange(pci_num_range):
        error.context("Prepare the %d removable pci device" % pci_num,
                      logging.info)
        add_device(pci_num)
        if pci_info[pci_num][4] is not None:
            partition = pci_info[pci_num][4]
            cmd = mark_cmd % (partition, partition, offset)
            session.cmd(cmd)
        else:
            raise error.TestError("Device not init in guest")

    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[i][4] == partition id in guest
        pci_num = random.randint(0, len(pci_info) - 1)
        error.context("start unplug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        pci_del(pci_num)
        device_del = find_del_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device is not deleted in guest.")
        error.context("Start plug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        add_device(pci_num, pci_id=pci_info[pci_num][0])
        device_del = find_new_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device partition changed from %s to %s" %
                                 (pci_info[pci_num][4], device_del))
        cmd = confirm_cmd % (pci_info[pci_num][4], offset)
        confirm_info = session.cmd_output(cmd)
        if device_del not in confirm_info:
            raise error.TestFail("Can not find partition tag in Guest: %s" %
                                 confirm_info)
Ejemplo n.º 10
0
def run(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_invaild_addr = params.get("pci_invaild_addr")
    modprobe_cmd = params.get("modprobe_cmd")

    device = {}
    device["type"] = params.get("hotplug_device_type", "vf")
    device['mac'] = utils_net.generate_mac_address_simple()
    if params.get("device_name"):
        device["name"] = params.get("device_name")

    if vm.pci_assignable is not None:
        pa_pci_ids = vm.pci_assignable.request_devs(device)
    # 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("Unknown version of qemu")

    cmd_type = utils_misc.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_invaild_addr)
        elif cmd_type == "device_add":
            pci_add_cmd = make_device_add_cmd(pa_pci_ids[0], pci_invaild_addr)
        try:
            msg = "Adding pci device with command '%s'" % pci_add_cmd
            error.context(msg, logging.info)
            case_fail = False
            pci_add_cmd += ",bus=root_port"
            add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
            case_fail = True
        except Exception, err:
            if neg_msg:
                msg = "Check negative hotplug error message"
                error.context(msg, logging.info)
                if neg_msg not in str(err):
                    msg = "Could not find '%s' in" % neg_msg
                    msg += " command output '%s'" % add_output
                    raise error.TestFail(msg)
            logging.debug("Could not boot up vm, %s" % err)
        if case_fail:
            if neg_msg:
                msg = "Check negative hotplug error message"
                error.context(msg, logging.info)
                if neg_msg not in str(add_output):
                    msg = "Could not find '%s' in" % neg_msg
                    msg += " command output '%s'" % add_output
                    raise error.TestFail(msg)
            logging.debug("Could not boot up vm, %s" % add_output)
Ejemplo n.º 11
0
def run(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'", logging.info)
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        pci_info.append(['', '', add_output, pci_model])

        if "OK domain" not 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, queues=1):
        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" or pci_model == "scsi-hd":
            if pci_model == "scsi":
                pci_model = "scsi-disk"
                if arch.ARCH in ('ppc64', 'ppc64le'):
                    controller_model = "spapr-vscsi"
                else:
                    controller_model = "lsi53c895a"
            if pci_model == "scsi-hd":
                controller_model = "virtio-scsi-pci"
            verify_supported_device(controller_model)
            controller_id = "controller-" + device_id
            if vm.monitor.protocol == "human":
                controller_add_cmd = ("device_add %s,id=%s" %
                                      (controller_model, controller_id))
            else:
                controller_add_cmd = ("device_add driver=%s,id=%s" %
                                      (controller_model, controller_id))
            error.context("Adding SCSI controller.", logging.info)
            vm.monitor.send_args_cmd(controller_add_cmd, convert=False)

        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 block device to vm device container
        image_name = img_list[pci_num + 1]
        image_params = params.object_params(image_name)
        image_name = pci_info[pci_num][0]
        blk_insert = vm.devices.images_define_by_params(
            image_name, image_params, 'disk')
        vm.devices.insert(blk_insert)
        env.register_vm(vm.name, vm)

        # add driver.
        error.context("Adding driver.", logging.info)
        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'",
                      logging.info)
        if vm.monitor.protocol == 'qmp':
            add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        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 str(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 | re.M):
                    return True
                return False

            error.context("Start checking new added device", logging.info)
            # 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:
                if params.get("pci_test_cmd"):
                    test_cmd = re.sub("PCI_NUM", "%s" % (pci_num + 1),
                                      params.get("pci_test_cmd"))
                    session.cmd(test_cmd, timeout=disk_op_timeout)
            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")
        blk_removed = []
        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)
            blk_removed.append(pci_info[pci_num][1])
        elif cmd_type == "device_add":
            if vm.monitor.protocol == "human":
                cmd = "device_del %s" % pci_info[pci_num][1]
            else:
                cmd = "device_del id=%s" % pci_info[pci_num][1]
            vm.monitor.send_args_cmd(cmd, convert=False)
            if params.get("cmd_after_unplug_dev"):
                cmd = re.sub("PCI_NUM", "%s" % (pci_num + 1),
                             params.get("cmd_after_unplug_dev"))
                session.cmd(cmd, timeout=disk_op_timeout)
            blk_removed.append(pci_info[pci_num][1])
            pci_model = params.get("pci_model")
            if pci_model == "scsi" or pci_model == "scsi-hd":
                controller_id = "controller-" + pci_info[pci_num][0]
                if vm.monitor.protocol == "human":
                    controller_del_cmd = "device_del %s" % controller_id
                else:
                    controller_del_cmd = "device_del id=%s" % controller_id
                error.context("Deleting SCSI controller.", logging.info)
                vm.monitor.send_args_cmd(controller_del_cmd, convert=False)
                blk_removed.append(controller_id)

        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))
        # Remove the device from vm device container
        for device in vm.devices:
            if device.str_short() in blk_removed:
                vm.devices.remove(device)
        env.register_vm(vm.name, vm)

    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))
    disk_op_timeout = int(params.get("disk_op_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 = utils_misc.get_qemu_binary(params)
    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_misc.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_misc.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", 1))
    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,
                          logging.info)
            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,
                          logging.info)
            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()
Ejemplo n.º 12
0
def run(test, params, env):
    """
    Test hotplug of PCI devices and check the status in guest.
    1 Boot up a guest
    2 Hotplug virtio disk to the guest. Record the id and partition name of
      the disk in a list.
    3 Random choice a disk in the list. Unplug the disk and check the
      partition status.
    4 Hotpulg the disk back to guest with the same monitor cmdline and same
      id which is record in step 2.
    5 Check the partition status in guest. And confirm the disk with dd cmd
    6 Repeat step 3 to 5 for N times

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

    def prepare_image_params(params):
        pci_num = int(params['pci_num'])
        for i in xrange(pci_num):
            image_name = '%s_%s' % ('stg', i)
            params['images'] = ' '.join([params['images'], image_name])
            image_image_name = '%s_%s' % ('image_name', image_name)
            params[image_image_name] = '%s_%s' % ('storage', i)
            image_image_format = '%s_%s' % ('image_format', image_name)
            params[image_image_format] = params.get('image_format_extra', 'qcow2')
            image_image_size = '%s_%s' % ('image_size', image_name)
            params[image_image_size] = params.get('image_size_extra', '128K')
        return params

    def find_new_device(check_cmd, device_string, chk_timeout=5.0):
        end_time = time.time() + chk_timeout
        idx = ("wmic" in check_cmd and [0] or [-1])[0]
        while time.time() < end_time:
            new_line = session.cmd_output(check_cmd)
            for line in re.split("\n+", new_line.strip()):
                dev_name = re.split("\s+", line.strip())[idx]
                if dev_name not in device_string:
                    return dev_name
            time.sleep(0.1)
        return None

    def find_del_device(check_cmd, device_string, chk_timeout=5.0):
        end_time = time.time() + chk_timeout
        idx = ("wmic" in check_cmd and [0] or [-1])[0]
        while time.time() < end_time:
            new_line = session.cmd_output(check_cmd)
            for line in re.split("\n+", device_string.strip()):
                dev_name = re.split("\s+", line.strip())[idx]
                if dev_name not in new_line:
                    return dev_name
            time.sleep(0.1)
        return None

    # 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_block(pci_num, queues, pci_id):
        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):
        guest_devices = session.cmd_output(chk_cmd)
        error.context("Adding pci device with command 'pci_add'")
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        guest_device = find_new_device(chk_cmd, guest_devices)
        pci_info.append(['', '', add_output, pci_model, guest_device])
        if "OK domain" not 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("Unknown 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_block(pci_num, queues=1, pci_id=None):
        if pci_id is not None:
            device_id = pci_type + "-" + pci_id
        else:
            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"
            if arch.ARCH in ('ppc64', 'ppc64le'):
                controller_model = "spapr-vscsi"
            else:
                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, pci_id=pci_id)

    def device_add(pci_num, pci_add_cmd, pci_id=None):
        error.context("Adding pci device with command 'device_add'")
        guest_devices = session.cmd_output(chk_cmd)
        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)
        guest_device = find_new_device(chk_cmd, guest_devices)
        if pci_id is None:
            pci_info[pci_num].append(add_output)
            pci_info[pci_num].append(pci_model)
            pci_info[pci_num].append(guest_device)

        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][1] not in str(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, pci_id=None):
        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 " % pci_type +
                                  "with '%s'" % cmd_type)
        after_add = None
        if add_fuction:
            # Do add pci device.
            after_add = add_fuction(pci_num, queues, pci_id)

        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", 3))
            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 " % (pci_model, pci_type) +
                                     "device not found in guest. Command " +
                                     "was: %s" % 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" % pci_type +
                                     "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 = 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))

    params = prepare_image_params(params)
    env_process.process_images(env_process.preprocess_image, test, params)
    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 = utils_misc.get_qemu_binary(params)
    # 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_misc.find_substring(str(cmd_output), "device_add",
                                         "pci_add")
    if not cmd_type:
        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_misc.find_substring(str(cmd_output),
                                               "__com.redhat_drive_add",
                                               "drive_add")
    if not drive_cmd_type:
        raise error.TestError("Unknown version of qemu")

    local_functions = locals()

    pci_num_range = int(params.get("pci_num"))
    rp_times = int(params.get("repeat_times"))
    img_list = params.get("images").split()
    chk_cmd = params.get("guest_check_cmd")
    mark_cmd = params.get("mark_cmd")
    offset = params.get("offset")
    confirm_cmd = params.get("confirm_cmd")

    pci_info = []
    # Add block device into guest
    for pci_num in xrange(pci_num_range):
        error.context("Prepare the %d removable pci device" % pci_num,
                      logging.info)
        add_device(pci_num)
        if pci_info[pci_num][4] is not None:
            partition = pci_info[pci_num][4]
            cmd = mark_cmd % (partition, partition, offset)
            session.cmd(cmd)
        else:
            raise error.TestError("Device not init in guest")

    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[i][4] == partition id in guest
        pci_num = random.randint(0, len(pci_info) - 1)
        error.context("start unplug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        pci_del(pci_num)
        device_del = find_del_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device is not deleted in guest.")
        error.context("Start plug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        add_device(pci_num, pci_id=pci_info[pci_num][0])
        device_del = find_new_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device partition changed from %s to %s" %
                                 (pci_info[pci_num][4], device_del))
        cmd = confirm_cmd % (pci_info[pci_num][4], offset)
        confirm_info = session.cmd_output(cmd)
        if device_del not in confirm_info:
            raise error.TestFail("Can not find partition tag in Guest: %s" %
                                 confirm_info)
Ejemplo n.º 13
0
def run(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_invaild_addr = params.get("pci_invaild_addr")
    modprobe_cmd = params.get("modprobe_cmd")

    device = {}
    device["type"] = params.get("hotplug_device_type", "vf")
    device['mac'] = utils_net.generate_mac_address_simple()
    if params.get("device_name"):
        device["name"] = params.get("device_name")

    if vm.pci_assignable is not None:
        pa_pci_ids = vm.pci_assignable.request_devs(device)
    # 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("Unknown version of qemu")

    cmd_type = utils_misc.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_invaild_addr)
        elif cmd_type == "device_add":
            pci_add_cmd = make_device_add_cmd(pa_pci_ids[0], pci_invaild_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, err:
            if neg_msg:
                msg = "Check negative hotplug error message"
                error.context(msg, logging.info)
                if neg_msg not in str(err):
                    msg = "Could not find '%s' in" % neg_msg
                    msg += " command output '%s'" % add_output
                    raise error.TestFail(msg)
            logging.debug("Could not boot up vm, %s" % err)
        if case_fail:
            if neg_msg:
                msg = "Check negative hotplug error message"
                error.context(msg, logging.info)
                if neg_msg not in str(add_output):
                    msg = "Could not find '%s' in" % neg_msg
                    msg += " command output '%s'" % add_output
                    raise error.TestFail(msg)
            logging.debug("Could not boot up vm, %s" % add_output)
Ejemplo n.º 14
0
def run(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) Disable the primary link(s) of guest.
    4) PCI add one/multi sr-io  deivce with (or without) repeat
    5) Compare output of monitor command 'info pci'.
    6) Compare output of guest command [reference_cmd].
    7) Verify whether pci_model is shown in [pci_find_cmd].
    8) Check whether the newly added PCI device works fine.
    9) Delete the device, verify whether could remove the sr-iov device.
    10) Re-enabling the primary link(s) of guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def check_interface(iface, nic_filter):
        cmd = "ifconfig %s" % str(iface)
        session = vm.wait_for_serial_login(timeout=timeout)
        status, output = session.cmd_status_output(cmd)
        if status:
            test.error("Guest command '%s' fail with output: %s." %
                       (cmd, output))
        if re.findall(nic_filter, output, re.MULTILINE | re.DOTALL):
            return True
        return False

    def get_active_network_device(session, nic_filter):
        devnames = []
        cmd = "ifconfig -a"
        nic_reg = r"\w+(?=: flags)|\w+(?=\s*Link)"
        status, output = session.cmd_status_output(cmd)
        if status:
            test.error("Guest command '%s' fail with output: %s." %
                       (cmd, output))
        ifaces = re.findall(nic_reg, output)
        for iface in ifaces:
            if check_interface(str(iface), nic_filter):
                devnames.append(iface)
        return devnames

    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.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 "OK domain" not in add_output:
            test.fail("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 vm.monitor.protocol == 'qmp':
            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_misc.find_substring(devices_supported, dev)
        if not is_support:
            test.error("%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])
        driver = params.get("device_driver", "pci-assign")
        check_support_device(driver)
        pci_add_cmd = ("device_add id=%s,driver=%s,host=%s" %
                       (pci_info[pci_num][0], driver, 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.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)
        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][0] not in str(after_add):
            logging.debug("Print info pci after add the block: %s", after_add)
            test.fail("Add device failed. Monitor command is: %s"
                      ". Output: %r" % (pci_add_cmd, add_output))
        return after_add

    def clean_network_scripts():
        logging.debug("Clean up network scripts in guest")
        session = vm.wait_for_serial_login(timeout=timeout)
        if "ubuntu" in vm.get_distro().lower():
            iface_script = "/etc/network/interfaces"
            cmd = "cat %s.BACKUP" % iface_script
            if not session.cmd_status(cmd):
                cmd = "mv %s.BACKUP %s" % (iface_script, iface_script)
                status, output = session.cmd_status_output(cmd)
                if status:
                    test.error("Failed to cleanup network script in guest: "
                               "%s" % output)
        else:
            global iface_scripts
            for iface_script in iface_scripts:
                cmd = "rm -f %s" % iface_script
                status, output = session.cmd_status_output(cmd)
                if status:
                    test.error("Failed to delete iface_script")
                iface_scripts.remove(iface_script)

    # Hot add a pci device
    def add_device(pci_num):
        global iface_scripts
        reference_cmd = params["reference_cmd"]
        info_pci_ref = vm.monitor.info("pci")
        session = vm.wait_for_serial_login(timeout=timeout)
        reference = session.cmd_output(reference_cmd)
        active_nics = get_active_network_device(session, nic_filter)
        logging.debug("Active nics before hotplug - %s", active_nics)

        # Stop the VM monitor and try hot adding SRIOV dev
        if params.get("vm_stop", "no") == "yes":
            logging.debug("stop the monitor of the VM before hotplug")
            vm.pause()
        try:
            # get function for adding device.
            add_function = local_functions["%s_iov" % cmd_type]
        except Exception:
            test.error("No function for adding sr-iov dev with '%s'" %
                       cmd_type)
        after_add = None
        if add_function:
            # Do add pci device.
            after_add = add_function(pci_num)

        try:
            # Define a helper function to compare the output
            def _new_shown():
                output = session.cmd_output(reference_cmd)
                return output != reference

            # Define a helper function to make sure new nic could get ip.
            def _check_ip():
                post_nics = get_active_network_device(session, nic_filter)
                logging.debug("Active nics after hotplug - %s", post_nics)
                return (len(active_nics) <= len(post_nics)
                        and active_nics != post_nics)

            # Define a helper function to catch PCI device string
            def _find_pci():
                output = session.cmd_output("lspci -nn")
                if re.search(vf_filter, output, re.IGNORECASE):
                    return True
                else:
                    return False

            # Resume the VM
            if params.get("vm_resume", "no") == "yes":
                logging.debug("resuming the VM after hotplug")
                vm.resume()

            # Reboot the VM
            if params.get("vm_reboot", "no") == "yes":
                logging.debug("Rebooting the VM after hotplug")
                vm.reboot()
            session = vm.wait_for_serial_login(timeout=timeout)

            error_context.context("Start checking new added device")
            # Compare the output of 'info pci'
            if after_add == info_pci_ref:
                test.fail("No new PCI device shown after executing "
                          "monitor command: 'info pci'")

            secs = int(params["wait_secs_for_hook_up"])
            if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3):
                test.fail("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):
                test.fail("New add device not found in guest. "
                          "Command was: lspci -nn")

            # Assign static IP to the hotplugged interface
            if params.get("assign_static_ip", "no") == "yes":
                cmd = "service networking restart"
                static_ip = next(ip_gen)
                net_mask = params.get("static_net_mask", "255.255.255.0")
                broadcast = params.get("static_broadcast", "10.10.10.255")
                pci_id = utils_misc.get_pci_id_using_filter(vf_filter, session)
                logging.debug("PCIs associated with %s - %s", vf_filter,
                              ', '.join(map(str, pci_id)))
                for each_pci in pci_id:
                    iface_name = utils_misc.get_interface_from_pci_id(
                        each_pci, session)
                    logging.debug("Interface associated with PCI %s - %s",
                                  each_pci, iface_name)
                    mac = session.cmd_output("ethtool -P %s" % iface_name)
                    mac = mac.split("Permanent address:")[-1].strip()
                    logging.debug("mac address of %s: %s", iface_name, mac)
                    # backup the network script for other distros
                    if "ubuntu" not in vm.get_distro().lower():
                        cmd = "service network restart"
                        iface_scripts.append(
                            utils_net.get_network_cfg_file(iface_name))
                    if not check_interface(str(iface_name), nic_filter):
                        utils_net.create_network_script(iface_name,
                                                        mac,
                                                        boot_proto="static",
                                                        net_mask=net_mask,
                                                        vm=vm,
                                                        ip_addr=static_ip)
                        status, output = session.cmd_status_output(cmd)
                        if status:
                            test.error("Failed to set static ip in guest: "
                                       "%s" % output)
            # Test the newly added device
            if not utils_misc.wait_for(_check_ip, 120, 3, 3):
                ifconfig = session.cmd_output("ifconfig -a")
                test.fail("New hotpluged device could not get ip "
                          "after 120s in guest. guest ifconfig "
                          "output: \n%s" % ifconfig)
            try:
                session.cmd(params["pci_test_cmd"] % (pci_num + 1))
            except aexpect.ShellError as e:
                test.fail("Check 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):
            test.fail("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_serial_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")
    vf_filter = params.get("vf_filter_re")
    generate_mac = params.get("generate_mac", "yes")
    nic_filter = params["nic_interface_filter"]
    devices = []
    device_type = params.get("hotplug_device_type", "vf")
    for i in range(pci_num_range):
        device = {}
        device["type"] = device_type
        if generate_mac == "yes":
            device['mac'] = utils_net.generate_mac_address_simple()
        if params.get("device_name"):
            device["name"] = params.get("device_name")
        devices.append(device)
    device_driver = params.get("device_driver", "pci-assign")
    if vm.pci_assignable is None:
        vm.pci_assignable = test_setup.PciAssignable(
            driver=params.get("driver"),
            driver_option=params.get("driver_option"),
            host_set_flag=params.get("host_setup_flag"),
            kvm_params=params.get("kvm_default"),
            vf_filter_re=vf_filter,
            pf_filter_re=params.get("pf_filter_re"),
            device_driver=device_driver,
            pa_type=params.get("pci_assignable"))

    pa_pci_ids = vm.pci_assignable.request_devs(devices)
    # Modprobe the module if specified in config file
    module = params.get("modprobe_module")
    if module:
        error_context.context("modprobe the module %s" % module, logging.info)
        session.cmd("modprobe %s" % module)

    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == 'qmp':
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")

    cmd_type = utils_misc.find_substring(str(cmd_o), "device_add", "pci_add")
    if not cmd_o:
        test.error("Unknown version of qemu")

    local_functions = locals()

    if params.get("enable_set_link" "yes") == "yes":
        error_context.context("Disable the primary link(s) of guest",
                              logging.info)
        for nic in vm.virtnet:
            vm.set_link(nic.device_id, up=False)

    try:
        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 = []
            if params.get("assign_static_ip", "no") == "yes":
                ip_gen = utils_net.gen_ipv4_addr(exclude_ips=[])
                # backup the network script file if it is ubuntu
                if "ubuntu" in vm.get_distro().lower():
                    session = vm.wait_for_serial_login(timeout=timeout)
                    iface_script = "/etc/network/interfaces"
                    cmd = "cat %s" % iface_script
                    if not session.cmd_status(cmd):
                        logging.debug("Backup network script in guest - %s",
                                      iface_script)
                        cmd = "cp %s %s.BACKUP" % (iface_script, iface_script)
                        status, output = session.cmd_status_output(cmd)
                        if status:
                            test.error("Failed to backup in guest: %s" %
                                       output)
            for pci_num in range(pci_num_range):
                msg = "Start hot-adding %sth pci device," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error_context.context(msg, logging.info)
                add_device(pci_num)
            sub_type = params.get("sub_type_after_plug")
            if sub_type:
                error_context.context(
                    "Running sub test '%s' after hotplug" % sub_type,
                    logging.info)
                utils_test.run_virt_sub_test(test, params, env, sub_type)
                if "guest_suspend" == sub_type:
                    # Hotpluged device have been released after guest suspend,
                    # so do not need unpluged step.
                    break
            for pci_num in range(pci_num_range):
                msg = "start hot-deleting %sth pci device," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error_context.context(msg, logging.info)
                pci_del(-(pci_num + 1))

            # cleanup network script after hot deleting pci device
            clean_network_scripts()
    finally:
        # clean network scripts on error
        clean_network_scripts()
        if params.get("enable_set_link", "yes") == "yes":
            error_context.context("Re-enabling the primary link(s) of guest",
                                  logging.info)
            for nic in vm.virtnet:
                vm.set_link(nic.device_id, up=True)
        if session:
            session.close()
Ejemplo n.º 15
0
def run(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)

    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == "qmp":
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")
    if not cmd_o:
        raise error.TestError("Unknown version of qemu")

    cmd_type = utils_misc.find_substring(str(cmd_o), "device_del")

    devices = find_pci()
    context_msg = "Running sub test '%s' %s"
    sub_type = params.get("sub_type_before_unplug")
    if sub_type:
        error.context(context_msg % (sub_type, "before unplug"), logging.info)
        utils_test.run_virt_sub_test(test, params, env, sub_type)

    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)

    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)
Ejemplo n.º 16
0
def run(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) Disable the primary link(s) of guest.
    4) PCI add one/multi sr-io  deivce with (or without) repeat
    5) Compare output of monitor command 'info pci'.
    6) Compare output of guest command [reference_cmd].
    7) Verify whether pci_model is shown in [pci_find_cmd].
    8) Check whether the newly added PCI device works fine.
    9) Delete the device, verify whether could remove the sr-iov device.
    10) Re-enabling the primary link(s) of guest.

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

    def check_interface(iface, nic_filter):
        cmd = "ifconfig %s" % str(iface)
        session = vm.wait_for_serial_login(timeout=timeout)
        status, output = session.cmd_status_output(cmd)
        if status:
            test.error("Guest command '%s' fail with output: %s." % (cmd, output))
        if re.findall(nic_filter, output, re.MULTILINE | re.DOTALL):
            return True
        return False

    def get_active_network_device(session, nic_filter):
        devnames = []
        cmd = "ifconfig -a"
        nic_reg = r"\w+(?=: flags)|\w+(?=\s*Link)"
        status, output = session.cmd_status_output(cmd)
        if status:
            test.error("Guest command '%s' fail with output: %s." % (cmd, output))
        ifaces = re.findall(nic_reg, output)
        for iface in ifaces:
            if check_interface(str(iface), nic_filter):
                devnames.append(iface)
        return devnames

    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.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 "OK domain" not in add_output:
            test.fail("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 vm.monitor.protocol == 'qmp':
            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_misc.find_substring(devices_supported, dev)
        if not is_support:
            test.error("%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])
        driver = params.get("device_driver", "pci-assign")
        check_support_device(driver)
        pci_add_cmd = ("device_add id=%s,driver=%s,host=%s" %
                       (pci_info[pci_num][0], driver, 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.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)
        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][0] not in str(after_add):
            logging.debug("Print info pci after add the block: %s" % after_add)
            test.fail("Add device failed. Monitor command is: %s"
                      ". Output: %r" % (pci_add_cmd, add_output))
        return after_add

    def clean_network_scripts():
        logging.debug("Clean up network scripts in guest")
        session = vm.wait_for_serial_login(timeout=timeout)
        if "ubuntu" in vm.get_distro().lower():
            iface_script = "/etc/network/interfaces"
            cmd = "cat %s.BACKUP" % iface_script
            if not session.cmd_status(cmd):
                cmd = "mv %s.BACKUP %s" % (iface_script, iface_script)
                status, output = session.cmd_status_output(cmd)
                if status:
                    test.error("Failed to cleanup network script in guest: "
                               "%s" % output)
        else:
            global iface_scripts
            for iface_script in iface_scripts:
                cmd = "rm -f %s" % iface_script
                status, output = session.cmd_status_output(cmd)
                if status:
                    test.error("Failed to delete iface_script")
                iface_scripts.remove(iface_script)

    # Hot add a pci device
    def add_device(pci_num):
        global iface_scripts
        reference_cmd = params["reference_cmd"]
        info_pci_ref = vm.monitor.info("pci")
        session = vm.wait_for_serial_login(timeout=timeout)
        reference = session.cmd_output(reference_cmd)
        active_nics = get_active_network_device(session, nic_filter)
        logging.debug("Active nics before hotplug - %s", active_nics)

        # Stop the VM monitor and try hot adding SRIOV dev
        if params.get("vm_stop", "no") == "yes":
            logging.debug("stop the monitor of the VM before hotplug")
            vm.pause()
        try:
            # get function for adding device.
            add_function = local_functions["%s_iov" % cmd_type]
        except Exception:
            test.error("No function for adding sr-iov dev with '%s'" %
                       cmd_type)
        after_add = None
        if add_function:
            # Do add pci device.
            after_add = add_function(pci_num)

        try:
            # Define a helper function to compare the output
            def _new_shown():
                output = session.cmd_output(reference_cmd)
                return output != reference

            # Define a helper function to make sure new nic could get ip.
            def _check_ip():
                post_nics = get_active_network_device(session, nic_filter)
                logging.debug("Active nics after hotplug - %s", post_nics)
                return (len(active_nics) <= len(post_nics) and
                        active_nics != post_nics)

            # Define a helper function to catch PCI device string
            def _find_pci():
                output = session.cmd_output("lspci -nn")
                if re.search(vf_filter, output, re.IGNORECASE):
                    return True
                else:
                    return False

            # Resume the VM
            if params.get("vm_resume", "no") == "yes":
                logging.debug("resuming the VM after hotplug")
                vm.resume()

            # Reboot the VM
            if params.get("vm_reboot", "no") == "yes":
                logging.debug("Rebooting the VM after hotplug")
                vm.reboot()
            session = vm.wait_for_serial_login(timeout=timeout)

            error_context.context("Start checking new added device")
            # Compare the output of 'info pci'
            if after_add == info_pci_ref:
                test.fail("No new PCI device shown after executing "
                          "monitor command: 'info pci'")

            secs = int(params["wait_secs_for_hook_up"])
            if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3):
                test.fail("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):
                test.fail("New add device not found in guest. "
                          "Command was: lspci -nn")

            # Assign static IP to the hotplugged interface
            if params.get("assign_static_ip", "no") == "yes":
                cmd = "service networking restart"
                static_ip = next(ip_gen)
                net_mask = params.get("static_net_mask", "255.255.255.0")
                broadcast = params.get("static_broadcast", "10.10.10.255")
                pci_id = utils_misc.get_pci_id_using_filter(vf_filter,
                                                            session)
                logging.debug("PCIs associated with %s - %s", vf_filter,
                              ', '.join(map(str, pci_id)))
                for each_pci in pci_id:
                    iface_name = utils_misc.get_interface_from_pci_id(each_pci,
                                                                      session)
                    logging.debug("Interface associated with PCI %s - %s",
                                  each_pci, iface_name)
                    mac = session.cmd_output("ethtool -P %s" % iface_name)
                    mac = mac.split("Permanent address:")[-1].strip()
                    logging.debug("mac address of %s: %s", iface_name, mac)
                    # backup the network script for other distros
                    if "ubuntu" not in vm.get_distro().lower():
                        cmd = "service network restart"
                        iface_scripts.append(utils_net.get_network_cfg_file(iface_name))
                    if not check_interface(str(iface_name), nic_filter):
                        utils_net.create_network_script(iface_name, mac,
                                                        boot_proto="static",
                                                        net_mask=net_mask,
                                                        vm=vm,
                                                        ip_addr=static_ip)
                        status, output = session.cmd_status_output(cmd)
                        if status:
                            test.error("Failed to set static ip in guest: "
                                       "%s" % output)
            # Test the newly added device
            if not utils_misc.wait_for(_check_ip, 120, 3, 3):
                ifconfig = session.cmd_output("ifconfig -a")
                test.fail("New hotpluged device could not get ip "
                          "after 120s in guest. guest ifconfig "
                          "output: \n%s" % ifconfig)
            try:
                session.cmd(params["pci_test_cmd"] % (pci_num + 1))
            except aexpect.ShellError as e:
                test.fail("Check 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):
            test.fail("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_serial_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")
    vf_filter = params.get("vf_filter_re")
    generate_mac = params.get("generate_mac", "yes")
    nic_filter = params["nic_interface_filter"]
    devices = []
    device_type = params.get("hotplug_device_type", "vf")
    for i in range(pci_num_range):
        device = {}
        device["type"] = device_type
        if generate_mac == "yes":
            device['mac'] = utils_net.generate_mac_address_simple()
        if params.get("device_name"):
            device["name"] = params.get("device_name")
        devices.append(device)
    device_driver = params.get("device_driver", "pci-assign")
    if vm.pci_assignable is None:
        vm.pci_assignable = test_setup.PciAssignable(
            driver=params.get("driver"),
            driver_option=params.get("driver_option"),
            host_set_flag=params.get("host_setup_flag"),
            kvm_params=params.get("kvm_default"),
            vf_filter_re=vf_filter,
            pf_filter_re=params.get("pf_filter_re"),
            device_driver=device_driver,
            pa_type=params.get("pci_assignable"))

    pa_pci_ids = vm.pci_assignable.request_devs(devices)
    # Modprobe the module if specified in config file
    module = params.get("modprobe_module")
    if module:
        error_context.context("modprobe the module %s" % module, logging.info)
        session.cmd("modprobe %s" % module)

    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == 'qmp':
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")

    cmd_type = utils_misc.find_substring(str(cmd_o), "device_add", "pci_add")
    if not cmd_o:
        test.error("Unknown version of qemu")

    local_functions = locals()

    if params.get("enable_set_link" "yes") == "yes":
        error_context.context("Disable the primary link(s) of guest", logging.info)
        for nic in vm.virtnet:
            vm.set_link(nic.device_id, up=False)

    try:
        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 = []
            if params.get("assign_static_ip", "no") == "yes":
                ip_gen = utils_net.gen_ipv4_addr(exclude_ips=[])
                # backup the network script file if it is ubuntu
                if "ubuntu" in vm.get_distro().lower():
                    session = vm.wait_for_serial_login(timeout=timeout)
                    iface_script = "/etc/network/interfaces"
                    cmd = "cat %s" % iface_script
                    if not session.cmd_status(cmd):
                        logging.debug("Backup network script in guest - %s",
                                      iface_script)
                        cmd = "cp %s %s.BACKUP" % (iface_script, iface_script)
                        status, output = session.cmd_status_output(cmd)
                        if status:
                            test.error("Failed to backup in guest: %s" %
                                       output)
            for pci_num in range(pci_num_range):
                msg = "Start hot-adding %sth pci device," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error_context.context(msg, logging.info)
                add_device(pci_num)
            sub_type = params.get("sub_type_after_plug")
            if sub_type:
                error_context.context("Running sub test '%s' after hotplug" %
                                      sub_type, logging.info)
                utils_test.run_virt_sub_test(test, params, env, sub_type)
                if "guest_suspend" == sub_type:
                    # Hotpluged device have been released after guest suspend,
                    # so do not need unpluged step.
                    break
            for pci_num in range(pci_num_range):
                msg = "start hot-deleting %sth pci device," % (pci_num + 1)
                msg += " repeat %d" % (j + 1)
                error_context.context(msg, logging.info)
                pci_del(-(pci_num + 1))

            # cleanup network script after hot deleting pci device
            clean_network_scripts()
    finally:
        # clean network scripts on error
        clean_network_scripts()
        if params.get("enable_set_link", "yes") == "yes":
            error_context.context("Re-enabling the primary link(s) of guest",
                                  logging.info)
            for nic in vm.virtnet:
                vm.set_link(nic.device_id, up=True)
        if session:
            session.close()