block_resize.py 7.0 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

from virttest import utils_misc
S
Suqin Huang 已提交
7
from virttest import utils_test
8 9
from virttest import storage
from virttest import data_dir
Y
Yiqiao Pu 已提交
10 11 12


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

41 42 43 44 45 46 47
    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 已提交
48 49
        if (current_size <= block_size and
                current_size >= block_size * (1 - accept_ratio)):
50 51 52 53 54 55
            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 已提交
56 57 58
    vm = env.get_vm(params["main_vm"])
    vm.verify_alive()
    timeout = float(params.get("login_timeout", 240))
S
Suqin Huang 已提交
59
    driver_name = params.get("driver_name")
Y
Yiqiao Pu 已提交
60

S
Suqin Huang 已提交
61 62
    if params.get("os_type") == "windows":
        utils_test.qemu.setup_win_driver_verifier(driver_name, vm, timeout)
S
Suqin Huang 已提交
63

S
Suqin Huang 已提交
64
    session = vm.wait_for_login(timeout=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 76 77 78
    drive_path = ""
    if params.get("os_type") == 'linux':
        drive_id = params["blk_extra_params_%s" % data_image].split("=")[1]
        drive_path = utils_misc.get_linux_drive_path(session, drive_id)
        if not drive_path:
S
Suqin Huang 已提交
79 80
            raise error.TestError("Failed to get '%s' drive path"
                                  % data_image)
81 82

    block_size_cmd = params["block_size_cmd"].format(drive_path)
Y
Yiqiao Pu 已提交
83 84 85 86
    block_size_pattern = params.get("block_size_pattern")
    need_reboot = params.get("need_reboot", "no") == "yes"
    accept_ratio = float(params.get("accept_ratio", 0))

S
Suqin Huang 已提交
87
    error.context("Check image size in guest", logging.info)
Y
Yiqiao Pu 已提交
88
    block_size = get_block_size(session, block_size_cmd, block_size_pattern)
L
Lukáš Doktor 已提交
89 90
    if (block_size > data_image_size or
            block_size < data_image_size * (1 - accept_ratio)):
S
Suqin Huang 已提交
91 92 93 94
        raise error.TestError("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 已提交
95 96 97 98

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

S
Suqin Huang 已提交
99 100 101 102 103
    if params.get("format_disk", "no") == "yes":
        error.context("Format disk", logging.info)
        utils_misc.format_windows_disk(session, params["disk_index"],
                                       mountpoint=params["disk_letter"])

Y
Yiqiao Pu 已提交
104 105 106 107
    disk_update_cmd = params.get("disk_update_cmd")
    if disk_update_cmd:
        disk_update_cmd = disk_update_cmd.split("::")

108 109
    disk_rescan_cmd = params.get("disk_rescan_cmd")

Y
Yiqiao Pu 已提交
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    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:
S
Suqin Huang 已提交
137 138
            error.context("Shrink disk size to %s in guest"
                          % block_size, logging.info)
Y
Yiqiao Pu 已提交
139
            session.cmd(disk_update_cmd[index])
140

S
Suqin Huang 已提交
141 142
        error.context("Change disk size to %s in monitor"
                      % block_size, logging.info)
143 144
        vm.monitor.block_resize(data_image_dev, block_size)

Y
Yiqiao Pu 已提交
145 146
        if need_reboot:
            session = vm.reboot(session=session)
147
        elif disk_rescan_cmd:
S
Suqin Huang 已提交
148
            error.context("Rescan disk", logging.info)
149 150
            session.cmd(disk_rescan_cmd)

Y
Yiqiao Pu 已提交
151 152
        # We need expand disk in monitor first than extend it in guest
        if block_size > old_block_size and disk_update_cmd:
S
Suqin Huang 已提交
153 154
            error.context("Extend disk to %s in guest"
                          % block_size, logging.info)
Y
Yiqiao Pu 已提交
155 156
            session.cmd(disk_update_cmd[index])

157 158 159 160 161 162
        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"):
S
Suqin Huang 已提交
163 164 165 166 167
            raise error.TestFail("Block size get from guest is not"
                                 "the same as expected \n"
                                 "Reported: %s\n"
                                 "Expect: %s\n" % (current_size,
                                                   block_size))