block_hotplug.py 8.7 KB
Newer Older
1 2 3 4 5 6
import logging
import re

from virttest import data_dir
from virttest import storage
from virttest import error_context
7
from virttest import utils_misc
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
from virttest import utils_test
from virttest.qemu_devices import qdevices


@error_context.context_aware
def run(test, params, env):
    """
    Test hotplug of block devices.

    1) Boot up guest with/without block device(s).
    2) Hoplug block device and verify
    3) Do read/write data on hotplug block.
    4) Unplug block device and verify

    :param test:   QEMU test object.
    :param params: Dictionary with the test parameters.
    :param env:    Dictionary with test environment.
    """
    def find_image(image_name):
        """
        Find the path of the iamge.
        """
        image_params = params.object_params(image_name)
        o = storage.get_image_filename(image_params, data_dir.get_data_dir())
        return o

34
    def find_disk(vm, cmd):
35 36 37 38 39
        """
        Find all disks in guest.
        """
        if params.get("os_type") == "linux":
            pattern = params.get("get_disk_pattern", "^/dev/vd[a-z]*$")
40
        elif params.get("os_type") == "windows":
41 42
            pattern = "^\d+"
            cmd = params.get("get_disk_index", "wmic diskdrive get index")
43 44
        else:
            test.cancel("Unsupported OS type '%s'" % params.get("os_type"))
45

46
        session = vm.wait_for_login(timeout=timeout)
47 48
        output = session.cmd_output_safe(cmd)
        disks = re.findall(pattern, output, re.M)
49
        session.close()
50 51 52 53 54 55 56 57 58 59 60 61
        return disks

    def get_new_disk(disk1, disk2):
        """
        Get the different disk between disk1 and disk2.
        """
        disk = list(set(disk2).difference(set(disk1)))
        return disk

    img_list = params.get("images").split()
    img_format_type = params.get("img_format_type", "qcow2")
    pci_type = params.get("pci_type", "virtio-blk-pci")
62 63
    #sometimes, ppc can't get new plugged disk in 5s, so time to 10s
    pause = float(params.get("virtio_block_pause", 10.0))
64 65 66 67 68 69 70
    blk_num = int(params.get("blk_num", 1))
    repeat_times = int(params.get("repeat_times", 3))
    timeout = int(params.get("login_timeout", 360))
    disk_op_timeout = int(params.get("disk_op_timeout", 360))
    get_disk_cmd = params.get("get_disk_cmd")
    context_msg = "Running sub test '%s' %s"
    device_list = []
71 72
    disk_index = params.objects("disk_index")
    disk_letter = params.objects("disk_letter")
73 74 75 76

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

77 78
    for iteration in xrange(repeat_times):
        error_context.context("Hotplug block device (iteration %d)" % iteration,
79 80 81 82 83 84 85 86 87 88 89
                              logging.info)

        sub_type = params.get("sub_type_before_plug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "before hotplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)

        for num in xrange(blk_num):
            device = qdevices.QDevice(pci_type)
            if params.get("need_plug") == "yes":
90 91
                disks_before_plug = find_disk(vm, get_disk_cmd)

92 93 94
                if params.get("need_controller", "no") == "yes":
                    controller_model = params.get("controller_model")
                    controller = qdevices.QDevice(controller_model)
95 96 97 98 99 100 101
                    bus_extra_param = params.get("bus_extra_params_%s" % img_list[num + 1])
                    # TODO:Add iothread support for qdevice
                    if bus_extra_param and "iothread" in bus_extra_param:
                        match = re.search("iothread=(\w+)", bus_extra_param)
                        if match:
                            qdevice_params = {"iothread": match.group(1)}
                            controller.params.update(qdevice_params)
102 103 104 105
                    controller.hotplug(vm.monitor)
                    ver_out = controller.verify_hotplug("", vm.monitor)
                    if not ver_out:
                        err = "%s is not in qtree after hotplug" % controller_model
106
                        test.fail(err)
107 108 109 110 111 112 113 114 115

                drive = qdevices.QRHDrive("block%d" % num)
                drive.set_param("file", find_image(img_list[num + 1]))
                drive.set_param("format", img_format_type)
                drive_id = drive.get_param("id")
                drive.hotplug(vm.monitor)

                device.set_param("drive", drive_id)
                device.set_param("id", "block%d" % num)
116 117 118 119 120
                blk_extra_param = params.get("blk_extra_params_%s" % img_list[num + 1])
                if blk_extra_param and "iothread" in blk_extra_param:
                    match = re.search("iothread=(\w+)", blk_extra_param)
                    if match:
                        device.set_param("iothread", match.group(1))
121 122 123 124
                device.hotplug(vm.monitor)
                ver_out = device.verify_hotplug("", vm.monitor)
                if not ver_out:
                    err = "%s is not in qtree after hotplug" % pci_type
125
                    test.fail(err)
126 127 128 129 130 131 132
                plug_status = utils_misc.wait_for(lambda: len(get_new_disk(disks_before_plug,
                                                  find_disk(vm, get_disk_cmd))) != 0, pause)
                if plug_status:
                    disks_after_plug = find_disk(vm, get_disk_cmd)
                    new_disks = get_new_disk(disks_before_plug, disks_after_plug)
                else:
                    test.fail("Can't get new disks")
133 134 135 136 137
            else:
                if params.get("drive_format") in pci_type:
                    get_disk_cmd += " | egrep -v '^/dev/[hsv]da[0-9]*$'"

                device.set_param("id", img_list[num + 1])
138
                new_disks = find_disk(vm, get_disk_cmd)
139 140 141

            device_list.append(device)
            if not new_disks:
142
                test.fail("Cannot find new disk after hotplug.")
143 144 145 146 147 148

            if params.get("need_plug") == "yes":
                disk = new_disks[0]
            else:
                disk = new_disks[num]

149 150 151 152 153 154
            session = vm.wait_for_login(timeout=timeout)
            if params.get("os_type") == "windows":
                if iteration == 0:
                    error_context.context("Format disk", logging.info)
                    utils_misc.format_windows_disk(session, disk_index[num],
                                                   mountpoint=disk_letter[num])
155 156
            error_context.context("Check block device after hotplug.",
                                  logging.info)
157
            if params.get("disk_op_cmd"):
158
                if params.get("os_type") == "linux":
159 160 161 162 163
                    test_cmd = params.get("disk_op_cmd") % (disk, disk)
                elif params.get("os_type") == "windows":
                    test_cmd = params.get("disk_op_cmd") % (disk_letter[num],
                                                            disk_letter[num])
                    test_cmd = utils_misc.set_winutils_letter(session, test_cmd)
164
                else:
165 166 167 168 169 170 171 172
                    test.cancel("Unsupported OS type '%s'" % params.get("os_type"))

                status, output = session.cmd_status_output(test_cmd,
                                                           timeout=disk_op_timeout)
                if status:
                    test.fail("Check for block device failed "
                              "after hotplug, Output: %r" % output)
            session.close()
173 174 175 176 177 178

        sub_type = params.get("sub_type_after_plug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "after hotplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)
179 180
            if vm.is_dead():
                return
181 182 183 184 185 186 187 188

        sub_type = params.get("sub_type_before_unplug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "before unplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)

        for num in xrange(blk_num):
189
            error_context.context("Unplug block device (iteration %d)" % iteration,
190
                                  logging.info)
191
            disks_before_unplug = find_disk(vm, get_disk_cmd)
192 193
            device_list[num].unplug(vm.monitor)
            device_list[num].verify_unplug("", vm.monitor)
194 195 196 197
            unplug_status = utils_misc.wait_for(lambda: len(get_new_disk(find_disk(vm, get_disk_cmd),
                                                disks_before_unplug)) != 0, pause)
            if not unplug_status:
                test.fail("Failed to unplug disks")
198 199 200 201 202 203

        sub_type = params.get("sub_type_after_unplug")
        if sub_type:
            error_context.context(context_msg % (sub_type, "after unplug"),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)