示例#1
0
 def configure_data_disks():
     """ Configure the data disks. """
     if windows:
         utils_disk.update_windows_disk_attributes(
             session, (disk for disk, _ in get_data_disks()))
     return [utils_disk.configure_empty_disk(
         session, disk, size, os_type)[0] for disk, size in get_data_disks()]
示例#2
0
文件: fwcfg.py 项目: huangyum/tp-qemu
def run(test, params, env):
    """
    Fwcfg64 basic function test:

    1) Boot guest with -device vmcoreinfo.
    2) Check the fwcfgg64 driver has been installed.
    3) Run "dump-guest-memory -w memory.dmp" in qemu monitor.
    4) Check the memory.dmp can be saved and the size is larger then 0Kb.
    5) Check the dump file can be open with windb tools.
    """
    win_dump_utils.set_vm_for_dump(test, params)
    vm_name = params['main_vm']
    params['start_vm'] = 'yes'
    env_process.preprocess_vm(test, params, env, vm_name)
    vm = env.get_vm(vm_name)

    session = vm.wait_for_login()
    driver = params["driver_name"]
    wdbg_timeout = params.get("wdbg_timeout", 600)
    error_context.context("Check fwcfg driver is running", logging.info)
    utils_test.qemu.windrv_verify_running(session, test, driver)
    if params.get("setup_verifier", "yes") == "yes":
        error_context.context("Enable fwcfg driver verified", logging.info)
        session = utils_test.qemu.setup_win_driver_verifier(
            session, driver, vm)

    disk = sorted(session.cmd('wmic diskdrive get index').split()[1:])[-1]
    utils_disk.update_windows_disk_attributes(session, disk)
    disk_letter = utils_disk.configure_empty_disk(session, disk,
                                                  params['image_size_stg'],
                                                  params["os_type"])[0]

    error_context.context("Generate the Memory.dmp file", logging.info)
    dump_file, dump_zip_file = win_dump_utils.generate_mem_dump(
        test, params, vm)

    try:
        error_context.context(
            "Copy the Memory.dmp.zip file "
            "from host to guest", logging.info)
        unzip_speed = int(params.get("unzip_speed", 80))
        vm.copy_files_to(dump_zip_file, "%s:\\Memory.dmp.zip" % disk_letter)
        unzip_cmd = params["unzip_cmd"] % (disk_letter, disk_letter)
        unzip_timeout = int(params["mem"]) // unzip_speed
        status, output = session.cmd_status_output(unzip_cmd,
                                                   timeout=unzip_timeout)
        if status:
            test.error("unzip dump file failed as:\n%s" % output)
        session.cmd(params["move_cmd"].format(disk_letter))
        win_dump_utils.install_windbg(test,
                                      params,
                                      session,
                                      timeout=wdbg_timeout)
        win_dump_utils.dump_windbg_check(test, params, session)
    finally:
        process.system("rm %s %s" % (dump_file, dump_zip_file), shell=True)
        session.close()
示例#3
0
def run(test, params, env):
    """
    Test hot plug and unplug NVMe device.

    Steps:
        1. Install guest with local filesystem.
        2. Hot plug NVMe device to guest.
        3. Check if the NVMe device exists in qemu side.
        4. Check if the NVMe has been successfully added to guest.
        5. Run fio in the hot plugged NVMe device in guest.
        6. Unplug the NVMe device.
        7. Check if the NVMe device still exists.
        8. Check if the NVMe has been successfully removed from guest.
        9. Reboot guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    unattended_install.run(test, params, env)

    if params.get('remove_options'):
        for option in params.get('remove_options').split():
            del params[option]
    params['cdroms'] = params.get('default_cdroms')

    params['start_vm'] = 'yes'
    env_process.preprocess_vm(test, params, env, params["main_vm"])
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login()

    plug = BlockDevicesPlug(vm)
    plug.hotplug_devs_serial()
    target = '/dev/%s' % plug[0]
    os_type = params['os_type']
    data_img_size = params.get('image_size_%s' % params.get('data_img_tag'))
    if os_type == 'windows':
        utils_disk.update_windows_disk_attributes(session, plug[0])
        drive_letter = utils_disk.configure_empty_disk(session, plug[0],
                                                       data_img_size,
                                                       os_type)[0]
        target = r'%s\:\\%s' % (drive_letter, params.get('fio_filename'))
    fio = generate_instance(params, vm, 'fio')
    for option in params['fio_options'].split(';'):
        fio.run('--filename=%s %s' % (target, option))
    plug.unplug_devs_serial()
    vm.reboot(session)
 def _initial_win_drives():
     size = params['stg_image_size']
     disks = utils_disk.get_windows_disks_index(session, size)
     if not utils_disk.update_windows_disk_attributes(session, disks):
         test.fail("Failed to update windows disk attributes.")
     for disk in disks[1:24]:
         yield utils_disk.configure_empty_windows_disk(session, disk, size)[0]
示例#5
0
def check_data_disks(test, params, env, vm, session):
    """
    Check guest data disks (except image1)

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    :param vm: VM object
    :param session: VM session
    """
    image_list = params.objects("images")
    del image_list[0]
    image_num = len(image_list)

    error_context.context("Check data disks in monitor!", logging.info)
    monitor_info_block = vm.monitor.info_block(False)
    blocks = ','.join(monitor_info_block.keys())
    for image in image_list:
        if image not in blocks:
            test.fail("drive_%s is missed: %s!" % (image, blocks))

    error_context.context("Read and write on data disks!", logging.info)
    os_type = params["os_type"]
    if os_type == "linux":
        sub_test_type = params.get("sub_test_type", "dd_test")
        for image in image_list:
            params["dd_if"] = "ZERO"
            params["dd_of"] = image
            utils_test.run_virt_sub_test(test, params, env, sub_test_type)

            params["dd_if"] = image
            params["dd_of"] = "NULL"
            utils_test.run_virt_sub_test(test, params, env, sub_test_type)
    elif os_type == "windows":
        iozone_cmd = params["iozone_cmd"]
        iozone_cmd = utils_misc.set_winutils_letter(session, iozone_cmd)
        data_image_size = params["data_image_size"]
        disks = utils_disk.get_windows_disks_index(session, data_image_size)
        disk_num = len(disks)
        if disk_num < image_num:
            err_msg = "set disk num: %d" % image_num
            err_msg += ", get in guest: %d" % disk_num
            test.fail("Fail to list all the volumes, %s" % err_msg)
        if not utils_disk.update_windows_disk_attributes(session, disks):
            test.fail("Failed to update windows disk attributes.")
        for disk in disks:
            drive_letter = utils_disk.configure_empty_disk(
                session, disk, data_image_size, os_type)
            if not drive_letter:
                test.fail("Fail to format disks.")
            iozone_cmd_disk = iozone_cmd % drive_letter[0]
            status, output = session.cmd_status_output(iozone_cmd_disk,
                                                       timeout=3600)
            if status:
                test.fail("Check block device '%s' failed! Output: %s" %
                          (drive_letter[0], output))
            utils_disk.clean_partition(session, disk, os_type)
    else:
        test.cancel("Unsupported OS type '%s'" % os_type)
示例#6
0
 def format_data_disks():
     """ Format the data disks. """
     for disk, size in get_data_disks():
         if windows:
             if not utils_disk.update_windows_disk_attributes(
                     session, disk):
                 test.fail("Failed to update windows disk attributes.")
         yield utils_disk.configure_empty_disk(session, disk, size,
                                               os_type)[0]
 def format_plug_disk(session, did):
     """Format new hotpluged disk."""
     stg_image_size = params["stg_image_size"]
     ostype = params["os_type"]
     if ostype == "windows":
         if not utils_disk.update_windows_disk_attributes(session, did):
             test.fail("Failed to clear readonly for all disks and online "
                       "them in guest")
     partition = utils_disk.configure_empty_disk(session, did,
                                                 stg_image_size, ostype)
     if not partition:
         test.fail("Fail to format disks.")
     return partition[0]
示例#8
0
    def get_windows_drive_letters(session, index_sizes):
        """
        Format windows disk and get drive_letter for empty disks

        :param session: A shell session object.
        :param index_sizes: List for hotplug disk's index_size
        """
        drive_indexs = []
        for item in index_sizes:
            drive_indexs.append(item.split()[0])
        if not utils_disk.update_windows_disk_attributes(session, drive_indexs):
            test.fail("Failed to clear readonly for all disks and online "
                      "them in guest")
        error_context.context("Format disk", logging.info)
        for item in index_sizes:
            did, size = item.split()
            drive_letter = utils_disk.configure_empty_windows_disk(session,
                                                                   did, size + "B")
            windows_drive_letters.extend(drive_letter)
示例#9
0
    def get_windows_drive_letters(session, index_sizes):
        """
        Format windows disk and get drive_letter for empty disks

        :param session: A shell session object.
        :param index_sizes: List for hotplug disk's index_size
        """
        drive_indexs = []
        for item in index_sizes:
            drive_indexs.append(item.split()[0])
        if not utils_disk.update_windows_disk_attributes(session, drive_indexs):
            test.fail("Failed to clear readonly for all disks and online "
                      "them in guest")
        error_context.context("Format disk", logging.info)
        for item in index_sizes:
            did, size = item.split()
            drive_letter = utils_disk.configure_empty_windows_disk(session,
                                                                   did, size + "B")
            windows_drive_letters.extend(drive_letter)
示例#10
0
 def _get_mount_points():
     """ Get data disk mount point(s) """
     mount_points = []
     os_type = params["os_type"]
     if os_type == "linux":
         mounts = session.cmd_output_safe('cat /proc/mounts | grep /dev/')
         for img in image_list:
             size = params["image_size_%s" % img]
             img_param = params["blk_extra_params_%s" % img].split('=')[1]
             drive_path = utils_misc.get_linux_drive_path(
                 session, img_param)
             if not drive_path:
                 test.error("Failed to get drive path of '%s'" % img)
             did = drive_path[5:]
             for mp in re.finditer(r'/dev/%s\d+\s+(\S+)\s+' % did, mounts):
                 mount_points.append(mp.group(1))
             else:
                 mp = utils_disk.configure_empty_linux_disk(
                     session, did, size)
                 mount_points.extend(mp)
     elif os_type == "windows":
         size_record = []
         for img in image_list:
             size = params["image_size_%s" % img]
             if size in size_record:
                 continue
             size_record.append(size)
             disks = utils_disk.get_windows_disks_index(session, size)
             if not disks:
                 test.fail("Fail to list image %s" % img)
             if not utils_disk.update_windows_disk_attributes(
                     session, disks):
                 test.fail("Failed to update windows disk attributes")
             for disk in disks:
                 d_letter = utils_disk.configure_empty_windows_disk(
                     session, disk, size)
             if not d_letter:
                 test.fail("Fail to format disks")
             mount_points.extend(d_letter)
     else:
         test.cancel("Unsupported OS type '%s'" % os_type)
     return mount_points
示例#11
0
def io_test(session, disk_op_cmd, disks, windows=False, image_size=None):
    """
    Perform io test on disks
    :param session: vm session
    :param disk_op_cmd: The disk operation command
    :param plug_disks: The list of disks
    :param windows: If it is windows guest
    :param image_size: The size of images, only for windows
    """
    for index, disk in enumerate(disks):
        if windows:
            if not utils_disk.update_windows_disk_attributes(session, disk):
                raise exceptions.TestError("Failed to clear readonly for all"
                                           " disks and online them in guest")
            partition = utils_disk.configure_empty_windows_disk(
                session, disk, image_size)
            test_cmd = disk_op_cmd % (partition[0], partition[0])
            test_cmd = utils_misc.set_winutils_letter(session, test_cmd)
        else:
            test_cmd = disk_op_cmd % (disk, disk)
        session.cmd(test_cmd, timeout=360)
示例#12
0
 def get_disk_op_cmd(disk_op_cmd, disk_size):
     """
     Find the disk driver letter and format the disk, and get
     disk driver letter,return disk_op_command
     """
     if os_type == "windows":
         disk_op_cmd = utils_misc.set_winutils_letter(session, disk_op_cmd)
         logging.info("Get windows disk index that to be formatted")
         disk_id = utils_disk.get_windows_disks_index(session, disk_size)
         if not utils_disk.update_windows_disk_attributes(session, disk_id):
             test.error("Failed to enable data disk %s" % disk_id)
         d_letter = utils_disk.configure_empty_windows_disk(session,
                                                            disk_id[0],
                                                            disk_size)[0]
         output_path = d_letter + ":\\test.dat"
     else:
         disks = utils_disk.get_linux_disks(session)
         for key, value in disks.items():
             if value[1] == disk_size and value[2] == "disk":
                 output_path = key
     if not output_path:
         test.fail("Can not get output file path in guest.")
     disk_op_cmd %= output_path
     return disk_op_cmd
示例#13
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)
示例#14
0
def run(test, params, env):
    """
    KVM block resize test:

    1) Start guest with data disk or system disk.
    2) Do format disk in guest if needed.
    3) Record md5 of test file on the data disk.
       Enlarge the data disk image from qemu monitor.
    4) Extend data disk partition/file-system in guest.
    5) Verify the data disk size match expected size.
    6) Reboot the guest.
    7) Do iozone test, compare the md5 of test file.
    8) Shrink data disk partition/file-system in guest.
    9) Shrink data disk image from qemu monitor.
    10) Verify the data disk size match expected size.
    11) Reboot the guest.
    12) Do iozone test, compare the md5 of test file.

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    def verify_disk_size(session, os_type, disk):
        """
        Verify the current block size match with the expected size.
        """
        global current_size
        current_size = utils_disk.get_disk_size(session, os_type, disk)
        accept_ratio = float(params.get("accept_ratio", 0))
        if (current_size <= block_size
                and current_size >= block_size * (1 - accept_ratio)):
            logging.info(
                "Block Resizing Finished !!! \n"
                "Current size %s is same as the expected %s", current_size,
                block_size)
            return True

    def create_md5_file(filename):
        """
        Create the file to verify md5 value.
        """
        logging.debug("create md5 file %s" % filename)
        if os_type == 'windows':
            vm.copy_files_to(params["tmp_md5_file"], filename)
        else:
            session.cmd(params["dd_cmd"] % filename)

    def get_md5_of_file(filename):
        """
        Get the md5 value of filename.
        """
        ex_args = (mpoint, filename) if os_type == 'windows' else filename
        return session.cmd(md5_cmd % ex_args).split()[0]

    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = float(params.get("login_timeout", 240))
    driver_name = params.get("driver_name")
    os_type = params["os_type"]
    fstype = params.get("fstype")
    labeltype = params.get("labeltype", "msdos")
    img_size = params.get("image_size_stg", "10G")
    mpoint = params.get("disk_letter", "C")
    disk = params.get("disk_index", 0)
    md5_cmd = params.get("md5_cmd", "md5sum %s")
    md5_file = params.get("md5_file", "md5.dat")
    data_image = params.get("images").split()[-1]
    data_image_params = params.object_params(data_image)
    data_image_filename = storage.get_image_filename(data_image_params,
                                                     data_dir.get_data_dir())
    data_image_dev = vm.get_block({'file': data_image_filename})
    img = QemuImg(data_image_params, data_dir.get_data_dir(), data_image)
    block_virtual_size = json.loads(img.info(force_share=True,
                                             output="json"))["virtual-size"]

    session = vm.wait_for_login(timeout=timeout)

    if os_type == 'windows' and driver_name:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, driver_name, timeout)

    if params.get("format_disk") == "yes":
        if os_type == 'linux':
            disk = sorted(utils_disk.get_linux_disks(session).keys())[0]
        else:
            disk = utils_disk.get_windows_disks_index(session, img_size)[0]
            utils_disk.update_windows_disk_attributes(session, disk)
        error_context.context("Formatting disk", logging.info)
        mpoint = utils_disk.configure_empty_disk(session,
                                                 disk,
                                                 img_size,
                                                 os_type,
                                                 fstype=fstype,
                                                 labeltype=labeltype)[0]
        partition = mpoint.replace('mnt', 'dev') if 'mnt' in mpoint else None

    for ratio in params.objects("disk_change_ratio"):
        block_size = int(int(block_virtual_size) * float(ratio))

        # Record md5
        if params.get('md5_test') == 'yes':
            junction = ":\\" if os_type == 'windows' else "/"
            md5_filename = mpoint + junction + md5_file
            create_md5_file(md5_filename)
            md5 = get_md5_of_file(md5_filename)
            logging.debug("Got md5 %s ratio:%s on %s" % (md5, ratio, disk))

        # We need shrink the disk in guest first, than in monitor
        if float(ratio) < 1.0:
            error_context.context(
                "Shrink disk size to %s in guest" % block_size, logging.info)
            if os_type == 'windows':
                shr_size = utils_numeric.normalize_data_size(
                    str(
                        utils_disk.get_disk_size(session, os_type, disk) -
                        block_size), 'M').split(".")[0]
                drive.shrink_volume(session, mpoint, shr_size)
            else:
                utils_disk.resize_filesystem_linux(session, partition,
                                                   str(block_size))
                utils_disk.resize_partition_linux(session, partition,
                                                  str(block_size))

        error_context.context("Change disk size to %s in monitor" % block_size,
                              logging.info)
        if vm.check_capability(Flags.BLOCKDEV):
            args = (None, block_size, data_image_dev)
        else:
            args = (data_image_dev, block_size)
        vm.monitor.block_resize(*args)

        if params.get("guest_prepare_cmd", ""):
            session.cmd(params.get("guest_prepare_cmd"))
        # Update GPT due to size changed
        if os_type == "linux" and labeltype == "gpt":
            session.cmd("sgdisk -e /dev/%s" % disk)
        if params.get("need_reboot") == "yes":
            session = vm.reboot(session=session)
        if params.get("need_rescan") == "yes":
            drive.rescan_disks(session)

        # We need extend disk in monitor first than extend it in guest
        if float(ratio) > 1.0:
            error_context.context("Extend disk to %s in guest" % block_size,
                                  logging.info)
            if os_type == 'windows':
                drive.extend_volume(session, mpoint)
            else:
                utils_disk.resize_partition_linux(session, partition,
                                                  str(block_size))
                utils_disk.resize_filesystem_linux(session, partition,
                                                   utils_disk.SIZE_AVAILABLE)
        global current_size
        current_size = 0
        if not wait.wait_for(lambda: verify_disk_size(session, os_type, disk),
                             20, 0, 1, "Block Resizing"):
            test.fail("Block size get from guest is not same as expected.\n"
                      "Reported: %s\nExpect: %s\n" %
                      (current_size, block_size))
        session = vm.reboot(session=session)

        if os_type == 'linux':
            if not utils_disk.is_mount(
                    partition, dst=mpoint, fstype=fstype, session=session):
                utils_disk.mount(partition,
                                 mpoint,
                                 fstype=fstype,
                                 session=session)

        if params.get('iozone_test') == 'yes':
            iozone_timeout = float(params.get("iozone_timeout", 1800))
            iozone_cmd_options = params.get("iozone_option") % mpoint
            io_test = generate_instance(params, vm, 'iozone')
            try:
                io_test.run(iozone_cmd_options, iozone_timeout)
            finally:
                io_test.clean()

        # Verify md5
        if params.get('md5_test') == 'yes':
            new_md5 = get_md5_of_file(md5_filename)
            test.assertTrue(new_md5 == md5, "Unmatched md5: %s" % new_md5)

    session.close()
示例#15
0
def run(test, params, env):
    """
    KVM reboot test:
    1) Log into a guest with virtio data disk
    2) Format the disk and copy file to it
    3) Stop the guest and boot up it again with the data disk set to readonly
    4) Try to copy file to the data disk
    5) Try to copy file from the data disk

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    error_context.context(
        "TEST STEPS 1: Try to log into guest.", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = float(params.get("login_timeout", 240))
    session = vm.wait_for_login(timeout=timeout)

    error_context.context(
        "TEST STEPS 2: Format the disk and copy file to it", logging.info)
    os_type = params["os_type"]
    copy_cmd = params.get("copy_cmd", "copy %s %s")
    fstype = params.get("fstype", "ntfs")
    data_image_size = params.get("image_size_data", "1G")
    data_image_num = int(params.get("data_image_num",
                                    len(params.objects("images")) - 1))
    error_context.context("Get windows disk index that to "
                          "be formatted", logging.info)
    disk_index_list = utils_disk.get_windows_disks_index(session, data_image_size)
    if len(disk_index_list) < data_image_num:
        test.fail("Fail to list all data disks. "
                  "Set disk number: %d, "
                  "get disk number in guest: %d."
                  % (data_image_num, len(disk_index_list)))
    src_file = utils_misc.set_winutils_letter(
        session, params["src_file"], label="WIN_UTILS")
    error_context.context("Clear readonly for all disks and online "
                          "them in guest.", logging.info)
    if not utils_disk.update_windows_disk_attributes(session, disk_index_list):
        test.fail("Failed to update windows disk attributes.")
    error_context.context("Format disk %s in guest." % disk_index_list[0],
                          logging.info)
    drive_letter = utils_disk.configure_empty_disk(
        session, disk_index_list[0], data_image_size, os_type, fstype=fstype)
    if not drive_letter:
        test.fail("Fail to format disks.")
    dst_file = params["dst_file"] % drive_letter[0]
    session.cmd(copy_cmd % (src_file, dst_file))

    msg = "TEST STEPS 3: Stop the guest and boot up again with the data disk"
    msg += " set to readonly"
    error_context.context(msg, logging.info)
    session.close()
    vm.destroy()

    data_img = params.get("images").split()[-1]
    params["image_readonly_%s" % data_img] = "yes"
    params["force_create_image_%s" % data_img] = "no"
    env_process.preprocess(test, params, env)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=timeout)

    error_context.context(
        "TEST STEPS 4: Write to the readonly disk expect:"
        "The media is write protected", logging.info)
    dst_file_readonly = params["dst_file_readonly"] % drive_letter[0]
    o = session.cmd_output(copy_cmd % (src_file, dst_file_readonly))
    if not o.find("write protect"):
        test.fail("Write in readonly disk should failed\n. {}".format(o))

    error_context.context(
        "TEST STEPS 5: Try to read from the readonly disk", logging.info)
    s, o = session.cmd_status_output(copy_cmd % (dst_file, r"C:\\"))
    if s != 0:
        test.fail("Read file failed\n. {}".format(o))

    session.close()
示例#16
0
def run(test, params, env):
    """
    KVM reboot test:
    1) Log into a guest with virtio data disk
    2) Format the disk and copy file to it
    3) Stop the guest and boot up it again with the data disk set to readonly
    4) Try to copy file to the data disk
    5) Try to copy file from the data disk

    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
    """
    error_context.context("TEST STEPS 1: Try to log into guest.", logging.info)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = float(params.get("login_timeout", 240))
    session = vm.wait_for_login(timeout=timeout)

    error_context.context("TEST STEPS 2: Format the disk and copy file to it",
                          logging.info)
    os_type = params["os_type"]
    copy_cmd = params.get("copy_cmd", "copy %s %s")
    fstype = params.get("fstype", "ntfs")
    data_image_size = params.get("image_size_data", "1G")
    data_image_num = int(
        params.get("data_image_num",
                   len(params.objects("images")) - 1))
    error_context.context("Get windows disk index that to "
                          "be formatted", logging.info)
    disk_index_list = utils_disk.get_windows_disks_index(
        session, data_image_size)
    if len(disk_index_list) < data_image_num:
        test.fail("Fail to list all data disks. "
                  "Set disk number: %d, "
                  "get disk number in guest: %d." %
                  (data_image_num, len(disk_index_list)))
    src_file = utils_misc.set_winutils_letter(session,
                                              params["src_file"],
                                              label="WIN_UTILS")
    error_context.context(
        "Clear readonly for all disks and online "
        "them in guest.", logging.info)
    if not utils_disk.update_windows_disk_attributes(session, disk_index_list):
        test.fail("Failed to update windows disk attributes.")
    error_context.context("Format disk %s in guest." % disk_index_list[0],
                          logging.info)
    drive_letter = utils_disk.configure_empty_disk(session,
                                                   disk_index_list[0],
                                                   data_image_size,
                                                   os_type,
                                                   fstype=fstype)
    if not drive_letter:
        test.fail("Fail to format disks.")
    dst_file = params["dst_file"] % drive_letter[0]
    session.cmd(copy_cmd % (src_file, dst_file))

    msg = "TEST STEPS 3: Stop the guest and boot up again with the data disk"
    msg += " set to readonly"
    error_context.context(msg, logging.info)
    session.close()
    vm.destroy()

    data_img = params.get("images").split()[-1]
    params["image_readonly_%s" % data_img] = "yes"
    params["force_create_image_%s" % data_img] = "no"
    env_process.preprocess(test, params, env)
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=timeout)

    error_context.context(
        "TEST STEPS 4: Write to the readonly disk expect:"
        "The media is write protected", logging.info)
    dst_file_readonly = params["dst_file_readonly"] % drive_letter[0]
    o = session.cmd_output(copy_cmd % (src_file, dst_file_readonly))
    if not o.find("write protect"):
        test.fail("Write in readonly disk should failed\n. {}".format(o))

    error_context.context("TEST STEPS 5: Try to read from the readonly disk",
                          logging.info)
    s, o = session.cmd_status_output(copy_cmd % (dst_file, r"C:\\"))
    if s != 0:
        test.fail("Read file failed\n. {}".format(o))

    session.close()
示例#17
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)
def run(test, params, env):
    """
    Test to check the size of data disk increased can be detected
    automatically inside windows guest.

    Steps:
        1) Start a windows guest with a data disk and format it.
        2) Increase this data disk by qmp command.
        3) Copy a file to this data disk.
        4) The guest can detect the data disk size increased
           automatically.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def increase_block_device(dev):
        """Increase the block device."""
        logging.info("Start to increase image '%s' to %s.", img,
                     img_resize_size)
        resize_size = int(
            float(
                normalize_data_size(
                    re.search(r'(\d+\.?(\d+)?\w)', img_resize_size).group(1),
                    "B")))
        args = (dev, resize_size)
        if vm.check_capability(Flags.BLOCKDEV):
            args = (None, resize_size, dev)
        vm.monitor.block_resize(*args)
        return resize_size

    def get_disk_size_by_diskpart(index):
        """Get the disk size by the diskpart."""
        cmd = ' && '.join(
            ("echo list disk > {0}", "echo exit >> {0}", "diskpart /s {0}",
             "del /f {0}")).format('disk_script')
        pattern = r'Disk\s+%s\s+Online\s+(\d+\s+\w+)\s+\d+\s+\w+' % index
        return re.search(pattern, session.cmd_output(cmd), re.M).group(1)

    def check_disk_size(index):
        """Check the disk size after increasing inside guest."""
        logging.info(
            'Check whether the size of disk %s is equal to %s after '
            'increasing inside guest.', index, img_resize_size)
        v, u = re.search(r"(\d+\.?\d*)\s*(\w?)", img_resize_size).groups()
        size = get_disk_size_by_diskpart(index)
        logging.info('The size of disk %s is %s', index, size)
        if normalize_data_size(size, u) != v:
            test.fail('The size of disk %s is not equal to %s' %
                      (index, img_resize_size))

    img = params.get("images").split()[-1]
    img_params = params.object_params(img)
    img_size = img_params.get("image_size")
    img_resize_size = img_params.get('image_resize_size')
    img_filename = storage.get_image_filename(img_params,
                                              data_dir.get_data_dir())

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

    session = utils_test.qemu.windrv_check_running_verifier(
        vm.wait_for_login(), vm, test, 'viostor', 300)
    indices = utils_disk.get_windows_disks_index(session, img_size)
    utils_disk.update_windows_disk_attributes(session, indices)
    index = indices[0]
    mpoint = utils_disk.configure_empty_windows_disk(session, index,
                                                     img_size)[0]
    increase_block_device(vm.get_block({'file': img_filename}))
    vm.copy_files_to('/home/dd_file', "%s:\\dd_file" % mpoint)
    check_disk_size(index)
示例#19
0
def run(test, params, env):
    """
    Test hotplug of block devices.

    1) Boot up guest with virtio-blk or virtio-scsi system disk.
    2) Hoplug a virtio-blk or virtio-scsi data disk by qmp.
    3) Do read/write data on hotplug block.
    4) Unplug block device during serving block io, then verify devices.
    5) repeat step2~step4 100 times.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _check_iozone_status():
        ck_session = vm.wait_for_login(timeout=360)
        if not utils_misc.wait_for(lambda: check_cmd[os_type].split(
        )[-1].lower() in ck_session.cmd_output(check_cmd[os_type]).lower(),
                                   180,
                                   step=3.0):
            test.fail("Iozone is not alive!")
        ck_session.close()

    def _run_iozone_background():
        logging.info("Start iozone under background.")
        thread = utils_misc.InterruptedThread(
            iozone.run, (params['iozone_options'].format(mount_point),
                         float(params['iozone_timeout'])))
        thread.start()
        _check_iozone_status()
        return thread

    check_cmd = {
        'linux': 'pgrep -lx iozone',
        'windows': 'TASKLIST /FI "IMAGENAME eq IOZONE.EXE'
    }
    os_type = params['os_type']
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    session = vm.wait_for_login(timeout=360)

    iozone = generate_instance(params, vm, 'iozone')
    plug = BlockDevicesPlug(vm)
    need_format = True
    try:
        for i in range(int(params['repeat_time'])):
            logging.info('Start to run testing.(iteration: %d).', (i + 1))
            plug.hotplug_devs_serial()
            if need_format:
                if os_type == 'windows':
                    utils_disk.update_windows_disk_attributes(session, plug[0])
                mount_point = utils_disk.configure_empty_disk(
                    session, plug[0], params['image_size_stg0'], os_type)[0]
                if os_type == 'windows':
                    need_format = False
            iozone_thread = _run_iozone_background()
            time.sleep(float(params['sleep_time']))
            _check_iozone_status()
            plug.unplug_devs_serial()
            iozone_thread.join(suppress_exception=True)
    finally:
        iozone.clean(force=True)
        session.close()
示例#20
0
def run(test, params, env):
    """
    Test simple io on FC device pass-through to guest as lun device.

    Step:
     1. Find FC device on host.
     2. Boot a guest with FC disk as scsi-block device for guest.
     3. Access guest then do io on the data disk.
     4. Check vm status.
     5. repeat step 2-4 but as scsi-generic
    """
    def _clean_disk_windows(index):
        tmp_file = "disk_" + ''.join(
            random.sample(string.ascii_letters + string.digits, 4))
        online_cmd = "echo select disk %s > " + tmp_file
        online_cmd += " && echo clean >> " + tmp_file
        online_cmd += " && echo rescan >> " + tmp_file
        online_cmd += " && echo detail disk >> " + tmp_file
        online_cmd += " && diskpart /s " + tmp_file
        online_cmd += " && del /f " + tmp_file
        return session.cmd(online_cmd % index, timeout=timeout)

    def _get_window_disk_index_by_wwn(uid):
        cmd = "powershell -command \"get-disk| Where-Object"
        cmd += " {$_.UniqueId -eq '%s'}|select number|FL\"" % uid
        status, output = session.cmd_status_output(cmd)
        if status != 0:
            test.fail("execute command fail: %s" % output)
        output = "".join([s for s in output.splitlines(True) if s.strip()])
        logging.debug(output)
        info = output.split(":")
        if len(info) > 1:
            return info[1].strip()
        test.fail("Not find expected disk ")

    def _get_fc_devices():
        devs = []
        cmd = "lsblk -Spo 'NAME,TRAN' |awk '{if($2==\"fc\") print $1}'"
        status, output = process.getstatusoutput(cmd)
        devs_str = output.strip().replace("\n", " ")
        if devs_str:
            cmd = "lsblk -Jpo 'NAME,HCTL,SERIAL,TRAN,FSTYPE,WWN' %s" % devs_str
            status, output = process.getstatusoutput(cmd)
            devs = copy.deepcopy(json.loads(output)["blockdevices"])

        for dev in devs:
            cmd = "lsscsi -gb %s|awk '{print $3}'" % dev["hctl"]
            status, output = process.getstatusoutput(cmd)
            dev["sg_dev"] = output
        logging.debug(devs)
        return devs

    fc_devs = _get_fc_devices()
    if not len(fc_devs):
        test.cancel("No FC device")
    fc_dev = fc_devs[0]

    vm = env.get_vm(params['main_vm'])
    timeout = float(params.get("timeout", 240))
    drive_type = params.get("drive_type")
    os_type = params["os_type"]
    driver_name = params.get("driver_name")
    guest_cmd = params["guest_cmd"]
    clean_cmd = params["clean_cmd"]

    if drive_type == "scsi_block":
        params["image_name_stg0"] = fc_dev["name"]
        if fc_dev["fstype"] == "mpath_member":
            params["image_name_stg0"] = fc_dev["children"][0]["name"]
    else:
        params["image_name_stg0"] = fc_dev["sg_dev"]

    clean_cmd = clean_cmd % params["image_name_stg0"]
    error_context.context("run clean cmd %s" % clean_cmd, logging.info)
    process.getstatusoutput(clean_cmd)

    params['start_vm'] = 'yes'
    env_process.process(test, params, env, env_process.preprocess_image,
                        env_process.preprocess_vm)

    session = vm.wait_for_login(timeout=timeout)

    disk_wwn = fc_dev["wwn"]
    disk_wwn = disk_wwn.replace("0x", "")
    if os_type == 'windows' and driver_name:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, driver_name, timeout)

    if os_type == 'windows':
        part_size = params["part_size"]
        guest_cmd = utils_misc.set_winutils_letter(session, guest_cmd)
        did = _get_window_disk_index_by_wwn(disk_wwn)
        utils_disk.update_windows_disk_attributes(session, did)
        logging.info("Clean partition disk:%s", did)
        _clean_disk_windows(did)
        try:
            driver = configure_empty_disk(session, did, part_size, os_type)[0]
        except Exception as err:
            logging.warning("configure_empty_disk again due to:%s", err)
            time.sleep(10)
            _clean_disk_windows(did)
            driver = configure_empty_disk(session, did, part_size, os_type)[0]
            logging.debug("configure_empty_disk over")
        output_path = driver + ":\\test.dat"
    else:
        output_path = get_linux_drive_path(session, disk_wwn)

    if not output_path:
        test.fail("Can not get output file path in guest.")

    logging.debug("Get output file path %s", output_path)
    guest_cmd = guest_cmd.format(output_path)

    error_context.context('Start io test...', logging.info)
    session.cmd(guest_cmd, timeout=360)
    if not vm.monitor.verify_status("running"):
        test.fail("Guest not run after dd")
示例#21
0
def run(test, params, env):
    """
    QEMU 'disk images extension on lvm in io-error status' test

    1) Create small size lvm on large vg size.
    2) Create qcow2 image based on the lvm
    3) Boot vm with the lvm as vm data disk
    4) Execute large size io on the data disk.
    5) The vm will step in pause status due to no enough disk space.
    6) Start to periodic increase lvm disk size(128M) at first pause.
    7) Increase disk size when vm step in pause and resume vm.
    8) Repeat step 7 until final disk size exceed max size (50G)


    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """
    def _get_window_disk_index_by_serail(serial):
        cmd = "wmic diskdrive where SerialNumber='%s' get Index,Name"
        disks = session.cmd_output(cmd % serial)
        info = disks.splitlines()
        if len(info) > 1:
            attr = info[1].split()
            return attr[0]
        test.fail("Not find expected disk ")

    def _get_free_size():
        cmd = "df /home -BG|tail -n 1|awk '{print $4}'|tr -d 'G'"
        return int(process.system_output(cmd, shell=True))

    def _extend_lvm(size):
        process.system_output(extend_lvm_command % size, shell=True)

    def _get_lvm_size():
        return float(process.system_output(get_lvm_size_command, shell=True))

    def _extend_lvm_daemon():
        while _get_lvm_size() < disk_size:
            logging.debug("periodical extension.")
            _extend_lvm("128M")
            time.sleep(5)

    disk_size = int(params["disk_size"][0:-1])
    timeout = int(params.get("login_timeout", 360))
    wait_timeout = int(params.get("wait_timeout", 360))
    os_type = params["os_type"]
    driver_name = params.get("driver_name")
    disk_serial = params["disk_serial"]
    guest_cmd = params["guest_cmd"]
    extend_lvm_command = params["extend_lvm_command"]
    get_lvm_size_command = params["get_lvm_size_command"]
    free_size = int(params["free_size"][0:-1])

    if _get_free_size() < free_size:
        test.cancel("No enough space to run this case %d %d" %
                    (_get_free_size(), free_size))

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

    session = vm.wait_for_login(timeout=timeout)
    if os_type == 'windows' and driver_name:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, driver_name, timeout)

    if os_type == 'windows':
        img_size = params["disk_size"]
        guest_cmd = utils_misc.set_winutils_letter(session, guest_cmd)
        disk = _get_window_disk_index_by_serail(disk_serial)
        utils_disk.update_windows_disk_attributes(session, disk)
        logging.info("Formatting disk:%s", disk)
        driver = utils_disk.configure_empty_disk(session, disk, img_size,
                                                 os_type)[0]
        output_path = driver + ":\\test.dat"
    else:
        output_path = get_linux_drive_path(session, disk_serial)

    if not output_path:
        test.fail("Can not get output file path in guest.")

    logging.debug("Get output file path %s", output_path)
    guest_cmd = guest_cmd % output_path
    session.sendline(guest_cmd)

    test.assertTrue(vm.wait_for_status("paused", wait_timeout))
    thread = threading.Thread(target=_extend_lvm_daemon)
    thread.start()
    while _get_lvm_size() < disk_size:
        if vm.is_paused():
            logging.debug("pause extension.")
            _extend_lvm("500M")
            vm.monitor.cmd("cont")

            # Verify the guest status
            if _get_lvm_size() < disk_size:
                try:
                    test.assertTrue(vm.wait_for_status("paused", wait_timeout))
                except AssertionError:
                    if _get_lvm_size() < disk_size:
                        raise
                    else:
                        logging.debug("Ignore timeout.")
            else:
                test.assertTrue(vm.wait_for_status("running", wait_timeout))
        else:
            time.sleep(0.1)
def run(test, params, env):
    """
    Test hotplug of block devices.

    1) Boot up a guest with a system disk and a data disk.
    2) Do IO stress test on data disk.
    3) Unplug data disk during io stress.
    4) Reboot guest.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _check_stress_status():
        """ Check the status of stress. """
        ck_session = vm.wait_for_login(timeout=360)
        proc_name = check_cmd[os_type].split()[-1]
        cmd = check_cmd[os_type]
        if not utils_misc.wait_for(lambda: proc_name.lower() in ck_session.
                                   cmd_output(cmd).lower(),
                                   180,
                                   step=3.0):
            test.fail("%s is not alive!" % proc_name)
        ck_session.close()

    def _get_data_disk():
        """ Get the data disk. """
        extra_params = params["blk_extra_params_%s" %
                              params['images'].split()[-1]]
        if windows:
            return sorted(
                session.cmd('wmic diskdrive get index').split()[1:])[-1]
        drive_id = re.search(r"(serial|wwn)=(\w+)", extra_params,
                             re.M).group(2)
        return utils_misc.get_linux_drive_path(session, drive_id)

    def _run_stress_background():
        """ Run stress under background. """
        logging.info("Start io stress under background.")
        thread = utils_misc.InterruptedThread(target[os_type]['name'],
                                              (target[os_type]['args'], ))
        thread.start()
        _check_stress_status()
        return thread

    check_cmd = {
        'linux': 'pgrep -lx dd',
        'windows': 'TASKLIST /FI "IMAGENAME eq IOZONE.EXE'
    }
    os_type = params['os_type']
    args = params['stress_args']
    windows = os_type == 'windows'
    target = {}
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=360)
    disk = _get_data_disk()
    if windows:
        iozone = generate_instance(params, vm, 'iozone')
        utils_disk.update_windows_disk_attributes(session, disk)
        disk_letter = utils_disk.configure_empty_disk(
            session, disk, params['image_size_stg0'], os_type)[0]
        target[os_type] = {
            'name': iozone.run,
            'args': args.format(disk_letter)
        }
    else:
        target[os_type] = {'name': session.cmd, 'args': args.format(disk)}

    stress_thread = _run_stress_background()
    time.sleep(float(params['sleep_time']))
    _check_stress_status()
    BlockDevicesPlug(vm).unplug_devs_serial()
    stress_thread.join(suppress_exception=True)
    session.close()
    vm.monitor.system_reset()
    logging.info('Login guest after reboot.')
    session = vm.wait_for_login(timeout=360)
示例#23
0
def run(test, params, env):
    """
    Test to hot plug with block resize.
    Steps:
        1) Boot the guest with system disk.
        2) Hotplug a virtio disk via qmp.
        3) For Windows: check whether viostor.sys verifier enabled in
           guest.
        4) block_resize data disk, e.g, enlarge to 10GB; shrink to 1GB.
        5) Check the disk using qemu-img check on host and do io test
           in guest.
        6) Reboot or shutdown guest by qmp and shell.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def _change_vm_power():
        """ Change the vm power. """
        method, command = params['command_opts'].split(',')
        logging.info('Sending command(%s): %s' % (method, command))
        if method == 'shell':
            power_session = vm.wait_for_login(timeout=360)
            power_session.sendline(command)
        else:
            getattr(vm.monitor, command)()
        if shutdown_vm:
            if not utils_misc.wait_for(
                    lambda: vm.monitor.get_event("SHUTDOWN"), 600):
                raise test.fail("Not received SHUTDOWN QMP event.")

    def _check_vm_status(timeout=600):
        """ Check the status of vm. """
        action = 'shutdown' if shutdown_vm else 'login'
        if not getattr(vm, 'wait_for_%s' % action)(timeout=timeout):
            test.fail('Failed to %s vm.' % action)

    def _block_resize(dev):
        """ Resize the block size. """
        resize_size = int(
            float(
                normalize_data_size(
                    re.search(r'(\d+\.?(\d+)?\w)',
                              params['resize_size']).group(1), "B")))
        size = str(data_image_size +
                   resize_size) if resize_op == ENLARGE else str(
                       data_image_size - resize_size)
        logging.info("Start to %s %s to %sB." % (resize_op, plug[0], size))
        vm.monitor.block_resize(dev, size)
        return size

    def _check_img_size(size):
        """ Check the size of image after resize. """
        img = qemu_storage.QemuImg(data_image_params, data_dir.get_data_dir(),
                                   data_image)
        if json.loads(img.info(True, 'json'))['virtual-size'] != int(size):
            test.fail('The virtual size is not equal to %sB after %s.' %
                      (size, resize_op))

    shutdown_vm = params.get('shutdown_vm', 'no') == 'yes'
    reboot = params.get('reboot_vm', 'no') == 'yes'
    data_image = params.get("images").split()[-1]
    data_image_params = params.object_params(data_image)
    data_image_size = int(
        float(normalize_data_size(data_image_params.get("image_size"), "B")))
    data_image_filename = storage.get_image_filename(data_image_params,
                                                     data_dir.get_data_dir())
    resize_op = SHRINK if '-' in params['resize_size'] else ENLARGE
    os_type = params['os_type']
    is_windows = os_type == 'windows'

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

    if is_windows:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, params['driver_name'], 300)
    plug = BlockDevicesPlug(vm)
    plug.hotplug_devs_serial()
    block_size = _block_resize(vm.get_block({'file': data_image_filename}))
    _check_img_size(block_size)

    iozone = generate_instance(params, vm, 'iozone')
    try:
        if is_windows:
            if not utils_disk.update_windows_disk_attributes(session, plug[:]):
                test.fail('Failed to clear readonly and online on %s.' %
                          plug[:])
        mount_point = utils_disk.configure_empty_disk(session, plug[0],
                                                      block_size + 'B',
                                                      os_type)[0]
        iozone_size = str(int(float(normalize_data_size(block_size)))) + 'M'
        iozone.run(params['iozone_options'].format(mount_point, iozone_size),
                   float(params['iozone_timeout']))
    finally:
        iozone.clean()
        if shutdown_vm or reboot:
            _change_vm_power()
            _check_vm_status()
def run(test, params, env):
    """
    Test the block write threshold for block devices.
    Steps:
        1. Create a data disk.
        2. Boot up the guest with a data disk attached.
        3. Set block write threshold for the data block drive in QMP.
        4. Login to guest then do stress io to trigger the threshold.
        5. Verify the event 'BLOCK_WRITE_THRESHOLD' in QMP.
        6. Set block write threshold to 0 for the data block drive in QMP
           which will not trigger the threshold.
        7. Login to guest then do stress io.
        8. Verify event 'BLOCK_WRITE_THRESHOLD' in QMP which should not be
           triggered.

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def get_node_name(image_tag):
        """ Get the node name. """
        img_params = params.object_params(image_tag)
        file = storage.get_image_filename(img_params, data_dir.get_data_dir())
        for block in vm.monitor.info("block"):
            if file == block['inserted']['file']:
                return block['inserted']['node-name']

    def set_block_write_threshold(monitor, node_name, size):
        """ Set block write threshold for the block drive. """
        error_context.context(
            "Set block write threshold to %s for the block "
            "drive in QMP." % size, logging.info)
        monitor.cmd('block-set-write-threshold', {
            "node-name": node_name,
            "write-threshold": size
        })

    def verify_block_write_threshold_event(monitor):
        """ Verify the event 'BLOCK_WRITE_THRESHOLD' in QMP. """
        return wait_for(lambda: monitor.get_event('BLOCK_WRITE_THRESHOLD'), 30)

    def get_data_disk(session):
        """ Get the data disk. """
        if is_linux:
            extra_params = params["blk_extra_params_%s" % data_img_tag]
            drive_id = re.search(r"(serial|wwn)=(\w+)", extra_params,
                                 re.M).group(2)
            return utils_misc.get_linux_drive_path(session, drive_id)
        return sorted(session.cmd('wmic diskdrive get index').split()[1:])[-1]

    def _io_stress_linux(target):
        session.cmd(params['dd_cmd'] % target, 180)

    def _io_stress_windows(target):
        fio = generate_instance(params, vm, 'fio')
        try:
            fio.run(params['fio_opts'] % target)
        finally:
            fio.clean()

    def run_io_stress(stress_func, target):
        """ Run io stress inside guest. """
        error_context.context("Run io stress inside guest.", logging.info)
        stress_func(target)

    is_linux = params['os_type'] == 'linux'
    data_img_tag = params['images'].split()[-1]
    data_img_size = params['image_size_%s' % data_img_tag]
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=360)
    target = get_data_disk(session)
    if not is_linux:
        session = utils_test.qemu.windrv_check_running_verifier(
            session, vm, test, params['driver_name'])
        utils_disk.update_windows_disk_attributes(session, target)
        target = utils_disk.configure_empty_windows_disk(
            session, target, data_img_size)[-1]

    qmp_monitor = vm.monitors[0]
    node_name = get_node_name(data_img_tag)
    set_block_write_threshold(qmp_monitor, node_name,
                              int(params['threshold_size']))
    stress_func = locals()['_io_stress_%s' %
                           ('linux' if is_linux else 'windows')]
    run_io_stress(stress_func, target)
    if not verify_block_write_threshold_event(qmp_monitor):
        test.fail('Failed to get the event \'BLOCK_WRITE_THRESHOLD\'.')

    qmp_monitor.clear_event('BLOCK_WRITE_THRESHOLD')
    set_block_write_threshold(qmp_monitor, node_name, 0)
    run_io_stress(stress_func, target)
    if verify_block_write_threshold_event(qmp_monitor):
        test.fail('Failed to disable threshold.')
def run(test, params, env):

    """
    Special hardware test case.
    FC host: ibm-x3650m4-05.lab.eng.pek2.redhat.com
    Disk serial name: scsi-360050763008084e6e0000000000001a4
    # multipath -ll
    mpathb (360050763008084e6e0000000000001a8) dm-4 IBM,2145
    size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
    |-+- policy='service-time 0' prio=50 status=active
    | `- 2:0:1:0 sde 8:64 active ready running
    `-+- policy='service-time 0' prio=10 status=enabled
      `- 2:0:0:0 sdd 8:48 active ready running
    mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
    size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
    |-+- policy='service-time 0' prio=50 status=active
    | `- 1:0:1:0 sdc 8:32 active ready running
    `-+- policy='service-time 0' prio=10 status=enabled
      `- 1:0:0:0 sdb 8:16 active ready running
    Customer Bug ID: 1720047  1753992

    format passthrough disk and do iozone test on it.

    1) pass-through /dev/sdb
    2) format it and do iozone test
    3) pass-through /dev/sg1
    4) format it and do iozone test
    5) pass-through /dev/mapper/mpatha
    6) format it and do iozone test

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

    def get_multipath_disks(mpath_name="mpatha"):

        """
        Get all disks of multiple paths.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16  active ready running

        :param mpath_name: multi-path name.
        :return: a list. if get disks successfully or raise a error
        """
        disks = []
        disk_str = []
        outputs = process.run("multipath -ll", shell=True).stdout.decode()
        outputs = outputs.split(mpath_name)[-1]
        disk_str.append("active ready running")
        disk_str.append("active faulty offline")
        disk_str.append("failed faulty offline")
        for line in outputs.splitlines():
            if disk_str[0] in line or disk_str[1] in line or disk_str[2] in line:
                disks.append(line.split()[-5])
        if not disks:
            test.fail("Failed to get disks by 'multipath -ll'")
        else:
            return disks

    def get_multipath_disks_status(mpath_name="mpatha"):

        """
        Get status of multiple paths.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16  active ready running

        :param mpath_name: multi-path name.
        :return: a list. if get status successfully or raise a error
        """
        disks = get_multipath_disks(mpath_name)
        disks_status = []
        outputs = process.run("multipath -ll", shell=True).stdout.decode()
        outputs = outputs.split(mpath_name)[-1]
        for line in outputs.splitlines():
            for i in range(len(disks)):
                if disks[i] in line:
                    disks_status.append(line.strip().split()[-1])
                    break
        if not disks_status or len(disks_status) != len(disks):
            test.fail("Failed to get disks status by 'multipath -ll'")
        else:
            return disks_status

    def compare_multipath_status(status, mpath_name="mpatha"):

        """
        Compare status whether equal to the given status.
        This function just focus on all paths are running or all are offline.

        :param status: the state of disks.
        :param mpath_name: multi-path name.
        :return: True, if equal to the given status or False
        """
        status_list = get_multipath_disks_status(mpath_name)
        if len(set(status_list)) == 1 and status_list[0] == status:
            return True
        else:
            return False

    def set_disk_status_to_online_offline(disk, status):

        """
        set disk state to online/offline.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16 failed faulty offline

        :param disk: disk name.
        :param status: the state of disk.
        :return: by default
        """
        error_context.context("Set disk '%s' to status '%s'."
                              % (disk, status), logging.info)
        process.run("echo %s >  /sys/block/%s/device/state"
                    % (status, disk), shell=True)

    def set_multipath_disks_status(disks, status):

        """
        set multiple paths to same status. all disks online or offline.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16 failed faulty offline

        :param disks: disk list.
        :param status: the state of disk. online/offline
        :return: by default
        """
        for disk in disks:
            set_disk_status_to_online_offline(disk, status)
        wait.wait_for(lambda: compare_multipath_status(status),
                      first=2, step=1.5, timeout=60)

    def _do_post_cmd(session):
        """
        do post command after test.

        :param session: A shell session object.
        :return: by default
        """
        cmd = params.get("post_cmd")
        if cmd:
            session.cmd_status_output(cmd)
        session.close()

    def get_disk_by_sg_map(image_name_stg):
        """
        get disk name by sg_map.

        :param image_name_stg: linux sg. e.g. /dev/sg1
        :return: disk name. e.g. sdb
        """
        outputs = process.run("sg_map", shell=True).stdout.decode().splitlines()
        for output in outputs:
            if image_name_stg in output:
                return output.strip().split()[-1].split("/")[-1]

    def _get_windows_disks_index(session, image_size):
        """
        Get all disks index which show in 'diskpart list disk'.
        except for system disk.
        in diskpart: if disk size < 8GB: it displays as MB
                     else: it displays as GB

        :param session: session object to guest.
        :param image_size: image size. e.g. 40M
        :return: a list with all disks index except for system disk.
        """
        disk = "disk_" + ''.join(random.sample(string.ascii_letters + string.digits, 4))
        disk_indexs = []
        list_disk_cmd = "echo list disk > " + disk
        list_disk_cmd += " && echo exit >> " + disk
        list_disk_cmd += " && diskpart /s " + disk
        list_disk_cmd += " && del /f " + disk
        disks = session.cmd_output(list_disk_cmd)
        size_type = image_size[-1] + "B"
        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' % 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])
        return disk_indexs

    def delete_partition_on_host(did):
        """
        Delete partitions on the given disk.

        :param did: disk ID. disk kname. e.g. 'sdb', 'nvme0n1'
        :return: by default.
        """
        # process.run("partprobe /dev/%s" % did, shell=True)
        list_disk_cmd = "lsblk -o KNAME,MOUNTPOINT"
        output = process.run(list_disk_cmd, shell=True).stdout.decode()
        regex_str = did + "\w*(\d+)"
        rm_cmd = 'parted -s "/dev/%s" rm %s'
        for line in output.splitlines():
            partition = re.findall(regex_str, line, re.I | re.M)
            if partition:
                if "/" in line.split()[-1]:
                    process.run("umount %s" % line.split()[-1], shell=True)
        list_partition_number = "parted -s /dev/%s print|awk '/^ / {print $1}'"
        partition_numbers = process.run(list_partition_number % did,
                                        shell=True).stdout.decode()
        ignore_err_msg = "unrecognised disk label"
        if ignore_err_msg in partition_numbers:
            logging.info("no partition to delete on %s" % did)
        else:
            partition_numbers = partition_numbers.splitlines()
            for number in partition_numbers:
                logging.info("remove partition %s on %s" % (number, did))
                process.run(rm_cmd % (did, number), shell=True)
            process.run("partprobe /dev/%s" % did, shell=True)

    def delete_multipath_partition_on_host(mpath_name="mpatha"):
        """
        Delete partitions on the given multipath.

        :param mpath_name: multi-path name.
        :return: by default.
        """
        # process.run("partprobe /dev/mapper/%s" % mpath_name, shell=True)
        output = process.run("lsblk", shell=True).stdout.decode()
        mpath_dict = {}
        pattern = r'%s(\d+)' % mpath_name
        rm_cmd = 'parted -s "/dev/mapper/%s" rm %s'
        for line in output.splitlines():
            for part_num in re.findall(pattern, line, re.I | re.M):
                if part_num not in mpath_dict.keys():
                    mpath_dict[part_num] = line.split()[-1]
        for key, value in mpath_dict.items():
            if "/" in value:
                process.run("umount %s" % value, shell=True)
            logging.info("remove partition %s on %s" % (key, mpath_name))
            process.run(rm_cmd % (mpath_name, key), shell=True)
        output = process.run("dmsetup ls", shell=True).stdout.decode()
        for line in output.splitlines():
            for key in mpath_dict.keys():
                if (mpath_name + key) in line:
                    process.run("dmsetup remove %s%s" % (mpath_name, key),
                                shell=True)
        process.run("partprobe /dev/mapper/%s" % mpath_name, shell=True)

    def clean_partition_on_host(mpath_name="mpatha"):
        """
        Delete partitions on multi-path disks.

        :param mpath_name: multi-path name.
        :return: by default
        """
        delete_multipath_partition_on_host(mpath_name)
        disks = get_multipath_disks(mpath_name)
        for disk in disks:
            delete_partition_on_host(disk)

    error_context.context("Get FC host name:", logging.info)
    hostname = process.run("hostname", shell=True).stdout.decode().strip()
    if hostname != params["special_host"]:
        test.cancel("The special host is not '%s', cancel the test."
                    % params["special_host"])
    error_context.context("Get FC disk serial name:", logging.info)
    stg_serial_name = params["stg_serial_name"]
    image_name_stg = params["image_name_stg"].split("/")[-1]
    if "mpath" not in image_name_stg:
        if "sg" in image_name_stg:
            image_name_stg = get_disk_by_sg_map(image_name_stg)
            if not image_name_stg:
                test.cancel("Failed to get disk by sg_map,"
                            " output is '%s'" % image_name_stg)
        query_cmd = "udevadm info -q property -p /sys/block/%s" % image_name_stg
        outputs = process.run(query_cmd, shell=True).stdout.decode().splitlines()
        for output in outputs:
            # ID_SERIAL=360050763008084e6e0000000000001a4
            if stg_serial_name in output and output.startswith("ID_SERIAL="):
                break
        else:
            test.cancel("The special disk is not '%s', cancel the test."
                        % stg_serial_name)
    else:
        outputs = process.run("multipath -ll", shell=True).stdout.decode().splitlines()
        for output in outputs:
            if stg_serial_name in output and image_name_stg in output:
                break
        else:
            test.cancel("The special disk is not '%s', cancel the test."
                        % stg_serial_name)
        mpath_name = image_name_stg
        multi_disks = get_multipath_disks(mpath_name)
        error_context.context("Get all disks for '%s': %s"
                              % (mpath_name, multi_disks), logging.info)
        error_context.context("Verify all paths are running for %s before "
                              "start vm." % mpath_name, logging.info)
        if compare_multipath_status("running", mpath_name):
            logging.info("All paths are running for %s." % mpath_name)
        else:
            logging.info("Not all paths are running for %s, set "
                         "them to running." % mpath_name)
            set_multipath_disks_status(multi_disks, "running")
    error_context.context("Delete partitions on host before testing.",
                          logging.info)
    clean_partition_on_host(params["mpath_name"])
    vm = env.get_vm(params["main_vm"])
    try:
        vm.create(params=params)
    except Exception as e:
        test.error("failed to create VM: %s" % six.text_type(e))
    session = vm.wait_for_login(timeout=int(params.get("timeout", 240)))
    file_system = [_.strip() for _ in params["file_system"].split()]
    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'))
    image_num_stg = int(params["image_num_stg"])
    image_size_stg = params["image_size_stg"]
    ostype = params["os_type"]
    try:
        if ostype == "windows":
            error_context.context("Get windows disk index that to "
                                  "be formatted", logging.info)
            # disks = utils_disk.get_windows_disks_index(session, image_size_stg)
            disks = _get_windows_disks_index(session, image_size_stg)
            if len(disks) != image_num_stg:
                test.fail("Failed to list all disks by image size. The expected "
                          "is %s, actual is %s" % (image_num_stg, len(disks)))
            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.")
        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) != image_num_stg:
                test.fail("Failed to list all disks by image size. The expected "
                          "is %s, actual is %s" % (image_num_stg, len(disks)))
            # logging.info("Get data disk by serial name: '%s'" % stg_serial_name)
            # drive_path = utils_misc.get_linux_drive_path(session, stg_serial_name)
            # if not drive_path:
            #     test.fail("Failed to get data disk by serial name: %s"
            #               % stg_serial_name)
    except Exception:
        _do_post_cmd(session)
        raise
    if iozone_options:
        iozone = generate_instance(params, vm, 'iozone')
    try:
        error_context.context("Make sure guest is running before test",
                              logging.info)
        vm.resume()
        vm.verify_status("running")
        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, image_size_stg, ostype,
                fstype=fstype, labeltype=labeltype)
            if not partitions:
                test.fail("Fail to format disks.")
            for partition in partitions:
                if iozone_options and n < iozone_target_num:
                    iozone.run(iozone_options.format(partition), iozone_timeout)
        error_context.context("Reboot guest after format disk "
                              "and iozone test.", logging.info)
        session = vm.reboot(session=session, timeout=int(params.get("timeout", 240)))
        error_context.context("Shutting down guest after reboot it.", logging.info)
        vm.graceful_shutdown(timeout=int(params.get("timeout", 240)))
        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=int(params.get("timeout", 240)))
        error_context.context("Delete partitions in guest.", logging.info)
        for disk in disks:
            utils_disk.clean_partition(session, disk, ostype)
        error_context.context("Inform the OS of partition table changes "
                              "after testing.", logging.info)
        if "sg1" in params["image_name_stg"]:
            image_name_stg = get_disk_by_sg_map(params["image_name_stg"])
            process.run("partprobe /dev/%s" % image_name_stg, shell=True)
        else:
            process.run("partprobe %s" % params["image_name_stg"], shell=True)
    finally:
        if iozone_options:
            iozone.clean()
        _do_post_cmd(session)
示例#26
0
def run(test, params, env):
    """
    Test disk trimming in windows guest
    1) boot the vm with a data disk
    2) format the data disk without quick mode
    3) check the disk file size in host, and record for compare
    4) trim the data disk in guest
    5) check the disk file again in host, the file size should shrink

    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """
    def _get_size_value(size_str):
        """
        Get size value form size string

        :param size_str: data size string
        :return: the size numeric value, measured by MB
        """
        size_str = utils_misc.normalize_data_size(size_str)
        size = float(size_str)
        return size

    def _disk_size_smaller(ori_size):
        """
        Check till the disk size becomes smaller than ori_size
        :param ori_size: original size to compare to
        :return: new size if it smaller than ori_size, else None
        """
        output = process.system_output(host_check_cmd, shell=True).decode()
        new_size = _get_size_value(str(output))
        logging.info("Current data disk size: %sMB", new_size)
        if new_size < ori_size:
            return new_size
        return None

    def query_system_events(filter_options):
        """Query the system events in filter options."""
        logging.info("Query the system event log.")
        cmd = params.get("query_cmd") % filter_options
        return params.get("searched_keywords") in session.cmd(cmd).strip()

    host_check_cmd = params.get("host_check_cmd")
    image_dir = os.path.join(data_dir.get_data_dir(), 'images')
    host_check_cmd %= image_dir
    image_name = params["stg_name"]
    stg_param = params.object_params(image_name)
    image_size_str = stg_param["image_size"]
    guest_trim_cmd = params["guest_trim_cmd"]
    driver_verifier = params["driver_verifier"]
    event_id = params.get("event_id")

    timeout = float(params.get("timeout", 360))
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()

    session = vm.wait_for_login(timeout=timeout)
    error_context.context("Check if the driver is installed and verified",
                          logging.info)
    session = utils_test.qemu.windrv_check_running_verifier(
        session, vm, test, driver_verifier, timeout)

    error_context.context("Format data disk", logging.info)
    disk_index = utils_misc.wait_for(
        lambda: utils_disk.get_windows_disks_index(session, image_size_str),
        120)
    if not disk_index:
        test.error("Failed to get the disk index of size %s" % image_size_str)
    if not utils_disk.update_windows_disk_attributes(session, disk_index):
        test.error("Failed to enable data disk %s" % disk_index)
    drive_letter_list = utils_disk.configure_empty_windows_disk(
        session, disk_index[0], image_size_str, quick_format=False)
    if not drive_letter_list:
        test.error("Failed to format the data disk")
    drive_letter = drive_letter_list[0]

    error_context.context("Check size from host before disk trimming")
    output = process.system_output(host_check_cmd, shell=True).decode()
    ori_size = _get_size_value(output)
    logging.info("Data disk size: %sMB", ori_size)

    error_context.context("Trim data disk in guest")
    status, output = session.cmd_status_output(guest_trim_cmd % drive_letter,
                                               timeout=timeout)
    if status:
        test.error("Error when trim the volume, status=%s, output=%s" %
                   (status, output))
    if event_id:
        time.sleep(10)
        session = vm.reboot(session)
        if query_system_events(params['filter_options']):
            test.fail("Disk corruption after trim for %s" %
                      params.get("block_size"))

    error_context.context("Check size from host after disk trimming")
    new_size = utils_misc.wait_for(lambda: _disk_size_smaller(ori_size), 20,
                                   10, 1)

    if new_size is None:
        test.error("Data disk size is not smaller than: %sMB" % ori_size)
示例#27
0
def run(test, params, env):
    """
    QEMU 'disk images extension in io-error status' test

    1) Create folder and mounted it as tmpfs type.
    2) Create a raw image file with small size(50M) under the tmpfs folder.
    3) Attach loop device with above raw image file.
    4) Create qcow2 image on the loop device with larger size (500M).
    5) Boot vm with loop device as data disk.
    6) Access  guest vm and execute dd operation on the data disk.
     the IO size is same as the loop device virtual disk size.
    7) Verify vm status is paused status in qmp or hmp.
    8) Continue to increase disk size of the raw image file,
     and update the loop device.
    9) Verify vm status whether in expected status:
      if the raw image file size is smaller than loop device virtual disk size,
      it is in paused status,Otherwise it is in running status.

    :param test: QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """
    def cleanup_test_env(dirname, loop_device_name):
        cmd = "if losetup -l {0};then losetup -d {0};fi;".format(
            loop_device_name)
        cmd += "umount -l {0};rm -rf {0};".format(dirname)
        process.system_output(cmd, shell=True)

    def prepare_tmpfs_folder(dirname):
        cmd = "umount -l {0};rm -rf {0};mkdir -p {0};".format(dirname)
        process.system_output(cmd, ignore_status=True, shell=True)
        cmd = "mount -t tmpfs -o rw,nosuid,nodev,seclabel tmpfs {}".format(
            dirname)
        process.system_output(cmd, shell=True)

    def create_image_on_loop_device(backend_img, device_img):
        backend_img.create(backend_img.params)
        backend_filename = backend_img.image_filename
        loop_device_name = device_img.image_filename
        cmd = "losetup -d {}".format(loop_device_name)
        process.system_output(cmd, ignore_status=True, shell=True)
        cmd = "losetup {0} {1} && chmod 666 {0}".format(
            loop_device_name, backend_filename)
        process.system_output(cmd, shell=True)
        device_img.create(device_img.params)

    def update_loop_device_backend_size(backend_img, device_img, size):
        cmd = "qemu-img resize -f raw %s %s && losetup -c %s" % (
            backend_img.image_filename, size, device_img.image_filename)
        process.system_output(cmd, shell=True)

    current_size = int(params["begin_size"][0:-1])
    max_size = int(params["max_size"][0:-1])
    increment_size = int(params["increment_size"][0:-1])
    size_unit = params["increment_size"][-1]
    guest_cmd = params["guest_cmd"]

    loop_device_backend_img_tag = params["loop_device_backend_img_tag"]
    loop_device_img_tag = params["loop_device_img_tag"]

    loop_device_backend_img_param = params.object_params(
        loop_device_backend_img_tag)
    loop_device_img_param = params.object_params(loop_device_img_tag)
    tmpfs_folder = params.get("tmpfs_folder", "/tmp/xtmpfs")

    if loop_device_backend_img_param["image_format"] != "raw":
        test.cancel("Wrong loop device backend image format in config file.")

    error_context.context("Start to setup tmpfs folder", logging.info)
    prepare_tmpfs_folder(tmpfs_folder)

    error_context.context("Start to create image on loop device", logging.info)
    loop_device_backend_img = QemuImg(loop_device_backend_img_param,
                                      data_dir.get_data_dir(),
                                      loop_device_backend_img_tag)
    loop_device_img = QemuImg(loop_device_img_param, data_dir.get_data_dir(),
                              loop_device_img_tag)
    create_image_on_loop_device(loop_device_backend_img, loop_device_img)

    try:
        # start to boot vm
        params["start_vm"] = "yes"
        timeout = int(params.get("login_timeout", 360))
        os_type = params["os_type"]
        driver_name = params.get("driver_name")
        disk_serial = params["disk_serial"]

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

        session = vm.wait_for_login(timeout=timeout)
        if os_type == 'windows' and driver_name:
            session = utils_test.qemu.windrv_check_running_verifier(
                session, vm, test, driver_name, timeout)

        if os_type == 'windows':
            img_size = loop_device_img_param["image_size"]
            guest_cmd = utils_misc.set_winutils_letter(session, guest_cmd)
            disk = utils_disk.get_windows_disks_index(session, img_size)[0]
            utils_disk.update_windows_disk_attributes(session, disk)
            logging.info("Formatting disk:%s" % disk)
            driver = utils_disk.configure_empty_disk(session, disk, img_size,
                                                     os_type)[0]
            output_path = driver + ":\\test.dat"

        else:
            output_path = get_linux_drive_path(session, disk_serial)

        if not output_path:
            test.fail("Can not get output file path in guest.")

        logging.debug("Get output file path %s" % output_path)

        guest_cmd = guest_cmd % output_path
        wait_timeout = int(params.get("wait_timeout", 60))

        session.sendline(guest_cmd)

        test.assertTrue(vm.wait_for_status("paused", wait_timeout))

        while current_size < max_size:
            current_size += increment_size
            current_size_string = str(current_size) + size_unit

            error_context.context(
                "Update backend image size to %s" % current_size_string,
                logging.info)
            update_loop_device_backend_size(loop_device_backend_img,
                                            loop_device_img,
                                            current_size_string)

            vm.monitor.cmd("cont")

            # Verify the guest status
            if current_size < max_size:
                test.assertTrue(vm.wait_for_status("paused", wait_timeout))
            else:
                test.assertTrue(vm.wait_for_status("running", wait_timeout))
    finally:
        cleanup_test_env(tmpfs_folder, params["loop_device"])
示例#28
0
def run(test, params, env):
    """
    Special hardware test case.
    FC host: ibm-x3650m4-05.lab.eng.pek2.redhat.com
    Disk serial name: scsi-360050763008084e6e0000000000001a4
    # multipath -ll
    mpathb (360050763008084e6e0000000000001a8) dm-4 IBM,2145
    size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
    |-+- policy='service-time 0' prio=50 status=active
    | `- 2:0:1:0 sde 8:64 active ready running
    `-+- policy='service-time 0' prio=10 status=enabled
      `- 2:0:0:0 sdd 8:48 active ready running
    mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
    size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
    |-+- policy='service-time 0' prio=50 status=active
    | `- 1:0:1:0 sdc 8:32 active ready running
    `-+- policy='service-time 0' prio=10 status=enabled
      `- 1:0:0:0 sdb 8:16 active ready running
    Customer Bug ID: 1741937  1673546

    Test if VM paused/resume when fc storage offline/online.

    1) pass-through /dev/mapper/mpatha
    2) install guest on pass-through disk
    3) Disconnect the storage during installation
    4) Check if VM status is 'paused'
    5) Connect the storage, Wait until the storage is accessible again
    6) resume the vm
    7) Check if VM status is 'running'
    8) installation completed successfully
    9) re-pass-through /dev/mapper/mpatha
    10) fio test on pass-through disk
    11) Disconnect any path of multipath during fio testing
    12) Check if VM status is 'paused'
    13) Connect the storage, Wait until the storage is accessible again
    14) resume the vm
    15) fio testing completed successfully

    :param test: kvm test object.
    :param params: Dictionary with the test parameters.
    :param env: Dictionary with test environment.
    """
    def check_vm_status(vm, status):
        """
        Check if VM has the given status or not.

        :param vm: VM object.
        :param status: String with desired status.
        :return: True if VM status matches our desired status.
        :return: False if VM status does not match our desired status.
        """
        try:
            current_status = vm.monitor.get_status()
            vm.verify_status(status)
        except (virt_vm.VMStatusError, qemu_monitor.MonitorLockError):
            logging.info("Failed to check vm status, it is '%s' "
                         "instead of '%s'" % (current_status, status))
            return False
        except Exception as e:
            logging.info("Failed to check vm status: %s" % six.text_type(e))
            logging.info("vm status is '%s' instead of"
                         " '%s'" % (current_status, status))
            return False
        else:
            logging.info("Check vm status successfully. It is '%s'" % status)
            return True

    def get_multipath_disks(mpath_name="mpatha"):
        """
        Get all disks of multiple paths.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16  active ready running

        :param mpath_name: multi-path name.
        :return: a list. if get disks successfully or raise a error
        """
        logging.info("get_multipath_disks:" + mpath_name)
        disks = []
        disk_str = []
        outputs = process.run("multipath -ll " + mpath_name,
                              shell=True).stdout.decode()
        outputs = outputs.split(mpath_name)[-1]
        disk_str.append("active ready running")
        disk_str.append("active faulty offline")
        disk_str.append("failed faulty offline")
        disk_str.append("failed ready running")
        for line in outputs.splitlines():
            if disk_str[0] in line or disk_str[1] in line or disk_str[2] \
                    in line or disk_str[3] in line:
                disks.append(line.split()[-5])
        if not disks:
            test.fail("Failed to get disks by 'multipath -ll'")
        else:
            return disks

    def get_multipath_disks_status(mpath_name="mpatha"):
        """
        Get status of multiple paths.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16  active ready running

        :param mpath_name: multi-path name.
        :return: a dict. e.g. {"sdb": "running", "sdc": "running"}
        """
        disks = get_multipath_disks(mpath_name)
        disks_status = {}
        outputs = process.run("multipath -ll " + mpath_name,
                              shell=True).stdout.decode()
        outputs = outputs.split(mpath_name)[-1]
        for line in outputs.splitlines():
            for i in range(len(disks)):
                if disks[i] in line:
                    disks_status[disks[i]] = line.strip().split()[-1]
                    break
        if not disks_status or len(disks_status) != len(disks):
            logging.info("Failed to get disks status by 'multipath -ll'")
            return {}
        else:
            return disks_status

    def compare_onepath_status(status, disk):
        """
        Compare status whether equal to the given status.
        This function just focus on all paths are running or all are offline.

        :param status: the state of disks.
        :param disk: disk kname.
        :return: True, if equal to the given status or False
        """
        status_dict = get_multipath_disks_status(mpath_name)
        logging.debug("compare_onepath_status disk:", disk, status_dict,
                      status)
        if disk in status_dict.keys() and status == status_dict[disk]:
            return True
        else:
            return False

    def compare_multipath_status(status, mpath_name="mpatha"):
        """
        Compare status whether equal to the given status.
        This function just focus on all paths are running or all are offline.

        :param status: the state of disks.
        :param mpath_name: multi-path name.
        :return: True, if equal to the given status or False
        """
        status_dict = get_multipath_disks_status(mpath_name)
        logging.debug("compare_multipath_status mpath_name:", mpath_name,
                      status_dict, status)
        if len(set(
                status_dict.values())) == 1 and status in status_dict.values():
            return True
        else:
            return False

    def set_disk_status_to_online_offline(disk, status):
        """
        set disk state to online/offline.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16 failed faulty offline

        :param disk: disk name.
        :param status: the state of disk.
        :return: by default
        """
        error_context.context("Set disk '%s' to status '%s'." % (disk, status),
                              logging.info)
        process.run("echo %s >  /sys/block/%s/device/state" % (status, disk),
                    shell=True)

    def set_multipath_disks_status(disks, status):
        """
        set multiple paths to same status. all disks online or offline.
        multipath like below:
        mpatha (360050763008084e6e0000000000001a4) dm-3 IBM,2145
        size=100G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
        |-+- policy='service-time 0' prio=50 status=active
        | `- 1:0:1:0 sdc 8:32  active ready running
        `-+- policy='service-time 0' prio=10 status=enabled
          `- 1:0:0:0 sdb 8:16 failed faulty offline

        :param disks: disk list.
        :param status: the state of disk. online/offline
        :return: by default
        """
        for disk in disks:
            set_disk_status_to_online_offline(disk, status)
            time.sleep(2)
        if len(disks) == 1:
            wait.wait_for(lambda: compare_onepath_status(status, disks[0]),
                          first=wait_time,
                          step=3,
                          timeout=60)
        else:
            wait.wait_for(lambda: compare_multipath_status(status),
                          first=wait_time,
                          step=3,
                          timeout=60)

    def get_lvm_dm_name(blkdevs_used):
        """
        Get dm name for lvm. such as rhel_ibm--x3650m4--05-root in below
        NAME                           MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
        sda                              8:0    0 278.9G  0 disk
        ├─sda1                           8:1    0     1G  0 part  /boot
        └─sda2                           8:2    0 277.9G  0 part
            ├─rhel_ibm--x3650m4--05-root 253:0    0    50G  0 lvm   /
            ├─rhel_ibm--x3650m4--05-swap 253:1    0  15.7G  0 lvm   [SWAP]
            └─rhel_ibm--x3650m4--05-home 253:2    0 212.2G  0 lvm   /home
        # ls /dev/mapper/* -l
        crw-------. 1 root root 10, 236 Oct 25 02:07 /dev/mapper/control
        lrwxrwxrwx. 1 root root       7 Oct 25 09:26 /dev/mapper/mpatha -> ../dm-3
        lrwxrwxrwx. 1 root root       7 Oct 25 09:26 /dev/mapper/mpatha1 -> ../dm-5
        lrwxrwxrwx. 1 root root       7 Oct 25 09:26 /dev/mapper/mpatha2 -> ../dm-6
        lrwxrwxrwx. 1 root root       7 Oct 25 06:49 /dev/mapper/mpathb -> ../dm-4
        lrwxrwxrwx. 1 root root       7 Oct 25 09:17 /dev/mapper/rhel_bootp--73--199--5-home -> ../dm-8
        lrwxrwxrwx. 1 root root       7 Oct 25 09:17 /dev/mapper/rhel_bootp--73--199--5-root -> ../dm-9
        lrwxrwxrwx. 1 root root       7 Oct 25 09:17 /dev/mapper/rhel_bootp--73--199--5-swap -> ../dm-7
        lrwxrwxrwx. 1 root root       7 Oct 25 02:07 /dev/mapper/rhel_ibm--x3650m4--05-home -> ../dm-2
        lrwxrwxrwx. 1 root root       7 Oct 25 02:07 /dev/mapper/rhel_ibm--x3650m4--05-root -> ../dm-0
        lrwxrwxrwx. 1 root root       7 Oct 25 02:07 /dev/mapper/rhel_ibm--x3650m4--05-swap -> ../dm-1
        -rw-r--r--. 1 root root       0 Oct 25 07:52 /dev/mapper/vg_raid10-lv_home
        # dmsetup info -c -o name,blkdevs_used
        Name                        BlkDevNamesUsed
        rhel_bootp--73--199--5-home dm-6
        mpathb                      sdd,sde
        mpatha                      sdb,sdc
        mpatha2                     dm-3
        rhel_bootp--73--199--5-swap dm-6
        rhel_bootp--73--199--5-root dm-6
        mpatha1                     dm-3
        rhel_ibm--x3650m4--05-home  sda2
        rhel_ibm--x3650m4--05-swap  sda2
        rhel_ibm--x3650m4--05-root  sda2

        :param blkdevs_used: block name, e.g. sda2
        :return: a list contains all dm name for one blkdev
        """
        dm_list = []
        logging.info("Get dm name for '%s'" % blkdevs_used)
        output = process.run("ls /dev/mapper/* -l", shell=True).stdout.decode()
        for line in output.splitlines():
            if blkdevs_used in line:
                dm_name = line.split("/")[-1]
                break
        output = process.run("dmsetup info -c -o name,blkdevs_used",
                             shell=True).stdout.decode()
        for line in output.splitlines():
            if dm_name == line.split()[-1]:
                dm_list.append(line.split()[0])
        return dm_list

    def delete_lvm_on_multipath(mpath_name="mpatha"):
        """
        Delete lvm on the given multipath.

        :param mpath_name: multi-path name.
        :return: by default.
        """
        output = process.run("pvscan", shell=True).stdout.decode()
        pv_list = []
        vg_list = []
        lv_list = []
        for line in output.splitlines():
            if mpath_name in line:
                if line.split()[1] not in pv_list:
                    pv_list.append(line.split()[1])
                if line.split()[3] not in vg_list:
                    vg_list.append(line.split()[3])
        output = process.run("lvscan", shell=True).stdout.decode()
        for line in output.splitlines():
            for vg in vg_list:
                lv = "/dev/%s/" % vg
                if lv in line and line.split("'")[1] not in lv_list:
                    lv_list.append(line.split("'")[1])
        logging.info("pv list: %s" % pv_list)
        logging.info("vg list: %s" % vg_list)
        logging.info("lv list: %s" % lv_list)
        for lv in lv_list:
            logging.info("Remove lvm '%s'." % lv)
            process.run("lvremove -y %s" % lv, ignore_status=True, shell=True)
        for vg in vg_list:
            logging.info("Remove vg '%s'." % vg)
            process.run("vgremove -y %s" % vg, ignore_status=True, shell=True)
        for pv in pv_list:
            pv_name = pv.split("/")[-1]
            for dm in get_lvm_dm_name(pv_name):
                process.run("dmsetup remove %s" % dm,
                            ignore_status=True,
                            shell=True)
            logging.info("Remove pv '%s'." % pv)
            process.run("pvremove -y %s" % pv, ignore_status=True, shell=True)

    def delete_partition_on_host(did):
        """
        Delete partitions on the given disk.

        :param did: disk ID. disk kname. e.g. 'sdb', 'nvme0n1'
        :return: by default.
        """
        # process.run("partprobe /dev/%s" % did, shell=True)
        list_disk_cmd = "lsblk -o KNAME,MOUNTPOINT"
        output = process.run(list_disk_cmd, shell=True).stdout.decode()
        regex_str = did + "\w*(\d+)"
        rm_cmd = 'parted -s "/dev/%s" rm %s'
        for line in output.splitlines():
            partition = re.findall(regex_str, line, re.I | re.M)
            if partition:
                if "/" in line.split()[-1]:
                    process.run("umount %s" % line.split()[-1], shell=True)
        list_partition_number = "parted -s /dev/%s print|awk '/^ / {print $1}'"
        partition_numbers = process.run(list_partition_number % did,
                                        ignore_status=True,
                                        shell=True).stdout.decode()
        ignore_err_msg = "unrecognised disk label"
        if ignore_err_msg in partition_numbers:
            logging.info("no partition to delete on %s" % did)
        else:
            partition_numbers = partition_numbers.splitlines()
            for number in partition_numbers:
                logging.info("remove partition %s on %s" % (number, did))
                process.run(rm_cmd % (did, number),
                            ignore_status=True,
                            shell=True)
            process.run("partprobe /dev/%s" % did, shell=True)

    def delete_multipath_partition_on_host(mpath_name="mpatha"):
        """
        Delete partitions on the given multipath.

        :param mpath_name: multi-path name.
        :return: by default.
        """
        # process.run("partprobe /dev/mapper/%s" % mpath_name, shell=True)
        output = process.run("lsblk", shell=True).stdout.decode()
        mpath_dict = {}
        pattern = r'%s(\d+)' % mpath_name
        rm_cmd = 'parted -s "/dev/mapper/%s" rm %s'
        for line in output.splitlines():
            for part_num in re.findall(pattern, line, re.I | re.M):
                if part_num not in mpath_dict.keys():
                    mpath_dict[part_num] = line.split()[-1]
        for key, value in mpath_dict.items():
            if "/" in value:
                process.run("umount %s" % value, shell=True)
            logging.info("remove partition %s on %s" % (key, mpath_name))
            process.run(rm_cmd % (mpath_name, key),
                        ignore_status=True,
                        shell=True)
        output = process.run("dmsetup ls", shell=True).stdout.decode()
        for line in output.splitlines():
            for key in mpath_dict.keys():
                if (mpath_name + key) in line:
                    process.run("dmsetup remove %s%s" % (mpath_name, key),
                                ignore_status=True,
                                shell=True)
        process.run("partprobe /dev/mapper/%s" % mpath_name, shell=True)

    def clean_partition_on_host(mpath_name="mpatha"):
        """
        Delete partitions on multi-path disks.

        :param mpath_name: multi-path name.
        :return: by default
        """
        delete_multipath_partition_on_host(mpath_name)
        disks = get_multipath_disks(mpath_name)
        for disk in disks:
            delete_partition_on_host(disk)

    def _run_fio_background(session, filename):
        """run fio testing by thread"""

        logging.info("Start fio in background.")
        cmd = fio_multipath.cfg.fio_path + params['fio_options'] % filename
        logging.info(cmd)
        session.cmdline(cmd)
        # args = (params['fio_options'] % filename, 3600)
        # fio_thread = utils_misc.InterruptedThread(fio_multipath.run, args)
        # fio_thread.start()
        # if not utils_misc.wait_for(lambda: fio_thread.is_alive, 60):
        #     test.fail("Failed to start fio thread.")
        # return fio_thread

    # def _run_fio_background(filename):
    #     """run fio testing by thread"""
    #
    #     logging.info("Start fio in background.")
    #     args = (params['fio_options'] % filename, 3600)
    #     fio_thread = utils_misc.InterruptedThread(fio_multipath.run, args)
    #     fio_thread.start()
    #     if not utils_misc.wait_for(lambda: fio_thread.is_alive, 60):
    #         test.fail("Failed to start fio thread.")
    #     return fio_thread

    def _get_windows_disks_index(session, image_size):
        """
        Get all disks index which show in 'diskpart list disk'.
        except for system disk.
        in diskpart: if disk size < 8GB: it displays as MB
                     else: it displays as GB

        :param session: session object to guest.
        :param image_size: image size. e.g. 40M
        :return: a list with all disks index except for system disk.
        """
        disk = "disk_" + ''.join(
            random.sample(string.ascii_letters + string.digits, 4))
        disk_indexs = []
        list_disk_cmd = "echo list disk > " + disk
        list_disk_cmd += " && echo exit >> " + disk
        list_disk_cmd += " && diskpart /s " + disk
        list_disk_cmd += " && del /f " + disk
        disks = session.cmd_output(list_disk_cmd)
        size_type = image_size[-1] + "B"
        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' % 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])
        return disk_indexs

    def resume_vm_plus(vm, timeout=120):
        """resume vm when it is paused.

        :param vm: VM object.
        :param timeout: re-try times, if it is still paused after resume
        :return: True or None.
                 If resume successfully return True or return None
        """
        logging.info("Try to resume vm within %s seconds." % timeout)
        try:
            vm_status = vm.resume(timeout=timeout)
        except Exception as e:
            logging.error("Failed to resume vm: %s" % six.text_type(e))
        return vm_status

    def resume_vm(vm, n_repeat=2):
        """resume vm when it is paused.

        :param vm: VM object.
        :param n_repeat: re-try times, if it is still paused after resume
        :return: True or False.
                 If resume successfully return True or return False
        """
        for i in range(1, n_repeat + 1):
            logging.info("Try to resume vm %s time(s)" % i)
            try:
                vm.resume()
                time.sleep(wait_time * 15)
            except Exception as e:
                logging.error("Failed to resume vm: %s" % six.text_type(e))
            finally:
                if check_vm_status(vm, "running"):
                    return True
                if vm.is_paused() and i == 3:
                    return False

    error_context.context("Get FC host name:", logging.info)
    hostname = process.run("hostname", shell=True).stdout.decode().strip()
    if hostname != params["special_host"]:
        test.cancel("The special host is not '%s', cancel the test." %
                    params["special_host"])
    error_context.context("Get FC disk serial name:", logging.info)
    outputs = process.run("multipath -ll",
                          shell=True).stdout.decode().splitlines()
    stg_serial_name = params["stg_serial_name"]
    image_name_stg = params["image_name_stg"]
    mpath_name = image_name_stg.split("/")[-1]
    for output in outputs:
        if stg_serial_name in output and mpath_name in output:
            break
    else:
        test.cancel("The special disk is not '%s', cancel the test." %
                    stg_serial_name)
    wait_time = float(params.get("sub_test_wait_time", 0))
    repeat_times = int(params.get("repeat_times", 2))
    multi_disks = get_multipath_disks(mpath_name)
    error_context.context(
        "Get all disks for '%s': %s" % (mpath_name, multi_disks), logging.info)
    error_context.context(
        "Verify all paths are running for %s before"
        "start vm." % mpath_name, logging.info)
    if compare_multipath_status("running", mpath_name):
        logging.info("All paths are running for %s." % mpath_name)
    else:
        logging.info("Not all paths are running for %s, set "
                     "them to running." % mpath_name)
        set_multipath_disks_status(multi_disks, "running")
    error_context.context(
        "Delete lvm on multipath disks on host "
        "before testing.", logging.info)
    delete_lvm_on_multipath(mpath_name)
    error_context.context("Delete partitions on host before testing.",
                          logging.info)
    clean_partition_on_host(mpath_name)
    vm = env.get_vm(params["main_vm"])
    try:
        if params.get("need_install") == "yes":
            error_context.context("Install guest on passthrough disk:",
                                  logging.info)
            args = (test, params, env)
            bg = utils_misc.InterruptedThread(
                utils_test.run_virt_sub_test, args,
                {"sub_type": "unattended_install"})
            bg.start()
            utils_misc.wait_for(bg.is_alive, timeout=10)
            time.sleep(random.uniform(60, 180))
        else:
            vm.create(params=params)
            session = vm.wait_for_login(
                timeout=int(params.get("timeout", 240)))
            fio_multipath = generate_instance(params, vm, 'fio')
            image_size_stg = params["image_size_stg"]
            image_num_stg = int(params["image_num_stg"])
            os_type = params["os_type"]
    except Exception as e:
        test.error("failed to create VM: %s" % six.text_type(e))
    try:
        error_context.context("Make sure guest is running before test",
                              logging.info)
        if vm.is_paused():
            vm.resume()
        vm.verify_status("running")
        if "fio_multipath" in locals().keys():
            if os_type == "windows":
                error_context.context(
                    "Get windows disk index that to "
                    "be formatted", logging.info)
                disks = _get_windows_disks_index(session, image_size_stg)
                if len(disks) != image_num_stg:
                    test.fail(
                        "Failed to list all disks by image size. The expected "
                        "is %s, actual is %s" % (image_num_stg, len(disks)))
                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.")
            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) != image_num_stg:
                    test.fail(
                        "Failed to list all disks by image size. The expected "
                        "is %s, actual is %s" % (image_num_stg, len(disks)))
            file_system = [_.strip() for _ in params["file_system"].split()]
            labeltype = params.get("labeltype", "gpt")
            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,
                    image_size_stg,
                    os_type,
                    fstype=fstype,
                    labeltype=labeltype)
                if not partitions:
                    test.fail("Fail to format disks.")
            fio_file_name = params["fio_file_name"] % partitions[0]
            # fio_thread = _run_fio_background(fio_file_name)
            _run_fio_background(session, fio_file_name)
        # disk = random.sample(multi_disks, 1)
        for disk in multi_disks:
            error_context.context(
                "Disable disk %s during guest running" % disk, logging.info)
            set_multipath_disks_status([disk], "offline")
            time.sleep(wait_time * 15)
            if vm.is_paused():
                logging.info("vm is paused, will resume it.")
                if not resume_vm(vm, repeat_times):
                    test.fail("Failed to resume guest after disable one disk")
                logging.info("Has resumed vm already. Then verify it running.")
                if not utils_misc.wait_for(
                        lambda: check_vm_status(vm, "running"), 60):
                    test.fail("Guest is not running after disable one disk")
            error_context.context("Enable disk %s during guest running" % disk,
                                  logging.info)
            set_multipath_disks_status([disk], "running")
            time.sleep(wait_time * 15)
        error_context.context(
            "Disable multipath '%s' during guest "
            "running." % mpath_name, logging.info)
        set_multipath_disks_status(multi_disks, "offline")
        time.sleep(wait_time * 15)
        error_context.context("Check if VM status is 'paused'", logging.info)
        if not utils_misc.wait_for(lambda: check_vm_status(vm, "paused"), 120):
            test.fail("Guest is not paused after all disks offline")
        error_context.context(
            "Re-connect fc storage, wait until the "
            "storage is accessible again", logging.info)
        set_multipath_disks_status(multi_disks, "running")
        time.sleep(wait_time * 15)
        error_context.context("vm is paused, resume it.", logging.info)
        if not resume_vm(vm, repeat_times):
            test.fail("Failed to resume guest after enable multipath.")
        logging.info("Has resumed vm already. Then verify it running.")
        time.sleep(wait_time * 15)
        error_context.context("Check if VM status is 'running'", logging.info)
        if not utils_misc.wait_for(lambda: check_vm_status(vm, "running"),
                                   120):
            test.fail("Guest is not running after all disks online")
        if "bg" in locals().keys() and bg.is_alive and not vm.is_paused():
            bg.join()
        # wq comment ,why need wait fio
        # if "fio_thread" in locals().keys() and fio_thread.is_alive \
        #         and not vm.is_paused():
        #     fio_thread.join()
        error_context.context(
            "Verify Host and guest kernel no error "
            "and call trace", logging.info)
        vm.verify_kernel_crash()
    # except Exception as e:
    #     logging.error(e)
    finally:
        logging.info("Finally, clean environment.")