Ejemplo n.º 1
0
    def create_snapshot(vm):
        """
        Create live snapshot:
        1). Check which monitor is used
        2). Get device info
        3). Create snapshot
        """

        cmd = params.get("create_sn_cmd")

        block_info = vm.monitor.info("block")
        if utils_misc.qemu_has_option("qmp") and params.get(
                "monitor_type") == "qmp":
            device = block_info[0]["device"]
        else:
            string = ""
            device = string.join(block_info).split(":")[0]
        cmd += " %s" % device

        snapshot_name = params.get("snapshot_name")
        cmd += " %s" % snapshot_name

        format = params.get("snapshot_format")
        if format:
            cmd += " %s" % format
        logging.info("Creating live snapshot ...")
        vm.monitor.send_args_cmd(cmd)

        logging.info("Check snapshot is created ...")
        snapshot_info = str(vm.monitor.info("block"))
        if snapshot_name not in snapshot_info:
            logging.error(snapshot_info)
            raise error.TestFail("Snapshot doesn't exist")
Ejemplo n.º 2
0
    def create_snapshot(vm):
        """
        Create live snapshot:
        1). Check which monitor is used
        2). Get device info
        3). Create snapshot
        """

        cmd = params.get("create_sn_cmd")

        block_info = vm.monitor.info("block")
        if utils_misc.qemu_has_option("qmp") and params.get("monitor_type") == "qmp":
            device = block_info[0]["device"]
        else:
            string = ""
            device = string.join(block_info).split(":")[0]
        cmd += " %s" % device

        snapshot_name = params.get("snapshot_name")
        cmd += " %s" % snapshot_name

        format = params.get("snapshot_format")
        if format:
            cmd += " %s" % format
        logging.info("Creating live snapshot ...")
        vm.monitor.send_args_cmd(cmd)

        logging.info("Check snapshot is created ...")
        snapshot_info = str(vm.monitor.info("block"))
        if snapshot_name not in snapshot_info:
            logging.error(snapshot_info)
            raise error.TestFail("Snapshot doesn't exist")
Ejemplo n.º 3
0
def run_qmp_event_notification(test, params, env):
    """
    Test qmp event notification function:
    1) Boot up guest with qmp.
    2) Trigger qmp event in guest.
    3) Try to catch qmp event notification in qmp monitor.

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

    if not utils_misc.qemu_has_option("qmp"):
        error.TestNAError(
            "This test case requires a host QEMU with QMP monitor support")
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    callback = {
        "host_cmd": commands.getoutput,
        "guest_cmd": session.get_command_output,
        "monitor_cmd": vm.monitor.send_args_cmd,
        "qmp_cmd": vm.monitors[1].send_args_cmd
    }

    def send_cmd(cmd):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    event_cmd = params.get("event_cmd")
    cmd_type = params.get("event_cmd_type")
    event_check = params.get("event_check")
    timeout = int(params.get("check_timeout", 360))
    action_check = params.get("action_check")

    if params.get("pre_event_cmd"):
        send_cmd(params.get("pre_event_cmd"))

    cmd_o = send_cmd(event_cmd)

    end_time = time.time() + timeout
    qmp_monitors = []
    for monitor in vm.monitors:
        monitor_params = params.object_params(monitor.name)
        if monitor_params.get("monitor_type") == "qmp":
            qmp_monitors += [monitor]
    qmp_num = len(qmp_monitors)
    logging.info("Try to get qmp events in %s seconds!" % timeout)
    while time.time() < end_time:
        for monitor in qmp_monitors:
            event = monitor.get_event(event_check)
            if event_check == "WATCHDOG":
                if event and event['data']['action'] == action_check:
                    logging.info("Receive watchdog %s event notification" %
                                 action_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
            else:
                if event:
                    logging.info("Receive qmp %s event notification" %
                                 event_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
        time.sleep(5)
        if qmp_num <= 0:
            break

    if qmp_num > 0:
        raise error.TestFail("Did not receive qmp %s event notification" %
                             event_check)

    if params.get("post_event_cmd"):
        send_cmd(params.get("post_event_cmd"))
    if session:
        session.close()
Ejemplo n.º 4
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.º 5
0
def run(test, params, env):
    """
    Test qmp event notification function:
    1) Boot up guest with qmp and macvtap.
    2) In guest, change network interface to promisc state.
    3) Try to catch qmp event notification in qmp monitor.
    4) Execute query-rx-filter in host qmp session.

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

    if not utils_misc.qemu_has_option("qmp"):
        error.TestNAError("This test case requires a host QEMU with QMP "
                          "monitor support")
    if params.get("nettype", "macvtap") != "macvtap":
        error.TestNAError("This test case test macvtap.")

    params["start_vm"] = "yes"
    vm_name = params.get("main_vm", "vm1")
    env_process.preprocess_vm(test, params, env, vm_name)

    vm = env.get_vm(vm_name)
    vm.verify_alive()

    event_cmd = params.get("event_cmd")
    event_cmd_type = params.get("event_cmd_type")
    event_check = params.get("event_check")
    timeout = int(params.get("check_timeout", 360))
    action_check = params.get("action_check")
    pre_cmd = params.get("pre_cmd")
    post_cmd = params.get("post_cmd")
    post_cmd_type = params.get("post_cmd_type")

    session = vm.wait_for_serial_login(timeout=int(params.get("login_timeout",
                                                              360)))

    callback = {"host_cmd": utils.system_output,
                "guest_cmd": session.get_command_output,
                "qmp_cmd": vm.get_monitors_by_type("qmp")[0].send_args_cmd}

    def send_cmd(cmd, cmd_type):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    if pre_cmd:
        error.context("Run pre_cmd '%s'", logging.info)
        pre_cmd_type = params.get("pre_cmd_type", event_cmd_type)
        send_cmd(pre_cmd, pre_cmd_type)

    mac = vm.get_mac_address()
    interface_name = utils_net.get_linux_ifname(session, mac)

    error.context("In guest, change network interface to promisc state.",
                  logging.info)
    event_cmd = params.get("event_cmd") % interface_name
    send_cmd(event_cmd, event_cmd_type)

    error.context("Try to get qmp events in %s seconds!" % timeout,
                  logging.info)
    end_time = time.time() + timeout
    qmp_monitors = vm.get_monitors_by_type("qmp")
    qmp_num = len(qmp_monitors)
    while time.time() < end_time:
        for monitor in qmp_monitors:
            event = monitor.get_event(event_check)
            if event:
                txt = "Monitr %s " % monitor.name
                txt += "receive qmp %s event notification" % event_check
                logging.info(txt)
                qmp_num -= 1
                qmp_monitors.remove(monitor)
        time.sleep(5)
        if qmp_num <= 0:
            break
    if qmp_num > 0:
        output = session.cmd("ip link show")
        err = "Monitor(s) "
        for monitor in qmp_monitors:
            err += "%s " % monitor.name
        err += " did not receive qmp %s event notification." % event_check
        err += " ip link show command output in guest: %s" % output
        raise error.TestFail(err)

    if post_cmd:
        for nic in vm.virtnet:
            post_cmd = post_cmd % nic.device_id
            error.context("Run post_cmd '%s'" % post_cmd, logging.info)
            post_cmd_type = params.get("post_cmd_type", event_cmd_type)
            output = send_cmd(post_cmd, post_cmd_type)
            post_cmd_check = params.get("post_cmd_check")
            if post_cmd_check:
                if post_cmd_check not in str(output):
                    err = "Did not find '%s' in " % post_cmd_check
                    err += "'%s' command's output: %s" % (post_cmd, output)
                    raise error.TestFail(err)

    if session:
        session.close()
Ejemplo n.º 6
0
def run(test, params, env):
    """
    change a removable media:
    1) Boot VM with QMP/human monitor enabled.
    2) Connect to QMP/human monitor server.
    3) Eject original cdrom.
    4) Eject original cdrom for second time.
    5) Insert new image to cdrom.
    6) Eject device after add new image by change command.
    7) Insert original cdrom to cdrom.
    8) Try to eject non-removable device w/o force option.

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

    if not utils_misc.qemu_has_option("qmp"):
        logging.warn("qemu does not support qmp. Human monitor will be used.")
    qmp_used = False
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    logging.info("Wait until device is ready")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if isinstance(blocks_info, dict):
        qmp_used = True

    orig_img_name = params.get("cdrom_cd1")
    p_dict = {"file": orig_img_name}
    device_name = vm.get_block(p_dict)
    if device_name is None:
        msg = "Fail to get device using image %s" % orig_img_name
        raise error.TestFail(msg)
    error.context("Eject original device.")
    eject_cmd = "eject device=%s" % device_name
    vm.monitor.send_args_cmd(eject_cmd)
    logging.info("Wait until device is ejected")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if orig_img_name in str(blocks_info):
        raise error.TestFail("Fail to eject cdrom %s. " % orig_img_name)

    error.context("Eject original device for second time")
    vm.monitor.send_args_cmd(eject_cmd)

    new_img_name = params.get("new_img_name")
    error.context("Insert new image to device.")
    change_cmd = "change device=%s,target=%s" % (device_name, new_img_name)
    vm.monitor.send_args_cmd(change_cmd)
    logging.info("Wait until device changed")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if new_img_name not in str(blocks_info):
        raise error.TestFail("Fail to chang cdrom to %s." % new_img_name)
    if qmp_used:
        eject_cmd = "eject device=%s, force=True" % device_name
    else:
        eject_cmd = "eject device=%s" % device_name
    error.context("Eject device after add new image by change command")
    vm.monitor.send_args_cmd(eject_cmd)
    logging.info("Wait until new image is ejected")
    time.sleep(10)

    blocks_info = vm.monitor.info("block")
    if new_img_name in str(blocks_info):
        raise error.TestFail("Fail to eject cdrom %s." % orig_img_name)

    error.context("Insert %s to device %s" % (orig_img_name, device_name))
    change_cmd = "change device=%s,target=%s" % (device_name, orig_img_name)
    vm.monitor.send_args_cmd(change_cmd)
    logging.info("Wait until device changed")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if orig_img_name not in str(blocks_info):
        raise error.TestFail("Fail to change cdrom to %s." % orig_img_name)

    error.context("Try to eject non-removable device")
    p_dict = {"removable": False}
    device_name = vm.get_block(p_dict)
    if device_name is None:
        raise error.TestFail("Could not find non-removable device")
    if params.get("force_eject", "no") == "yes":
        if not qmp_used:
            eject_cmd = "eject -f %s " % device_name
    else:
        eject_cmd = "eject device=%s," % device_name
    try:
        vm.monitor.send_args_cmd(eject_cmd)
    except Exception, e:
        logging.debug("Catch exception message: %s" % e)
Ejemplo n.º 7
0
def run(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

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

    def check_list(qmp_o, key, val=None, check_item_in_pair=True):
        """
        Check if the expect key, val are contained in QMP output qmp_o.

        :param qmp_o: output of QMP command
        :type qmp_o: list
        :param key: expect result
        :type key: str
        :param val: expect result
        :type val: str or None(if check_item_in_pair=False)
        :param check_item_in_pair: If expect result is dict (True) or str (False)
        :type check_item_in_pair: bool.

        :return check result
        :rtype: bool
        """
        for element in qmp_o:
            if isinstance(element, dict):
                if _check_dict(element, key, val, check_item_in_pair):
                    return True
            elif isinstance(element, list):
                if check_list(element, key, val, check_item_in_pair):
                    return True
            elif element != '' and not check_item_in_pair:
                if strict_match:
                    if operator.eq(key, element):
                        return True
                else:
                    if key in str(element):
                        return True
        return False

    def _check_dict(dic, key, val, check_item_in_pair=True):
        """
        Check if the expect key, val are contained in QMP output dic.

        :param dic: content of QMP command return value
        :type dic: dict
        :param key: expect result
        :type key: str
        :param val: expect result
        :type val: str or None(if check_item_in_pair=False)
        :param check_item_in_pair: If expect result is dict or str
        :type check_item_in_pair: bool. Means expect result is dict or str.

        :return check result
        :rtype: bool
        """
        if key in dic and not check_item_in_pair:
            return True
        elif key in dic and val == dic[key]:
            return True
        else:
            for value in dic.values():
                if isinstance(value, dict):
                    if _check_dict(value, key, val, check_item_in_pair):
                        return True
                elif isinstance(value, list):
                    if check_list(value, key, val, check_item_in_pair):
                        return True
                elif value != '' and not check_item_in_pair:
                    if strict_match:
                        if operator.eq(key, value):
                            return True
                    else:
                        if key in str(value):
                            return True
            return False

    def check_result(qmp_o, expect_o=None):
        """
        Check test result with difference way according to result_check.
        result_check = equal, expect_o should equal to qmp_o.
        result_check = contain, expect_o should be contained in qmp_o
        result_check = not_contain, expect_o should not be contained in qmp_o.

        :param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        :type qmp_o: list
        :param expect_o: the expect result.
        :type expect_o: list
        """
        logging.info("Expect result is %s" % expect_o)
        logging.info("Actual result that get from qmp_cmd/post_cmd is %s" % qmp_o)
        if result_check == "equal":
            if not operator.eq(qmp_o, expect_o):
                test.fail("QMP output does not equal to the expect result.\n "
                          "Expect result: '%s'\n"
                          "Actual result: '%s'" % (expect_o, qmp_o))
        elif result_check == "contain":
            for o in expect_o:
                if isinstance(o, dict):
                    for key, val in o.items():
                        result = check_list(qmp_o, key, val)
                        if not result:
                            break
                elif isinstance(o, str):
                    result = check_list(qmp_o, o, check_item_in_pair=False)

                if result:
                    logging.info("QMP output contain the expect value %s" % o)
                else:
                    test.fail("QMP output does not contain the expect value.\n"
                              "Missed expect value: '%s'\n"
                              "Actual result: '%s'\n" % (o, qmp_o))
        elif result_check == "not_contain":
            for o in expect_o:
                if isinstance(o, dict):
                    for key, val in o.items():
                        result = check_list(qmp_o, key, val)
                        if result:
                            break
                elif isinstance(o, str):
                    result = check_list(qmp_o, o, check_item_in_pair=False)

                if result:
                    test.fail("QMP output contain the unexpect result.\n"
                              "Unexpect result: '%s'\n"
                              "Actual result: '%s'" % (o, qmp_o))

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        test.cancel("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        logging.info("modprobe the module %s", module)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type('qmp')
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        test.error("Incorrect configuration, no QMP monitor found.")
    callback = {"host_cmd": lambda cmd: process.system_output(cmd, shell=True).decode(),
                "guest_cmd": session.cmd_output,
                "qmp_cmd": qmp_port.send_args_cmd}

    def send_cmd(cmd):
        """ Helper to execute command on host/ssh guest/qmp monitor """
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            test.error("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    post_cmd = params.get("post_cmd")
    cmd_type = params.get("event_cmd_type")
    result_check = params.get("cmd_result_check")
    strict_match = params.get("strict_match", "yes") == 'yes'
    expect_o = eval(params.get("cmd_return_value", "[]"))

    # Pre command
    if pre_cmd is not None:
        logging.info("Run prepare command '%s'.", pre_cmd)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: '%s'\n Output: '%s'", pre_cmd, pre_o)

    # qmp command
    try:
        # Testing command
        logging.info("Run qmp command '%s'.", qmp_cmd)
        qmp_o = qmp_port.send_args_cmd(qmp_cmd)
        if not isinstance(qmp_o, list):
            qmp_o = [qmp_o]
        logging.debug("QMP command: '%s' \n Output: '%s'", qmp_cmd, qmp_o)
    except qemu_monitor.QMPCmdError as err:
        if params.get("negative_test") == 'yes':
            logging.debug("Negative QMP command: '%s'\n output:'%s'", qmp_cmd,
                          err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    test.fail("'%s' not in exception '%s'"
                              % (check_pattern, err))
        else:
            test.fail(err)
    except qemu_monitor.MonitorProtocolError as err:
        test.fail(err)
    except Exception as err:
        test.fail(err)

    # sleep 10s to make netdev_del take effect
    if 'netdev_del' in qmp_cmd:
        time.sleep(10)

    # Post command
    if post_cmd is not None:
        logging.info("Run post command '%s'.", post_cmd)
        post_o = send_cmd(post_cmd)
        if not isinstance(post_o, list):
            post_o = [post_o]
        logging.debug("Post-command: '%s'\n Output: '%s'", post_cmd, post_o)

    if result_check == "equal" or result_check == "contain":
        logging.info("Verify qmp command '%s' works as designed." % qmp_cmd)
        if qmp_cmd == "query-name":
            vm_name = params["main_vm"]
            expect_o = [{'name': vm_name}]
        elif qmp_cmd == "query-uuid":
            uuid_input = params["uuid"]
            expect_o = [{'UUID': uuid_input}]
        elif qmp_cmd == "query-version":
            qemu_version_cmd = "rpm -qa | grep -E 'qemu-kvm(-(rhev|ma))?-[0-9]' | head -n 1"
            host_arch = platform.machine()
            qemu_version = callback["host_cmd"](qemu_version_cmd).replace('.%s' % host_arch, '')
            expect_o = [str(qemu_version)]
        elif qmp_cmd == "query-block":
            images = params['images'].split()
            image_info = {}
            for image in images:
                image_params = params.object_params(image)
                image_format = image_params['image_format']
                image_drive = "drive_%s" % image
                image_info['device'] = image_drive
                image_info['qdev'] = image
                image_info['format'] = image_format
                expect_o.append(image_info)
        check_result(qmp_o, expect_o)
    elif result_check.startswith("post_"):
        logging.info("Verify post qmp command '%s' works as designed." % post_cmd)
        result_check = result_check.split('_', 1)[1]
        check_result(post_o, expect_o)
    session.close()
Ejemplo n.º 8
0
def run_qmp_command(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environmen.
    """
    def check_result(qmp_o, output=None):
        """
        Check test result with difference way accoriding to
        result_check.
        result_check = equal, will compare cmd_return_value with qmp
                       command output.
        result_check = contain, will try to find cmd_return_value in qmp
                       command output.
        result_check = m_equal_q, will compare key value in monitor command
                       output and qmp command output.
        result_check = m_in_q, will try to find monitor command output's key
                       value in qmp command output.
        result_check = m_format_q, will try to match the output's format with
                       check pattern.

        :param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        :param o: output from pre_cmd, qmp_cmd or post_cmd or an execpt
        result set in config file.
        """
        if result_check == "equal":
            value = output
            if value != str(qmp_o):
                raise error.TestFail("QMP command return value does not match "
                                     "the expect result. Expect result: '%s'\n"
                                     "Actual result: '%s'" % (value, qmp_o))
        elif result_check == "contain":
            values = output.split(';')
            for value in values:
                if value.strip() not in str(qmp_o):
                    raise error.TestFail("QMP command output does not contain "
                                         "expect result. Expect result: '%s'\n"
                                         "Actual result: '%s'"
                                         % (value, qmp_o))
        elif result_check == "not_contain":
            values = output.split(';')
            for value in values:
                if value in str(qmp_o):
                    raise error.TestFail("QMP command output contains unexpect"
                                         " result. Unexpect result: '%s'\n"
                                         "Actual result: '%s'"
                                         % (value, qmp_o))
        elif result_check == "m_equal_q":
            msg = "QMP command ouput is not equal to in human monitor command."
            msg += "\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman command output: '%s'" % output
            res = output.splitlines(True)
            if type(qmp_o) != type(res):
                len_o = 1
            else:
                len_o = len(qmp_o)
            if len(res) != len_o:
                raise error.TestFail(msg)
            re_str = r'([^ \t\n\r\f\v=]*)=([^ \t\n\r\f\v=]*)'
            for i in range(len(res)):
                if qmp_cmd == "query-version":
                    version = qmp_o['qemu']
                    version = "%s.%s.%s" % (version['major'], version['minor'],
                                            version['micro'])
                    package = qmp_o['package']
                    re_str = r"([0-9]+\.[0-9]+\.[0-9]+)\s*(\(\S*\))?"
                    hmp_version, hmp_package = re.findall(re_str, res[i])[0]
                    if not hmp_package:
                        hmp_package = package
                    if version != hmp_version or package != hmp_package:
                        raise error.TestFail(msg)
                else:
                    matches = re.findall(re_str, res[i])
                    for key, val in matches:
                        if '0x' in val:
                            val = long(val, 16)
                            if val != qmp_o[i][key]:
                                msg += "\nValue in human monitor: '%s'" % val
                                msg += "\nValue in qmp: '%s'" % qmp_o[i][key]
                                raise error.TestFail(msg)
                        elif qmp_cmd == "query-block":
                            cmp_str = "u'%s': u'%s'" % (key, val)
                            cmp_s = "u'%s': %s" % (key, val)
                            if '0' == val:
                                cmp_str_b = "u'%s': False" % key
                            elif '1' == val:
                                cmp_str_b = "u'%s': True" % key
                            else:
                                cmp_str_b = cmp_str
                            if (cmp_str not in str(qmp_o[i]) and
                               cmp_str_b not in str(qmp_o[i]) and
                               cmp_s not in str(qmp_o[i])):
                                msg += ("\nCan not find '%s', '%s' or '%s' in "
                                        " QMP command output."
                                        % (cmp_s, cmp_str_b, cmp_str))
                                raise error.TestFail(msg)
                        elif qmp_cmd == "query-balloon":
                            if (int(val) * 1024 * 1024 != qmp_o[key] and
                               val not in str(qmp_o[key])):
                                msg += ("\n'%s' is not in QMP command output"
                                        % val)
                                raise error.TestFail(msg)
                        else:
                            if (val not in str(qmp_o[i][key]) and
                               str(bool(int(val))) not in str(qmp_o[i][key])):
                                msg += ("\n'%s' is not in QMP command output"
                                        % val)
                                raise error.TestFail(msg)
        elif result_check == "m_in_q":
            res = output.splitlines(True)
            msg = "Key value from human monitor command is not in"
            msg += "QMP command output.\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman monitor command output '%s'" % output
            for i in range(len(res)):
                params = res[i].rstrip().split()
                for param in params:
                    try:
                        str_o = str(qmp_o.values())
                    except AttributeError:
                        str_o = qmp_o
                    if param.rstrip() not in str(str_o):
                        msg += "\nKey value is '%s'" % param.rstrip()
                        raise error.TestFail(msg)
        elif result_check == "m_format_q":
            match_flag = True
            for i in qmp_o:
                if output is None:
                    raise error.TestError("QMP output pattern is missing")
                if re.match(output.strip(), str(i)) is None:
                    match_flag = False
            if not match_flag:
                msg = "Output does not match the pattern: '%s'" % output
                raise error.TestFail(msg)

    def qmp_cpu_check(output):
        """ qmp_cpu test check """
        last_cpu = int(params['smp']) - 1
        for out in output:
            cpu = out.get('CPU')
            if cpu is None:
                raise error.TestFail("'CPU' index is missing in QMP output "
                                     "'%s'" % out)
            else:
                current = out.get('current')
                if current is None:
                    raise error.TestFail("'current' key is missing in QMP "
                                         "output '%s'" % out)
                elif cpu < last_cpu:
                    if current is False:
                        pass
                    else:
                        raise error.TestFail("Attribute 'current' should be "
                                             "'False', but is '%s' instead.\n"
                                             "'%s'" % (current, out))
                elif cpu == last_cpu:
                    if current is True:
                        pass
                    else:
                        raise error.TestFail("Attribute 'current' should be "
                                             "'True', but is '%s' instead.\n"
                                             "'%s'" % (current, out))
                elif cpu <= last_cpu:
                    continue
                else:
                    raise error.TestFail("Incorrect CPU index '%s' (corrupted "
                                         "or higher than no_cpus).\n%s"
                                         % (cpu, out))

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        raise error.TestNAError("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        error.context("modprobe the module %s" % module, logging.info)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type('qmp')
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        raise error.TestError("Incorrect configuration, no QMP monitor found.")
    hmp_ports = vm.get_monitors_by_type('human')
    if hmp_ports:
        hmp_port = hmp_ports[0]
    else:
        raise error.TestError("Incorrect configuration, no QMP monitor found.")
    callback = {"host_cmd": utils.system_output,
                "guest_cmd": session.get_command_output,
                "monitor_cmd": hmp_port.send_args_cmd,
                "qmp_cmd": qmp_port.send_args_cmd}

    def send_cmd(cmd):
        """ Helper to execute command on ssh/host/monitor """
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    cmd_type = params.get("event_cmd_type")
    post_cmd = params.get("post_cmd")
    result_check = params.get("cmd_result_check")
    cmd_return_value = params.get("cmd_return_value")

    # HOOKs
    if result_check == 'qmp_cpu':
        pre_cmd = "cpu index=%d" % (int(params['smp']) - 1)

    # Pre command
    if pre_cmd is not None:
        error.context("Run prepare command '%s'." % pre_cmd, logging.info)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: '%s'\n Output: '%s'", pre_cmd, pre_o)
    try:
        # Testing command
        error.context("Run qmp command '%s'." % qmp_cmd, logging.info)
        output = qmp_port.send_args_cmd(qmp_cmd)
        logging.debug("QMP command: '%s' \n Output: '%s'", qmp_cmd, output)
    except qemu_monitor.QMPCmdError, err:
        if params.get("negative_test") == 'yes':
            logging.debug("Negative QMP command: '%s'\n output:'%s'", qmp_cmd,
                          err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    raise error.TestFail("'%s' not in exception '%s'"
                                         % (check_pattern, err))
        else:
            raise error.TestFail(err)
Ejemplo n.º 9
0
def run(test, params, env):
    """
    Test qmp event notification function:
    1) Boot up guest with qmp.
    2) Trigger qmp event in guest.
    3) Try to catch qmp event notification in qmp monitor.

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

    if not utils_misc.qemu_has_option("qmp"):
        error.TestNAError("This test case requires a host QEMU with QMP "
                          "monitor support")
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    qmp_monitor = filter(lambda x: x.protocol == "qmp", vm.monitors)[0]
    humam_monitor = filter(lambda x: x.protocol == "human", vm.monitors)[0]
    callback = {
        "host_cmd": commands.getoutput,
        "guest_cmd": session.cmd,
        "monitor_cmd": humam_monitor.send_args_cmd,
        "qmp_cmd": qmp_monitor.send_args_cmd
    }

    def send_cmd(cmd, options={}):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd, **options)
        else:
            raise error.TestError("cmd_type is not supported")

    pre_event_cmd = params.get("pre_event_cmd", "")
    pre_event_cmd_options = eval("dict({0})".format(
        params.get("pre_event_cmd_options", "")))
    event_cmd = params.get("event_cmd")
    event_cmd_options = eval("dict({0})".format(
        params.get("event_cmd_options", "")))
    post_event_cmd = params.get("post_event_cmd", "")
    post_event_cmd_options = eval("dict({0})".format(
        params.get("post_event_cmd_options", "")))
    cmd_type = params.get("event_cmd_type")
    event_check = params.get("event_check")
    timeout = int(params.get("check_timeout", 360))
    action_check = params.get("action_check")

    if pre_event_cmd:
        send_cmd(pre_event_cmd, pre_event_cmd_options)

    send_cmd(event_cmd, event_cmd_options)

    end_time = time.time() + timeout
    qmp_monitors = vm.get_monitors_by_type("qmp")
    qmp_num = len(qmp_monitors)
    logging.info("Try to get qmp events in %s seconds!", timeout)
    while time.time() < end_time:
        for monitor in qmp_monitors:
            event = monitor.get_event(event_check)
            if event_check == "WATCHDOG":
                if event and event['data']['action'] == action_check:
                    logging.info("Receive watchdog %s event notification",
                                 action_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
            else:
                if event:
                    logging.info("Receive qmp %s event notification",
                                 event_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
        time.sleep(5)
        if qmp_num <= 0:
            break

    if qmp_num > 0:
        raise error.TestFail("Did not receive qmp %s event notification" %
                             event_check)

    if post_event_cmd:
        send_cmd(post_event_cmd, post_event_cmd_options)
    if session:
        session.close()
Ejemplo n.º 10
0
def run(test, params, env):
    """
    Test qmp event notification function:
    1) Boot up guest with qmp.
    2) Trigger qmp event in guest.
    3) Try to catch qmp event notification in qmp monitor.

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

    if not utils_misc.qemu_has_option("qmp"):
        error.TestNAError("This test case requires a host QEMU with QMP "
                          "monitor support")
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    qmp_monitor = filter(lambda x: x.protocol == "qmp", vm.monitors)[0]
    humam_monitor = filter(lambda x: x.protocol == "human", vm.monitors)[0]
    callback = {"host_cmd": commands.getoutput,
                "guest_cmd": session.cmd,
                "monitor_cmd": humam_monitor.send_args_cmd,
                "qmp_cmd": qmp_monitor.send_args_cmd}

    def send_cmd(cmd, options={}):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd, **options)
        else:
            raise error.TestError("cmd_type is not supported")

    pre_event_cmd = params.get("pre_event_cmd", "")
    pre_event_cmd_options = eval(
        "dict({0})".format(params.get("pre_event_cmd_options", "")))
    event_cmd = params.get("event_cmd")
    event_cmd_options = eval(
        "dict({0})".format(params.get("event_cmd_options", "")))
    post_event_cmd = params.get("post_event_cmd", "")
    post_event_cmd_options = eval(
        "dict({0})".format(params.get("post_event_cmd_options", "")))
    cmd_type = params.get("event_cmd_type")
    event_check = params.get("event_check")
    timeout = int(params.get("check_timeout", 360))
    action_check = params.get("action_check")

    if pre_event_cmd:
        send_cmd(pre_event_cmd, pre_event_cmd_options)

    send_cmd(event_cmd, event_cmd_options)

    end_time = time.time() + timeout
    qmp_monitors = vm.get_monitors_by_type("qmp")
    qmp_num = len(qmp_monitors)
    logging.info("Try to get qmp events in %s seconds!", timeout)
    while time.time() < end_time:
        for monitor in qmp_monitors:
            event = monitor.get_event(event_check)
            if event_check == "WATCHDOG":
                if event and event['data']['action'] == action_check:
                    logging.info("Receive watchdog %s event notification",
                                 action_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
            else:
                if event:
                    logging.info("Receive qmp %s event notification",
                                 event_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
        time.sleep(5)
        if qmp_num <= 0:
            break

    if qmp_num > 0:
        raise error.TestFail("Did not receive qmp %s event notification"
                             % event_check)

    if post_event_cmd:
        send_cmd(post_event_cmd, post_event_cmd_options)
    if session:
        session.close()
Ejemplo n.º 11
0
def run_sr_iov_hotplug(test, params, env):
    """
    Test hotplug of sr-iov devices.

    (Elements between [] are configurable test parameters)
    1) Set up sr-iov test environment in host.
    2) Start VM.
    3) PCI add one/multi sr-io  deivce with (or without) repeat
    4) Compare output of monitor command 'info pci'.
    5) Compare output of guest command [reference_cmd].
    6) Verify whether pci_model is shown in [pci_find_cmd].
    7) Check whether the newly added PCI device works fine.
    8) Delete the device, verify whether could remove the sr-iov device.

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


    def pci_add_iov(pci_num):
        pci_add_cmd = ("pci_add pci_addr=auto host host=%s,if=%s" %
                       (pa_pci_ids[pci_num], pci_model))
        if params.get("hotplug_params"):
            assign_param = params.get("hotplug_params").split()
            for param in assign_param:
                value = params.get(param)
                if value:
                    pci_add_cmd += ",%s=%s" % (param, value)

        return pci_add(pci_add_cmd)

    def pci_add(pci_add_cmd):
        error.context("Adding pci device with command 'pci_add'")
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        pci_info.append(['' , add_output])

        if not "OK domain" in add_output:
            raise error.TestFail("Add PCI device failed. "
                                 "Monitor command is: %s, Output: %r" %
                                 (pci_add_cmd, add_output))
        return  vm.monitor.info("pci")

    def check_support_device(dev):
        if is_qmp_monitor:
            devices_supported = vm.monitor.human_monitor_cmd("%s ?" % cmd_type)
        else:
            devices_supported = vm.monitor.send_args_cmd("%s ?" % cmd_type)
        # Check if the device is support in qemu
        is_support = utils_test.find_substring(devices_supported, dev)
        if not is_support:
            raise error.TestError("%s doesn't support device: %s" %
                                  (cmd_type, dev))


    def device_add_iov(pci_num):
        device_id = "%s" % pci_model + "-" + utils_misc.generate_random_id()
        pci_info.append([device_id])
        check_support_device("pci-assign")
        pci_add_cmd = ("device_add id=%s,driver=pci-assign,host=%s" %
                       (pci_info[pci_num][0], pa_pci_ids[pci_num]))
        if params.get("hotplug_params"):
            assign_param = params.get("hotplug_params").split()
            for param in assign_param:
                value = params.get(param)
                if value:
                    pci_add_cmd += ",%s=%s" % (param, value)
        return device_add(pci_num, pci_add_cmd)

    def device_add(pci_num, pci_add_cmd):
        error.context("Adding pci device with command 'device_add'")
        if is_qmp_monitor:
            add_output = vm.monitor.send_args_cmd(pci_add_cmd)
        else:
            add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        pci_info[pci_num].append(add_output)

        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][0] not in after_add:
            logging.debug("Print info pci after add the block: %s" % after_add)
            raise error.TestFail("Add device failed. Monitor command is: %s"
                                 ". Output: %r" % (pci_add_cmd, add_output))
        return after_add

    # Hot add a pci device
    def add_device(pci_num):
        reference_cmd = params.get("reference_cmd")
        find_pci_cmd = params.get("find_pci_cmd")
        info_pci_ref = vm.monitor.info("pci")
        reference = session.cmd_output(reference_cmd)

        try:
            # get function for adding device.
            add_fuction = local_functions["%s_iov" % cmd_type]
        except Exception:
            raise error.TestError("No function for adding sr-iov dev with '%s'" %
                                  cmd_type)
        after_add = None
        if add_fuction:
            # Do add pci device.
            after_add = add_fuction(pci_num)

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

            # Define a helper function to catch PCI device string
            def _find_pci():
                o = session.cmd_output(find_pci_cmd)
                if re.search(match_string, o, re.IGNORECASE):
                    return True
                else:
                    return False

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

            secs = int(params.get("wait_secs_for_hook_up"))
            if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3):
                raise error.TestFail("No new device shown in output of command "
                                     "executed inside the guest: %s" %
                                     reference_cmd)

            if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3):
                raise error.TestFail("New add sr-iov device not found in guest. "
                                     "Command was: %s" % find_pci_cmd)

            # Test the newly added device
            try:
                session.cmd(params.get("pci_test_cmd") % (pci_num+1))
            except aexpect.ShellError, e:
                raise error.TestFail("Check for sr-iov device failed after PCI "
                                     "hotplug. Output: %r" % e.output)

        except Exception:
            pci_del(pci_num, ignore_failure=True)
            raise

    # Hot delete a pci device
    def pci_del(pci_num, ignore_failure=False):
        def _device_removed():
            after_del = vm.monitor.info("pci")
            return after_del != before_del

        before_del = vm.monitor.info("pci")
        if cmd_type == "pci_add":
            slot_id = "0" + pci_info[pci_num][1].split(",")[2].split()[1]
            cmd = "pci_del pci_addr=%s" % slot_id
            vm.monitor.send_args_cmd(cmd, convert=False)
        elif cmd_type == "device_add":
            cmd = "device_del id=%s" % pci_info[pci_num][0]
            vm.monitor.send_args_cmd(cmd)

        if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1)
            and not ignore_failure):
            raise error.TestFail("Failed to hot remove PCI device: %s. "
                                 "Monitor command: %s" %
                                 (pci_model, cmd))


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

    test_timeout = int(params.get("test_timeout", 360))
    # Test if it is nic or block
    pci_num_range = int(params.get("pci_num", 1))
    rp_times = int(params.get("repeat_times", 1))
    pci_model = params.get("pci_model", "pci-assign")
    # Need udpate match_string if you use a card other than 82576
    match_string = params.get("match_string", "82576")
    if vm.pci_assignable is not None:
        pa_pci_ids = vm.pci_assignable.request_devs(pci_num_range)

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

    # check monitor type
    qemu_binary = params.get("qemu_binary", "/usr/bin/qemu-kvm")
    qemu_binary = utils_misc.get_path(test.bindir, qemu_binary)
    is_qmp_monitor = (utils_misc.qemu_has_option("qmp", qemu_binary)
                     and params.get("monitor_type") == "qmp")
    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if is_qmp_monitor:
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")

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


    local_functions = locals()

    for j in range(rp_times):
        # pci_info is a list of list.
        # each element 'i' has 4 members:
        # pci_info[i][0] == device id, only used for device_add
        # pci_info[i][1] == output of device add command
        pci_info = []
        for pci_num in xrange(pci_num_range):
            msg = "Start hot-adding %sth pci device, repeat %d" % (pci_num + 1,
                                                                  j + 1)
            error.context(msg, logging.info)
            add_device(pci_num)
        for pci_num in xrange(pci_num_range):
            msg = "start hot-deleting %sth pci device repeat %d" % (pci_num + 1,
                                                                    j + 1)
            error.context(msg, logging.info)
            pci_del(-(pci_num + 1))
Ejemplo n.º 12
0
def run_pci_hotunplug(test, params, env):
    """
    Test hot unplug of PCI devices.

    1) Set up test environment in host if test sr-iov.
    2) Start VM.
    3) Get the device id that want to unplug.
    4) Delete the device, verify whether could remove the PCI device.

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

    def find_pci():
        output = vm.monitor.info("qtree")
        devices = re.findall(match_string, output)
        return devices

    # Hot delete a pci device
    def pci_del(device, ignore_failure=False):
        def _device_removed():
            after_del = vm.monitor.info("pci")
            return after_del != before_del

        before_del = vm.monitor.info("pci")
        if cmd_type == "device_del":
            cmd = "device_del id=%s" % device
            vm.monitor.send_args_cmd(cmd)
        else:
            raise error.TestFail("device_del command is not supported")

        if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1)
                and not ignore_failure):
            raise error.TestFail("Failed to hot remove PCI device: %s. "
                                 "Monitor command: %s" %
                                 (pci_model, cmd))

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

    test_timeout = int(params.get("test_timeout", 360))
    # Test if it is nic or block
    pci_num = int(params.get("unplug_pci_num", 1))
    pci_model = params.get("pci_model", "pci-assign")
    # Need udpate match_string if you use a card other than 82576
    match_string = params.get("match_string", "dev: %s, id \"(.*)\"")
    match_string = match_string % pci_model

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

    # check monitor type
    is_qmp_monitor = (utils_misc.qemu_has_option("qmp")
                      and params.get("monitor_type") == "qmp")
    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if is_qmp_monitor:
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")
    if not cmd_o:
        raise error.TestError("Unknow version of qemu")

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

    devices = find_pci()
    if devices:
        for device in devices[:pci_num]:
            # (lmr) I think here is the place where pci_info should go
            pci_info = []
            error.context("Hot unplug device %s" % device, logging.info)
            pci_del(device)
Ejemplo n.º 13
0
def run(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environmen.
    """
    def check_result(qmp_o, output=None, exception_list=""):
        """
        Check test result with difference way accoriding to
        result_check.
        result_check = equal, will compare cmd_return_value with qmp
                       command output.
        result_check = contain, will try to find cmd_return_value in qmp
                       command output.
        result_check = m_equal_q, will compare key value in monitor command
                       output and qmp command output.
        result_check = m_in_q, will try to find monitor command output's key
                       value in qmp command output.
        result_check = m_format_q, will try to match the output's format with
                       check pattern.

        :param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        :param o: output from pre_cmd, qmp_cmd or post_cmd or an execpt
        :param exception_list: element no need check.
        result set in config file.
        """
        if result_check == "equal":
            value = output
            if value != str(qmp_o):
                raise exceptions.TestFail("QMP command return value does not match "
                                          "the expect result. Expect result: '%s'\n"
                                          "Actual result: '%s'" % (value, qmp_o))
        elif result_check == "contain":
            values = output.split(';')
            for value in values:
                if value in exception_list:
                    continue
                if value.strip() not in str(qmp_o):
                    raise exceptions.TestFail("QMP command output does not contain "
                                              "expect result. Expect result: '%s'\n"
                                              "Actual result: '%s'"
                                              % (value, qmp_o))
        elif result_check == "not_contain":
            values = output.split(';')
            for value in values:
                if value in exception_list:
                    continue
                if value in str(qmp_o):
                    raise exceptions.TestFail("QMP command output contains unexpect"
                                              " result. Unexpect result: '%s'\n"
                                              "Actual result: '%s'"
                                              % (value, qmp_o))
        elif result_check == "m_equal_q":
            msg = "QMP command ouput is not equal to in human monitor command."
            msg += "\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman command output: '%s'" % output
            res = output.splitlines(True)
            if type(qmp_o) != type(res):
                len_o = 1
            else:
                len_o = len(qmp_o)
            if len(res) != len_o:
                if res[0].startswith(' '):
                    raise exceptions.TestFail("Human command starts with ' ', "
                                              "there is probably some garbage in "
                                              "the output.\n" + msg)
                res_tmp = []
                #(qemu)info block in RHEL7 divided into 3 lines
                for line in res:
                    if not line.startswith(' '):
                        res_tmp.append(line)
                    else:
                        res_tmp[-1] += line
                res = res_tmp
                if len(res) != len_o:
                    raise exceptions.TestFail(msg)
            re_str = r'([^ \t\n\r\f\v=]*)=([^ \t\n\r\f\v=]*)'
            for i in range(len(res)):
                if qmp_cmd == "query-version":
                    version = qmp_o['qemu']
                    version = "%s.%s.%s" % (version['major'], version['minor'],
                                            version['micro'])
                    package = qmp_o['package']
                    re_str = r"([0-9]+\.[0-9]+\.[0-9]+)\s*(\(\S*\))?"
                    hmp_version, hmp_package = re.findall(re_str, res[i])[0]
                    if not hmp_package:
                        hmp_package = package
                    hmp_package = hmp_package.strip()
                    package = package.strip()
                    hmp_version = hmp_version.strip()
                    if version != hmp_version or package != hmp_package:
                        raise exceptions.TestFail(msg)
                else:
                    matches = re.findall(re_str, res[i])
                    for key, val in matches:
                        if key in exception_list:
                            continue
                        if '0x' in val:
                            val = long(val, 16)
                            val_str = str(bin(val))
                            com_str = ""
                            for p in range(3, len(val_str)):
                                if val_str[p] == '1':
                                    com_str += '0'
                                else:
                                    com_str += '1'
                            com_str = "0b" + com_str
                            value = eval(com_str) + 1
                            if val_str[2] == '1':
                                value = -value
                            if value != qmp_o[i][key]:
                                msg += "\nValue in human monitor: '%s'" % value
                                msg += "\nValue in qmp: '%s'" % qmp_o[i][key]
                                raise exceptions.TestFail(msg)
                        elif qmp_cmd == "query-block":
                            cmp_str = "u'%s': u'%s'" % (key, val)
                            cmp_s = "u'%s': %s" % (key, val)
                            if '0' == val:
                                cmp_str_b = "u'%s': False" % key
                            elif '1' == val:
                                cmp_str_b = "u'%s': True" % key
                            else:
                                cmp_str_b = cmp_str
                            if (cmp_str not in str(qmp_o[i]) and
                                    cmp_str_b not in str(qmp_o[i]) and
                                    cmp_s not in str(qmp_o[i])):
                                msg += ("\nCan not find '%s', '%s' or '%s' in "
                                        " QMP command output."
                                        % (cmp_s, cmp_str_b, cmp_str))
                                raise exceptions.TestFail(msg)
                        elif qmp_cmd == "query-balloon":
                            if (int(val) * 1024 * 1024 != qmp_o[key] and
                                    val not in str(qmp_o[key])):
                                msg += ("\n'%s' is not in QMP command output"
                                        % val)
                                raise exceptions.TestFail(msg)
                        else:
                            if (val not in str(qmp_o[i][key]) and
                                    str(bool(int(val))) not in str(qmp_o[i][key])):
                                msg += ("\n'%s' is not in QMP command output"
                                        % val)
                                raise exceptions.TestFail(msg)
        elif result_check == "m_in_q":
            res = output.splitlines(True)
            msg = "Key value from human monitor command is not in"
            msg += "QMP command output.\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman monitor command output '%s'" % output
            for i in range(len(res)):
                params = res[i].rstrip().split()
                for param in params:
                    if param.rstrip() in exception_list:
                        continue
                    try:
                        str_o = str(qmp_o.values())
                    except AttributeError:
                        str_o = qmp_o
                    if param.rstrip() not in str(str_o):
                        msg += "\nKey value is '%s'" % param.rstrip()
                        raise error.TestFail(msg)
        elif result_check == "m_format_q":
            match_flag = True
            for i in qmp_o:
                if output is None:
                    raise exceptions.TestError("QMP output pattern is missing")
                if re.match(output.strip(), str(i)) is None:
                    match_flag = False
            if not match_flag:
                msg = "Output does not match the pattern: '%s'" % output
                raise exceptions.TestFail(msg)

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        raise exceptions.TestSkipError("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        logging.info("modprobe the module %s", module)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type('qmp')
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        raise exceptions.TestError("Incorrect configuration, no QMP monitor found.")
    hmp_ports = vm.get_monitors_by_type('human')
    if hmp_ports:
        hmp_port = hmp_ports[0]
    else:
        raise exceptions.TestError("Incorrect configuration, no QMP monitor found.")
    callback = {"host_cmd": lambda cmd: process.system_output(cmd, shell=True),
                "guest_cmd": session.get_command_output,
                "monitor_cmd": hmp_port.send_args_cmd,
                "qmp_cmd": qmp_port.send_args_cmd}

    def send_cmd(cmd):
        """ Helper to execute command on ssh/host/monitor """
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise exceptions.TestError("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    cmd_type = params.get("event_cmd_type")
    post_cmd = params.get("post_cmd")
    result_check = params.get("cmd_result_check")
    cmd_return_value = params.get("cmd_return_value")
    exception_list = params.get("exception_list", "")

    # Pre command
    if pre_cmd is not None:
        logging.info("Run prepare command '%s'.", pre_cmd)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: '%s'\n Output: '%s'", pre_cmd, pre_o)
    try:
        # Testing command
        logging.info("Run qmp command '%s'.", qmp_cmd)
        output = qmp_port.send_args_cmd(qmp_cmd)
        logging.debug("QMP command: '%s' \n Output: '%s'", qmp_cmd, output)
    except qemu_monitor.QMPCmdError, err:
        if params.get("negative_test") == 'yes':
            logging.debug("Negative QMP command: '%s'\n output:'%s'", qmp_cmd,
                          err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    raise exceptions.TestFail("'%s' not in exception '%s'"
                                              % (check_pattern, err))
        else:
            raise exceptions.TestFail(err)
Ejemplo n.º 14
0
def run_qmp_command(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

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

    def check_result(qmp_o, output=None):
        """
        Check test result with difference way accoriding to
        result_check.
        result_check = equal, will compare cmd_return_value with qmp
                       command output.
        result_check = contain, will try to find cmd_return_value in qmp
                       command output.
        result_check = m_equal_q, will compare key value in monitor command
                       output and qmp command output.
        result_check = m_in_q, will try to find monitor command output's key
                       value in qmp command output.
        result_check = m_format_q, will try to match the output's format with
                       check pattern.

        @param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        @param o: output from pre_cmd, qmp_cmd or post_cmd or an execpt
        result set in config file.
        """
        if result_check == "equal":
            value = output
            if value != str(qmp_o):
                raise error.TestFail(
                    "QMP command return value does not match"
                    " the expect result. Expect result: %s\n"
                    "Actual result: %s" % (value, qmp_o)
                )
        elif result_check == "contain":
            values = output.split(";")
            for value in values:
                if value.strip() not in str(qmp_o):
                    raise error.TestFail(
                        "QMP command output does not contain"
                        " expect result. Expect result: %s\n"
                        "Actual result: %s" % (value, qmp_o)
                    )
        elif result_check == "not_contain":
            values = output.split(";")
            for value in values:
                if value in str(qmp_o):
                    raise error.TestFail(
                        "QMP command output contains unexpect"
                        " result. Unexpect result: %s\n"
                        "Actual result: %s" % (value, qmp_o)
                    )
        elif result_check == "m_equal_q":
            msg = "QMP command ouput is not equal to in human monitor command."
            msg += "\nQMP command output: %s" % qmp_o
            msg += "\nHuman command output: %s" % output
            res = output.splitlines(True)
            if type(qmp_o) != type(res):
                len_o = 1
            else:
                len_o = len(qmp_o)
            if len(res) != len_o:
                raise error.TestFail(msg)
            re_str = r"([^ \t\n\r\f\v=]*)=([^ \t\n\r\f\v=]*)"
            for i in range(len(res)):
                if qmp_cmd == "query-version":
                    version = qmp_o["qemu"]
                    version = "%s.%s.%s" % (version["major"], version["minor"], version["micro"])
                    package = qmp_o["package"]
                    re_str = "([0-9]+\.[0-9]+\.[0-9]+)\s*(\(\S*\))?"
                    hmp_version, hmp_package = re.findall(re_str, res[i])[0]
                    if not hmp_package:
                        hmp_package = package
                    if version != hmp_version or package != hmp_package:
                        raise error.TestFail(msg)
                else:
                    matches = re.findall(re_str, res[i])
                    for key, val in matches:
                        if "0x" in val:
                            val = long(val, 16)
                            if val != qmp_o[i][key]:
                                msg += "\nValue in human monitor: %s" % val
                                msg += "\nValue in qmp: %s" % qmp_o[i][key]
                                raise error.TestFail(msg)
                        elif qmp_cmd == "query-block":
                            cmp_str = "u'%s': u'%s'" % (key, val)
                            cmp_s = "u'%s': %s" % (key, val)
                            if "0" == val:
                                cmp_str_b = "u'%s': False" % key
                            elif "1" == val:
                                cmp_str_b = "u'%s': True" % key
                            else:
                                cmp_str_b = cmp_str
                            if (
                                cmp_str not in str(qmp_o[i])
                                and cmp_str_b not in str(qmp_o[i])
                                and cmp_s not in str(qmp_o[i])
                            ):
                                msg += "\nCan not find %s, %s or %s" % (cmp_s, cmp_str_b, cmp_str)
                                msg += " in QMP command output"
                                raise error.TestFail(msg)
                        elif qmp_cmd == "query-balloon":
                            if int(val) * 1024 * 1024 != qmp_o[key] and val not in str(qmp_o[key]):
                                msg += "\n%s is not in QMP command output" % val
                                raise error.TestFail(msg)
                        else:
                            if val not in str(qmp_o[i][key]) and str(bool(int(val))) not in str(qmp_o[i][key]):
                                msg += "\n%s is not in QMP command output" % val
                                raise error.TestFail(msg)
        elif result_check == "m_in_q":
            res = output.splitlines(True)
            msg = "Key value from human monitor command is not in"
            msg += "QMP command output.\nQMP command output: %s" % qmp_o
            msg += "\nHuman monitor command output %s" % output
            for i in range(len(res)):
                params = res[i].rstrip().split()
                for param in params:
                    try:
                        str_o = str(qmp_o.values())
                    except AttributeError:
                        str_o = qmp_o
                    if param.rstrip() not in str(str_o):
                        msg += "\nKey value is %s" % param.rstrip()
                        raise error.TestFail(msg)
        elif result_check == "m_format_q":
            match_flag = True
            for i in qmp_o:
                if output is None:
                    raise error.TestError("QMP output pattern is missing")
                if re.match(output.strip(), str(i)) is None:
                    match_flag = False
            if not match_flag:
                msg = "Output does not match the pattern: %s" % output
                raise error.TestFail(msg)

    if not utils_misc.qemu_has_option("qmp"):
        raise error.TestNAError("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        error.context("modprobe the module %s" % module, logging.info)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type("qmp")
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        raise error.TestError("Incorrect configuration, no QMP monitor found.")
    hmp_ports = vm.get_monitors_by_type("human")
    if hmp_ports:
        hmp_port = hmp_ports[0]
    else:
        raise error.TestError("Incorrect configuration, no QMP monitor found.")
    callback = {
        "host_cmd": utils.system_output,
        "guest_cmd": session.get_command_output,
        "monitor_cmd": hmp_port.send_args_cmd,
        "qmp_cmd": qmp_port.send_args_cmd,
    }

    def send_cmd(cmd):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    cmd_type = params.get("event_cmd_type")
    post_cmd = params.get("post_cmd")
    result_check = params.get("cmd_result_check")
    cmd_return_value = params.get("cmd_return_value")

    if pre_cmd is not None:
        error.context("Run prepare command '%s'." % pre_cmd, logging.info)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: %s\n Output: %s", pre_cmd, pre_o)
    try:
        error.context("Run qmp command '%s'." % qmp_cmd, logging.info)
        output = qmp_port.send_args_cmd(qmp_cmd)
        logging.debug("QMP command: %s \n Output: %s", qmp_cmd, output)
    except qemu_monitor.QMPCmdError, err:
        if params.get("negative_test") == "yes":
            logging.debug("Negative QMP command: %s\n output:%s", qmp_cmd, err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    raise error.TestFail("%s not in exception %s" % (check_pattern, err))
        else:
            raise error.TestFail(err)
Ejemplo n.º 15
0
def run(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environmen.
    """
    def check_list(qmp_o, key, val=None, check_item_in_pair=True):
        """
        Check if the expect key, val are contained in QMP output qmp_o.

        :param qmp_o: output of QMP command
        :type qmp_o: list
        :param key: expect result
        :type key: str
        :param val: expect result
        :type val: str or None(if check_item_in_pair=False)
        :param check_item_in_pair: If expect result is dict (True) or str (False)
        :type check_item_in_pair: bool.

        :return check result
        :rtype: bool
        """
        for element in qmp_o:
            if isinstance(element, dict):
                if _check_dict(element, key, val, check_item_in_pair):
                    return True
            elif isinstance(element, list):
                if check_list(element, key, val, check_item_in_pair):
                    return True
            elif element != '' and not check_item_in_pair:
                if strict_match:
                    if operator.eq(key, element):
                        return True
                else:
                    if key in str(element):
                        return True
        return False

    def _check_dict(dic, key, val, check_item_in_pair=True):
        """
        Check if the expect key, val are contained in QMP output dic.

        :param dic: content of QMP command return value
        :type dic: dict
        :param key: expect result
        :type key: str
        :param val: expect result
        :type val: str or None(if check_item_in_pair=False)
        :param check_item_in_pair: If expect result is dict or str
        :type check_item_in_pair: bool. Means expect result is dict or str.

        :return check result
        :rtype: bool
        """
        if key in dic and not check_item_in_pair:
            return True
        elif key in dic and val == dic[key]:
            return True
        else:
            for value in dic.values():
                if isinstance(value, dict):
                    if _check_dict(value, key, val, check_item_in_pair):
                        return True
                elif isinstance(value, list):
                    if check_list(value, key, val, check_item_in_pair):
                        return True
                elif value != '' and not check_item_in_pair:
                    if strict_match:
                        if operator.eq(key, value):
                            return True
                    else:
                        if key in str(value):
                            return True
            return False

    def check_result(qmp_o, expect_o=None):
        """
        Check test result with difference way according to result_check.
        result_check = equal, expect_o should equal to qmp_o.
        result_check = contain, expect_o should be contained in qmp_o
        result_check = not_contain, expect_o should not be contained in qmp_o.

        :param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        :type qmp_o: list
        :param expect_o: the expect result.
        :type expect_o: list
        """
        logging.info("Expect result is %s", expect_o)
        logging.info("Actual result that get from qmp_cmd/post_cmd is %s",
                     qmp_o)
        if result_check == "equal":
            if not operator.eq(qmp_o, expect_o):
                test.fail("QMP output does not equal to the expect result.\n "
                          "Expect result: '%s'\n"
                          "Actual result: '%s'" % (expect_o, qmp_o))
        elif result_check == "contain":
            for o in expect_o:
                if isinstance(o, dict):
                    for key, val in o.items():
                        result = check_list(qmp_o, key, val)
                        if not result:
                            break
                elif isinstance(o, str):
                    result = check_list(qmp_o, o, check_item_in_pair=False)

                if result:
                    logging.info("QMP output contain the expect value %s", o)
                else:
                    test.fail("QMP output does not contain the expect value.\n"
                              "Missed expect value: '%s'\n"
                              "Actual result: '%s'\n" % (o, qmp_o))
        elif result_check == "not_contain":
            for o in expect_o:
                if isinstance(o, dict):
                    for key, val in o.items():
                        result = check_list(qmp_o, key, val)
                        if result:
                            break
                elif isinstance(o, str):
                    result = check_list(qmp_o, o, check_item_in_pair=False)

                if result:
                    test.fail("QMP output contain the unexpect result.\n"
                              "Unexpect result: '%s'\n"
                              "Actual result: '%s'" % (o, qmp_o))

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        test.cancel("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        logging.info("modprobe the module %s", module)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type('qmp')
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        test.error("Incorrect configuration, no QMP monitor found.")
    callback = {
        "host_cmd":
        lambda cmd: process.system_output(cmd, shell=True).decode(),
        "guest_cmd": session.cmd_output,
        "qmp_cmd": qmp_port.send_args_cmd
    }

    def send_cmd(cmd):
        """ Helper to execute command on host/ssh guest/qmp monitor """
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            test.error("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    post_cmd = params.get("post_cmd")
    cmd_type = params.get("event_cmd_type")
    result_check = params.get("cmd_result_check")
    strict_match = params.get("strict_match", "yes") == 'yes'
    expect_o = eval(params.get("cmd_return_value", "[]"))

    # Pre command
    if pre_cmd is not None:
        logging.info("Run prepare command '%s'.", pre_cmd)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: '%s'\n Output: '%s'", pre_cmd, pre_o)

    # qmp command
    try:
        # Testing command
        logging.info("Run qmp command '%s'.", qmp_cmd)
        qmp_o = qmp_port.send_args_cmd(qmp_cmd)
        if not isinstance(qmp_o, list):
            qmp_o = [qmp_o]
        logging.debug("QMP command: '%s' \n Output: '%s'", qmp_cmd, qmp_o)
    except qemu_monitor.QMPCmdError as err:
        if params.get("negative_test") == 'yes':
            logging.debug("Negative QMP command: '%s'\n output:'%s'", qmp_cmd,
                          err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    test.fail("'%s' not in exception '%s'" %
                              (check_pattern, err))
        else:
            test.fail(err)
    except qemu_monitor.MonitorProtocolError as err:
        test.fail(err)
    except Exception as err:
        test.fail(err)

    # sleep 10s to make netdev_del take effect
    if 'netdev_del' in qmp_cmd:
        time.sleep(10)

    # Post command
    if post_cmd is not None:
        logging.info("Run post command '%s'.", post_cmd)
        post_o = send_cmd(post_cmd)
        if not isinstance(post_o, list):
            post_o = [post_o]
        logging.debug("Post-command: '%s'\n Output: '%s'", post_cmd, post_o)

    if result_check == "equal" or result_check == "contain":
        logging.info("Verify qmp command '%s' works as designed.", qmp_cmd)
        if qmp_cmd == "query-name":
            vm_name = params["main_vm"]
            expect_o = [{'name': vm_name}]
        elif qmp_cmd == "query-uuid":
            uuid_input = params["uuid"]
            expect_o = [{'UUID': uuid_input}]
        elif qmp_cmd == "query-version":
            qemu_version_cmd = "rpm -qa | grep -E 'qemu-kvm(-(rhev|ma))?-[0-9]' | head -n 1"
            host_arch = platform.machine()
            qemu_version = callback["host_cmd"](qemu_version_cmd).replace(
                '.%s' % host_arch, '')
            expect_o = [str(qemu_version)]
        elif qmp_cmd == "query-block":
            images = params['images'].split()
            image_info = {}
            for image in images:
                image_params = params.object_params(image)
                image_format = image_params['image_format']
                image_drive = "drive_%s" % image
                if vm.check_capability(Flags.BLOCKDEV):
                    image_info['node-name'] = image_drive
                else:
                    image_info['device'] = image_drive
                image_info['qdev'] = image
                image_info['format'] = image_format
                expect_o.append(image_info)
        elif qmp_cmd == "query-target":
            host_arch = platform.machine()
            if host_arch == "ppc64le":
                host_arch = host_arch[:5]
            expect_o = [{"arch": host_arch}]
        elif qmp_cmd == "query-machines":
            # Remove avocado machine type
            vm_machines = params["machine_type"].split(':', 1)[-1]
            expect_o = [{'alias': vm_machines}]
        check_result(qmp_o, expect_o)
    elif result_check.startswith("post_"):
        logging.info("Verify post qmp command '%s' works as designed.",
                     post_cmd)
        result_check = result_check.split('_', 1)[1]
        check_result(post_o, expect_o)
    session.close()
Ejemplo n.º 16
0
def run(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environmen.
    """
    def check_result(qmp_o, output=None):
        """
        Check test result with difference way accoriding to
        result_check.
        result_check = equal, will compare cmd_return_value with qmp
                       command output.
        result_check = contain, will try to find cmd_return_value in qmp
                       command output.
        result_check = m_equal_q, will compare key value in monitor command
                       output and qmp command output.
        result_check = m_in_q, will try to find monitor command output's key
                       value in qmp command output.
        result_check = m_format_q, will try to match the output's format with
                       check pattern.

        :param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        :param o: output from pre_cmd, qmp_cmd or post_cmd or an execpt
        result set in config file.
        """
        if result_check == "equal":
            value = output
            if value != str(qmp_o):
                raise error.TestFail("QMP command return value does not match "
                                     "the expect result. Expect result: '%s'\n"
                                     "Actual result: '%s'" % (value, qmp_o))
        elif result_check == "contain":
            values = output.split(';')
            for value in values:
                if value.strip() not in str(qmp_o):
                    raise error.TestFail("QMP command output does not contain "
                                         "expect result. Expect result: '%s'\n"
                                         "Actual result: '%s'" %
                                         (value, qmp_o))
        elif result_check == "not_contain":
            values = output.split(';')
            for value in values:
                if value in str(qmp_o):
                    raise error.TestFail("QMP command output contains unexpect"
                                         " result. Unexpect result: '%s'\n"
                                         "Actual result: '%s'" %
                                         (value, qmp_o))
        elif result_check == "m_equal_q":
            msg = "QMP command ouput is not equal to in human monitor command."
            msg += "\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman command output: '%s'" % output
            res = output.splitlines(True)
            if type(qmp_o) != type(res):
                len_o = 1
            else:
                len_o = len(qmp_o)
            if len(res) != len_o:
                raise error.TestFail(msg)
            re_str = r'([^ \t\n\r\f\v=]*)=([^ \t\n\r\f\v=]*)'
            for i in range(len(res)):
                if qmp_cmd == "query-version":
                    version = qmp_o['qemu']
                    version = "%s.%s.%s" % (version['major'], version['minor'],
                                            version['micro'])
                    package = qmp_o['package']
                    re_str = r"([0-9]+\.[0-9]+\.[0-9]+)\s*(\(\S*\))?"
                    hmp_version, hmp_package = re.findall(re_str, res[i])[0]
                    if not hmp_package:
                        hmp_package = package
                    if version != hmp_version or package != hmp_package:
                        raise error.TestFail(msg)
                else:
                    matches = re.findall(re_str, res[i])
                    for key, val in matches:
                        if '0x' in val:
                            val = long(val, 16)
                            if val != qmp_o[i][key]:
                                msg += "\nValue in human monitor: '%s'" % val
                                msg += "\nValue in qmp: '%s'" % qmp_o[i][key]
                                raise error.TestFail(msg)
                        elif qmp_cmd == "query-block":
                            cmp_str = "u'%s': u'%s'" % (key, val)
                            cmp_s = "u'%s': %s" % (key, val)
                            if '0' == val:
                                cmp_str_b = "u'%s': False" % key
                            elif '1' == val:
                                cmp_str_b = "u'%s': True" % key
                            else:
                                cmp_str_b = cmp_str
                            if (cmp_str not in str(qmp_o[i])
                                    and cmp_str_b not in str(qmp_o[i])
                                    and cmp_s not in str(qmp_o[i])):
                                msg += ("\nCan not find '%s', '%s' or '%s' in "
                                        " QMP command output." %
                                        (cmp_s, cmp_str_b, cmp_str))
                                raise error.TestFail(msg)
                        elif qmp_cmd == "query-balloon":
                            if (int(val) * 1024 * 1024 != qmp_o[key]
                                    and val not in str(qmp_o[key])):
                                msg += ("\n'%s' is not in QMP command output" %
                                        val)
                                raise error.TestFail(msg)
                        else:
                            if (val not in str(qmp_o[i][key]) and str(
                                    bool(int(val))) not in str(qmp_o[i][key])):
                                msg += ("\n'%s' is not in QMP command output" %
                                        val)
                                raise error.TestFail(msg)
        elif result_check == "m_in_q":
            res = output.splitlines(True)
            msg = "Key value from human monitor command is not in"
            msg += "QMP command output.\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman monitor command output '%s'" % output
            for i in range(len(res)):
                params = res[i].rstrip().split()
                for param in params:
                    try:
                        str_o = str(qmp_o.values())
                    except AttributeError:
                        str_o = qmp_o
                    if param.rstrip() not in str(str_o):
                        msg += "\nKey value is '%s'" % param.rstrip()
                        raise error.TestFail(msg)
        elif result_check == "m_format_q":
            match_flag = True
            for i in qmp_o:
                if output is None:
                    raise error.TestError("QMP output pattern is missing")
                if re.match(output.strip(), str(i)) is None:
                    match_flag = False
            if not match_flag:
                msg = "Output does not match the pattern: '%s'" % output
                raise error.TestFail(msg)

    def qmp_cpu_check(output):
        """ qmp_cpu test check """
        last_cpu = int(params['smp']) - 1
        for out in output:
            cpu = out.get('CPU')
            if cpu is None:
                raise error.TestFail("'CPU' index is missing in QMP output "
                                     "'%s'" % out)
            else:
                current = out.get('current')
                if current is None:
                    raise error.TestFail("'current' key is missing in QMP "
                                         "output '%s'" % out)
                elif cpu < last_cpu:
                    if current is False:
                        pass
                    else:
                        raise error.TestFail("Attribute 'current' should be "
                                             "'False', but is '%s' instead.\n"
                                             "'%s'" % (current, out))
                elif cpu == last_cpu:
                    if current is True:
                        pass
                    else:
                        raise error.TestFail("Attribute 'current' should be "
                                             "'True', but is '%s' instead.\n"
                                             "'%s'" % (current, out))
                elif cpu <= last_cpu:
                    continue
                else:
                    raise error.TestFail("Incorrect CPU index '%s' (corrupted "
                                         "or higher than no_cpus).\n%s" %
                                         (cpu, out))

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        raise error.TestNAError("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        error.context("modprobe the module %s" % module, logging.info)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type('qmp')
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        raise error.TestError("Incorrect configuration, no QMP monitor found.")
    hmp_ports = vm.get_monitors_by_type('human')
    if hmp_ports:
        hmp_port = hmp_ports[0]
    else:
        raise error.TestError("Incorrect configuration, no QMP monitor found.")
    callback = {
        "host_cmd": utils.system_output,
        "guest_cmd": session.get_command_output,
        "monitor_cmd": hmp_port.send_args_cmd,
        "qmp_cmd": qmp_port.send_args_cmd
    }

    def send_cmd(cmd):
        """ Helper to execute command on ssh/host/monitor """
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    cmd_type = params.get("event_cmd_type")
    post_cmd = params.get("post_cmd")
    result_check = params.get("cmd_result_check")
    cmd_return_value = params.get("cmd_return_value")

    # HOOKs
    if result_check == 'qmp_cpu':
        pre_cmd = "cpu index=%d" % (int(params['smp']) - 1)

    # Pre command
    if pre_cmd is not None:
        error.context("Run prepare command '%s'." % pre_cmd, logging.info)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: '%s'\n Output: '%s'", pre_cmd, pre_o)
    try:
        # Testing command
        error.context("Run qmp command '%s'." % qmp_cmd, logging.info)
        output = qmp_port.send_args_cmd(qmp_cmd)
        logging.debug("QMP command: '%s' \n Output: '%s'", qmp_cmd, output)
    except qemu_monitor.QMPCmdError, err:
        if params.get("negative_test") == 'yes':
            logging.debug("Negative QMP command: '%s'\n output:'%s'", qmp_cmd,
                          err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    raise error.TestFail("'%s' not in exception '%s'" %
                                         (check_pattern, err))
        else:
            raise error.TestFail(err)
Ejemplo n.º 17
0
def run(test, params, env):
    """
    Test qmp event notification, this case will:
    1) Start VM with qmp enable.
    2) Connect to qmp port then run qmp_capabilities command.
    3) Initiate the qmp command defined in config (qmp_cmd)
    4) Verify that qmp command works as designed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environmen.
    """
    def check_result(qmp_o, output=None, exception_list=""):
        """
        Check test result with difference way accoriding to
        result_check.
        result_check = equal, will compare cmd_return_value with qmp
                       command output.
        result_check = contain, will try to find cmd_return_value in qmp
                       command output.
        result_check = m_equal_q, will compare key value in monitor command
                       output and qmp command output.
        result_check = m_in_q, will try to find monitor command output's key
                       value in qmp command output.
        result_check = m_format_q, will try to match the output's format with
                       check pattern.

        :param qmp_o: output from pre_cmd, qmp_cmd or post_cmd.
        :param o: output from pre_cmd, qmp_cmd or post_cmd or an execpt
        :param exception_list: element no need check.
        result set in config file.
        """
        if result_check == "equal":
            value = output
            if value != str(qmp_o):
                test.fail("QMP command return value does not match "
                          "the expect result. Expect result: '%s'\n"
                          "Actual result: '%s'" % (value, qmp_o))
        elif result_check == "contain":
            values = output.split(';')
            for value in values:
                if value in exception_list:
                    continue
                if value.strip() not in str(qmp_o):
                    test.fail("QMP command output does not contain "
                              "expect result. Expect result: '%s'\n"
                              "Actual result: '%s'" % (value, qmp_o))
        elif result_check == "not_contain":
            values = output.split(';')
            for value in values:
                if value in exception_list:
                    continue
                if value in str(qmp_o):
                    test.fail("QMP command output contains unexpect"
                              " result. Unexpect result: '%s'\n"
                              "Actual result: '%s'" % (value, qmp_o))
        elif result_check == "m_equal_q":
            msg = "QMP command ouput is not equal to in human monitor command."
            msg += "\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman command output: '%s'" % output
            res = output.splitlines(True)
            if type(qmp_o) != type(res):
                len_o = 1
            else:
                len_o = len(qmp_o)
            if len(res) != len_o:
                if res[0].startswith(' '):
                    test.fail("Human command starts with ' ', "
                              "there is probably some garbage in "
                              "the output.\n" + msg)
                res_tmp = []
                #(qemu)info block in RHEL7 divided into 3 lines
                for line in res:
                    if not line.startswith(' '):
                        res_tmp.append(line)
                    else:
                        res_tmp[-1] += line
                res = res_tmp
                if len(res) != len_o:
                    test.fail(msg)
            re_str = r'([^ \t\n\r\f\v=]*)=([^ \t\n\r\f\v=]*)'
            for i in range(len(res)):
                if qmp_cmd == "query-version":
                    version = qmp_o['qemu']
                    version = "%s.%s.%s" % (version['major'], version['minor'],
                                            version['micro'])
                    package = qmp_o['package']
                    re_str = r"([0-9]+\.[0-9]+\.[0-9]+)\s*(\(\S*\))?"
                    hmp_version, hmp_package = re.findall(re_str, res[i])[0]
                    if not hmp_package:
                        hmp_package = package
                    hmp_package = hmp_package.strip()
                    package = package.strip()
                    hmp_version = hmp_version.strip()
                    if version != hmp_version or package != hmp_package:
                        test.fail(msg)
                else:
                    matches = re.findall(re_str, res[i])
                    for key, val in matches:
                        if key in exception_list:
                            continue
                        if '0x' in val:
                            val = int(val, 16)
                            val_str = str(bin(val))
                            com_str = ""
                            for p in range(3, len(val_str)):
                                if val_str[p] == '1':
                                    com_str += '0'
                                else:
                                    com_str += '1'
                            com_str = "0b" + com_str
                            value = eval(com_str) + 1
                            if val_str[2] == '1':
                                value = -value
                            if value != qmp_o[i][key]:
                                msg += "\nValue in human monitor: '%s'" % value
                                msg += "\nValue in qmp: '%s'" % qmp_o[i][key]
                                test.fail(msg)
                        elif qmp_cmd == "query-block":
                            cmp_str = "u'%s': u'%s'" % (key, val)
                            cmp_s = "u'%s': %s" % (key, val)
                            if '0' == val:
                                cmp_str_b = "u'%s': False" % key
                            elif '1' == val:
                                cmp_str_b = "u'%s': True" % key
                            else:
                                cmp_str_b = cmp_str
                            if (cmp_str not in str(qmp_o[i]) and
                                    cmp_str_b not in str(qmp_o[i]) and
                                    cmp_s not in str(qmp_o[i])):
                                msg += ("\nCan not find '%s', '%s' or '%s' in "
                                        " QMP command output."
                                        % (cmp_s, cmp_str_b, cmp_str))
                                test.fail(msg)
                        elif qmp_cmd == "query-balloon":
                            if (int(val) * 1024 * 1024 != qmp_o[key] and
                                    val not in str(qmp_o[key])):
                                msg += ("\n'%s' is not in QMP command output"
                                        % val)
                                test.fail(msg)
                        else:
                            if (val not in str(qmp_o[i][key]) and
                                    str(bool(int(val))) not in str(qmp_o[i][key])):
                                msg += ("\n'%s' is not in QMP command output"
                                        % val)
                                test.fail(msg)
        elif result_check == "m_in_q":
            res = output.splitlines(True)
            msg = "Key value from human monitor command is not in"
            msg += "QMP command output.\nQMP command output: '%s'" % qmp_o
            msg += "\nHuman monitor command output '%s'" % output
            for i in range(len(res)):
                params = res[i].rstrip().split()
                for param in params:
                    if param.rstrip() in exception_list:
                        continue
                    try:
                        str_o = str(qmp_o.values())
                    except AttributeError:
                        str_o = qmp_o
                    if param.rstrip() not in str(str_o):
                        msg += "\nKey value is '%s'" % param.rstrip()
                        test.fail(msg)
        elif result_check == "m_format_q":
            match_flag = True
            for i in qmp_o:
                if output is None:
                    test.error("QMP output pattern is missing")
                if re.match(output.strip(), str(i)) is None:
                    match_flag = False
            if not match_flag:
                msg = "Output does not match the pattern: '%s'" % output
                test.fail(msg)

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        test.cancel("Host qemu does not support qmp.")

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

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    module = params.get("modprobe_module")
    if module:
        logging.info("modprobe the module %s", module)
        session.cmd("modprobe %s" % module)

    qmp_ports = vm.get_monitors_by_type('qmp')
    if qmp_ports:
        qmp_port = qmp_ports[0]
    else:
        test.error("Incorrect configuration, no QMP monitor found.")
    hmp_ports = vm.get_monitors_by_type('human')
    if hmp_ports:
        hmp_port = hmp_ports[0]
    else:
        test.error("Incorrect configuration, no QMP monitor found.")
    callback = {"host_cmd": lambda cmd: process.system_output(cmd, shell=True).decode(),
                "guest_cmd": session.cmd_output,
                "monitor_cmd": hmp_port.send_args_cmd,
                "qmp_cmd": qmp_port.send_args_cmd}

    def send_cmd(cmd):
        """ Helper to execute command on ssh/host/monitor """
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            test.error("cmd_type is not supported")

    pre_cmd = params.get("pre_cmd")
    qmp_cmd = params.get("qmp_cmd")
    cmd_type = params.get("event_cmd_type")
    post_cmd = params.get("post_cmd")
    result_check = params.get("cmd_result_check")
    cmd_return_value = params.get("cmd_return_value")
    exception_list = params.get("exception_list", "")

    # Pre command
    if pre_cmd is not None:
        logging.info("Run prepare command '%s'.", pre_cmd)
        pre_o = send_cmd(pre_cmd)
        logging.debug("Pre-command: '%s'\n Output: '%s'", pre_cmd, pre_o)
    try:
        # Testing command
        logging.info("Run qmp command '%s'.", qmp_cmd)
        output = qmp_port.send_args_cmd(qmp_cmd)
        logging.debug("QMP command: '%s' \n Output: '%s'", qmp_cmd, output)
    except qemu_monitor.QMPCmdError as err:
        if params.get("negative_test") == 'yes':
            logging.debug("Negative QMP command: '%s'\n output:'%s'", qmp_cmd,
                          err)
            if params.get("negative_check_pattern"):
                check_pattern = params.get("negative_check_pattern")
                if check_pattern not in str(err):
                    test.fail("'%s' not in exception '%s'"
                              % (check_pattern, err))
        else:
            test.fail(err)
    except qemu_monitor.MonitorProtocolError as err:
        test.fail(err)
    except Exception as err:
        test.fail(err)

    # Post command
    if post_cmd is not None:
        logging.info("Run post command '%s'.", post_cmd)
        post_o = send_cmd(post_cmd)
        logging.debug("Post-command: '%s'\n Output: '%s'", post_cmd, post_o)

    if result_check is not None:
        txt = "Verify that qmp command '%s' works as designed." % qmp_cmd
        logging.info(txt)
        if result_check == "equal" or result_check == "contain":
            if qmp_cmd == "query-name":
                vm_name = params["main_vm"]
                check_result(output, vm_name, exception_list)
            elif qmp_cmd == "query-uuid":
                uuid_input = params["uuid"]
                check_result(output, uuid_input, exception_list)
            else:
                check_result(output, cmd_return_value, exception_list)
        elif result_check == "m_format_q":
            check_result(output, cmd_return_value, exception_list)
        elif 'post' in result_check:
            result_check = result_check.split('_', 1)[1]
            check_result(post_o, cmd_return_value, exception_list)
        else:
            check_result(output, post_o, exception_list)
    session.close()
def run(test, params, env):
    """
    Test qmp event notification function:
    1) Boot up guest with qmp and macvtap.
    2) In guest, change network interface to promisc state.
    3) Try to catch qmp event notification in qmp monitor.
    4) Execute query-rx-filter in host qmp session.

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

    if not utils_misc.qemu_has_option("qmp"):
        error.TestNAError("This test case requires a host QEMU with QMP "
                          "monitor support")
    if params.get("nettype", "macvtap") != "macvtap":
        error.TestNAError("This test case test macvtap.")

    params["start_vm"] = "yes"
    vm_name = params.get("main_vm", "vm1")
    env_process.preprocess_vm(test, params, env, vm_name)

    vm = env.get_vm(vm_name)
    vm.verify_alive()

    event_cmd = params.get("event_cmd")
    event_cmd_type = params.get("event_cmd_type")
    event_check = params.get("event_check")
    timeout = int(params.get("check_timeout", 360))
    pre_cmd = params.get("pre_cmd")
    post_cmd = params.get("post_cmd")
    post_cmd_type = params.get("post_cmd_type")

    session = vm.wait_for_serial_login(timeout=int(params.get("login_timeout",
                                                              360)))

    callback = {"host_cmd": utils.system_output,
                "guest_cmd": session.get_command_output,
                "qmp_cmd": vm.get_monitors_by_type("qmp")[0].send_args_cmd}

    def send_cmd(cmd, cmd_type):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    if pre_cmd:
        error.context("Run pre_cmd '%s'", logging.info)
        pre_cmd_type = params.get("pre_cmd_type", event_cmd_type)
        send_cmd(pre_cmd, pre_cmd_type)

    mac = vm.get_mac_address()
    interface_name = utils_net.get_linux_ifname(session, mac)

    error.context("In guest, change network interface to promisc state.",
                  logging.info)
    event_cmd = params.get("event_cmd") % interface_name
    send_cmd(event_cmd, event_cmd_type)

    error.context("Try to get qmp events in %s seconds!" % timeout,
                  logging.info)
    end_time = time.time() + timeout
    qmp_monitors = vm.get_monitors_by_type("qmp")
    qmp_num = len(qmp_monitors)
    while time.time() < end_time:
        for monitor in qmp_monitors:
            event = monitor.get_event(event_check)
            if event:
                txt = "Monitr %s " % monitor.name
                txt += "receive qmp %s event notification" % event_check
                logging.info(txt)
                qmp_num -= 1
                qmp_monitors.remove(monitor)
        time.sleep(5)
        if qmp_num <= 0:
            break
    if qmp_num > 0:
        output = session.cmd("ip link show")
        err = "Monitor(s) "
        for monitor in qmp_monitors:
            err += "%s " % monitor.name
        err += " did not receive qmp %s event notification." % event_check
        err += " ip link show command output in guest: %s" % output
        raise error.TestFail(err)

    if post_cmd:
        for nic in vm.virtnet:
            post_cmd = post_cmd % nic.device_id
            error.context("Run post_cmd '%s'" % post_cmd, logging.info)
            post_cmd_type = params.get("post_cmd_type", event_cmd_type)
            output = send_cmd(post_cmd, post_cmd_type)
            post_cmd_check = params.get("post_cmd_check")
            if post_cmd_check:
                if post_cmd_check not in str(output):
                    err = "Did not find '%s' in " % post_cmd_check
                    err += "'%s' command's output: %s" % (post_cmd, output)
                    raise error.TestFail(err)

    if session:
        session.close()
Ejemplo n.º 19
0
def run(test, params, env):
    """
    change a removable media:
    1) Boot VM with QMP/human monitor enabled.
    2) Connect to QMP/human monitor server.
    3) Eject original cdrom.
    4) Eject original cdrom for second time.
    5) Insert new image to cdrom.
    6) Eject device after add new image by change command.
    7) Insert original cdrom to cdrom.
    8) Try to eject non-removable device w/o force option.

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

    qemu_binary = utils_misc.get_qemu_binary(params)
    if not utils_misc.qemu_has_option("qmp", qemu_binary):
        logging.warn("qemu does not support qmp. Human monitor will be used.")
    qmp_used = False
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    logging.info("Wait until device is ready")
    time.sleep(10)
    if vm.monitor.protocol == "qmp":
        qmp_used = True

    orig_img_name = params.get("cdrom_cd1")
    p_dict = {"file": orig_img_name}
    device_name = vm.get_block(p_dict)
    if device_name is None:
        msg = "Fail to get device using image %s" % orig_img_name
        raise error.TestFail(msg)
    error.context("Eject original device.")
    eject_cmd = "eject device=%s" % device_name
    vm.monitor.send_args_cmd(eject_cmd)
    logging.info("Wait until device is ejected")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if orig_img_name in str(blocks_info):
        raise error.TestFail("Fail to eject cdrom %s. " % orig_img_name)

    error.context("Eject original device for second time")
    vm.monitor.send_args_cmd(eject_cmd)

    new_img_name = params.get("new_img_name")
    error.context("Insert new image to device.")
    change_cmd = "change device=%s,target=%s" % (device_name, new_img_name)
    vm.monitor.send_args_cmd(change_cmd)
    logging.info("Wait until device changed")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if new_img_name not in str(blocks_info):
        raise error.TestFail("Fail to chang cdrom to %s." % new_img_name)
    if qmp_used:
        eject_cmd = "eject device=%s, force=True" % device_name
    else:
        eject_cmd = "eject device=%s" % device_name
    error.context("Eject device after add new image by change command")
    vm.monitor.send_args_cmd(eject_cmd)
    logging.info("Wait until new image is ejected")
    time.sleep(10)

    blocks_info = vm.monitor.info("block")
    if new_img_name in str(blocks_info):
        raise error.TestFail("Fail to eject cdrom %s." % orig_img_name)

    error.context("Insert %s to device %s" % (orig_img_name, device_name))
    change_cmd = "change device=%s,target=%s" % (device_name, orig_img_name)
    vm.monitor.send_args_cmd(change_cmd)
    logging.info("Wait until device changed")
    time.sleep(10)
    blocks_info = vm.monitor.info("block")
    if orig_img_name not in str(blocks_info):
        raise error.TestFail("Fail to change cdrom to %s." % orig_img_name)

    error.context("Try to eject non-removable device")
    p_dict = {"removable": False}
    device_name = vm.get_block(p_dict)
    if device_name is None:
        raise error.TestFail("Could not find non-removable device")
    if params.get("force_eject", "no") == "yes":
        if not qmp_used:
            eject_cmd = "eject -f %s " % device_name
        else:
            eject_cmd = "eject device=%s, force=True" % device_name
    else:
        eject_cmd = "eject device=%s," % device_name
    try:
        vm.monitor.send_args_cmd(eject_cmd)
    except Exception, e:
        if "is not removable" not in str(e):
            raise error.TestFail(e)
        logging.debug("Catch exception message: %s" % e)
Ejemplo n.º 20
0
def run_sr_iov_hotplug(test, params, env):
    """
    Test hotplug of sr-iov devices.

    (Elements between [] are configurable test parameters)
    1) Set up sr-iov test environment in host.
    2) Start VM.
    3) PCI add one/multi sr-io  deivce with (or without) repeat
    4) Compare output of monitor command 'info pci'.
    5) Compare output of guest command [reference_cmd].
    6) Verify whether pci_model is shown in [pci_find_cmd].
    7) Check whether the newly added PCI device works fine.
    8) Delete the device, verify whether could remove the sr-iov device.

    @param test:   KVM test object.
    @param params: Dictionary with the test parameters.
    @param env:    Dictionary with test environment.
    """
    def pci_add_iov(pci_num):
        pci_add_cmd = ("pci_add pci_addr=auto host host=%s,if=%s" %
                       (pa_pci_ids[pci_num], pci_model))
        if params.get("hotplug_params"):
            assign_param = params.get("hotplug_params").split()
            for param in assign_param:
                value = params.get(param)
                if value:
                    pci_add_cmd += ",%s=%s" % (param, value)

        return pci_add(pci_add_cmd)

    def pci_add(pci_add_cmd):
        error.context("Adding pci device with command 'pci_add'")
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        pci_info.append(['', add_output])

        if not "OK domain" in add_output:
            raise error.TestFail("Add PCI device failed. "
                                 "Monitor command is: %s, Output: %r" %
                                 (pci_add_cmd, add_output))
        return vm.monitor.info("pci")

    def check_support_device(dev):
        if is_qmp_monitor:
            devices_supported = vm.monitor.human_monitor_cmd("%s ?" % cmd_type)
        else:
            devices_supported = vm.monitor.send_args_cmd("%s ?" % cmd_type)
        # Check if the device is support in qemu
        is_support = utils_test.find_substring(devices_supported, dev)
        if not is_support:
            raise error.TestError("%s doesn't support device: %s" %
                                  (cmd_type, dev))

    def device_add_iov(pci_num):
        device_id = "%s" % pci_model + "-" + utils_misc.generate_random_id()
        pci_info.append([device_id])
        check_support_device("pci-assign")
        pci_add_cmd = ("device_add id=%s,driver=pci-assign,host=%s" %
                       (pci_info[pci_num][0], pa_pci_ids[pci_num]))
        if params.get("hotplug_params"):
            assign_param = params.get("hotplug_params").split()
            for param in assign_param:
                value = params.get(param)
                if value:
                    pci_add_cmd += ",%s=%s" % (param, value)
        return device_add(pci_num, pci_add_cmd)

    def device_add(pci_num, pci_add_cmd):
        error.context("Adding pci device with command 'device_add'")
        if is_qmp_monitor:
            add_output = vm.monitor.send_args_cmd(pci_add_cmd)
        else:
            add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        pci_info[pci_num].append(add_output)

        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][0] not in after_add:
            logging.debug("Print info pci after add the block: %s" % after_add)
            raise error.TestFail("Add device failed. Monitor command is: %s"
                                 ". Output: %r" % (pci_add_cmd, add_output))
        return after_add

    # Hot add a pci device
    def add_device(pci_num):
        reference_cmd = params.get("reference_cmd")
        find_pci_cmd = params.get("find_pci_cmd")
        info_pci_ref = vm.monitor.info("pci")
        reference = session.cmd_output(reference_cmd)

        try:
            # get function for adding device.
            add_fuction = local_functions["%s_iov" % cmd_type]
        except Exception:
            raise error.TestError(
                "No function for adding sr-iov dev with '%s'" % cmd_type)
        after_add = None
        if add_fuction:
            # Do add pci device.
            after_add = add_fuction(pci_num)

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

            # Define a helper function to catch PCI device string
            def _find_pci():
                o = session.cmd_output(find_pci_cmd)
                if re.search(match_string, o, re.IGNORECASE):
                    return True
                else:
                    return False

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

            secs = int(params.get("wait_secs_for_hook_up"))
            if not utils_misc.wait_for(_new_shown, test_timeout, secs, 3):
                raise error.TestFail(
                    "No new device shown in output of command "
                    "executed inside the guest: %s" % reference_cmd)

            if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3):
                raise error.TestFail(
                    "New add sr-iov device not found in guest. "
                    "Command was: %s" % find_pci_cmd)

            # Test the newly added device
            try:
                session.cmd(params.get("pci_test_cmd") % (pci_num + 1))
            except aexpect.ShellError, e:
                raise error.TestFail(
                    "Check for sr-iov device failed after PCI "
                    "hotplug. Output: %r" % e.output)

        except Exception:
            pci_del(pci_num, ignore_failure=True)
            raise

    # Hot delete a pci device
    def pci_del(pci_num, ignore_failure=False):
        def _device_removed():
            after_del = vm.monitor.info("pci")
            return after_del != before_del

        before_del = vm.monitor.info("pci")
        if cmd_type == "pci_add":
            slot_id = "0" + pci_info[pci_num][1].split(",")[2].split()[1]
            cmd = "pci_del pci_addr=%s" % slot_id
            vm.monitor.send_args_cmd(cmd, convert=False)
        elif cmd_type == "device_add":
            cmd = "device_del id=%s" % pci_info[pci_num][0]
            vm.monitor.send_args_cmd(cmd)

        if (not utils_misc.wait_for(_device_removed, test_timeout, 0, 1)
                and not ignore_failure):
            raise error.TestFail("Failed to hot remove PCI device: %s. "
                                 "Monitor command: %s" % (pci_model, cmd))

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

    test_timeout = int(params.get("test_timeout", 360))
    # Test if it is nic or block
    pci_num_range = int(params.get("pci_num", 1))
    rp_times = int(params.get("repeat_times", 1))
    pci_model = params.get("pci_model", "pci-assign")
    # Need udpate match_string if you use a card other than 82576
    match_string = params.get("match_string", "82576")
    if vm.pci_assignable is not None:
        pa_pci_ids = vm.pci_assignable.request_devs(pci_num_range)

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

    # check monitor type
    qemu_binary = params.get("qemu_binary", "/usr/bin/qemu-kvm")
    qemu_binary = utils_misc.get_path(test.bindir, qemu_binary)
    is_qmp_monitor = (utils_misc.qemu_has_option("qmp", qemu_binary)
                      and params.get("monitor_type") == "qmp")
    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if is_qmp_monitor:
        cmd_o = vm.monitor.info("commands")
    else:
        cmd_o = vm.monitor.send_args_cmd("help")

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

    local_functions = locals()

    for j in range(rp_times):
        # pci_info is a list of list.
        # each element 'i' has 4 members:
        # pci_info[i][0] == device id, only used for device_add
        # pci_info[i][1] == output of device add command
        pci_info = []
        for pci_num in xrange(pci_num_range):
            msg = "Start hot-adding %sth pci device, repeat %d" % (pci_num + 1,
                                                                   j + 1)
            error.context(msg, logging.info)
            add_device(pci_num)
        for pci_num in xrange(pci_num_range):
            msg = "start hot-deleting %sth pci device repeat %d" % (pci_num +
                                                                    1, j + 1)
            error.context(msg, logging.info)
            pci_del(-(pci_num + 1))
Ejemplo n.º 21
0
def run_qmp_event_notification(test, params, env):
    """
    Test qmp event notification function:
    1) Boot up guest with qmp.
    2) Trigger qmp event in guest.
    3) Try to catch qmp event notification in qmp monitor.

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

    if not utils_misc.qemu_has_option("qmp"):
        error.TestNAError("This test case requires a host QEMU with QMP monitor support")
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
    callback = {
        "host_cmd": commands.getoutput,
        "guest_cmd": session.get_command_output,
        "monitor_cmd": vm.monitor.send_args_cmd,
        "qmp_cmd": vm.monitors[1].send_args_cmd,
    }

    def send_cmd(cmd):
        if cmd_type in callback.keys():
            return callback[cmd_type](cmd)
        else:
            raise error.TestError("cmd_type is not supported")

    event_cmd = params.get("event_cmd")
    cmd_type = params.get("event_cmd_type")
    event_check = params.get("event_check")
    timeout = int(params.get("check_timeout", 360))
    action_check = params.get("action_check")

    if params.get("pre_event_cmd"):
        send_cmd(params.get("pre_event_cmd"))

    cmd_o = send_cmd(event_cmd)

    end_time = time.time() + timeout
    qmp_monitors = []
    for monitor in vm.monitors:
        monitor_params = params.object_params(monitor.name)
        if monitor_params.get("monitor_type") == "qmp":
            qmp_monitors += [monitor]
    qmp_num = len(qmp_monitors)
    logging.info("Try to get qmp events in %s seconds!" % timeout)
    while time.time() < end_time:
        for monitor in qmp_monitors:
            event = monitor.get_event(event_check)
            if event_check == "WATCHDOG":
                if event and event["data"]["action"] == action_check:
                    logging.info("Receive watchdog %s event notification" % action_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
            else:
                if event:
                    logging.info("Receive qmp %s event notification" % event_check)
                    qmp_num -= 1
                    qmp_monitors.remove(monitor)
        time.sleep(5)
        if qmp_num <= 0:
            break

    if qmp_num > 0:
        raise error.TestFail("Did not receive qmp %s event notification" % event_check)

    if params.get("post_event_cmd"):
        send_cmd(params.get("post_event_cmd"))
    if session:
        session.close()