Ejemplo n.º 1
0
def run(test, params, env):
    """
    [pci-bridge]Check stress when 31 block devices attached to 1 pci-bridge, this case will:
    1) Attach one pci-bridge to guest.
    2) Create 31 disks to this pci-bridge.
    3) Start the guest.
    4) Check 'info block'.
    5) Read and write data on disks under pci bridge.

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

    error_context.context("Modify params!", logging.info)
    image_parent_bus = params.get("image_parent_bus")
    image_num = int(params.get("image_num", 0))
    if image_num != 0:
        for index in range(image_num):
            image = "stg%s" % index
            params["images"] = ' '.join([params["images"], image])
            params["disk_pci_bus_%s" % image] = image_parent_bus
            params["image_name_%s" % image] = "images/%s" % image
            params["image_size_%s" % image] = "100M"
            params["force_create_image_%s" % image] = "yes"
            params["remove_image_%s" % image] = "yes"
            params["blk_extra_params_%s" %
                   image] = "serial=TARGET_DISK%s" % index

    env_process.process_images(env_process.preprocess_image, test, params)
    env_process.preprocess_vm(test, params, env, params["main_vm"])

    error_context.context("Get the main VM!", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

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

    error_context.context("Check 'info block'!", logging.info)
    monitor_info_block = vm.monitor.info_block(False)
    if image_num + 1 != len(monitor_info_block.keys()):
        test.fail("Check 'info block' failed!")
    logging.info("Check 'info block' succeed!")

    error_context.context("Read and write data on all disks!", logging.info)
    sub_test_type = params.get("sub_test_type", "dd_test")
    images = params["images"]
    images = images.split()
    images.pop(0)
    for image in images:
        if params.get("dd_if") == "ZERO":
            params["dd_of"] = image
        else:
            params["dd_if"] = image
        utils_test.run_virt_sub_test(test, params, env, sub_test_type)

    logging.info("Read and write data on all disks succeed!")
    session.close()
Ejemplo n.º 2
0
def run(test, params, env):
    """
    [pci-bridge]Check stress when 31 block devices attached to 1 pci-bridge, this case will:
    1) Attach one pci-bridge to guest.
    2) Create 31 disks to this pci-bridge.
    3) Start the guest.
    4) Check 'info block'.
    5) Read and write data on disks under pci bridge.

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

    error_context.context("Modify params!", logging.info)
    image_parent_bus = params.get("image_parent_bus")
    image_num = int(params.get("image_num", 0))
    if image_num != 0:
        for index in xrange(image_num):
            image = "stg%s" % index
            params["images"] = ' '.join([params["images"], image])
            params["disk_pci_bus_%s" % image] = image_parent_bus
            params["image_name_%s" % image] = "images/%s" % image
            params["image_size_%s" % image] = "100M"
            params["force_create_image_%s" % image] = "yes"
            params["remove_image_%s" % image] = "yes"
            params["blk_extra_params_%s" % image] = "serial=TARGET_DISK%s" % index

    env_process.process_images(env_process.preprocess_image, test, params)
    env_process.preprocess_vm(test, params, env, params["main_vm"])

    error_context.context("Get the main VM!", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

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

    error_context.context("Check 'info block'!", logging.info)
    monitor_info_block = vm.monitor.info_block(False)
    if image_num + 1 != len(monitor_info_block.keys()):
        raise error.TestFail("Check 'info block' failed!")
    logging.info("Check 'info block' succeed!")

    error_context.context("Read and write data on all disks!", logging.info)
    sub_test_type = params.get("sub_test_type", "dd_test")
    images = params["images"]
    images = images.split()
    images.pop(0)
    for image in images:
        if params.get("dd_if") == "ZERO":
            params["dd_of"] = image
        else:
            params["dd_if"] = image
        utils_test.run_virt_sub_test(test, params, env, sub_test_type)

    logging.info("Read and write data on all disks succeed!")
    session.close()
Ejemplo n.º 3
0
    def generate_image(dev_slots, plug, params, qdev, image_size, pcie, test):
        """
        Generate the data disk devices to be plugged

        :param dev_slots: All the slots to be plugged
        :param plug: BlockDevicesPlug
        :param params: vm.params
        :param qdev: DevContainer
        :param image_size: The image size to be specified
        :param pcie: if itis pcie bus
        """
        disks = []
        for slot in dev_slots:
            scsi_bus = 1
            parent_bus = 'pcie_extra_root_port_%s' % slot if pcie else 'pci.0'
            images = []
            for i in range(1, 9):
                stg = 'stg%s%s' % (slot, i)
                images.append(stg)
                params['images'] += ' %s' % stg
                params['image_name_%s' % stg] = 'images/%s' % stg
                params['image_size_%s' % stg] = image_size
                params['remove_image_%s' % stg] = 'yes'
                params['force_create_image_%s' % stg] = 'no'
                params['create_image_%s' % stg] = 'yes'
                params['boot_drive_%s' % stg] = 'no'
                # Specify the address of the device, plug them into same slot
                addr = 0 if pcie else slot
                set_addr(stg, addr, i, params)
                if params['drive_format'].startswith('scsi'):
                    # Create oen new scsi bus for each block device
                    params['drive_bus_%s' % stg] = scsi_bus
                    scsi_bus += 1
            env_process.process_images(env_process.preprocess_image, test, params)
            parent_bus_obj = qdev.get_buses({'aobject': parent_bus})[0]
            plug._hotplug_devs(images, vm.monitor, bus=parent_bus_obj)
            disks.extend(plug)
        return disks
Ejemplo n.º 4
0
def run(test, params, env):
    """
    [pci-bridge] Check devices which attached to 1 pci-bridge
    [pci-bridge] Check devices which attached to different pci-bridges
    [pci-bridge] Hotplug and unplug different devices to 1 pci-bridge
    [pci-bridge] Hotplug and unplug different devices to different pci-bridges
    [pci-bridge] Migration with pci-bridge
    This case will:
    1) Attach one or multiple pci-bridge(s) to guest.
    2) Prepare devices attached to pci-bridge(s).
    3) Start the guest.
    4) Hotplug devices (if needed).
    5) Check devices.
    6) Hotunplug devices (if needed).
    7) Do migration (if needed).

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

    error_context.context("Modify params!", logging.info)
    pci_bridge_num = int(params.get("pci_bridge_num", 1))
    prepare_pci_bridge(test, params, pci_bridge_num)
    pci_bridges = params.objects("pci_controllers")

    opr = params.get("operation")
    image_num = int(params.get("image_num", 3))
    device_num = prepare_images(test, params, image_num, pci_bridge_num, opr)

    if opr != "block_stress":
        device_num = prepare_nics(test, params, pci_bridge_num, opr,
                                  device_num)

    params["start_vm"] = "yes"
    env_process.process_images(env_process.preprocess_image, test, params)
    env_process.preprocess_vm(test, params, env, params["main_vm"])

    error_context.context("Get the main VM!", logging.info)
    vm = env.get_vm(params["main_vm"])

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

    if opr == "hotplug_unplug":
        device_list = []
        fmt_list = params.objects("disk_driver")
        image_list = params.objects("images")
        del image_list[0]
        if image_num > len(fmt_list):
            test.error("No sufficient disk driver type!")
        for i in range(image_num):
            image = image_list[i]
            fmt = fmt_list[i]
            if pci_bridge_num == 1:
                pci_bridge_id = pci_bridges[0]
            else:
                index = i % pci_bridge_num
                pci_bridge_id = pci_bridges[index]
            if fmt == "scsi-hd" and params["drive_format"] == "scsi-hd":
                params["drive_bus_%s" % image] = 1
            error_context.context(
                "Hotplug a %s disk on %s!" % (fmt, pci_bridge_id),
                logging.info)
            device_list += disk_hotplug(test, params, vm, session, image, fmt,
                                        pci_bridge_id)

    check_data_disks(test, params, env, vm, session)

    error_context.context("Ping guest!", logging.info)
    guest_ip = vm.get_address()
    status, output = utils_test.ping(guest_ip, count=10, timeout=20)
    if status:
        test.fail("Ping guest failed!")
    elif utils_test.get_loss_ratio(output) == 100:
        test.fail("All packets lost during ping guest %s." % guest_ip)

    if opr == "hotplug_unplug":
        error_context.context("Unplug those hotplugged devices!", logging.info)
        device_list.reverse()
        for dev in device_list:
            ret = vm.devices.simple_unplug(dev, vm.monitor)
            if ret[1] is False:
                test.fail("Failed to unplug device '%s'."
                          "Output:\n%s" % (dev, ret[0]))
    elif opr == "with_migration":
        error_context.context("Migrating...", logging.info)
        vm.migrate(float(params.get("mig_timeout", "3600")))

    error_context.context("Check kernel crash message!", logging.info)
    vm.verify_kernel_crash()

    session.close()
Ejemplo n.º 5
0
def run(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params. (Optional)
    4) Create partition on those disks.
    5) Get disk dev filenames in guest.
    6) Format those disks in guest.
    7) Copy file into / out of those disks.
    8) Compare the original file and the copied file using md5 or fc comand.
    9) Repeat steps 3-5 if needed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    def _do_post_cmd(session):
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    error_context.context("Parsing test configuration", logging.info)
    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    stg_params += _add_param("drive_cache", params.get("stg_drive_cache"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                       stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in range(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm is False:
                test.error("Incorrect cfg: stg_params %s looks "
                           "like range(..) but doesn't contain "
                           "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', 'images/%s')
    for i in range(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.items():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     astring.tabular_output(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    error_context.context("Start the guest with new disks", logging.info)
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        env_process.process_images(env_process.preprocess_image, test,
                                   vm_params)

    error_context.context("Start the guest with those disks", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    login_timeout = int(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=login_timeout)

    n_repeat = int(params.get("n_repeat", "1"))
    file_system = [_.strip() for _ in params["file_system"].split()]
    cmd_timeout = float(params.get("cmd_timeout", 360))
    black_list = params["black_list"].split()
    drive_letters = int(params.get("drive_letters", "26"))
    stg_image_size = params["stg_image_size"]
    dd_test = params.get("dd_test", "no")
    pre_command = params.get("pre_command", "")
    labeltype = params.get("labeltype", "gpt")
    iozone_target_num = int(params.get('iozone_target_num', '5'))
    iozone_options = params.get('iozone_options')
    iozone_timeout = float(params.get('iozone_timeout', '7200'))

    have_qtree = True
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        have_qtree = False

    if (params.get("check_guest_proc_scsi") == "yes") and have_qtree:
        error_context.context("Verifying qtree vs. test params")
        err = 0
        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
        disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block())
        err += tmp1 + tmp2
        err += disks.generate_params()
        err += disks.check_disk_params(params)
        (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
            session.cmd_output('cat /proc/scsi/scsi'))
        err += tmp1 + tmp2

        if err:
            test.fail("%s errors occurred while verifying qtree vs."
                      " params" % err)
        if params.get('multi_disk_only_qtree') == 'yes':
            return
    try:
        err_msg = "Set disks num: %d" % stg_image_num
        err_msg += ", Get disks num in guest: %d"
        ostype = params["os_type"]
        if ostype == "windows":
            error_context.context(
                "Get windows disk index that to "
                "be formatted", logging.info)
            disks = utils_disk.get_windows_disks_index(session, stg_image_size)
            if len(disks) < stg_image_num:
                test.fail("Fail to list all the volumes"
                          ", %s" % err_msg % len(disks))
            if len(disks) > drive_letters:
                black_list.extend(utils_misc.get_winutils_vol(session))
                disks = random.sample(disks, drive_letters - len(black_list))
            error_context.context(
                "Clear readonly for all disks and online "
                "them in windows guest.", logging.info)
            if not utils_disk.update_windows_disk_attributes(session, disks):
                test.fail("Failed to update windows disk attributes.")
            dd_test = "no"
        else:
            error_context.context("Get linux disk that to be "
                                  "formatted", logging.info)
            disks = sorted(utils_disk.get_linux_disks(session).keys())
            if len(disks) < stg_image_num:
                test.fail("Fail to list all the volumes"
                          ", %s" % err_msg % len(disks))
    except Exception:
        _do_post_cmd(session)
        raise
    try:
        if iozone_options:
            iozone = generate_instance(params, session, 'iozone')
            random.shuffle(disks)
        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            for n, disk in enumerate(disks):
                error_context.context("Format disk in guest: '%s'" % disk,
                                      logging.info)
                # Random select one file system from file_system
                index = random.randint(0, (len(file_system) - 1))
                fstype = file_system[index].strip()
                partitions = utils_disk.configure_empty_disk(
                    session,
                    disk,
                    stg_image_size,
                    ostype,
                    fstype=fstype,
                    labeltype=labeltype)
                if not partitions:
                    test.fail("Fail to format disks.")
                cmd_list = params["cmd_list"]
                for partition in partitions:
                    orig_partition = partition
                    if "/" not in partition:
                        partition += ":"
                    else:
                        partition = partition.split("/")[-1]
                    error_context.context(
                        "Copy file into / out of partition:"
                        " %s..." % partition, logging.info)
                    for cmd_l in cmd_list.split():
                        cmd = params.get(cmd_l)
                        if cmd:
                            session.cmd(cmd % partition, timeout=cmd_timeout)
                    cmd = params["compare_command"]
                    key_word = params["check_result_key_word"]
                    output = session.cmd_output(cmd)
                    if iozone_options and n < iozone_target_num:
                        iozone.run(iozone_options.format(orig_partition),
                                   iozone_timeout)
                    if key_word not in output:
                        test.fail("Files on guest os root fs and disk differ")
                    if dd_test != "no":
                        error_context.context(
                            "dd test on partition: %s..." % partition,
                            logging.info)
                        status, output = session.cmd_status_output(
                            dd_test % (partition, partition),
                            timeout=cmd_timeout)
                        if status != 0:
                            test.fail("dd test fail: %s" % output)
                    # When multiple SCSI disks are simulated by scsi_debug,
                    # they could be viewed as multiple paths to the same
                    # storage device. So need umount partition before operate
                    # next disk, in order to avoid corrupting the filesystem
                    # (xfs integrity checks error).
                    if ostype == "linux" and "scsi_debug add_host" in pre_command:
                        status, output = session.cmd_status_output(
                            "umount /dev/%s" % partition, timeout=cmd_timeout)
                        if status != 0:
                            test.fail("Failed to umount partition '%s': %s" %
                                      (partition, output))
            need_reboot = params.get("need_reboot", "no")
            need_shutdown = params.get("need_shutdown", "no")
            if need_reboot == "yes":
                error_context.context("Rebooting guest ...", logging.info)
                session = vm.reboot(session=session, timeout=login_timeout)
            if need_shutdown == "yes":
                error_context.context("Shutting down guest ...", logging.info)
                vm.graceful_shutdown(timeout=login_timeout)
                if vm.is_alive():
                    test.fail("Fail to shut down guest.")
                error_context.context("Start the guest again.", logging.info)
                vm = env.get_vm(params["main_vm"])
                vm.create(params=params)
                session = vm.wait_for_login(timeout=login_timeout)
            error_context.context("Delete partitions in guest.", logging.info)
            for disk in disks:
                utils_disk.clean_partition(session, disk, ostype)
    finally:
        if iozone_options:
            iozone.clean()
        _do_post_cmd(session)
Ejemplo n.º 6
0
def run(test, params, env):
    """
    Test hotplug of PCI devices and check the status in guest.
    1 Boot up a guest
    2 Hotplug virtio disk to the guest. Record the id and partition name of
      the disk in a list.
    3 Random choice a disk in the list. Unplug the disk and check the
      partition status.
    4 Hotpulg the disk back to guest with the same monitor cmdline and same
      id which is record in step 2.
    5 Check the partition status in guest. And confirm the disk with dd cmd
    6 Repeat step 3 to 5 for N times

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

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

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

    # Select an image file
    def find_image(pci_num):
        image_params = params.object_params("%s" % img_list[pci_num + 1])
        o = storage.get_image_filename(image_params, data_dir.get_data_dir())
        return o

    def pci_add_block(pci_num, queues, pci_id):
        image_filename = find_image(pci_num)
        pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" %
                       (image_filename, pci_model))
        return pci_add(pci_add_cmd)

    def pci_add(pci_add_cmd):
        guest_devices = session.cmd_output(chk_cmd)
        error.context("Adding pci device with command 'pci_add'")
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        guest_device = find_new_device(chk_cmd, guest_devices)
        pci_info.append(['', '', add_output, pci_model, guest_device])
        if "OK domain" not in add_output:
            raise error.TestFail("Add PCI device failed. "
                                 "Monitor command is: %s, Output: %r" %
                                 (pci_add_cmd, add_output))
        return vm.monitor.info("pci")

    def is_supported_device(dev):
        # Probe qemu to verify what is the supported syntax for PCI hotplug
        cmd_output = vm.monitor.human_monitor_cmd("?")
        if len(re.findall("\ndevice_add", cmd_output)) > 0:
            cmd_type = "device_add"
        elif len(re.findall("\npci_add", cmd_output)) > 0:
            cmd_type = "pci_add"
        else:
            raise error.TestError("Unknown version of qemu")

        # Probe qemu for a list of supported devices
        probe_output = vm.monitor.human_monitor_cmd("%s ?" % cmd_type)
        devices_supported = [
            j.strip('"') for j in re.findall('\"[a-z|0-9|\-|\_|\,|\.]*\"',
                                             probe_output, re.MULTILINE)
        ]
        logging.debug(
            "QEMU reported the following supported devices for "
            "PCI hotplug: %s", devices_supported)
        return (dev in devices_supported)

    def verify_supported_device(dev):
        if not is_supported_device(dev):
            raise error.TestError("%s doesn't support device: %s" %
                                  (cmd_type, dev))

    def device_add_block(pci_num, queues=1, pci_id=None):
        if pci_id is not None:
            device_id = pci_type + "-" + pci_id
        else:
            device_id = pci_type + "-" + utils_misc.generate_random_id()
            pci_info.append([device_id, device_id])

        image_format = params.get("image_format_%s" % img_list[pci_num + 1])
        if not image_format:
            image_format = params.get("image_format", "qcow2")
        image_filename = find_image(pci_num)

        pci_model = params.get("pci_model")
        controller_model = None
        if pci_model == "virtio":
            pci_model = "virtio-blk-pci"

        if pci_model == "scsi":
            pci_model = "scsi-disk"
            if arch.ARCH in ('ppc64', 'ppc64le'):
                controller_model = "spapr-vscsi"
            else:
                controller_model = "lsi53c895a"
            verify_supported_device(controller_model)
            controller_id = "controller-" + device_id
            controller_add_cmd = ("device_add %s,id=%s" %
                                  (controller_model, controller_id))
            error.context("Adding SCSI controller.")
            vm.monitor.send_args_cmd(controller_add_cmd)

        verify_supported_device(pci_model)
        if drive_cmd_type == "drive_add":
            driver_add_cmd = ("%s auto file=%s,if=none,format=%s,id=%s" %
                              (drive_cmd_type, image_filename, image_format,
                               pci_info[pci_num][0]))
        elif drive_cmd_type == "__com.redhat_drive_add":
            driver_add_cmd = ("%s file=%s,format=%s,id=%s" %
                              (drive_cmd_type, image_filename, image_format,
                               pci_info[pci_num][0]))
        # add driver.
        error.context("Adding driver.")
        vm.monitor.send_args_cmd(driver_add_cmd, convert=False)

        pci_add_cmd = ("device_add id=%s,driver=%s,drive=%s" %
                       (pci_info[pci_num][1], pci_model, pci_info[pci_num][0]))
        return device_add(pci_num, pci_add_cmd, pci_id=pci_id)

    def device_add(pci_num, pci_add_cmd, pci_id=None):
        error.context("Adding pci device with command 'device_add'")
        guest_devices = session.cmd_output(chk_cmd)
        if vm.monitor.protocol == 'qmp':
            add_output = vm.monitor.send_args_cmd(pci_add_cmd)
        else:
            add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        guest_device = find_new_device(chk_cmd, guest_devices)
        if pci_id is None:
            pci_info[pci_num].append(add_output)
            pci_info[pci_num].append(pci_model)
            pci_info[pci_num].append(guest_device)

        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][1] not in str(after_add):
            logging.error("Could not find matched id in monitor:"
                          " %s" % pci_info[pci_num][1])
            raise error.TestFail("Add device failed. Monitor command is: %s"
                                 ". Output: %r" % (pci_add_cmd, add_output))
        return after_add

    # Hot add a pci device
    def add_device(pci_num, queues=1, pci_id=None):
        info_pci_ref = vm.monitor.info("pci")
        reference = session.cmd_output(reference_cmd)

        try:
            # get function for adding device.
            add_fuction = local_functions["%s_%s" % (cmd_type, pci_type)]
        except Exception:
            raise error.TestError("No function for adding " +
                                  "'%s' dev " % pci_type +
                                  "with '%s'" % cmd_type)
        after_add = None
        if add_fuction:
            # Do add pci device.
            after_add = add_fuction(pci_num, queues, pci_id)

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

            # Define a helper function to catch PCI device string
            def _find_pci():
                output = session.cmd_output(params.get("find_pci_cmd"))
                output = map(string.strip, output.splitlines())
                ref = map(string.strip, reference.splitlines())
                output = [_ for _ in output if _ not in ref]
                output = "\n".join(output)
                if re.search(params.get("match_string"), output, re.I):
                    return True
                return False

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

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

            if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3):
                raise error.TestFail("PCI %s %s " % (pci_model, pci_type) +
                                     "device not found in guest. Command " +
                                     "was: %s" % params.get("find_pci_cmd"))

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

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

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

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

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

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

    test_timeout = int(params.get("hotplug_timeout", 360))
    reference_cmd = params["reference_cmd"]
    # Test if it is nic or block
    pci_type = params["pci_type"]
    pci_model = params["pci_model"]

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

    # check monitor type
    qemu_binary = utils_misc.get_qemu_binary(params)
    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == 'qmp':
        cmd_output = vm.monitor.info("commands")
    else:
        cmd_output = vm.monitor.human_monitor_cmd("help", debug=False)

    cmd_type = utils_misc.find_substring(str(cmd_output), "device_add",
                                         "pci_add")
    if not cmd_type:
        raise error.TestError("Could find a suitable method for hotplugging"
                              " device in this version of qemu")

    # Determine syntax of drive hotplug
    # __com.redhat_drive_add == qemu-kvm-0.12 on RHEL 6
    # drive_add == qemu-kvm-0.13 onwards
    drive_cmd_type = utils_misc.find_substring(str(cmd_output),
                                               "__com.redhat_drive_add",
                                               "drive_add")
    if not drive_cmd_type:
        raise error.TestError("Unknown version of qemu")

    local_functions = locals()

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

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

    for j in range(rp_times):
        # pci_info is a list of list.
        # each element 'i' has 4 members:
        # pci_info[i][0] == device drive id, only used for device_add
        # pci_info[i][1] == device id, only used for device_add
        # pci_info[i][2] == output of device add command
        # pci_info[i][3] == device module name.
        # pci_info[i][4] == partition id in guest
        pci_num = random.randint(0, len(pci_info) - 1)
        error.context("start unplug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        pci_del(pci_num)
        device_del = find_del_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device is not deleted in guest.")
        error.context("Start plug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        add_device(pci_num, pci_id=pci_info[pci_num][0])
        device_del = find_new_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device partition changed from %s to %s" %
                                 (pci_info[pci_num][4], device_del))
        cmd = confirm_cmd % (pci_info[pci_num][4], offset)
        confirm_info = session.cmd_output(cmd)
        if device_del not in confirm_info:
            raise error.TestFail("Can not find partition tag in Guest: %s" %
                                 confirm_info)
Ejemplo n.º 7
0
def run(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params. (Optional)
    4) Create partition on those disks.
    5) Get disk dev filenames in guest.
    6) Format those disks in guest.
    7) Copy file into / out of those disks.
    8) Compare the original file and the copied file using md5 or fc comand.
    9) Repeat steps 3-5 if needed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    def _do_post_cmd(session):
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    error.context("Parsing test configuration", logging.info)
    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    stg_params += _add_param("drive_cache", params.get("stg_drive_cache"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                       stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in xrange(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm is False:
                raise error.TestError("Incorrect cfg: stg_params %s looks "
                                      "like range(..) but doesn't contain "
                                      "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', 'images/%s')
    for i in xrange(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.iteritems():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     utils.matrix_to_string(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    error.context("Start the guest with new disks", logging.info)
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        env_process.process_images(env_process.preprocess_image, test,
                                   vm_params)

    error.context("Start the guest with those disks", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    n_repeat = int(params.get("n_repeat", "1"))
    file_system = [_.strip() for _ in params.get("file_system").split()]
    cmd_timeout = float(params.get("cmd_timeout", 360))
    re_str = params["re_str"]
    black_list = params["black_list"].split()

    have_qtree = True
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        have_qtree = False

    if (params.get("check_guest_proc_scsi") == "yes") and have_qtree:
        error.context("Verifying qtree vs. test params")
        err = 0
        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
        disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block())
        err += tmp1 + tmp2
        err += disks.generate_params()
        err += disks.check_disk_params(params)
        (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
            session.cmd_output('cat /proc/scsi/scsi'))
        err += tmp1 + tmp2

        if err:
            raise error.TestFail("%s errors occurred while verifying"
                                 " qtree vs. params" % err)
        if params.get('multi_disk_only_qtree') == 'yes':
            return

    try:
        cmd = params.get("clean_cmd")
        if cmd:
            session.cmd_status_output(cmd)

        cmd = params.get("pre_cmd")
        if cmd:
            error.context("Create partition on those disks", logging.info)
            s, output = session.cmd_status_output(cmd, timeout=cmd_timeout)
            if s != 0:
                raise error.TestFail("Create partition on disks failed.\n"
                                     "Output is: %s\n" % output)

        error.context("Get disks dev filenames in guest", logging.info)
        cmd = params["list_volume_command"]
        s, output = session.cmd_status_output(cmd, timeout=cmd_timeout)
        if s != 0:
            raise error.TestFail("List volume command failed with cmd '%s'.\n"
                                 "Output is: %s\n" % (cmd, output))

        output = session.cmd_output(cmd, timeout=cmd_timeout)
        disks = re.findall(re_str, output)
        disks = map(string.strip, disks)
        disks.sort()
        logging.debug("Volume list that meet regular expressions: %s",
                      " ".join(disks))

        images = params.get("images").split()
        if len(disks) < len(images):
            logging.debug("disks: %s , images: %s", len(disks), len(images))
            raise error.TestFail("Fail to list all the volumes!")

        if params.get("os_type") == "linux":
            output = session.cmd_output("mount")
            li = re.findall(r"^/dev/(%s)\d*" % re_str, output, re.M)
            if li:
                black_list.extend(li)
        else:
            black_list.extend(utils_misc.get_winutils_vol(session))
        disks = set(disks)
        black_list = set(black_list)
        logging.info("No need to check volume '%s'", (disks & black_list))
        disks = disks - black_list
    except Exception:
        _do_post_cmd(session)
        raise

    try:
        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            error.context("Format those disks in guest", logging.info)
            for disk in disks:
                disk = disk.strip()
                error.context("Preparing disk: %s..." % disk)

                # Random select one file system from file_system
                index = random.randint(0, (len(file_system) - 1))
                fs = file_system[index].strip()
                cmd = params["format_command"] % (fs, disk)
                error.context("formatting test disk")
                session.cmd(cmd, timeout=cmd_timeout)
                cmd = params.get("mount_command")
                if cmd:
                    cmd = cmd % (disk, disk, disk)
                    session.cmd(cmd)

            error.context("Cope file into / out of those disks", logging.info)
            for disk in disks:
                disk = disk.strip()

                error.context("Performing I/O on disk: %s..." % disk)
                cmd_list = params["cmd_list"].split()
                for cmd_l in cmd_list:
                    cmd = params.get(cmd_l)
                    if cmd:
                        session.cmd(cmd % disk, timeout=cmd_timeout)

                cmd = params["compare_command"]
                key_word = params["check_result_key_word"]
                output = session.cmd_output(cmd)
                if key_word not in output:
                    raise error.TestFail("Files on guest os root fs and disk "
                                         "differ")

            if params.get("umount_command"):
                cmd = params.get("show_mount_cmd")
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    disk = disk.strip()
                    error.context("Unmounting disk: %s..." % disk)
                    cmd = params.get("umount_command") % (disk, disk)
                    session.cmd(cmd)
    finally:
        cmd = params.get("show_mount_cmd")
        if cmd:
            try:
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    error.context("Unmounting disk: %s..." % disk)
                    cmd = params["umount_command"] % (disk, disk)
                    session.cmd(cmd)
            except Exception, err:
                logging.warn("Get error when cleanup, '%s'", err)

        _do_post_cmd(session)
        session.close()
Ejemplo n.º 8
0
def run(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params. (Optional)
    4) Create partition on those disks.
    5) Get disk dev filenames in guest.
    6) Format those disks in guest.
    7) Copy file into / out of those disks.
    8) Compare the original file and the copied file using md5 or fc comand.
    9) Repeat steps 3-5 if needed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    def _do_post_cmd(session):
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    def _get_disk_index(session, image_size, disk_indexs):
        list_disk_cmd = "echo list disk > disk && "
        list_disk_cmd += "echo exit >> disk && diskpart /s disk"
        disks = session.cmd_output(list_disk_cmd)
        size_type = image_size[-1] + "B"
        disk_size = ""

        if size_type == "MB":
            disk_size = image_size[:-1] + " MB"
        elif size_type == "GB" and int(image_size[:-1]) < 8:
            disk_size = str(int(image_size[:-1]) * 1024) + " MB"
        else:
            disk_size = image_size[:-1] + " GB"

        regex_str = 'Disk (\d+).*?%s.*?%s' % (disk_size, disk_size)
        for disk in disks.splitlines():
            if disk.startswith("  Disk"):
                o = re.findall(regex_str, disk, re.I | re.M)
                if o:
                    disk_indexs.append(o[0])

    error.context("Parsing test configuration", logging.info)
    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    stg_params += _add_param("drive_cache", params.get("stg_drive_cache"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                       stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in xrange(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm is False:
                raise error.TestError("Incorrect cfg: stg_params %s looks "
                                      "like range(..) but doesn't contain "
                                      "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', 'images/%s')
    for i in xrange(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.iteritems():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     utils.matrix_to_string(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    error.context("Start the guest with new disks", logging.info)
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        env_process.process_images(env_process.preprocess_image, test,
                                   vm_params)

    error.context("Start the guest with those disks", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))

    n_repeat = int(params.get("n_repeat", "1"))
    file_system = [_.strip() for _ in params.get("file_system").split()]
    cmd_timeout = float(params.get("cmd_timeout", 360))
    re_str = params["re_str"]
    black_list = params["black_list"].split()
    os_type = params["os_type"]
    stg_image_size = params.get("stg_image_size")
    disk_indexs = []

    have_qtree = True
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        have_qtree = False

    if (params.get("check_guest_proc_scsi") == "yes") and have_qtree:
        error.context("Verifying qtree vs. test params")
        err = 0
        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
        disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block())
        err += tmp1 + tmp2
        err += disks.generate_params()
        err += disks.check_disk_params(params)
        (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
            session.cmd_output('cat /proc/scsi/scsi'))
        err += tmp1 + tmp2

        if err:
            raise error.TestFail("%s errors occurred while verifying"
                                 " qtree vs. params" % err)
        if params.get('multi_disk_only_qtree') == 'yes':
            return

    try:
        cmd = params.get("clean_cmd")
        if cmd:
            session.cmd_status_output(cmd)

        if params.get("os_type") == "windows":
            error.context("Create partition on those disks", logging.info)
            # Get the disk index
            _get_disk_index(session, stg_image_size, disk_indexs)

            # Random select one file system from file_system
            index = random.randint(0, (len(file_system) - 1))
            fs_type = file_system[index].strip()
            for i in xrange(stg_image_num):
                utils_misc.format_windows_disk(session, disk_indexs[i], None,
                                               None, fs_type)

        error.context("Get disks dev filenames in guest", logging.info)
        cmd = params["list_volume_command"]
        s, output = session.cmd_status_output(cmd, timeout=cmd_timeout)
        if s != 0:
            raise error.TestFail("List volume command failed with cmd '%s'.\n"
                                 "Output is: %s\n" % (cmd, output))

        output = session.cmd_output(cmd, timeout=cmd_timeout)
        disks = re.findall(re_str, output)
        disks = map(string.strip, disks)
        disks.sort()
        logging.debug("Volume list that meet regular expressions: %s",
                      " ".join(disks))

        images = params.get("images").split()
        if len(disks) < len(images):
            logging.debug("disks: %s , images: %s", len(disks), len(images))
            raise error.TestFail("Fail to list all the volumes!")

        if params.get("os_type") == "linux":
            output = session.cmd_output("mount")
            li = re.findall(r"^/dev/(%s)\d*" % re_str, output, re.M)
            if li:
                black_list.extend(li)
        else:
            black_list.extend(utils_misc.get_winutils_vol(session))
        disks = set(disks)
        black_list = set(black_list)
        logging.info("No need to check volume '%s'", (disks & black_list))
        disks = disks - black_list
    except Exception:
        _do_post_cmd(session)
        raise

    try:
        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            error.context("Format those disks in guest", logging.info)
            for disk in disks:
                disk = disk.strip()
                error.context("Preparing disk: %s..." % disk)

                # Random select one file system from file_system
                index = random.randint(0, (len(file_system) - 1))
                fs = file_system[index].strip()
                cmd = params["format_command"] % (fs, disk)
                error.context("formatting test disk")
                session.cmd(cmd, timeout=cmd_timeout)
                cmd = params.get("mount_command")
                if cmd:
                    cmd = cmd % (disk, disk, disk)
                    session.cmd(cmd)

            error.context("Cope file into / out of those disks", logging.info)
            for disk in disks:
                disk = disk.strip()

                error.context("Performing I/O on disk: %s..." % disk)
                cmd_list = params["cmd_list"].split()
                for cmd_l in cmd_list:
                    cmd = params.get(cmd_l)
                    if cmd:
                        session.cmd(cmd % disk, timeout=cmd_timeout)

                cmd = params["compare_command"]
                key_word = params["check_result_key_word"]
                output = session.cmd_output(cmd)
                if key_word not in output:
                    raise error.TestFail("Files on guest os root fs and disk "
                                         "differ")

            if params.get("umount_command"):
                cmd = params.get("show_mount_cmd")
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    disk = disk.strip()
                    error.context("Unmounting disk: %s..." % disk)
                    cmd = params.get("umount_command") % (disk, disk)
                    session.cmd(cmd)
    finally:
        cmd = params.get("show_mount_cmd")
        if cmd:
            try:
                output = session.cmd_output(cmd)
                disks = re.findall(re_str, output)
                disks.sort()
                for disk in disks:
                    error.context("Unmounting disk: %s..." % disk)
                    cmd = params["umount_command"] % (disk, disk)
                    session.cmd(cmd)
            except Exception, err:
                logging.warn("Get error when cleanup, '%s'", err)

        _do_post_cmd(session)
        session.close()
Ejemplo n.º 9
0
def run(test, params, env):
    """
    Test multi disk suport of guest, this case will:
    1) Create disks image in configuration file.
    2) Start the guest with those disks.
    3) Checks qtree vs. test params. (Optional)
    4) Create partition on those disks.
    5) Get disk dev filenames in guest.
    6) Format those disks in guest.
    7) Copy file into / out of those disks.
    8) Compare the original file and the copied file using md5 or fc comand.
    9) Repeat steps 3-5 if needed.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def _add_param(name, value):
        """ Converts name+value to stg_params string """
        if value:
            value = re.sub(' ', '\\ ', value)
            return " %s:%s " % (name, value)
        else:
            return ''

    def _do_post_cmd(session):
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    error_context.context("Parsing test configuration", logging.info)
    stg_image_num = 0
    stg_params = params.get("stg_params", "")
    # Compatibility
    stg_params += _add_param("image_size", params.get("stg_image_size"))
    stg_params += _add_param("image_format", params.get("stg_image_format"))
    stg_params += _add_param("image_boot", params.get("stg_image_boot", "no"))
    stg_params += _add_param("drive_format", params.get("stg_drive_format"))
    stg_params += _add_param("drive_cache", params.get("stg_drive_cache"))
    if params.get("stg_assign_index") != "no":
        # Assume 0 and 1 are already occupied (hd0 and cdrom)
        stg_params += _add_param("drive_index", 'range(2,n)')
    param_matrix = {}

    stg_params = stg_params.split(' ')
    i = 0
    while i < len(stg_params) - 1:
        if not stg_params[i].strip():
            i += 1
            continue
        if stg_params[i][-1] == '\\':
            stg_params[i] = '%s %s' % (stg_params[i][:-1],
                                       stg_params.pop(i + 1))
        i += 1

    rerange = []
    has_name = False
    for i in range(len(stg_params)):
        if not stg_params[i].strip():
            continue
        (cmd, parm) = stg_params[i].split(':', 1)
        if cmd == "image_name":
            has_name = True
        if _RE_RANGE1.match(parm):
            parm = _range(parm)
            if parm is False:
                test.error("Incorrect cfg: stg_params %s looks "
                           "like range(..) but doesn't contain "
                           "numbers." % cmd)
            param_matrix[cmd] = parm
            if type(parm) is str:
                # When we know the stg_image_num, substitute it.
                rerange.append(cmd)
                continue
        else:
            # ',' separated list of values
            parm = parm.split(',')
            j = 0
            while j < len(parm) - 1:
                if parm[j][-1] == '\\':
                    parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1))
                j += 1
            param_matrix[cmd] = parm
        stg_image_num = max(stg_image_num, len(parm))

    stg_image_num = int(params.get('stg_image_num', stg_image_num))
    for cmd in rerange:
        param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num)
    # param_table* are for pretty print of param_matrix
    param_table = []
    param_table_header = ['name']
    if not has_name:
        param_table_header.append('image_name')
    for _ in param_matrix:
        param_table_header.append(_)

    stg_image_name = params.get('stg_image_name', 'images/%s')
    for i in range(stg_image_num):
        name = "stg%d" % i
        params['images'] += " %s" % name
        param_table.append([])
        param_table[-1].append(name)
        if not has_name:
            params["image_name_%s" % name] = stg_image_name % name
            param_table[-1].append(params.get("image_name_%s" % name))
        for parm in param_matrix.items():
            params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])])
            param_table[-1].append(params.get('%s_%s' % (parm[0], name)))

    if params.get("multi_disk_params_only") == 'yes':
        # Only print the test param_matrix and finish
        logging.info('Newly added disks:\n%s',
                     astring.tabular_output(param_table, param_table_header))
        return

    # Always recreate VMs and disks
    error_context.context("Start the guest with new disks", logging.info)
    for vm_name in params.objects("vms"):
        vm_params = params.object_params(vm_name)
        env_process.process_images(env_process.preprocess_image, test,
                                   vm_params)

    error_context.context("Start the guest with those disks", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.create(timeout=max(10, stg_image_num), params=params)
    login_timeout = int(params.get("login_timeout", 360))
    session = vm.wait_for_login(timeout=login_timeout)

    n_repeat = int(params.get("n_repeat", "1"))
    file_system = [_.strip() for _ in params["file_system"].split()]
    cmd_timeout = float(params.get("cmd_timeout", 360))
    black_list = params["black_list"].split()
    drive_letters = int(params.get("drive_letters", "26"))
    stg_image_size = params["stg_image_size"]
    dd_test = params.get("dd_test", "no")
    labeltype = params.get("labeltype", "gpt")

    have_qtree = True
    out = vm.monitor.human_monitor_cmd("info qtree", debug=False)
    if "unknown command" in str(out):
        have_qtree = False

    if (params.get("check_guest_proc_scsi") == "yes") and have_qtree:
        error_context.context("Verifying qtree vs. test params")
        err = 0
        qtree = qemu_qtree.QtreeContainer()
        qtree.parse_info_qtree(vm.monitor.info('qtree'))
        disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes())
        (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block())
        err += tmp1 + tmp2
        err += disks.generate_params()
        err += disks.check_disk_params(params)
        (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi(
            session.cmd_output('cat /proc/scsi/scsi'))
        err += tmp1 + tmp2

        if err:
            test.fail("%s errors occurred while verifying qtree vs."
                      " params" % err)
        if params.get('multi_disk_only_qtree') == 'yes':
            return
    try:
        err_msg = "Set disks num: %d" % stg_image_num
        err_msg += ", Get disks num in guest: %d"
        ostype = params["os_type"]
        if ostype == "windows":
            error_context.context("Get windows disk index that to "
                                  "be formatted", logging.info)
            disks = utils_disk.get_windows_disks_index(session, stg_image_size)
            if len(disks) < stg_image_num:
                test.fail("Fail to list all the volumes"
                          ", %s" % err_msg % len(disks))
            if len(disks) > drive_letters:
                black_list.extend(utils_misc.get_winutils_vol(session))
                disks = random.sample(disks, drive_letters - len(black_list))
            error_context.context("Clear readonly for all disks and online "
                                  "them in windows guest.", logging.info)
            if not utils_disk.update_windows_disk_attributes(session, disks):
                test.fail("Failed to update windows disk attributes.")
            dd_test = "no"
        else:
            error_context.context("Get linux disk that to be "
                                  "formatted", logging.info)
            disks = sorted(utils_disk.get_linux_disks(session).keys())
            if len(disks) < stg_image_num:
                test.fail("Fail to list all the volumes"
                          ", %s" % err_msg % len(disks))
    except Exception:
        _do_post_cmd(session)
        raise
    try:
        for i in range(n_repeat):
            logging.info("iterations: %s", (i + 1))
            for disk in disks:
                error_context.context("Format disk in guest: '%s'" % disk,
                                      logging.info)
                # Random select one file system from file_system
                index = random.randint(0, (len(file_system) - 1))
                fstype = file_system[index].strip()
                partitions = utils_disk.configure_empty_disk(
                    session, disk, stg_image_size, ostype,
                    fstype=fstype, labeltype=labeltype)
                if not partitions:
                    test.fail("Fail to format disks.")
                cmd_list = params["cmd_list"]
                for partition in partitions:
                    if "/" not in partition:
                        partition += ":"
                    else:
                        partition = partition.split("/")[-1]
                    error_context.context("Copy file into / out of partition:"
                                          " %s..." % partition, logging.info)
                    for cmd_l in cmd_list.split():
                        cmd = params.get(cmd_l)
                        if cmd:
                            session.cmd(cmd % partition, timeout=cmd_timeout)
                    cmd = params["compare_command"]
                    key_word = params["check_result_key_word"]
                    output = session.cmd_output(cmd)
                    if key_word not in output:
                        test.fail("Files on guest os root fs and disk differ")
                    if dd_test != "no":
                        error_context.context("dd test on partition: %s..."
                                              % partition, logging.info)
                        status, output = session.cmd_status_output(
                            dd_test % (partition, partition), timeout=cmd_timeout)
                        if status != 0:
                            test.fail("dd test fail: %s" % output)
            need_reboot = params.get("need_reboot", "no")
            need_shutdown = params.get("need_shutdown", "no")
            if need_reboot == "yes":
                error_context.context("Rebooting guest ...", logging.info)
                session = vm.reboot(session=session, timeout=login_timeout)
            if need_shutdown == "yes":
                error_context.context("Shutting down guest ...", logging.info)
                vm.graceful_shutdown(timeout=login_timeout)
                if vm.is_alive():
                    test.fail("Fail to shut down guest.")
                error_context.context("Start the guest again.", logging.info)
                vm = env.get_vm(params["main_vm"])
                vm.create(params=params)
                session = vm.wait_for_login(timeout=login_timeout)
            error_context.context("Delete partitions in guest.", logging.info)
            for disk in disks:
                utils_disk.clean_partition(session, disk, ostype)
    finally:
        _do_post_cmd(session)
Ejemplo n.º 10
0
def run(test, params, env):
    """
    Test hotplug of PCI devices and check the status in guest.
    1 Boot up a guest
    2 Hotplug virtio disk to the guest. Record the id and partition name of
      the disk in a list.
    3 Random choice a disk in the list. Unplug the disk and check the
      partition status.
    4 Hotpulg the disk back to guest with the same monitor cmdline and same
      id which is record in step 2.
    5 Check the partition status in guest. And confirm the disk with dd cmd
    6 Repeat step 3 to 5 for N times

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

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

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

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

    # Select an image file
    def find_image(pci_num):
        image_params = params.object_params("%s" % img_list[pci_num + 1])
        o = storage.get_image_filename(image_params, data_dir.get_data_dir())
        return o

    def pci_add_block(pci_num, queues, pci_id):
        image_filename = find_image(pci_num)
        pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" %
                       (image_filename, pci_model))
        return pci_add(pci_add_cmd)

    def pci_add(pci_add_cmd):
        guest_devices = session.cmd_output(chk_cmd)
        error.context("Adding pci device with command 'pci_add'")
        add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        guest_device = find_new_device(chk_cmd, guest_devices)
        pci_info.append(['', '', add_output, pci_model, guest_device])
        if "OK domain" not in add_output:
            raise error.TestFail("Add PCI device failed. "
                                 "Monitor command is: %s, Output: %r" %
                                 (pci_add_cmd, add_output))
        return vm.monitor.info("pci")

    def is_supported_device(dev):
        # Probe qemu to verify what is the supported syntax for PCI hotplug
        cmd_output = vm.monitor.human_monitor_cmd("?")
        if len(re.findall("\ndevice_add", cmd_output)) > 0:
            cmd_type = "device_add"
        elif len(re.findall("\npci_add", cmd_output)) > 0:
            cmd_type = "pci_add"
        else:
            raise error.TestError("Unknown version of qemu")

        # Probe qemu for a list of supported devices
        probe_output = vm.monitor.human_monitor_cmd("%s ?" % cmd_type)
        devices_supported = [j.strip('"') for j in
                             re.findall('\"[a-z|0-9|\-|\_|\,|\.]*\"',
                                        probe_output, re.MULTILINE)]
        logging.debug("QEMU reported the following supported devices for "
                      "PCI hotplug: %s", devices_supported)
        return (dev in devices_supported)

    def verify_supported_device(dev):
        if not is_supported_device(dev):
            raise error.TestError("%s doesn't support device: %s" %
                                  (cmd_type, dev))

    def device_add_block(pci_num, queues=1, pci_id=None):
        if pci_id is not None:
            device_id = pci_type + "-" + pci_id
        else:
            device_id = pci_type + "-" + utils_misc.generate_random_id()
            pci_info.append([device_id, device_id])

        image_format = params.get("image_format_%s" % img_list[pci_num + 1])
        if not image_format:
            image_format = params.get("image_format", "qcow2")
        image_filename = find_image(pci_num)

        pci_model = params.get("pci_model")
        controller_model = None
        if pci_model == "virtio":
            pci_model = "virtio-blk-pci"

        if pci_model == "scsi":
            pci_model = "scsi-disk"
            if arch.ARCH in ('ppc64', 'ppc64le'):
                controller_model = "spapr-vscsi"
            else:
                controller_model = "lsi53c895a"
            verify_supported_device(controller_model)
            controller_id = "controller-" + device_id
            controller_add_cmd = ("device_add %s,id=%s" %
                                  (controller_model, controller_id))
            error.context("Adding SCSI controller.")
            vm.monitor.send_args_cmd(controller_add_cmd)

        verify_supported_device(pci_model)
        if drive_cmd_type == "drive_add":
            driver_add_cmd = ("%s auto file=%s,if=none,format=%s,id=%s" %
                              (drive_cmd_type, image_filename, image_format,
                               pci_info[pci_num][0]))
        elif drive_cmd_type == "__com.redhat_drive_add":
            driver_add_cmd = ("%s file=%s,format=%s,id=%s" %
                              (drive_cmd_type, image_filename, image_format,
                               pci_info[pci_num][0]))
        # add driver.
        error.context("Adding driver.")
        vm.monitor.send_args_cmd(driver_add_cmd, convert=False)

        pci_add_cmd = ("device_add id=%s,driver=%s,drive=%s" %
                       (pci_info[pci_num][1],
                        pci_model,
                        pci_info[pci_num][0])
                       )
        return device_add(pci_num, pci_add_cmd, pci_id=pci_id)

    def device_add(pci_num, pci_add_cmd, pci_id=None):
        error.context("Adding pci device with command 'device_add'")
        guest_devices = session.cmd_output(chk_cmd)
        if vm.monitor.protocol == 'qmp':
            add_output = vm.monitor.send_args_cmd(pci_add_cmd)
        else:
            add_output = vm.monitor.send_args_cmd(pci_add_cmd, convert=False)
        guest_device = find_new_device(chk_cmd, guest_devices)
        if pci_id is None:
            pci_info[pci_num].append(add_output)
            pci_info[pci_num].append(pci_model)
            pci_info[pci_num].append(guest_device)

        after_add = vm.monitor.info("pci")
        if pci_info[pci_num][1] not in str(after_add):
            logging.error("Could not find matched id in monitor:"
                          " %s" % pci_info[pci_num][1])
            raise error.TestFail("Add device failed. Monitor command is: %s"
                                 ". Output: %r" % (pci_add_cmd, add_output))
        return after_add

    # Hot add a pci device
    def add_device(pci_num, queues=1, pci_id=None):
        info_pci_ref = vm.monitor.info("pci")
        reference = session.cmd_output(reference_cmd)

        try:
            # get function for adding device.
            add_fuction = local_functions["%s_%s" % (cmd_type, pci_type)]
        except Exception:
            raise error.TestError("No function for adding " +
                                  "'%s' dev " % pci_type +
                                  "with '%s'" % cmd_type)
        after_add = None
        if add_fuction:
            # Do add pci device.
            after_add = add_fuction(pci_num, queues, pci_id)

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

            # Define a helper function to catch PCI device string
            def _find_pci():
                output = session.cmd_output(params.get("find_pci_cmd"))
                output = map(string.strip, output.splitlines())
                ref = map(string.strip, reference.splitlines())
                output = [_ for _ in output if _ not in ref]
                output = "\n".join(output)
                if re.search(params.get("match_string"), output, re.I):
                    return True
                return False

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

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

            if not utils_misc.wait_for(_find_pci, test_timeout, 3, 3):
                raise error.TestFail("PCI %s %s " % (pci_model, pci_type) +
                                     "device not found in guest. Command " +
                                     "was: %s" % params.get("find_pci_cmd"))

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

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

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

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

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

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

    test_timeout = int(params.get("hotplug_timeout", 360))
    reference_cmd = params["reference_cmd"]
    # Test if it is nic or block
    pci_type = params["pci_type"]
    pci_model = params["pci_model"]

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

    # check monitor type
    qemu_binary = utils_misc.get_qemu_binary(params)
    # Probe qemu to verify what is the supported syntax for PCI hotplug
    if vm.monitor.protocol == 'qmp':
        cmd_output = vm.monitor.info("commands")
    else:
        cmd_output = vm.monitor.human_monitor_cmd("help", debug=False)

    cmd_type = utils_misc.find_substring(str(cmd_output), "device_add",
                                         "pci_add")
    if not cmd_type:
        raise error.TestError("Could find a suitable method for hotplugging"
                              " device in this version of qemu")

    # Determine syntax of drive hotplug
    # __com.redhat_drive_add == qemu-kvm-0.12 on RHEL 6
    # drive_add == qemu-kvm-0.13 onwards
    drive_cmd_type = utils_misc.find_substring(str(cmd_output),
                                               "__com.redhat_drive_add",
                                               "drive_add")
    if not drive_cmd_type:
        raise error.TestError("Unknown version of qemu")

    local_functions = locals()

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

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

    for j in range(rp_times):
        # pci_info is a list of list.
        # each element 'i' has 4 members:
        # pci_info[i][0] == device drive id, only used for device_add
        # pci_info[i][1] == device id, only used for device_add
        # pci_info[i][2] == output of device add command
        # pci_info[i][3] == device module name.
        # pci_info[i][4] == partition id in guest
        pci_num = random.randint(0, len(pci_info) - 1)
        error.context("start unplug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        pci_del(pci_num)
        device_del = find_del_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device is not deleted in guest.")
        error.context("Start plug pci device, repeat %d" % j, logging.info)
        guest_devices = session.cmd_output(chk_cmd)
        add_device(pci_num, pci_id=pci_info[pci_num][0])
        device_del = find_new_device(chk_cmd, guest_devices)
        if device_del != pci_info[pci_num][4]:
            raise error.TestFail("Device partition changed from %s to %s" %
                                 (pci_info[pci_num][4], device_del))
        cmd = confirm_cmd % (pci_info[pci_num][4], offset)
        confirm_info = session.cmd_output(cmd)
        if device_del not in confirm_info:
            raise error.TestFail("Can not find partition tag in Guest: %s" %
                                 confirm_info)
Ejemplo n.º 11
0
def run(test, params, env):
    """
    Test multi disk with multifunction on and off.

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

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

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

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

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

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

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

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

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

    # Replug disk 8 on slot 0 with multifunction='off'
    set_addr(images[-1], dev_slot, 0, vm.params, multifunction='off')
    plug._create_devices(unplug_dev.split(), {'aobject': parent_bus})
    for img, devs in plug._hotplugged_devs.items():
        for dev in devs:
            if (img == images[-1] and isinstance(dev, QDevice)
                    and qdev.is_pci_device(dev['driver'])):
                dev['addr'] = hex(dev_slot)  # for pci bus addr might be reset
                try:
                    parent_bus_obj.prepare_hotplug(dev)
                    dev.hotplug(vm.monitor, vm.devices.qemu_version)
                except QMPCmdError as e:
                    if 'single function' not in str(e):
                        raise
                else:
                    test.fail(
                        'It should fail to hotplug a single function device'
                        ' to the address where multifunction already on.')
                break
            else:
                plug._hotplug_atomic(dev, vm.monitor)
Ejemplo n.º 12
0
def run(test, params, env):
    """
    KVM Seabios test:
    [seabios] Check boot menu prompts with more than 10 available boot devices
    1) Start guest with sga bios
    2) Check the boot menu list
    3) Login into the guest

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def prepare_images(img_num):
        """
        prepare extra images
        """
        for i in range(img_num):
            img = "stg%s" % i
            params["images"] = ' '.join([params["images"], img])
            params["image_name_%s" % img] = "images/%s" % img
            params["image_size_%s" % img] = params["extra_img_size"]
            params["force_create_image_%s" % img] = "yes"
            params["remove_image_%s" % img] = "yes"

    def get_output(session_obj):
        """
        Use the function to short the lines in the scripts
        """
        return session_obj.get_stripped_output()

    def boot_menu():
        return re.search(boot_menu_hint, get_output(seabios_session))

    def get_boot_menu_list():
        return re.findall(r"^([1-9a-z])\. (.*)\s", get_output(seabios_session),
                          re.M)

    timeout = float(params.get("timeout", 60))
    boot_menu_hint = params["boot_menu_hint"]
    boot_menu_key = params.get("boot_menu_key", 'esc')
    boot_device = str(int(params["bootindex_image1"]) + 1)
    extra_img_num = int(params["extra_img_num"])

    error_context.context("Preprocess params", logging.info)
    prepare_images(extra_img_num)
    params["start_vm"] = "yes"
    env_process.process_images(env_process.preprocess_image, test, params)
    env_process.preprocess_vm(test, params, env, params["main_vm"])

    error_context.context("Start guest with sga bios", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    seabios_session = vm.logsessions['seabios']

    error_context.context("Get boot menu list", logging.info)
    if not utils_misc.wait_for(boot_menu, timeout, 1):
        test.fail("Could not get boot menu message")
    vm.send_key(boot_menu_key)

    boot_list = utils_misc.wait_for(get_boot_menu_list, timeout, 1)
    if not boot_list:
        test.fail("Could not get boot menu list")
    logging.info("Got boot menu entries: '%s'", boot_list)

    error_context.context("Login into the guest", logging.info)
    vm.send_key(boot_device)

    session = vm.wait_for_login()

    error_context.context("Check kernel crash message", logging.info)
    vm.verify_kernel_crash()

    session.close()