block_hotplug.py 6.7 KB
Newer Older
1 2 3 4
import logging
import re

from virttest import error_context
5
from virttest import utils_misc
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
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.
    """
24
    def find_disk(vm, cmd):
25 26 27 28 29
        """
        Find all disks in guest.
        """
        if params.get("os_type") == "linux":
            pattern = params.get("get_disk_pattern", "^/dev/vd[a-z]*$")
30
        elif params.get("os_type") == "windows":
X
Xu Han 已提交
31
            pattern = r"^\d+"
32
            cmd = params.get("get_disk_index", "wmic diskdrive get index")
33 34
        else:
            test.cancel("Unsupported OS type '%s'" % params.get("os_type"))
35

36
        session = vm.wait_for_login(timeout=timeout)
37 38
        output = session.cmd_output_safe(cmd)
        disks = re.findall(pattern, output, re.M)
39
        session.close()
40 41 42 43 44 45 46 47 48
        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

49
    def run_sub_test(params, plug_tag):
50
        """
51 52 53 54 55 56
        Run subtest before/after hotplug/unplug device.

        :param plug_tag: identify when to run subtest,
                         ex, before_hotplug.
        :return: whether vm was successfully shut-down
                 if needed
57
        """
58 59 60 61 62 63 64 65
        sub_type = params.get("sub_type_%s" % plug_tag)
        if sub_type:
            error_context.context(context_msg % (sub_type, plug_tag),
                                  logging.info)
            utils_test.run_virt_sub_test(test, params, env, sub_type)
            if sub_type == "shutdown" and vm.is_dead():
                return True
        return None
66

67
    img_list = params.get("images").split()
68 69
    #sometimes, ppc can't get new plugged disk in 5s, so time to 10s
    pause = float(params.get("virtio_block_pause", 10.0))
70 71 72 73 74 75
    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"
76 77
    disk_index = params.objects("disk_index")
    disk_letter = params.objects("disk_letter")
78 79 80 81

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

X
Xu Han 已提交
82
    for iteration in range(repeat_times):
83
        device_list = []
84
        error_context.context("Hotplug block device (iteration %d)" % iteration,
85 86
                              logging.info)

87 88
        plug_tag = "before_plug"
        run_sub_test(params, plug_tag)
89

X
Xu Han 已提交
90
        for num in range(blk_num):
91 92
            image_name = img_list[num + 1]
            image_params = params.object_params(image_name)
93
            if params.get("need_plug") == "yes":
94
                disks_before_plug = find_disk(vm, get_disk_cmd)
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 120 121 122
                devs = vm.devices.images_define_by_params(image_name,
                                                          image_params, 'disk')
                for dev in devs:
                    ret = vm.devices.simple_hotplug(dev, vm.monitor)
                    if ret[1] is False:
                        test.fail("Failed to hotplug device '%s'."
                                  "Output:\n%s" % (dev, ret[0]))
                plug_disks = utils_misc.wait_for(lambda: get_new_disk(disks_before_plug,
                                                 find_disk(vm, get_disk_cmd)), pause)
                if not plug_disks:
                    test.fail("Failed to hotplug device to guest")
                disk = plug_disks[0]

                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])
                error_context.context("Check block device after hotplug.",
                                      logging.info)
                if params.get("disk_op_cmd"):
                    if params.get("os_type") == "linux":
                        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)
123
                    else:
124
                        test.cancel("Unsupported OS type '%s'" % params.get("os_type"))
125

126 127 128 129 130
                    status, output = session.cmd_status_output(test_cmd,
                                                               timeout=disk_op_timeout)
                    if status:
                        test.fail("Check for block device failed."
                                  "Output: %s" % output)
131

132 133
                devs = [dev for dev in devs if not isinstance(dev, qdevices.QDrive)]
                device_list.extend(devs)
134
            else:
135 136 137
                for device in vm.devices:
                    if device.get_param("id") == img_list[num + 1]:
                        device_list.append(device)
138

139 140 141 142 143 144 145
        plug_tag = "after_plug"
        vm_switched_off = run_sub_test(params, plug_tag)
        if vm_switched_off:
            return

        plug_tag = "before_unplug"
        run_sub_test(params, plug_tag)
146

147 148
        error_context.context("Unplug block device (iteration %d)" % iteration,
                              logging.info)
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        disks_before_unplug = find_disk(vm, get_disk_cmd)
        for device in reversed(device_list):
            ret = vm.devices.simple_unplug(device, vm.monitor)
            if ret[1] is False:
                test.fail("Failed to unplug device '%s'."
                          "Ouptut:\n%s" % (dev, ret[0]))

        unplug_disks = utils_misc.wait_for(lambda: get_new_disk(find_disk(vm, get_disk_cmd),
                                           disks_before_unplug), pause)
        if len(unplug_disks) != blk_num:
            test.fail("Failed to unplug devices from guest, need to unplug: %d,"
                      "actual unplug: %d" % (blk_num, len(unplug_disks)))

        plug_tag = "after_unplug"
        run_sub_test(params, plug_tag)