block_resize.py 5.0 KB
Newer Older
Y
Yiqiao Pu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
import logging, re
from autotest.client.shared import error
from virttest import qemu_monitor, utils_misc, storage, data_dir


@error.context_aware
def run_block_resize(test, params, env):
    """
    KVM block resize test:

    1) Start guest with data image and check the data image size.
    2) Enlarge(or Decrease) the data image and check it in guest.

    @param test: QEMU test object
    @param params: Dictionary with the test parameters
    @param env: Dictionary with test environment.
    """
    def get_block_size(session, block_cmd, block_pattern):
        """
        Get block size inside guest.
        """
        output = session.cmd_output(block_cmd)
        block_size = re.findall(block_pattern, output)
        if block_size:
            if not re.search("[a-zA-Z]", block_size[0]):
                return int(block_size[0])
            else:
                return float(utils_misc.normalize_data_size(block_size[0],
                                                         order_magnitude="B"))
        else:
            raise error.TestError("Can not find the block size for the"
                                  " deivce. The output of command"
                                  " is: %s" % output)


    error.context("Check image size in 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)

    data_image = params.get("images").split()[-1]
    data_image_params = params.object_params(data_image)
    data_image_size = data_image_params.get("image_size")
    data_image_size = float(utils_misc.normalize_data_size(data_image_size,
                                                         order_magnitude="B"))
    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})

    block_size_cmd = params["block_size_cmd"]
    block_size_pattern = params.get("block_size_pattern")
    need_reboot = params.get("need_reboot", "no") == "yes"
    accept_ratio = float(params.get("accept_ratio", 0))

    block_size = get_block_size(session, block_size_cmd, block_size_pattern)
    if (block_size > data_image_size
        or block_size < data_image_size * (1 - accept_ratio)):
        raise error.TestError("Please check your system and image size check"
                              " command. The command output is not compatible"
                              " with the image size.")

    if params.get("guest_prepare_cmd"):
        session.cmd(params.get("guest_prepare_cmd"))

    disk_update_cmd = params.get("disk_update_cmd")
    if disk_update_cmd:
        disk_update_cmd = disk_update_cmd.split("::")

    block_size = data_image_size
    disk_change_ratio = params["disk_change_ratio"]
    for index, ratio in enumerate(disk_change_ratio.strip().split()):
        old_block_size = block_size
        block_size = int(int(data_image_size) * float(ratio))

        if block_size == old_block_size:
            logging.warn("Block size is not changed in round %s."
                         " Just skip it" % index)
            continue

        if disk_update_cmd:
            if "DISK_CHANGE_SIZE" in disk_update_cmd[index]:
                disk_unit = params.get("disk_unit", "M")
                size = abs(block_size - old_block_size)
                change_size = utils_misc.normalize_data_size("%sB" % size,
                                                             disk_unit)
                disk_update_cmd[index] = re.sub("DISK_CHANGE_SIZE",
                                                change_size.split(".")[0],
                                                disk_update_cmd[index])

        error.context("Change the disk size to %s" % block_size, logging.info)
        # So far only virtio drivers support online auto block size change in
        # linux guest. So we need manully update the the disk or even reboot
        # guest to get the right block size after change it from monitor.

        # We need shrink the disk in guest first, than in monitor
        if block_size < old_block_size and disk_update_cmd:
            session.cmd(disk_update_cmd[index])
        tmp = vm.monitor.block_resize(data_image_dev, block_size)
        if need_reboot:
            session = vm.reboot(session=session)
        # We need expand disk in monitor first than extend it in guest
        if block_size > old_block_size and disk_update_cmd:
            session.cmd(disk_update_cmd[index])

        current_size = get_block_size(session, block_size_cmd,
                                      block_size_pattern)
        if (current_size > block_size
            or current_size < block_size * (1 - accept_ratio)):
            raise error.TestFail("Guest reported a wrong disk size:\n"
                                 "    reported: %s\n"
                                 "    expect: %s\n" % (current_size,
                                                       block_size))