def run_qemu_img(test, params, env): """ 'qemu-img' functions test: 1) Judge what subcommand is going to be tested 2) Run subcommand test @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ cmd = virt_utils.get_path(test.bindir, params.get("qemu_img_binary")) if not os.path.exists(cmd): raise error.TestError("Binary of 'qemu-img' not found") image_format = params.get("image_format") image_size = params.get("image_size", "10G") image_name = virt_utils.get_image_filename(params, test.bindir) def _check(cmd, img): """ Simple 'qemu-img check' function implementation. @param cmd: qemu-img base command. @param img: image to be checked """ cmd += " check %s" % img logging.info("Checking image '%s'...", img) try: output = utils.system_output(cmd) except error.CmdError, e: if "does not support checks" in str(e): return (True, "") else: return (False, str(e)) return (True, output)
def rebase_test(cmd): """ Subcommand 'qemu-img rebase' test Change the backing file of a snapshot image in "unsafe mode": Assume the previous backing file had missed and we just have to change reference of snapshot to new one. After change the backing file of a snapshot image in unsafe mode, the snapshot should work still. @param cmd: qemu-img base command. """ if not 'rebase' in utils.system_output(cmd + ' --help', ignore_status=True): raise error.TestNAError("Current kvm user space version does not" " support 'rebase' subcommand") sn_fmt = params.get("snapshot_format", "qcow2") sn1 = params.get("image_name_snapshot1") sn1 = virt_utils.get_path(test.bindir, sn1) + ".%s" % sn_fmt base_img = virt_utils.get_image_filename(params, test.bindir) _create(cmd, sn1, sn_fmt, base_img=base_img, base_img_fmt=image_format) # Create snapshot2 based on snapshot1 sn2 = params.get("image_name_snapshot2") sn2 = virt_utils.get_path(test.bindir, sn2) + ".%s" % sn_fmt _create(cmd, sn2, sn_fmt, base_img=sn1, base_img_fmt=sn_fmt) rebase_mode = params.get("rebase_mode") if rebase_mode == "unsafe": os.remove(sn1) _rebase(cmd, sn2, base_img, image_format, mode=rebase_mode) # Check sn2's format and backing_file actual_base_img = _info(cmd, sn2, "backing file") base_img_name = os.path.basename(params.get("image_name")) if not base_img_name in actual_base_img: raise error.TestFail("After rebase the backing_file of 'sn2' is " "'%s' which is not expected as '%s'" % (actual_base_img, base_img_name)) s, o = _check(cmd, sn2) if not s: raise error.TestFail("Check image '%s' failed after rebase;" "got error: %s" % (sn2, o)) try: os.remove(sn2) os.remove(sn1) except Exception: pass
logging.error(fail_log) return f_fail vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) 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 = virt_utils.get_image_filename(params, test.bindir) # Check cpu count logging.info("CPU count check") expected_cpu_nr = int(params.get("smp")) actual_cpu_nr = vm.get_cpu_count() if expected_cpu_nr != actual_cpu_nr: fail_log = "CPU count mismatch:\n" fail_log += " Assigned to VM: %s \n" % expected_cpu_nr fail_log += " Reported by OS: %s" % actual_cpu_nr n_fail.append(fail_log) logging.error(fail_log) # Check memory size logging.info("Memory size check") expected_mem = int(params.get("mem"))
def _qtree_check(vm, session, params, root_dir): """ Tries to find differences between qemu qtree+info vs. /proc/scsi/scsi and vm params. @param vm: VM object @param session: ssh session to VM @param params: Dictionary with the test parameters @param root_dir: vm's root_dir (for get_image_name function) """ err = 0 # check [params_names, qtree search pattern] check = [['name', 'channel', 'scsiid', 'lun'], ['dev-prop: drive = ', 'bus-prop: channel = ', 'bus-prop: scsi-id = ', 'bus-prop: lun = ']] drive_formats = ['ide', 'scsi', 'virtio-blk-pci'] # Info about disks gathered from guest disks = {} no_virtio_disks = 0 # virtio-blk-pci disks are not in /proc/scsi/scsi error.context("Gather info from 'info qtree'") info = vm.monitor.info('qtree').split('\n') current = None line = info.pop(0) offset = None while len(info) > 0: if current is not None: # Get all info about disk _offset = len(re_blanks.match(line).group(0)) if offset == None: offset = _offset elif offset != _offset: # This line is about next device, store current and prepare # for next one. name = current.get('name') if not name: logging.error("Skipping disk without a name: %s", current) err += 1 elif name in disks: logging.error("Disk %s present multiple times in qtree", current) else: if current['drive_format'] == 'virtio-blk-pci': no_virtio_disks += 1 disks[name] = current current = None continue # this line have to be proceeded in next round line = line[offset:] for i in xrange(len(check[1])): if line.startswith(check[1][i]): current[check[0][i]] = line[len(check[1][i]):].strip() else: # Look for block with disk specification line = line.strip() for fmt in drive_formats: if line.startswith('dev: %s' % fmt): current = {'drive_format': fmt} offset = None line = info.pop(0) # Next line error.context("Gather info from 'info block'") info = vm.monitor.info("block").split('\n') for line in info: if not line: continue line = line.split(':', 1) name = line[0].strip() if name not in disks: logging.error("disk %s is in block but not in qtree", name) err += 1 continue item = {} for _ in line[1].strip().split(' '): _ = _.split('=') item[_[0]] = _[1] if item.get('backing_file'): disks[name]['snapshot'] = 'yes' disks[name]['image_name'] = os.path.realpath( item.get('backing_file')) elif item.get('file'): disks[name]['image_name'] = os.path.realpath(item.get('file')) else: logging.error("Can'T get info about %s disk file.", name) err += 1 if item.get('ro') and item.get('ro') != '0': disks[name]['readonly'] = 'yes' error.context("Verify info from guest's /proc/scsi/scsi") # host, channel, id, lun, vendor scsis = re.findall(r'Host:\s+(\w+)\s+Channel:\s+(\d+)\s+Id:\s+(\d+)\s+' 'Lun:\s+(\d+)\n\s+Vendor:\s+([a-zA-Z0-9_-]+)\s+Model: ', session.cmd_output('cat /proc/scsi/scsi')) if len(scsis) + no_virtio_disks != len(disks): logging.error("The number of disks in qtree and /proc/scsi/scsi is not" " equal.") err += 1 _disks = {} # Check only scsi disks for disk in disks.copy().iteritems(): if disk[1]['drive_format'].startswith('scsi'): _disks[disk[0]] = disk[1] _ = [] for scsi in scsis: if scsi[4].startswith('QEMU'): _.append("%d-%d-%d" % (int(scsi[1]), int(scsi[2]), int(scsi[3]))) scsis = _ # Check only channel, id and lun for now for disk in _disks.itervalues(): name = '%d-%d-%d' % (int(disk['channel']), int(disk['scsiid']), int(disk['lun'])) if name not in scsis: logging.error('Disk %s is in qtree but not in /proc/scsi/scsi.', disk) err += 1 continue scsis.remove(name) error.context("Verify the info from qtree+block vs. params.") _disks = disks.copy() for name in params.objects('images'): current = None image_params = params.object_params(name) image_name = os.path.realpath(get_image_filename(image_params, root_dir)) for disk in disks.itervalues(): if disk.get('image_name') == image_name: current = disk qname = current.get('name') current.pop('name') break if not current: logging.error("Disk %s is not in qtree but is in params.", name) err += 1 continue for prop in check[0]: if (image_params.get(prop) and current.get(prop) and image_params.get(prop) != current.get(prop)): logging.error("Disk %s's property %s=%s doesn't math params %s", qname, prop, current.get(prop), image_params.get(prop)) err += 1 _disks.pop(qname) if _disks: logging.error('Some disks were in qtree but not in autotest params: %s', _disks) err += 1 return err
def run_pci_hotplug(test, params, env): """ Test hotplug of PCI devices. (Elements between [] are configurable test parameters) 1) PCI add a deivce (NIC / block) 2) Compare output of monitor command 'info pci'. 3) Compare output of guest command [reference_cmd]. 4) Verify whether pci_model is shown in [pci_find_cmd]. 5) Check whether the newly added PCI device works fine. 6) PCI delete the device, verify whether could remove the PCI device. @param test: KVM test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=timeout) # Modprobe the module if specified in config file module = params.get("modprobe_module") if module: session.cmd("modprobe %s" % module) # Get output of command 'info pci' as reference info_pci_ref = vm.monitor.info("pci") # Get output of command as reference reference = session.cmd_output(params.get("reference_cmd")) tested_model = params.get("pci_model") test_type = params.get("pci_type") image_format = params.get("image_format_stg") # Probe qemu to verify what is the supported syntax for PCI hotplug cmd_output = vm.monitor.cmd("?") if len(re.findall("\ndevice_add", cmd_output)) > 0: cmd_type = "device_add" elif len(re.findall("\npci_add", cmd_output)) > 0: cmd_type = "pci_add" else: raise error.TestError("Unknow version of qemu") # Determine syntax of drive hotplug # __com.redhat_drive_add == qemu-kvm-0.12 on RHEL 6 if len(re.findall("\n__com.redhat_drive_add", cmd_output)) > 0: drive_cmd_type = "__com.redhat_drive_add" # drive_add == qemu-kvm-0.13 onwards elif len(re.findall("\ndrive_add", cmd_output)) > 0: drive_cmd_type = "drive_add" else: raise error.TestError("Unknow version of qemu") # Probe qemu for a list of supported devices devices_support = vm.monitor.cmd("%s ?" % cmd_type) if cmd_type == "pci_add": if test_type == "nic": pci_add_cmd = "pci_add pci_addr=auto nic model=%s" % tested_model elif test_type == "block": image_params = params.object_params("stg") image_filename = virt_utils.get_image_filename(image_params, test.bindir) pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" % (image_filename, tested_model)) # Execute pci_add (should be replaced by a proper monitor method call) add_output = vm.monitor.cmd(pci_add_cmd) if not "OK domain" in add_output: raise error.TestFail("Add PCI device failed. " "Monitor command is: %s, Output: %r" % (pci_add_cmd, add_output)) after_add = vm.monitor.info("pci") elif cmd_type == "device_add": driver_id = test_type + "-" + virt_utils.generate_random_id() device_id = test_type + "-" + virt_utils.generate_random_id() if test_type == "nic": if tested_model == "virtio": tested_model = "virtio-net-pci" pci_add_cmd = "device_add id=%s,driver=%s" % (device_id, tested_model) elif test_type == "block": image_params = params.object_params("stg") image_filename = virt_utils.get_image_filename(image_params, test.bindir) controller_model = None if tested_model == "virtio": tested_model = "virtio-blk-pci" if tested_model == "scsi": tested_model = "scsi-disk" controller_model = "lsi53c895a" if len(re.findall(controller_model, devices_support)) == 0: raise error.TestError("scsi controller device (%s) not " "supported by qemu" % controller_model) if controller_model is not None: controller_id = "controller-" + device_id controller_add_cmd = ("device_add %s,id=%s" % (controller_model, controller_id)) vm.monitor.cmd(controller_add_cmd) if drive_cmd_type == "drive_add": driver_add_cmd = ("drive_add auto " "file=%s,if=none,id=%s,format=%s" % (image_filename, driver_id, image_format)) elif drive_cmd_type == "__com.redhat_drive_add": driver_add_cmd = ("__com.redhat_drive_add " "file=%s,format=%s,id=%s" % (image_filename, image_format, driver_id)) pci_add_cmd = ("device_add id=%s,driver=%s,drive=%s" % (device_id, tested_model, driver_id)) vm.monitor.cmd(driver_add_cmd) # Check if the device is support in qemu if len(re.findall(tested_model, devices_support)) > 0: add_output = vm.monitor.cmd(pci_add_cmd) else: raise error.TestError("%s doesn't support device: %s" % (cmd_type, tested_model)) after_add = vm.monitor.info("pci") if not device_id in after_add: raise error.TestFail("Add device failed. Monitor command is: %s" ". Output: %r" % (pci_add_cmd, add_output)) # Define a helper function to delete the device def pci_del(ignore_failure=False): if cmd_type == "pci_add": result_domain, bus, slot, function = add_output.split(',') domain = int(result_domain.split()[2]) bus = int(bus.split()[1]) slot = int(slot.split()[1]) pci_addr = "%x:%x:%x" % (domain, bus, slot) cmd = "pci_del pci_addr=%s" % pci_addr elif cmd_type == "device_add": cmd = "device_del %s" % device_id # This should be replaced by a proper monitor method call vm.monitor.cmd(cmd) def device_removed(): after_del = vm.monitor.info("pci") return after_del != after_add if (not virt_utils.wait_for(device_removed, 10, 0, 1) and not ignore_failure): raise error.TestFail("Failed to hot remove PCI device: %s. " "Monitor command: %s" % (tested_model, cmd)) try: # Compare the output of 'info pci' if after_add == info_pci_ref: raise error.TestFail("No new PCI device shown after executing " "monitor command: 'info pci'") # Define a helper function to compare the output def new_shown(): o = session.cmd_output(params.get("reference_cmd")) return o != reference secs = int(params.get("wait_secs_for_hook_up")) if not virt_utils.wait_for(new_shown, 30, secs, 3): raise error.TestFail("No new device shown in output of command " "executed inside the guest: %s" % params.get("reference_cmd")) # Define a helper function to catch PCI device string def find_pci(): o = session.cmd_output(params.get("find_pci_cmd")) return params.get("match_string") in o if not virt_utils.wait_for(find_pci, 30, 3, 3): raise error.TestFail("PCI %s %s device not found in guest. " "Command was: %s" % (tested_model, test_type, params.get("find_pci_cmd"))) # Test the newly added device try: session.cmd(params.get("pci_test_cmd")) except aexpect.ShellError, e: raise error.TestFail("Check for %s device failed after PCI " "hotplug. Output: %r" % (test_type, e.output)) session.close()