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

X
Xu Han 已提交
4
from virttest import error_context
5
from virttest import utils_misc
S
Suqin Huang 已提交
6
from virttest import utils_test
7 8
from virttest import storage
from virttest import data_dir
Y
Yiqiao Pu 已提交
9 10


X
Xu Han 已提交
11
@error_context.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
        else:
X
Xu Han 已提交
36 37 38
            test.error("Can not find the block size for the"
                       " deivce. The output of command"
                       " is: %s" % output)
Y
Yiqiao Pu 已提交
39

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
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = float(params.get("login_timeout", 240))
S
Suqin Huang 已提交
58
    driver_name = params.get("driver_name")
59
    session = vm.wait_for_login(timeout=timeout)
Y
Yiqiao Pu 已提交
60

61
    if params.get("os_type") == "windows" and driver_name:
62 63 64
        session = utils_test.qemu.windrv_check_running_verifier(session, vm,
                                                                test, driver_name,
                                                                timeout)
Y
Yiqiao Pu 已提交
65 66 67 68
    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 已提交
69
                                                           order_magnitude="B"))
Y
Yiqiao Pu 已提交
70 71 72 73
    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})

74 75
    drive_path = ""
    if params.get("os_type") == 'linux':
76 77 78 79 80 81 82
        pattern = r"(serial|wwn)=(\w+)"
        match = re.search(pattern, params["blk_extra_params_%s"
                          % data_image], re.M)
        if match:
            drive_id = match.group(2)
        else:
            test.fail("No available tag to get drive id")
83 84
        drive_path = utils_misc.get_linux_drive_path(session, drive_id)
        if not drive_path:
X
Xu Han 已提交
85
            test.error("Failed to get '%s' drive path" % data_image)
86 87

    block_size_cmd = params["block_size_cmd"].format(drive_path)
Y
Yiqiao Pu 已提交
88 89 90 91
    block_size_pattern = params.get("block_size_pattern")
    need_reboot = params.get("need_reboot", "no") == "yes"
    accept_ratio = float(params.get("accept_ratio", 0))

X
Xu Han 已提交
92
    error_context.context("Check image size in guest", logging.info)
Y
Yiqiao Pu 已提交
93
    block_size = get_block_size(session, block_size_cmd, block_size_pattern)
L
Lukáš Doktor 已提交
94 95
    if (block_size > data_image_size or
            block_size < data_image_size * (1 - accept_ratio)):
X
Xu Han 已提交
96 97 98 99
        test.error("Image size from guest and image not match"
                   "Block size get from guest: %s \n"
                   "Image size get from image: %s \n"
                   % (block_size, data_image_size))
Y
Yiqiao Pu 已提交
100 101 102 103

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

S
Suqin Huang 已提交
104
    if params.get("format_disk", "no") == "yes":
X
Xu Han 已提交
105
        error_context.context("Format disk", logging.info)
S
Suqin Huang 已提交
106 107 108
        utils_misc.format_windows_disk(session, params["disk_index"],
                                       mountpoint=params["disk_letter"])

Y
Yiqiao Pu 已提交
109 110 111 112
    disk_update_cmd = params.get("disk_update_cmd")
    if disk_update_cmd:
        disk_update_cmd = disk_update_cmd.split("::")

113 114
    disk_rescan_cmd = params.get("disk_rescan_cmd")

Y
Yiqiao Pu 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    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])

        # 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:
X
Xu Han 已提交
142 143
            error_context.context("Shrink disk size to %s in guest"
                                  % block_size, logging.info)
Y
Yiqiao Pu 已提交
144
            session.cmd(disk_update_cmd[index])
145

X
Xu Han 已提交
146 147
        error_context.context("Change disk size to %s in monitor"
                              % block_size, logging.info)
148 149
        vm.monitor.block_resize(data_image_dev, block_size)

Y
Yiqiao Pu 已提交
150 151
        if need_reboot:
            session = vm.reboot(session=session)
152
        elif disk_rescan_cmd:
X
Xu Han 已提交
153
            error_context.context("Rescan disk", logging.info)
154 155
            session.cmd(disk_rescan_cmd)

Y
Yiqiao Pu 已提交
156 157
        # We need expand disk in monitor first than extend it in guest
        if block_size > old_block_size and disk_update_cmd:
X
Xu Han 已提交
158 159
            error_context.context("Extend disk to %s in guest"
                                  % block_size, logging.info)
Y
Yiqiao Pu 已提交
160 161
            session.cmd(disk_update_cmd[index])

162 163 164 165 166 167
        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"):
X
Xu Han 已提交
168 169 170 171
            test.fail("Block size get from guest is not"
                      "the same as expected \n"
                      "Reported: %s\n"
                      "Expect: %s\n" % (current_size, block_size))