block_resize.py 5.8 KB
Newer Older
L
Lucas Meneghel Rodrigues 已提交
1 2
import logging
import re
3

Y
Yiqiao Pu 已提交
4
from autotest.client.shared import error
5 6 7 8

from virttest import utils_misc
from virttest import storage
from virttest import data_dir
Y
Yiqiao Pu 已提交
9 10 11


@error.context_aware
12
def run(test, params, env):
Y
Yiqiao Pu 已提交
13 14 15 16 17 18
    """
    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.

L
Lucas Meneghel Rodrigues 已提交
19 20 21
    :param test: QEMU test object
    :param params: Dictionary with the test parameters
    :param env: Dictionary with test environment.
Y
Yiqiao Pu 已提交
22 23 24 25 26 27 28 29 30 31 32 33
    """
    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],
L
Lucas Meneghel Rodrigues 已提交
34
                                                            order_magnitude="B"))
Y
Yiqiao Pu 已提交
35 36 37 38 39
        else:
            raise error.TestError("Can not find the block size for the"
                                  " deivce. The output of command"
                                  " is: %s" % output)

40 41 42 43 44 45 46
    def compare_block_size(session, block_cmd, block_pattern):
        """
        Compare the current block size with the expected size.
        """
        global current_size
        current_size = get_block_size(session,
                                      block_size_cmd, block_size_pattern)
L
Lukáš Doktor 已提交
47 48
        if (current_size <= block_size and
                current_size >= block_size * (1 - accept_ratio)):
49 50 51 52 53 54
            logging.info("Block Resizing Finished !!! \n"
                         "Current size %s is same as the expected %s",
                         current_size, block_size)
            return True
        return

Y
Yiqiao Pu 已提交
55 56 57 58
    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))
L
Lucas Meneghel Rodrigues 已提交
59
    session = vm.wait_for_login(timeout=timeout)
Y
Yiqiao Pu 已提交
60 61 62 63 64

    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,
L
Lucas Meneghel Rodrigues 已提交
65
                                                           order_magnitude="B"))
Y
Yiqiao Pu 已提交
66 67 68 69 70 71 72 73 74 75
    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)
L
Lukáš Doktor 已提交
76 77
    if (block_size > data_image_size or
            block_size < data_image_size * (1 - accept_ratio)):
Y
Yiqiao Pu 已提交
78 79 80 81 82 83 84 85 86 87 88
        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("::")

89 90
    disk_rescan_cmd = params.get("disk_rescan_cmd")

Y
Yiqiao Pu 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    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])
120 121 122

        vm.monitor.block_resize(data_image_dev, block_size)

Y
Yiqiao Pu 已提交
123 124
        if need_reboot:
            session = vm.reboot(session=session)
125 126 127
        elif disk_rescan_cmd:
            session.cmd(disk_rescan_cmd)

Y
Yiqiao Pu 已提交
128 129 130 131
        # 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])

132 133 134 135 136 137
        global current_size
        current_size = 0
        if not utils_misc.wait_for(lambda: compare_block_size
                                   (session, block_size_cmd,
                                    block_size_pattern),
                                   20, 0, 1, "Block Resizing"):
Y
Yiqiao Pu 已提交
138 139 140 141
            raise error.TestFail("Guest reported a wrong disk size:\n"
                                 "    reported: %s\n"
                                 "    expect: %s\n" % (current_size,
                                                       block_size))