def verify_qtree(params, info_qtree, info_block, qdev): """ Verifies that params, info qtree, info block and /proc/scsi/ matches :param params: Dictionary with the test parameters :type params: virttest.utils_params.Params :param info_qtree: Output of "info qtree" monitor command :type info_qtree: string :param info_block: Output of "info block" monitor command :type info_block: dict of dicts :param qdev: qcontainer representation :type qdev: virttest.qemu_devices.qcontainer.DevContainer """ err = 0 qtree = qemu_qtree.QtreeContainer() qtree.parse_info_qtree(info_qtree) disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes()) (tmp1, tmp2) = disks.parse_info_block(info_block) err += tmp1 + tmp2 err += disks.generate_params() err += disks.check_disk_params(params) if err: logging.error("info qtree:\n%s", info_qtree) logging.error("info block:\n%s", info_block) logging.error(qdev.str_bus_long()) test.fail("%s errors occurred while verifying" " qtree vs. params" % err)
def setUp(self): # Get rid of logging errors def dumm(*args, **kvargs): pass self.god = mock.mock_god(ut=self) self.god.stub_with(qemu_qtree.logging, 'error', dumm) info = qtree_header info = combine(info, dev_ide_disk, 1) info = combine(info, dev_usb_disk, 1) info = combine(info, dev_dummy_mmio, 1) info += "\n" self.no_disks = 2 self.qtree = qemu_qtree.QtreeContainer() self.qtree.parse_info_qtree(info) self.disks = qemu_qtree.QtreeDisksContainer(self.qtree.get_nodes())
logging.info("Hard drive count check") _, f_fail = check_num("images", "block", image_name) n_fail.extend(f_fail) logging.info("NIC count check") _, f_fail = check_num("nics", "network", "model=") n_fail.extend(f_fail) logging.info("NICs model check") f_fail = chk_fmt_model("nics", "nic_model", "network", "model=(.*),") n_fail.extend(f_fail) if qtree is not None: logging.info("Images params check") logging.debug("Found devices: %s", params.objects('images')) qdisks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes()) _ = sum(qdisks.parse_info_block(vm.monitor.info_block())) _ += qdisks.generate_params() _ += qdisks.check_disk_params(params) if _: _ = ("Images check failed with %s errors, check the log for " "details" % _) logging.error(_) n_fail.append(_) else: logging.info("Images check param skipped (qemu monitor doesn't " "support 'info qtree')") logging.info("Network card MAC check") o = "" try:
def run(test, params, env): """ Test multi disk suport of guest, this case will: 1) Create disks image in configuration file. 2) Start the guest with those disks. 3) Checks qtree vs. test params. (Optional) 4) Create partition on those disks. 5) Get disk dev filenames in guest. 6) Format those disks in guest. 7) Copy file into / out of those disks. 8) Compare the original file and the copied file using md5 or fc comand. 9) Repeat steps 3-5 if needed. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _add_param(name, value): """ Converts name+value to stg_params string """ if value: value = re.sub(' ', '\\ ', value) return " %s:%s " % (name, value) else: return '' def _do_post_cmd(session): cmd = params.get("post_cmd") if cmd: session.cmd_status_output(cmd) session.close() error_context.context("Parsing test configuration", logging.info) stg_image_num = 0 stg_params = params.get("stg_params", "") # Compatibility stg_params += _add_param("image_size", params.get("stg_image_size")) stg_params += _add_param("image_format", params.get("stg_image_format")) stg_params += _add_param("image_boot", params.get("stg_image_boot", "no")) stg_params += _add_param("drive_format", params.get("stg_drive_format")) stg_params += _add_param("drive_cache", params.get("stg_drive_cache")) if params.get("stg_assign_index") != "no": # Assume 0 and 1 are already occupied (hd0 and cdrom) stg_params += _add_param("drive_index", 'range(2,n)') param_matrix = {} stg_params = stg_params.split(' ') i = 0 while i < len(stg_params) - 1: if not stg_params[i].strip(): i += 1 continue if stg_params[i][-1] == '\\': stg_params[i] = '%s %s' % (stg_params[i][:-1], stg_params.pop(i + 1)) i += 1 rerange = [] has_name = False for i in range(len(stg_params)): if not stg_params[i].strip(): continue (cmd, parm) = stg_params[i].split(':', 1) if cmd == "image_name": has_name = True if _RE_RANGE1.match(parm): parm = _range(parm) if parm is False: test.error("Incorrect cfg: stg_params %s looks " "like range(..) but doesn't contain " "numbers." % cmd) param_matrix[cmd] = parm if type(parm) is str: # When we know the stg_image_num, substitute it. rerange.append(cmd) continue else: # ',' separated list of values parm = parm.split(',') j = 0 while j < len(parm) - 1: if parm[j][-1] == '\\': parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1)) j += 1 param_matrix[cmd] = parm stg_image_num = max(stg_image_num, len(parm)) stg_image_num = int(params.get('stg_image_num', stg_image_num)) for cmd in rerange: param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num) # param_table* are for pretty print of param_matrix param_table = [] param_table_header = ['name'] if not has_name: param_table_header.append('image_name') for _ in param_matrix: param_table_header.append(_) stg_image_name = params.get('stg_image_name', 'images/%s') for i in range(stg_image_num): name = "stg%d" % i params['images'] += " %s" % name param_table.append([]) param_table[-1].append(name) if not has_name: params["image_name_%s" % name] = stg_image_name % name param_table[-1].append(params.get("image_name_%s" % name)) for parm in param_matrix.items(): params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])]) param_table[-1].append(params.get('%s_%s' % (parm[0], name))) if params.get("multi_disk_params_only") == 'yes': # Only print the test param_matrix and finish logging.info('Newly added disks:\n%s', astring.tabular_output(param_table, param_table_header)) return # Always recreate VMs and disks error_context.context("Start the guest with new disks", logging.info) for vm_name in params.objects("vms"): vm_params = params.object_params(vm_name) env_process.process_images(env_process.preprocess_image, test, vm_params) error_context.context("Start the guest with those disks", logging.info) vm = env.get_vm(params["main_vm"]) vm.create(timeout=max(10, stg_image_num), params=params) login_timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=login_timeout) n_repeat = int(params.get("n_repeat", "1")) file_system = [_.strip() for _ in params["file_system"].split()] cmd_timeout = float(params.get("cmd_timeout", 360)) black_list = params["black_list"].split() drive_letters = int(params.get("drive_letters", "26")) stg_image_size = params["stg_image_size"] dd_test = params.get("dd_test", "no") pre_command = params.get("pre_command", "") labeltype = params.get("labeltype", "gpt") iozone_target_num = int(params.get('iozone_target_num', '5')) iozone_options = params.get('iozone_options') iozone_timeout = float(params.get('iozone_timeout', '7200')) have_qtree = True out = vm.monitor.human_monitor_cmd("info qtree", debug=False) if "unknown command" in str(out): have_qtree = False if (params.get("check_guest_proc_scsi") == "yes") and have_qtree: error_context.context("Verifying qtree vs. test params") err = 0 qtree = qemu_qtree.QtreeContainer() qtree.parse_info_qtree(vm.monitor.info('qtree')) disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes()) (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block()) err += tmp1 + tmp2 err += disks.generate_params() err += disks.check_disk_params(params) (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi( session.cmd_output('cat /proc/scsi/scsi')) err += tmp1 + tmp2 if err: test.fail("%s errors occurred while verifying qtree vs." " params" % err) if params.get('multi_disk_only_qtree') == 'yes': return try: err_msg = "Set disks num: %d" % stg_image_num err_msg += ", Get disks num in guest: %d" ostype = params["os_type"] if ostype == "windows": error_context.context( "Get windows disk index that to " "be formatted", logging.info) disks = utils_disk.get_windows_disks_index(session, stg_image_size) if len(disks) < stg_image_num: test.fail("Fail to list all the volumes" ", %s" % err_msg % len(disks)) if len(disks) > drive_letters: black_list.extend(utils_misc.get_winutils_vol(session)) disks = random.sample(disks, drive_letters - len(black_list)) error_context.context( "Clear readonly for all disks and online " "them in windows guest.", logging.info) if not utils_disk.update_windows_disk_attributes(session, disks): test.fail("Failed to update windows disk attributes.") dd_test = "no" else: error_context.context("Get linux disk that to be " "formatted", logging.info) disks = sorted(utils_disk.get_linux_disks(session).keys()) if len(disks) < stg_image_num: test.fail("Fail to list all the volumes" ", %s" % err_msg % len(disks)) except Exception: _do_post_cmd(session) raise try: if iozone_options: iozone = generate_instance(params, session, 'iozone') random.shuffle(disks) for i in range(n_repeat): logging.info("iterations: %s", (i + 1)) for n, disk in enumerate(disks): error_context.context("Format disk in guest: '%s'" % disk, logging.info) # Random select one file system from file_system index = random.randint(0, (len(file_system) - 1)) fstype = file_system[index].strip() partitions = utils_disk.configure_empty_disk( session, disk, stg_image_size, ostype, fstype=fstype, labeltype=labeltype) if not partitions: test.fail("Fail to format disks.") cmd_list = params["cmd_list"] for partition in partitions: orig_partition = partition if "/" not in partition: partition += ":" else: partition = partition.split("/")[-1] error_context.context( "Copy file into / out of partition:" " %s..." % partition, logging.info) for cmd_l in cmd_list.split(): cmd = params.get(cmd_l) if cmd: session.cmd(cmd % partition, timeout=cmd_timeout) cmd = params["compare_command"] key_word = params["check_result_key_word"] output = session.cmd_output(cmd) if iozone_options and n < iozone_target_num: iozone.run(iozone_options.format(orig_partition), iozone_timeout) if key_word not in output: test.fail("Files on guest os root fs and disk differ") if dd_test != "no": error_context.context( "dd test on partition: %s..." % partition, logging.info) status, output = session.cmd_status_output( dd_test % (partition, partition), timeout=cmd_timeout) if status != 0: test.fail("dd test fail: %s" % output) # When multiple SCSI disks are simulated by scsi_debug, # they could be viewed as multiple paths to the same # storage device. So need umount partition before operate # next disk, in order to avoid corrupting the filesystem # (xfs integrity checks error). if ostype == "linux" and "scsi_debug add_host" in pre_command: status, output = session.cmd_status_output( "umount /dev/%s" % partition, timeout=cmd_timeout) if status != 0: test.fail("Failed to umount partition '%s': %s" % (partition, output)) need_reboot = params.get("need_reboot", "no") need_shutdown = params.get("need_shutdown", "no") if need_reboot == "yes": error_context.context("Rebooting guest ...", logging.info) session = vm.reboot(session=session, timeout=login_timeout) if need_shutdown == "yes": error_context.context("Shutting down guest ...", logging.info) vm.graceful_shutdown(timeout=login_timeout) if vm.is_alive(): test.fail("Fail to shut down guest.") error_context.context("Start the guest again.", logging.info) vm = env.get_vm(params["main_vm"]) vm.create(params=params) session = vm.wait_for_login(timeout=login_timeout) error_context.context("Delete partitions in guest.", logging.info) for disk in disks: utils_disk.clean_partition(session, disk, ostype) finally: if iozone_options: iozone.clean() _do_post_cmd(session)
def run(test, params, env): """ Check physical resources assigned to KVM virtual machines: 1) Log into the guest 2) Verify whether cpu counts ,memory size, nics' model, count and drives' format & count, drive_serial, UUID reported by the guest OS matches what has been assigned to the VM (qemu command line) 3) Verify all MAC addresses for guest NICs :param test: QEMU test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ # Define a function for checking number of hard drivers & NICs def check_num(devices, info_cmd, check_str): f_fail = [] expected_num = params.objects(devices).__len__() o = "" try: o = vm.monitor.human_monitor_cmd("info %s " % info_cmd) except qemu_monitor.MonitorError as e: fail_log = str(e) + "\n" fail_log += "info/query monitor command failed (%s)" % info_cmd f_fail.append(fail_log) logging.error(fail_log) ovmf_fd_num = o.count('%s.fd' % check_str) # Exclude ovmf fd drive actual_num = o.count(check_str) - ovmf_fd_num if expected_num != actual_num: fail_log = "%s number mismatch:\n" % str(devices) fail_log += " Assigned to VM: %d\n" % expected_num fail_log += " Reported by OS: %d" % actual_num f_fail.append(fail_log) logging.error(fail_log) return f_fail # Define a function for checking hard drives & NICs' model def chk_fmt_model(device, fmt_model, info_cmd, regexp): f_fail = [] devices = params.objects(device) for chk_device in devices: expected = params.object_params(chk_device).get(fmt_model) if not expected: expected = "rtl8139" o = "" try: o = vm.monitor.human_monitor_cmd("info %s" % info_cmd) except qemu_monitor.MonitorError as e: fail_log = str(e) + "\n" fail_log += "info/query monitor command failed (%s)" % info_cmd f_fail.append(fail_log) logging.error(fail_log) device_found = re.findall(regexp, o) logging.debug("Found devices: %s", device_found) found = False for fm in device_found: if expected in fm: found = True if not found: fail_log = "%s model mismatch:\n" % str(device) fail_log += " Assigned to VM: %s\n" % expected fail_log += " Reported by OS: %s" % device_found f_fail.append(fail_log) logging.error(fail_log) return f_fail # Define a function to verify UUID & Serial number def verify_device(expect, name, verify_cmd): f_fail = [] if verify_cmd: actual = session.cmd_output(verify_cmd) if not re.findall(expect, actual, re.I): fail_log = "%s mismatch:\n" % name fail_log += " Assigned to VM: %s\n" % expect.upper() fail_log += " Reported by OS: %s" % actual f_fail.append(fail_log) logging.error(fail_log) return f_fail def get_cpu_number(chk_type, chk_timeout): """ Get cpu sockets/cores/threads number. :param chk_type: Should be one of 'sockets', 'cores', 'threads'. :param chk_timeout: timeout of running chk_cmd. :return: Actual number of guest cpu number. """ chk_str = params["mem_chk_re_str"] chk_cmd = params.get("cpu_%s_chk_cmd" % chk_type) if chk_cmd is None: fail_log = "Unknown cpu number checking type: '%s'" % chk_type logging.error(fail_log) return -1 s, output = session.cmd_status_output(chk_cmd, timeout=chk_timeout) num = re.findall(chk_str, output) if s != 0 or not num: fail_log = "Failed to get guest %s number, " % chk_type fail_log += "guest output: '%s'" % output logging.error(fail_log) return -2 logging.info("CPU %s number: %d", chk_type.capitalize(), int(num[-1])) return int(num[-1]) def check_cpu_number(chk_type, actual_n, expected_n): """ Checking cpu sockets/cores/threads number. :param chk_type: Should be one of 'sockets', 'cores', 'threads'. :param actual_n: Actual number of guest cpu number. :param expected_n: Expected number of guest cpu number. :return: a list that contains fail report. """ f_fail = [] if actual_n == -1: fail_log = "Unknown cpu number checking type: '%s'" % chk_type logging.error(fail_log) f_fail.append(fail_log) return f_fail if actual_n == -2: fail_log = "Failed to get guest %s number." % chk_type logging.error(fail_log) f_fail.append(fail_log) return f_fail logging.info("CPU %s number check", chk_type.capitalize()) if actual_n != expected_n: fail_log = "%s output mismatch:\n" % chk_type.capitalize() fail_log += " Assigned to VM: '%s'\n" % expected_n fail_log += " Reported by OS: '%s'" % actual_n f_fail.append(fail_log) logging.error(fail_log) return f_fail logging.debug("%s check pass. Expected: '%s', Actual: '%s'", chk_type.capitalize(), expected_n, actual_n) return f_fail def verify_machine_type(): f_fail = [] cmd = params.get("check_machine_type_cmd") fail_log = "" if cmd is None: return f_fail status, actual_mtype = session.cmd_status_output(cmd) if status != 0: test.error("Failed to get machine type from vm") machine_type_cmd = "%s -M ?" % utils_misc.get_qemu_binary(params) machine_types = process.system_output(machine_type_cmd, ignore_status=True).decode() machine_types = machine_types.split(':')[-1] machine_type_map = {} for machine_type in machine_types.splitlines(): if not machine_type: continue type_pair = re.findall(r"([\w\.-]+)\s+([^(]+).*", machine_type) if len(type_pair) == 1 and len(type_pair[0]) == 2: machine_type_map[type_pair[0][0]] = type_pair[0][1] else: logging.warn("Unexpect output from qemu-kvm -M " "?: '%s'", machine_type) try: expect_mtype = machine_type_map[params['machine_type']].strip() except KeyError: logging.warn( "Can not find machine type '%s' from qemu-kvm -M ?" " output. Skip this test.", params['machine_type']) return f_fail if expect_mtype not in actual_mtype: fail_log += " Assigned to VM: '%s' \n" % expect_mtype fail_log += " Reported by OS: '%s'" % actual_mtype f_fail.append(fail_log) logging.error(fail_log) else: logging.info("MachineType check pass. Expected: %s, Actual: %s", expect_mtype, actual_mtype) return f_fail if params.get("catch_serial_cmd") is not None: length = int(params.get("length", "20")) id_leng = random.randint(0, length) drive_serial = "" convert_str = "!\"#$%&\'()*+./:;<=>?@[\\]^`{|}~" drive_serial = utils_misc.generate_random_string( id_leng, ignore_str=",", convert_str=convert_str) params["drive_serial"] = drive_serial params["start_vm"] = "yes" vm = params["main_vm"] vm_params = params.object_params(vm) env_process.preprocess_vm(test, vm_params, env, vm) vm = env.get_vm(vm) else: vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) chk_timeout = int(params.get("chk_timeout", 240)) error_context.context("Login to the guest", logging.info) session = vm.wait_for_login(timeout=timeout) qtree = qemu_qtree.QtreeContainer() try: qtree.parse_info_qtree(vm.monitor.info('qtree')) except AttributeError: # monitor doesn't support info qtree qtree = None logging.info("Starting physical resources check test") logging.info("Values assigned to VM are the values we expect " "to see reported by the Operating System") # Define a failure counter, as we want to check all physical # resources to know which checks passed and which ones failed n_fail = [] # We will check HDs with the image name image_name = storage.get_image_filename(params, data_dir.get_data_dir()) # Check cpu count error_context.context("CPU count check", logging.info) actual_cpu_nr = vm.get_cpu_count() cpu_cores_num = get_cpu_number("cores", chk_timeout) cpu_lp_num = get_cpu_number("logical_processors", chk_timeout) cpu_threads_num = get_cpu_number("threads", chk_timeout) cpu_sockets_num = get_cpu_number("sockets", chk_timeout) if ((params.get("os_type") == 'windows') and cpu_cores_num > 0 and cpu_lp_num > 0 and cpu_sockets_num > 0): actual_cpu_nr = cpu_lp_num * cpu_sockets_num cpu_threads_num = cpu_lp_num / cpu_cores_num if vm.cpuinfo.smp != actual_cpu_nr: fail_log = "CPU count mismatch:\n" fail_log += " Assigned to VM: %s \n" % vm.cpuinfo.smp fail_log += " Reported by OS: %s" % actual_cpu_nr n_fail.append(fail_log) logging.error(fail_log) n_fail.extend(check_cpu_number("cores", cpu_cores_num, vm.cpuinfo.cores)) n_fail.extend( check_cpu_number("threads", cpu_threads_num, vm.cpuinfo.threads)) n_fail.extend( check_cpu_number("sockets", cpu_sockets_num, vm.cpuinfo.sockets)) # Check the cpu vendor_id expected_vendor_id = params.get("cpu_model_vendor") cpu_vendor_id_chk_cmd = params.get("cpu_vendor_id_chk_cmd") if expected_vendor_id and cpu_vendor_id_chk_cmd: output = session.cmd_output(cpu_vendor_id_chk_cmd) if expected_vendor_id not in output: fail_log = "CPU vendor id check failed.\n" fail_log += " Assigned to VM: '%s'\n" % expected_vendor_id fail_log += " Reported by OS: '%s'" % output n_fail.append(fail_log) logging.error(fail_log) # Check memory size error_context.context("Memory size check", logging.info) expected_mem = int(params["mem"]) actual_mem = vm.get_memory_size() if actual_mem != expected_mem: fail_log = "Memory size mismatch:\n" fail_log += " Assigned to VM: %s\n" % expected_mem fail_log += " Reported by OS: %s\n" % actual_mem n_fail.append(fail_log) logging.error(fail_log) error_context.context("Hard drive count check", logging.info) f_fail = check_num("images", "block", image_name) n_fail.extend(f_fail) error_context.context("NIC count check", logging.info) f_fail = check_num("nics", "network", "model=") n_fail.extend(f_fail) error_context.context("NICs model check", logging.info) f_fail = chk_fmt_model("nics", "nic_model", "network", "model=(.*),") n_fail.extend(f_fail) if qtree is not None: error_context.context("Images params check", logging.info) logging.debug("Found devices: %s", params.objects('images')) qdisks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes()) disk_errors = sum(qdisks.parse_info_block(vm.monitor.info_block())) disk_errors += qdisks.generate_params() disk_errors += qdisks.check_disk_params(params) if disk_errors: disk_errors = ("Images check failed with %s errors, " "check the log for details" % disk_errors) logging.error(disk_errors) n_fail.append("\n".join(qdisks.errors)) else: logging.info("Images check param skipped (qemu monitor doesn't " "support 'info qtree')") error_context.context("Network card MAC check", logging.info) o = "" try: o = vm.monitor.human_monitor_cmd("info network") except qemu_monitor.MonitorError as e: fail_log = str(e) + "\n" fail_log += "info/query monitor command failed (network)" n_fail.append(fail_log) logging.error(fail_log) found_mac_addresses = re.findall(r"macaddr=(\S+)", o) logging.debug("Found MAC adresses: %s", found_mac_addresses) num_nics = len(params.objects("nics")) for nic_index in range(num_nics): mac = vm.get_mac_address(nic_index) if mac.lower() not in found_mac_addresses: fail_log = "MAC address mismatch:\n" fail_log += " Assigned to VM (not found): %s" % mac n_fail.append(fail_log) logging.error(fail_log) error_context.context("UUID check", logging.info) if vm.get_uuid(): f_fail = verify_device(vm.get_uuid(), "UUID", params.get("catch_uuid_cmd")) n_fail.extend(f_fail) error_context.context("Hard Disk serial number check", logging.info) catch_serial_cmd = params.get("catch_serial_cmd") f_fail = verify_device(params.get("drive_serial"), "Serial", catch_serial_cmd) n_fail.extend(f_fail) error_context.context("Machine Type Check", logging.info) f_fail = verify_machine_type() n_fail.extend(f_fail) if n_fail: session.close() test.fail("Physical resources check test " "reported %s failures:\n%s" % (len(n_fail), "\n".join(n_fail))) session.close()
def run_multi_disk(test, params, env): """ Test multi disk suport of guest, this case will: 1) Create disks image in configuration file. 2) Start the guest with those disks. 3) Checks qtree vs. test params. 4) Format those disks. 5) Copy file into / out of those disks. 6) Compare the original file and the copied file using md5 or fc comand. 7) Repeat steps 3-5 if needed. @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ def _add_param(name, value): """ Converts name+value to stg_params string """ if value: value = re.sub(' ', '\\ ', value) return " %s:%s " % (name, value) else: return '' stg_image_num = 0 stg_params = params.get("stg_params", "") # Compatibility stg_params += _add_param("image_size", params.get("stg_image_size")) stg_params += _add_param("image_format", params.get("stg_image_format")) stg_params += _add_param("image_boot", params.get("stg_image_boot", "no")) stg_params += _add_param("drive_format", params.get("stg_drive_format")) if params.get("stg_assign_index") != "no": # Assume 0 and 1 are already occupied (hd0 and cdrom) stg_params += _add_param("drive_index", 'range(2,n)') param_matrix = {} stg_params = stg_params.split(' ') i = 0 while i < len(stg_params) - 1: if not stg_params[i].strip(): i += 1 continue if stg_params[i][-1] == '\\': stg_params[i] = '%s %s' % (stg_params[i][:-1], stg_params.pop(i + 1)) i += 1 rerange = [] has_name = False for i in xrange(len(stg_params)): if not stg_params[i].strip(): continue (cmd, parm) = stg_params[i].split(':', 1) if cmd == "image_name": has_name = True if _RE_RANGE1.match(parm): parm = _range(parm) if parm == False: raise error.TestError("Incorrect cfg: stg_params %s looks " "like range(..) but doesn't contain " "numbers." % cmd) param_matrix[cmd] = parm if type(parm) is str: # When we know the stg_image_num, substitute it. rerange.append(cmd) continue else: # ',' separated list of values parm = parm.split(',') j = 0 while j < len(parm) - 1: if parm[j][-1] == '\\': parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1)) j += 1 param_matrix[cmd] = parm stg_image_num = max(stg_image_num, len(parm)) stg_image_num = int(params.get('stg_image_num', stg_image_num)) for cmd in rerange: param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num) # param_table* are for pretty print of param_matrix param_table = [] param_table_header = ['name'] if not has_name: param_table_header.append('image_name') for _ in param_matrix: param_table_header.append(_) stg_image_name = params.get('stg_image_name', '%s') for i in xrange(stg_image_num): name = "stg%d" % i params['images'] += " %s" % name param_table.append([]) param_table[-1].append(name) if not has_name: params["image_name_%s" % name] = stg_image_name % name param_table[-1].append(params.get("image_name_%s" % name)) for parm in param_matrix.iteritems(): params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])]) param_table[-1].append(params.get('%s_%s' % (parm[0], name))) if params.get("multi_disk_params_only") == 'yes': # Only print the test param_matrix and finish logging.info('Newly added disks:\n%s', utils.matrix_to_string(param_table, param_table_header)) return # Always recreate VMs and disks for vm_name in params.objects("vms"): vm_params = params.object_params(vm_name) for image_name in vm_params.objects("images"): image_params = vm_params.object_params(image_name) env_process.preprocess_image(test, image_params, image_name) vm = env.get_vm(params["main_vm"]) vm.create(timeout=max(10, stg_image_num), params=params) session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) images = params.get("images").split() n_repeat = int(params.get("n_repeat", "1")) image_num = len(images) file_system = params.get("file_system").split() fs_num = len(file_system) cmd_timeout = float(params.get("cmd_timeout", 360)) re_str = params.get("re_str") black_list = params.get("black_list").split() error.context("verifying qtree vs. test params") err = 0 qtree = qemu_qtree.QtreeContainer() qtree.parse_info_qtree(vm.monitor.info('qtree')) disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes()) (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info('block')) err += tmp1 + tmp2 err += disks.generate_params() err += disks.check_disk_params(params) (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi( session.cmd_output('cat /proc/scsi/scsi')) err += tmp1 + tmp2 if err: raise error.TestFail("%s errors occurred while verifying qtree vs. " "params" % err) if params.get('multi_disk_only_qtree') == 'yes': return try: if params.get("clean_cmd"): cmd = params.get("clean_cmd") session.cmd_status_output(cmd) if params.get("pre_cmd"): cmd = params.get("pre_cmd") error.context("creating partition on test disk") session.cmd(cmd, timeout=cmd_timeout) cmd = params.get("list_volume_command") output = session.cmd_output(cmd, timeout=cmd_timeout) disks = re.findall(re_str, output) disks = map(string.strip, disks) disks.sort() logging.debug("Volume list that meets regular expressions: '%s'", disks) if len(disks) < image_num: raise error.TestFail("Fail to list all the volumes!") if params.get("os_type") == "linux": df_output = session.cmd_output("df") li = re.findall("^/dev/(.*?)[ \d]", df_output, re.M) if li: black_list.extend(li) exclude_list = [d for d in disks if d in black_list] f = lambda d: logging.info("No need to check volume '%s'", d) map(f, exclude_list) disks = [d for d in disks if d not in exclude_list] for i in range(n_repeat): logging.info("iterations: %s", (i + 1)) for disk in disks: disk = disk.strip() logging.info("Format disk: %s...", disk) index = random.randint(0, fs_num - 1) # Random select one file system from file_system fs = file_system[index].strip() cmd = params.get("format_command") % (fs, disk) error.context("formatting test disk") session.cmd(cmd, timeout=cmd_timeout) if params.get("mount_command"): cmd = params.get("mount_command") % (disk, disk, disk) session.cmd(cmd, timeout=cmd_timeout) for disk in disks: disk = disk.strip() logging.info("Performing I/O on disk: %s...", disk) cmd_list = params.get("cmd_list").split() for cmd_l in cmd_list: if params.get(cmd_l): cmd = params.get(cmd_l) % disk session.cmd(cmd, timeout=cmd_timeout) cmd = params.get("compare_command") output = session.cmd_output(cmd) key_word = params.get("check_result_key_word") if key_word and key_word in output: logging.debug("Guest's virtual disk %s works fine", disk) elif key_word: raise error.TestFail("Files on guest os root fs and disk " "differ") else: raise error.TestError("Param check_result_key_word was not " "specified! Please check your config") if params.get("umount_command"): cmd = params.get("show_mount_cmd") output = session.cmd_output(cmd) disks = re.findall(re_str, output) disks.sort() for disk in disks: disk = disk.strip() cmd = params.get("umount_command") % (disk, disk) error.context("unmounting test disk") session.cmd(cmd) finally: if params.get("post_cmd"): cmd = params.get("post_cmd") session.cmd(cmd) session.close()
def run(test, params, env): """ Test multi disk suport of guest, this case will: 1) Create disks image in configuration file. 2) Start the guest with those disks. 3) Checks qtree vs. test params. (Optional) 4) Create partition on those disks. 5) Get disk dev filenames in guest. 6) Format those disks in guest. 7) Copy file into / out of those disks. 8) Compare the original file and the copied file using md5 or fc comand. 9) Repeat steps 3-5 if needed. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _add_param(name, value): """ Converts name+value to stg_params string """ if value: value = re.sub(' ', '\\ ', value) return " %s:%s " % (name, value) else: return '' def _do_post_cmd(session): cmd = params.get("post_cmd") if cmd: session.cmd_status_output(cmd) session.close() def _get_disk_index(session, image_size, disk_indexs): list_disk_cmd = "echo list disk > disk && " list_disk_cmd += "echo exit >> disk && diskpart /s disk" disks = session.cmd_output(list_disk_cmd) size_type = image_size[-1] + "B" disk_size = "" if size_type == "MB": disk_size = image_size[:-1] + " MB" elif size_type == "GB" and int(image_size[:-1]) < 8: disk_size = str(int(image_size[:-1]) * 1024) + " MB" else: disk_size = image_size[:-1] + " GB" regex_str = 'Disk (\d+).*?%s.*?%s' % (disk_size, disk_size) for disk in disks.splitlines(): if disk.startswith(" Disk"): o = re.findall(regex_str, disk, re.I | re.M) if o: disk_indexs.append(o[0]) error.context("Parsing test configuration", logging.info) stg_image_num = 0 stg_params = params.get("stg_params", "") # Compatibility stg_params += _add_param("image_size", params.get("stg_image_size")) stg_params += _add_param("image_format", params.get("stg_image_format")) stg_params += _add_param("image_boot", params.get("stg_image_boot", "no")) stg_params += _add_param("drive_format", params.get("stg_drive_format")) stg_params += _add_param("drive_cache", params.get("stg_drive_cache")) if params.get("stg_assign_index") != "no": # Assume 0 and 1 are already occupied (hd0 and cdrom) stg_params += _add_param("drive_index", 'range(2,n)') param_matrix = {} stg_params = stg_params.split(' ') i = 0 while i < len(stg_params) - 1: if not stg_params[i].strip(): i += 1 continue if stg_params[i][-1] == '\\': stg_params[i] = '%s %s' % (stg_params[i][:-1], stg_params.pop(i + 1)) i += 1 rerange = [] has_name = False for i in xrange(len(stg_params)): if not stg_params[i].strip(): continue (cmd, parm) = stg_params[i].split(':', 1) if cmd == "image_name": has_name = True if _RE_RANGE1.match(parm): parm = _range(parm) if parm is False: raise error.TestError("Incorrect cfg: stg_params %s looks " "like range(..) but doesn't contain " "numbers." % cmd) param_matrix[cmd] = parm if type(parm) is str: # When we know the stg_image_num, substitute it. rerange.append(cmd) continue else: # ',' separated list of values parm = parm.split(',') j = 0 while j < len(parm) - 1: if parm[j][-1] == '\\': parm[j] = '%s,%s' % (parm[j][:-1], parm.pop(j + 1)) j += 1 param_matrix[cmd] = parm stg_image_num = max(stg_image_num, len(parm)) stg_image_num = int(params.get('stg_image_num', stg_image_num)) for cmd in rerange: param_matrix[cmd] = _range(param_matrix[cmd], stg_image_num) # param_table* are for pretty print of param_matrix param_table = [] param_table_header = ['name'] if not has_name: param_table_header.append('image_name') for _ in param_matrix: param_table_header.append(_) stg_image_name = params.get('stg_image_name', 'images/%s') for i in xrange(stg_image_num): name = "stg%d" % i params['images'] += " %s" % name param_table.append([]) param_table[-1].append(name) if not has_name: params["image_name_%s" % name] = stg_image_name % name param_table[-1].append(params.get("image_name_%s" % name)) for parm in param_matrix.iteritems(): params['%s_%s' % (parm[0], name)] = str(parm[1][i % len(parm[1])]) param_table[-1].append(params.get('%s_%s' % (parm[0], name))) if params.get("multi_disk_params_only") == 'yes': # Only print the test param_matrix and finish logging.info('Newly added disks:\n%s', utils.matrix_to_string(param_table, param_table_header)) return # Always recreate VMs and disks error.context("Start the guest with new disks", logging.info) for vm_name in params.objects("vms"): vm_params = params.object_params(vm_name) env_process.process_images(env_process.preprocess_image, test, vm_params) error.context("Start the guest with those disks", logging.info) vm = env.get_vm(params["main_vm"]) vm.create(timeout=max(10, stg_image_num), params=params) session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) n_repeat = int(params.get("n_repeat", "1")) file_system = [_.strip() for _ in params.get("file_system").split()] cmd_timeout = float(params.get("cmd_timeout", 360)) re_str = params["re_str"] black_list = params["black_list"].split() os_type = params["os_type"] stg_image_size = params.get("stg_image_size") disk_indexs = [] have_qtree = True out = vm.monitor.human_monitor_cmd("info qtree", debug=False) if "unknown command" in str(out): have_qtree = False if (params.get("check_guest_proc_scsi") == "yes") and have_qtree: error.context("Verifying qtree vs. test params") err = 0 qtree = qemu_qtree.QtreeContainer() qtree.parse_info_qtree(vm.monitor.info('qtree')) disks = qemu_qtree.QtreeDisksContainer(qtree.get_nodes()) (tmp1, tmp2) = disks.parse_info_block(vm.monitor.info_block()) err += tmp1 + tmp2 err += disks.generate_params() err += disks.check_disk_params(params) (tmp1, tmp2, _, _) = disks.check_guests_proc_scsi( session.cmd_output('cat /proc/scsi/scsi')) err += tmp1 + tmp2 if err: raise error.TestFail("%s errors occurred while verifying" " qtree vs. params" % err) if params.get('multi_disk_only_qtree') == 'yes': return try: cmd = params.get("clean_cmd") if cmd: session.cmd_status_output(cmd) if params.get("os_type") == "windows": error.context("Create partition on those disks", logging.info) # Get the disk index _get_disk_index(session, stg_image_size, disk_indexs) # Random select one file system from file_system index = random.randint(0, (len(file_system) - 1)) fs_type = file_system[index].strip() for i in xrange(stg_image_num): utils_misc.format_windows_disk(session, disk_indexs[i], None, None, fs_type) error.context("Get disks dev filenames in guest", logging.info) cmd = params["list_volume_command"] s, output = session.cmd_status_output(cmd, timeout=cmd_timeout) if s != 0: raise error.TestFail("List volume command failed with cmd '%s'.\n" "Output is: %s\n" % (cmd, output)) output = session.cmd_output(cmd, timeout=cmd_timeout) disks = re.findall(re_str, output) disks = map(string.strip, disks) disks.sort() logging.debug("Volume list that meet regular expressions: %s", " ".join(disks)) images = params.get("images").split() if len(disks) < len(images): logging.debug("disks: %s , images: %s", len(disks), len(images)) raise error.TestFail("Fail to list all the volumes!") if params.get("os_type") == "linux": output = session.cmd_output("mount") li = re.findall(r"^/dev/(%s)\d*" % re_str, output, re.M) if li: black_list.extend(li) else: black_list.extend(utils_misc.get_winutils_vol(session)) disks = set(disks) black_list = set(black_list) logging.info("No need to check volume '%s'", (disks & black_list)) disks = disks - black_list except Exception: _do_post_cmd(session) raise try: for i in range(n_repeat): logging.info("iterations: %s", (i + 1)) error.context("Format those disks in guest", logging.info) for disk in disks: disk = disk.strip() error.context("Preparing disk: %s..." % disk) # Random select one file system from file_system index = random.randint(0, (len(file_system) - 1)) fs = file_system[index].strip() cmd = params["format_command"] % (fs, disk) error.context("formatting test disk") session.cmd(cmd, timeout=cmd_timeout) cmd = params.get("mount_command") if cmd: cmd = cmd % (disk, disk, disk) session.cmd(cmd) error.context("Cope file into / out of those disks", logging.info) for disk in disks: disk = disk.strip() error.context("Performing I/O on disk: %s..." % disk) cmd_list = params["cmd_list"].split() for cmd_l in cmd_list: cmd = params.get(cmd_l) if cmd: session.cmd(cmd % disk, timeout=cmd_timeout) cmd = params["compare_command"] key_word = params["check_result_key_word"] output = session.cmd_output(cmd) if key_word not in output: raise error.TestFail("Files on guest os root fs and disk " "differ") if params.get("umount_command"): cmd = params.get("show_mount_cmd") output = session.cmd_output(cmd) disks = re.findall(re_str, output) disks.sort() for disk in disks: disk = disk.strip() error.context("Unmounting disk: %s..." % disk) cmd = params.get("umount_command") % (disk, disk) session.cmd(cmd) finally: cmd = params.get("show_mount_cmd") if cmd: try: output = session.cmd_output(cmd) disks = re.findall(re_str, output) disks.sort() for disk in disks: error.context("Unmounting disk: %s..." % disk) cmd = params["umount_command"] % (disk, disk) session.cmd(cmd) except Exception, err: logging.warn("Get error when cleanup, '%s'", err) _do_post_cmd(session) session.close()