def copy_if_hash_differs(vm, local_path, remote_path): """ Copy a file to a guest if it doesn't exist or if its MD5sum differs. @param vm: VM object. @param local_path: Local path. @param remote_path: Remote path. """ copy = False local_hash = utils.hash_file(local_path) basename = os.path.basename(local_path) output = session.cmd_output("md5sum %s" % remote_path) if "such file" in output: remote_hash = "0" elif output: remote_hash = output.split()[0] else: logging.warning("MD5 check for remote path %s did not return.", remote_path) # Let's be a little more lenient here and see if it wasn't a # temporary problem remote_hash = "0" if remote_hash != local_hash: logging.debug("Copying %s to guest", basename) copy = True if copy: if not vm.copy_files_to(local_path, remote_path): raise error.TestFail("Could not copy %s to guest" % local_path)
def _take_screendumps(test, params, env): global _screendump_thread_termination_event temp_dir = test.debugdir if params.get("screendump_temp_dir"): temp_dir = kvm_utils.get_path(test.bindir, params.get("screendump_temp_dir")) try: os.makedirs(temp_dir) except OSError: pass temp_filename = os.path.join(temp_dir, "scrdump-%s.ppm" % kvm_utils.generate_random_string(6)) delay = float(params.get("screendump_delay", 5)) quality = int(params.get("screendump_quality", 30)) cache = {} while True: for vm in env.get_all_vms(): if not vm.is_alive(): continue try: vm.monitor.screendump(temp_filename) except kvm_monitor.MonitorError, e: logging.warn(e) continue if not os.path.exists(temp_filename): logging.warn("VM '%s' failed to produce a screendump", vm.name) continue if not ppm_utils.image_verify_ppm_file(temp_filename): logging.warn("VM '%s' produced an invalid screendump", vm.name) os.unlink(temp_filename) continue screendump_dir = os.path.join(test.debugdir, "screendumps_%s" % vm.name) try: os.makedirs(screendump_dir) except OSError: pass screendump_filename = os.path.join(screendump_dir, "%s_%s.jpg" % (vm.name, time.strftime("%Y-%m-%d_%H-%M-%S"))) hash = utils.hash_file(temp_filename) if hash in cache: try: os.link(cache[hash], screendump_filename) except OSError: pass else: try: image = PIL.Image.open(temp_filename) image.save(screendump_filename, format="JPEG", quality=quality) cache[hash] = screendump_filename except NameError: pass os.unlink(temp_filename) if _screendump_thread_termination_event.isSet(): _screendump_thread_termination_event = None break _screendump_thread_termination_event.wait(delay)
def check_iso(url, destination, hash): """ Verifies if ISO that can be find on url is on destination with right hash. This function will verify the SHA1 hash of the ISO image. If the file turns out to be missing or corrupted, let the user know we can download it. @param url: URL where the ISO file can be found. @param destination: Directory in local disk where we'd like the iso to be. @param hash: SHA1 hash for the ISO image. """ logging.info("Verifying iso %s", os.path.basename(url)) if not destination: os.makedirs(destination) iso_path = os.path.join(destination, os.path.basename(url)) if not os.path.isfile(iso_path) or ( utils.hash_file(iso_path, method="sha1") != hash): logging.warning("%s not found or corrupted", iso_path) logging.warning("Would you like to download it? (y/n)") iso_download = raw_input() if iso_download == 'y': utils.unmap_url_cache(destination, url, hash, method="sha1") else: logging.warning("Missing file %s. Please download it", iso_path) else: logging.debug("%s present, with proper checksum", iso_path)
def check_iso(url, destination, hash): """ Verifies if ISO that can be find on url is on destination with right hash. This function will verify the SHA1 hash of the ISO image. If the file turns out to be missing or corrupted, let the user know we can download it. @param url: URL where the ISO file can be found. @param destination: Directory in local disk where we'd like the iso to be. @param hash: SHA1 hash for the ISO image. """ logging.info("Verifying iso %s", os.path.basename(url)) if not destination: os.makedirs(destination) iso_path = os.path.join(destination, os.path.basename(url)) if not os.path.isfile(iso_path) or (utils.hash_file( iso_path, method="sha1") != hash): logging.warning("%s not found or corrupted", iso_path) logging.warning("Would you like to download it? (y/n)") iso_download = raw_input() if iso_download == 'y': utils.unmap_url_cache(destination, url, hash, method="sha1") else: logging.warning("Missing file %s. Please download it", iso_path) else: logging.debug("%s present, with proper checksum", iso_path)
def copy_if_hash_differs(vm, local_path, remote_path): """ Copy a file to a guest if it doesn't exist or if its MD5sum differs. @param vm: VM object. @param local_path: Local path. @param remote_path: Remote path. @return: Whether the hash differs (True) or not (False). """ hash_differs = False local_hash = utils.hash_file(local_path) basename = os.path.basename(local_path) output = session.cmd_output("md5sum %s" % remote_path) if "such file" in output: remote_hash = "0" elif output: remote_hash = output.split()[0] else: logging.warning("MD5 check for remote path %s did not return.", remote_path) # Let's be a little more lenient here and see if it wasn't a # temporary problem remote_hash = "0" if remote_hash != local_hash: hash_differs = True logging.debug("Copying %s to guest " "(remote hash: %s, local hash:%s)", basename, remote_hash, local_hash) vm.copy_files_to(local_path, remote_path) return hash_differs
def compare(origin_file, receive_file): check_sum1 = utils.hash_file(origin_file, method="md5") output2 = session.cmd("md5sum %s" % receive_file) check_sum2 = output2.strip().split()[0] logging.debug("original file md5: %s, received file md5: %s", check_sum1, check_sum2) if check_sum1 != check_sum2: logging.error("MD5 hash of origin and received files doesn't match") return False return True
def compare(filename): md5_host = utils.hash_file(filename, method="md5") md5_guest = session.cmd("md5sum %s" % filename) md5_guest = md5_guest.split()[0] if md5_host != md5_guest: logging.error("MD5 hash mismatch between file %s " "present on guest and on host", filename) logging.error("MD5 hash for file on guest: %s," "MD5 hash for file on host: %s", md5_host, md5_guest) return False return True
def compare_md5sum(name): logging.info("Compare md5sum of the files on guest and host") host_result = utils.hash_file(name, method="md5") try: o = session.cmd_output("md5sum %s" % name) guest_result = re.findall("\w+", o)[0] except IndexError: logging.error("Could not get file md5sum in guest") return False logging.debug("md5sum: guest(%s), host(%s)", guest_result, host_result) return guest_result == host_result
def compare(origin_file, receive_file): check_sum1 = utils.hash_file(origin_file, method="md5") output2 = session.cmd("md5sum %s" % receive_file) check_sum2 = output2.strip().split()[0] logging.debug("original file md5: %s, received file md5: %s", check_sum1, check_sum2) if check_sum1 != check_sum2: logging.error( "MD5 hash of origin and received files doesn't match") return False return True
def compare(filename): md5_host = utils.hash_file(filename, method="md5") md5_guest = session.cmd("md5sum %s" % filename) md5_guest = md5_guest.split()[0] if md5_host != md5_guest: logging.error( "MD5 hash mismatch between file %s " "present on guest and on host", filename) logging.error( "MD5 hash for file on guest: %s," "MD5 hash for file on host: %s", md5_host, md5_guest) return False return True
def _take_screendumps(test, params, env): global _screendump_thread_termination_event temp_dir = test.debugdir if params.get("screendump_temp_dir"): temp_dir = virt_utils.get_path(test.bindir, params.get("screendump_temp_dir")) try: os.makedirs(temp_dir) except OSError: pass temp_filename = os.path.join(temp_dir, "scrdump-%s.ppm" % virt_utils.generate_random_string(6)) delay = float(params.get("screendump_delay", 5)) quality = int(params.get("screendump_quality", 30)) cache = {} counter = {} while True: for vm in env.get_all_vms(): if vm not in counter.keys(): counter[vm] = 0 if not vm.is_alive(): continue try: vm.screendump(filename=temp_filename, debug=False) except kvm_monitor.MonitorError, e: logging.warn(e) continue except AttributeError, e: continue if not os.path.exists(temp_filename): logging.warn("VM '%s' failed to produce a screendump", vm.name) continue if not ppm_utils.image_verify_ppm_file(temp_filename): logging.warn("VM '%s' produced an invalid screendump", vm.name) os.unlink(temp_filename) continue screendump_dir = os.path.join(test.debugdir, "screendumps_%s" % vm.name) try: os.makedirs(screendump_dir) except OSError: pass counter[vm] += 1 screendump_filename = os.path.join(screendump_dir, "%04d.jpg" % counter[vm]) hash = utils.hash_file(temp_filename) if hash in cache: try: os.link(cache[hash], screendump_filename) except OSError: pass else: try: image = PIL.Image.open(temp_filename) image.save(screendump_filename, format="JPEG", quality=quality) cache[hash] = screendump_filename except NameError: pass os.unlink(temp_filename)
def create(self, name=None, params=None, root_dir=None, timeout=5.0, migration_mode=None, mac_source=None): """ Start the VM by running a qemu command. All parameters are optional. If name, params or root_dir are not supplied, the respective values stored as class attributes are used. @param name: The name of the object @param params: A dict containing VM params @param root_dir: Base directory for relative filenames @param migration_mode: If supplied, start VM for incoming migration using this protocol (either 'tcp', 'unix' or 'exec') @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."' (e.g. 'gzip -c -d filename') if migration_mode is 'exec' @param mac_source: A VM object from which to copy MAC addresses. If not specified, new addresses will be generated. @raise VMCreateError: If qemu terminates unexpectedly @raise VMKVMInitError: If KVM initialization fails @raise VMHugePageError: If hugepage initialization fails @raise VMImageMissingError: If a CD image is missing @raise VMHashMismatchError: If a CD image hash has doesn't match the expected hash @raise VMBadPATypeError: If an unsupported PCI assignment type is requested @raise VMPAError: If no PCI assignable devices could be assigned """ error.context("creating '%s'" % self.name) self.destroy(free_mac_addresses=False) if name is not None: self.name = name if params is not None: self.params = params if root_dir is not None: self.root_dir = root_dir name = self.name params = self.params root_dir = self.root_dir # Verify the md5sum of the ISO images for cdrom in params.objects("cdroms"): cdrom_params = params.object_params(cdrom) iso = cdrom_params.get("cdrom") if iso: iso = virt_utils.get_path(root_dir, iso) if not os.path.exists(iso): raise virt_vm.VMImageMissingError(iso) compare = False if cdrom_params.get("md5sum_1m"): logging.debug("Comparing expected MD5 sum with MD5 sum of " "first MB of ISO file...") actual_hash = utils.hash_file(iso, 1048576, method="md5") expected_hash = cdrom_params.get("md5sum_1m") compare = True elif cdrom_params.get("md5sum"): logging.debug("Comparing expected MD5 sum with MD5 sum of " "ISO file...") actual_hash = utils.hash_file(iso, method="md5") expected_hash = cdrom_params.get("md5sum") compare = True elif cdrom_params.get("sha1sum"): logging.debug("Comparing expected SHA1 sum with SHA1 sum " "of ISO file...") actual_hash = utils.hash_file(iso, method="sha1") expected_hash = cdrom_params.get("sha1sum") compare = True if compare: if actual_hash == expected_hash: logging.debug("Hashes match") else: raise virt_vm.VMHashMismatchError(actual_hash, expected_hash) # Make sure the following code is not executed by more than one thread # at the same time lockfile = open("/tmp/libvirt-autotest-vm-create.lock", "w+") fcntl.lockf(lockfile, fcntl.LOCK_EX) try: # Handle port redirections redir_names = params.objects("redirs") host_ports = virt_utils.find_free_ports(5000, 6000, len(redir_names)) self.redirs = {} for i in range(len(redir_names)): redir_params = params.object_params(redir_names[i]) guest_port = int(redir_params.get("guest_port")) self.redirs[guest_port] = host_ports[i] # Generate netdev/device IDs for all NICs self.netdev_id = [] self.device_id = [] for nic in params.objects("nics"): self.netdev_id.append(virt_utils.generate_random_id()) self.device_id.append(virt_utils.generate_random_id()) # Find available PCI devices self.pci_devices = [] for device in params.objects("pci_devices"): self.pci_devices.append(device) # Find available VNC port, if needed if params.get("display") == "vnc": self.vnc_port = virt_utils.find_free_port(5900, 6100) # Find available spice port, if needed if params.get("spice"): self.spice_port = virt_utils.find_free_port(8000, 8100) # Find random UUID if specified 'uuid = random' in config file if params.get("uuid") == "random": f = open("/proc/sys/kernel/random/uuid") self.uuid = f.read().strip() f.close() # Generate or copy MAC addresses for all NICs num_nics = len(params.objects("nics")) for vlan in range(num_nics): nic_name = params.objects("nics")[vlan] nic_params = params.object_params(nic_name) mac = (nic_params.get("nic_mac") or mac_source and mac_source.get_mac_address(vlan)) if mac: virt_utils.set_mac_address(self.instance, vlan, mac) else: virt_utils.generate_mac_address(self.instance, vlan) # Make qemu command install_command = self.__make_libvirt_command() logging.info("Running libvirt command:\n%s", install_command) utils.run(install_command, verbose=False) # Wait for the domain to be created virt_utils.wait_for(func=self.is_alive, timeout=60, text=("waiting for domain %s to start" % self.name)) # Establish a session with the serial console -- requires a version # of netcat that supports -U self.serial_console = aexpect.ShellSession( "nc -U %s" % self.get_serial_console_filename(), auto_close=False, output_func=virt_utils.log_line, output_params=("serial-%s.log" % name,)) finally: fcntl.lockf(lockfile, fcntl.LOCK_UN) lockfile.close()
def migrate(vm, env=None, mig_timeout=3600, mig_protocol="tcp", mig_cancel=False, offline=False, stable_check=False, clean=False, save_path=None, dest_host='localhost', mig_port=None): """ Migrate a VM locally and re-register it in the environment. @param vm: The VM to migrate. @param env: The environment dictionary. If omitted, the migrated VM will not be registered. @param mig_timeout: timeout value for migration. @param mig_protocol: migration protocol @param mig_cancel: Test migrate_cancel or not when protocol is tcp. @param dest_host: Destination host (defaults to 'localhost'). @param mig_port: Port that will be used for migration. @return: The post-migration VM, in case of same host migration, True in case of multi-host migration. """ def mig_finished(): o = vm.monitor.info("migrate") if isinstance(o, str): return "status: active" not in o else: return o.get("status") != "active" def mig_succeeded(): o = vm.monitor.info("migrate") if isinstance(o, str): return "status: completed" in o else: return o.get("status") == "completed" def mig_failed(): o = vm.monitor.info("migrate") if isinstance(o, str): return "status: failed" in o else: return o.get("status") == "failed" def mig_cancelled(): o = vm.monitor.info("migrate") if isinstance(o, str): return ("Migration status: cancelled" in o or "Migration status: canceled" in o) else: return (o.get("status") == "cancelled" or o.get("status") == "canceled") def wait_for_migration(): if not virt_utils.wait_for(mig_finished, mig_timeout, 2, 2, "Waiting for migration to finish"): raise error.TestFail("Timeout expired while waiting for migration " "to finish") if dest_host == 'localhost': dest_vm = vm.clone() if (dest_host == 'localhost') and stable_check: # Pause the dest vm after creation dest_vm.params['extra_params'] = (dest_vm.params.get('extra_params','') + ' -S') if dest_host == 'localhost': dest_vm.create(migration_mode=mig_protocol, mac_source=vm) try: try: if mig_protocol == "tcp": if dest_host == 'localhost': uri = "tcp:localhost:%d" % dest_vm.migration_port else: uri = 'tcp:%s:%d' % (dest_host, mig_port) elif mig_protocol == "unix": uri = "unix:%s" % dest_vm.migration_file elif mig_protocol == "exec": uri = '"exec:nc localhost %s"' % dest_vm.migration_port if offline: vm.monitor.cmd("stop") vm.monitor.migrate(uri) if mig_cancel: time.sleep(2) vm.monitor.cmd("migrate_cancel") if not virt_utils.wait_for(mig_cancelled, 60, 2, 2, "Waiting for migration " "cancellation"): raise error.TestFail("Failed to cancel migration") if offline: vm.monitor.cmd("cont") if dest_host == 'localhost': dest_vm.destroy(gracefully=False) return vm else: wait_for_migration() if (dest_host == 'localhost') and stable_check: save_path = None or "/tmp" save1 = os.path.join(save_path, "src") save2 = os.path.join(save_path, "dst") vm.save_to_file(save1) dest_vm.save_to_file(save2) # Fail if we see deltas md5_save1 = utils.hash_file(save1) md5_save2 = utils.hash_file(save2) if md5_save1 != md5_save2: raise error.TestFail("Mismatch of VM state before " "and after migration") if (dest_host == 'localhost') and offline: dest_vm.monitor.cmd("cont") except Exception: if dest_host == 'localhost': dest_vm.destroy() raise finally: if (dest_host == 'localhost') and stable_check and clean: logging.debug("Cleaning the state files") if os.path.isfile(save1): os.remove(save1) if os.path.isfile(save2): os.remove(save2) # Report migration status if mig_succeeded(): logging.info("Migration finished successfully") elif mig_failed(): raise error.TestFail("Migration failed") else: raise error.TestFail("Migration ended with unknown status") if dest_host == 'localhost': if dest_vm.monitor.verify_status("paused"): logging.debug("Destination VM is paused, resuming it") dest_vm.monitor.cmd("cont") # Kill the source VM vm.destroy(gracefully=False) # Replace the source VM with the new cloned VM if (dest_host == 'localhost') and (env is not None): env.register_vm(vm.name, dest_vm) # Return the new cloned VM if dest_host == 'localhost': return dest_vm else: return vm
if args: filenames = args else: parser.print_help() sys.exit(1) for filename in filenames: filename = os.path.abspath(filename) file_exists = os.path.isfile(filename) can_read_file = os.access(filename, os.R_OK) if not file_exists: logging.critical("File %s does not exist!", filename) continue if not can_read_file: logging.critical("File %s does not have read permissions!", filename) continue logging.info("Hash values for file %s", os.path.basename(filename)) logging.info("md5 (1m): %s", utils.hash_file(filename, 1024 * 1024, method="md5")) logging.info("sha1 (1m): %s", utils.hash_file(filename, 1024 * 1024, method="sha1")) logging.info("md5 (full): %s", utils.hash_file(filename, method="md5")) logging.info("sha1 (full): %s", utils.hash_file(filename, method="sha1")) logging.info("")
def run_file_transfer(test, params, env): """ Test ethrnet device function by ethtool 1) Boot up a VM. 2) Create a large file by dd on host. 3) Copy this file from host to guest. 4) Copy this file from guest to host. 5) Check if file transfers ended good. @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() login_timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=login_timeout) dir_name = test.tmpdir transfer_timeout = int(params.get("transfer_timeout")) transfer_type = params.get("transfer_type") tmp_dir = params.get("tmp_dir", "/tmp/") clean_cmd = params.get("clean_cmd", "rm -f") filesize = int(params.get("filesize", 4000)) count = int(filesize / 10) if count == 0: count = 1 host_path = os.path.join(dir_name, "tmp-%s" % kvm_utils.generate_random_string(8)) host_path2 = host_path + ".2" cmd = "dd if=/dev/zero of=%s bs=10M count=%d" % (host_path, count) guest_path = tmp_dir + "file_transfer-%s" % kvm_utils.generate_random_string(8) try: logging.info("Creating %dMB file on host", filesize) utils.run(cmd) if transfer_type == "remote": logging.info("Transfering file host -> guest, timeout: %ss", transfer_timeout) t_begin = time.time() vm.copy_files_to(host_path, guest_path, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) logging.info("File transfer host -> guest succeed, " "estimated throughput: %.2fMB/s", throughput) logging.info("Transfering file guest -> host, timeout: %ss", transfer_timeout) t_begin = time.time() vm.copy_files_from(guest_path, host_path2, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) logging.info("File transfer guest -> host succeed, " "estimated throughput: %.2fMB/s", throughput) else: raise error.TestError("Unknown test file transfer mode %s" % transfer_type) if utils.hash_file(host_path, method="md5") != utils.hash_file(host_path2, method="md5"): raise error.TestFail("File changed after transfer host -> guest " "and guest -> host") finally: logging.info("Cleaning temp file on guest") session.cmd("rm -rf %s" % guest_path) logging.info("Cleaning temp files on host") try: os.remove(host_path) os.remove(host_path2) except OSError: pass session.close()
def run_file_transfer(test, params, env): """ Test ethrnet device function by ethtool 1) Boot up a VM. 2) Create a large file by dd on host. 3) Copy this file from host to guest. 4) Copy this file from guest to host. 5) Check if file transfers ended good. @param test: KVM test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) timeout=int(params.get("login_timeout", 360)) session = kvm_test_utils.wait_for_login(vm, timeout=timeout) if not session: raise error.TestFail("Could not log into guest '%s'" % vm.name) dir_name = test.tmpdir transfer_timeout = int(params.get("transfer_timeout")) transfer_type = params.get("transfer_type") tmp_dir = params.get("tmp_dir", "/tmp/") clean_cmd = params.get("clean_cmd", "rm -f") filesize = int(params.get("filesize", 4000)) count = int(filesize / 10) if count == 0: count = 1 cmd = "dd if=/dev/zero of=%s/a.out bs=10M count=%d" % (dir_name, count) guest_path = tmp_dir + "b.out" try: logging.info("Creating %dMB file on host", filesize) utils.run(cmd) if transfer_type == "remote": logging.info("Transfering file host -> guest, timeout: %ss", transfer_timeout) t_begin = time.time() success = vm.copy_files_to("%s/a.out" % dir_name, guest_path, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) if not success: raise error.TestFail("Fail to transfer file from host to guest") logging.info("File transfer host -> guest succeed, " "estimated throughput: %.2fMB/s", throughput) logging.info("Transfering file guest -> host, timeout: %ss", transfer_timeout) t_begin = time.time() success = vm.copy_files_from(guest_path, "%s/c.out" % dir_name, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) if not success: raise error.TestFail("Fail to transfer file from guest to host") logging.info("File transfer guest -> host succeed, " "estimated throughput: %.2fMB/s", throughput) else: raise error.TestError("Unknown test file transfer mode %s" % transfer_type) for f in ['a.out', 'c.out']: p = os.path.join(dir_name, f) size = os.path.getsize(p) logging.debug('Size of %s: %sB', f, size) md5_orig = utils.hash_file("%s/a.out" % dir_name, method="md5") md5_new = utils.hash_file("%s/c.out" % dir_name, method="md5") if md5_orig != md5_new: raise error.TestFail("File changed after transfer host -> guest " "and guest -> host") finally: logging.info('Cleaning temp file on guest') clean_cmd += " %s" % guest_path session.cmd(clean_cmd) logging.info('Cleaning temp files on host') try: os.remove('%s/a.out' % dir_name) os.remove('%s/c.out' % dir_name) except OSError: pass session.close()
logging_manager.configure_logging(kvm_utils.KvmLoggingConfig()) if args: filenames = args else: parser.print_help() sys.exit(1) for filename in filenames: filename = os.path.abspath(filename) file_exists = os.path.isfile(filename) can_read_file = os.access(filename, os.R_OK) if not file_exists: logging.critical("File %s does not exist!", filename) continue if not can_read_file: logging.critical("File %s does not have read permissions!", filename) continue logging.info("Hash values for file %s", os.path.basename(filename)) logging.info("md5 (1m): %s", utils.hash_file(filename, 1024*1024, method="md5")) logging.info("sha1 (1m): %s", utils.hash_file(filename, 1024*1024, method="sha1")) logging.info("md5 (full): %s", utils.hash_file(filename, method="md5")) logging.info("sha1 (full): %s", utils.hash_file(filename, method="sha1")) logging.info("")
def run_file_transfer(test, params, env): """ Test ethrnet device function by ethtool 1) Boot up a VM. 2) Create a large file by dd on host. 3) Copy this file from host to guest. 4) Copy this file from guest to host. 5) Check if file transfers ended good. @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() login_timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=login_timeout) dir_name = test.tmpdir transfer_timeout = int(params.get("transfer_timeout")) transfer_type = params.get("transfer_type") tmp_dir = params.get("tmp_dir", "/tmp/") clean_cmd = params.get("clean_cmd", "rm -f") filesize = int(params.get("filesize", 4000)) count = int(filesize / 10) if count == 0: count = 1 cmd = "dd if=/dev/zero of=%s/a.out bs=10M count=%d" % (dir_name, count) guest_path = tmp_dir + "b.out" try: logging.info("Creating %dMB file on host", filesize) utils.run(cmd) if transfer_type == "remote": logging.info("Transfering file host -> guest, timeout: %ss", transfer_timeout) t_begin = time.time() vm.copy_files_to("%s/a.out" % dir_name, guest_path, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) logging.info("File transfer host -> guest succeed, " "estimated throughput: %.2fMB/s", throughput) logging.info("Transfering file guest -> host, timeout: %ss", transfer_timeout) t_begin = time.time() vm.copy_files_from(guest_path, "%s/c.out" % dir_name, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) logging.info("File transfer guest -> host succeed, " "estimated throughput: %.2fMB/s", throughput) else: raise error.TestError("Unknown test file transfer mode %s" % transfer_type) for f in ['a.out', 'c.out']: p = os.path.join(dir_name, f) size = os.path.getsize(p) logging.debug('Size of %s: %sB', f, size) md5_orig = utils.hash_file("%s/a.out" % dir_name, method="md5") md5_new = utils.hash_file("%s/c.out" % dir_name, method="md5") if md5_orig != md5_new: raise error.TestFail("File changed after transfer host -> guest " "and guest -> host") finally: logging.info('Cleaning temp file on guest') clean_cmd += " %s" % guest_path session.cmd(clean_cmd) logging.info('Cleaning temp files on host') try: os.remove('%s/a.out' % dir_name) os.remove('%s/c.out' % dir_name) except OSError: pass session.close()
def run_migration_with_file_transfer(test, params, env): """ KVM migration test: 1) Get a live VM and clone it. 2) Verify that the source VM supports migration. If it does, proceed with the test. 3) Transfer file from host to guest. 4) Repeatedly migrate VM and wait until transfer's finished. 5) Transfer file from guest back to host. 6) Repeatedly migrate VM and wait until transfer's finished. @param test: kvm test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() login_timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=login_timeout) mig_timeout = float(params.get("mig_timeout", "3600")) mig_protocol = params.get("migration_protocol", "tcp") mig_cancel_delay = int(params.get("mig_cancel") == "yes") * 2 host_path = "/tmp/file-%s" % kvm_utils.generate_random_string(6) host_path_returned = "%s-returned" % host_path guest_path = params.get("guest_path", "/tmp/file") file_size = params.get("file_size", "500") transfer_timeout = int(params.get("transfer_timeout", "240")) try: utils.run("dd if=/dev/urandom of=%s bs=1M count=%s" % (host_path, file_size)) def run_and_migrate(bg): bg.start() try: while bg.isAlive(): logging.info( "File transfer not ended, starting a round of " "migration...") vm.migrate(mig_timeout, mig_protocol, mig_cancel_delay) except: # If something bad happened in the main thread, ignore # exceptions raised in the background thread bg.join(suppress_exception=True) raise else: bg.join() error.context("transferring file to guest while migrating", logging.info) bg = kvm_utils.Thread(vm.copy_files_to, (host_path, guest_path), dict(verbose=True, timeout=transfer_timeout)) run_and_migrate(bg) error.context("transferring file back to host while migrating", logging.info) bg = kvm_utils.Thread(vm.copy_files_from, (guest_path, host_path_returned), dict(verbose=True, timeout=transfer_timeout)) run_and_migrate(bg) # Make sure the returned file is identical to the original one error.context("comparing hashes", logging.info) orig_hash = client_utils.hash_file(host_path) returned_hash = client_utils.hash_file(host_path_returned) if orig_hash != returned_hash: raise error.TestFail("Returned file hash (%s) differs from " "original one (%s)" % (returned_hash, orig_hash)) error.context() finally: session.close() if os.path.isfile(host_path): os.remove(host_path) if os.path.isfile(host_path_returned): os.remove(host_path_returned)
def create(self, name=None, params=None, root_dir=None, timeout=5.0, migration_mode=None, mac_source=None): """ Start the VM by running a qemu command. All parameters are optional. If name, params or root_dir are not supplied, the respective values stored as class attributes are used. @param name: The name of the object @param params: A dict containing VM params @param root_dir: Base directory for relative filenames @param migration_mode: If supplied, start VM for incoming migration using this protocol (either 'tcp', 'unix' or 'exec') @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."' (e.g. 'gzip -c -d filename') if migration_mode is 'exec' @param mac_source: A VM object from which to copy MAC addresses. If not specified, new addresses will be generated. @raise VMCreateError: If qemu terminates unexpectedly @raise VMKVMInitError: If KVM initialization fails @raise VMHugePageError: If hugepage initialization fails @raise VMImageMissingError: If a CD image is missing @raise VMHashMismatchError: If a CD image hash has doesn't match the expected hash @raise VMBadPATypeError: If an unsupported PCI assignment type is requested @raise VMPAError: If no PCI assignable devices could be assigned """ error.context("creating '%s'" % self.name) self.destroy(free_mac_addresses=False) if name is not None: self.name = name if params is not None: self.params = params if root_dir is not None: self.root_dir = root_dir name = self.name params = self.params root_dir = self.root_dir # Verify the md5sum of the ISO images for cdrom in params.objects("cdroms"): cdrom_params = params.object_params(cdrom) iso = cdrom_params.get("cdrom") if ((self.driver_type == self.LIBVIRT_XEN) and (params.get('hvm_or_pv') == 'pv') and (os.path.basename(iso) == 'ks.iso')): continue if iso: iso = virt_utils.get_path(root_dir, iso) if not os.path.exists(iso): raise virt_vm.VMImageMissingError(iso) compare = False if cdrom_params.get("md5sum_1m"): logging.debug("Comparing expected MD5 sum with MD5 sum of " "first MB of ISO file...") actual_hash = utils.hash_file(iso, 1048576, method="md5") expected_hash = cdrom_params.get("md5sum_1m") compare = True elif cdrom_params.get("md5sum"): logging.debug("Comparing expected MD5 sum with MD5 sum of " "ISO file...") actual_hash = utils.hash_file(iso, method="md5") expected_hash = cdrom_params.get("md5sum") compare = True elif cdrom_params.get("sha1sum"): logging.debug("Comparing expected SHA1 sum with SHA1 sum " "of ISO file...") actual_hash = utils.hash_file(iso, method="sha1") expected_hash = cdrom_params.get("sha1sum") compare = True if compare: if actual_hash == expected_hash: logging.debug("Hashes match") else: raise virt_vm.VMHashMismatchError( actual_hash, expected_hash) # Make sure the following code is not executed by more than one thread # at the same time lockfile = open("/tmp/libvirt-autotest-vm-create.lock", "w+") fcntl.lockf(lockfile, fcntl.LOCK_EX) try: # Handle port redirections redir_names = params.objects("redirs") host_ports = virt_utils.find_free_ports(5000, 6000, len(redir_names)) self.redirs = {} for i in range(len(redir_names)): redir_params = params.object_params(redir_names[i]) guest_port = int(redir_params.get("guest_port")) self.redirs[guest_port] = host_ports[i] # Generate netdev/device IDs for all NICs self.netdev_id = [] self.device_id = [] for nic in params.objects("nics"): self.netdev_id.append(virt_utils.generate_random_id()) self.device_id.append(virt_utils.generate_random_id()) # Find available PCI devices self.pci_devices = [] for device in params.objects("pci_devices"): self.pci_devices.append(device) # Find available VNC port, if needed if params.get("display") == "vnc": self.vnc_port = virt_utils.find_free_port(5900, 6100) # Find available spice port, if needed if params.get("spice"): self.spice_port = virt_utils.find_free_port(8000, 8100) # Find random UUID if specified 'uuid = random' in config file if params.get("uuid") == "random": f = open("/proc/sys/kernel/random/uuid") self.uuid = f.read().strip() f.close() # Generate or copy MAC addresses for all NICs num_nics = len(params.objects("nics")) for vlan in range(num_nics): nic_name = params.objects("nics")[vlan] nic_params = params.object_params(nic_name) mac = (nic_params.get("nic_mac") or mac_source and mac_source.get_mac_address(vlan)) if mac: virt_utils.set_mac_address(self.instance, vlan, mac) else: virt_utils.generate_mac_address(self.instance, vlan) # Make qemu command install_command = self.__make_libvirt_command() logging.info("Running libvirt command:\n%s", install_command) utils.run(install_command, verbose=False) # Wait for the domain to be created virt_utils.wait_for(func=self.is_alive, timeout=60, text=("waiting for domain %s to start" % self.name)) # Establish a session with the serial console -- requires a version # of netcat that supports -U self.serial_console = aexpect.ShellSession( "nc -U %s" % self.get_serial_console_filename(), auto_close=False, output_func=virt_utils.log_line, output_params=("serial-%s.log" % name, )) finally: fcntl.lockf(lockfile, fcntl.LOCK_UN) lockfile.close()
def _take_screendumps(test, params, env): global _screendump_thread_termination_event temp_dir = test.debugdir if params.get("screendump_temp_dir"): temp_dir = virt_utils.get_path(test.bindir, params.get("screendump_temp_dir")) try: os.makedirs(temp_dir) except OSError: pass temp_filename = os.path.join( temp_dir, "scrdump-%s.ppm" % virt_utils.generate_random_string(6)) delay = float(params.get("screendump_delay", 5)) quality = int(params.get("screendump_quality", 30)) cache = {} while True: for vm in env.get_all_vms(): if not vm.is_alive(): continue try: vm.monitor.screendump(filename=temp_filename, debug=False) except kvm_monitor.MonitorError, e: logging.warning(e) continue except AttributeError, e: continue if not os.path.exists(temp_filename): logging.warning("VM '%s' failed to produce a screendump", vm.name) continue if not ppm_utils.image_verify_ppm_file(temp_filename): logging.warning("VM '%s' produced an invalid screendump", vm.name) os.unlink(temp_filename) continue screendump_dir = os.path.join(test.debugdir, "screendumps_%s" % vm.name) try: os.makedirs(screendump_dir) except OSError: pass screendump_filename = os.path.join( screendump_dir, "%s_%s.jpg" % (vm.name, time.strftime("%Y-%m-%d_%H-%M-%S"))) hash = utils.hash_file(temp_filename) if hash in cache: try: os.link(cache[hash], screendump_filename) except OSError: pass else: try: image = PIL.Image.open(temp_filename) image.save(screendump_filename, format="JPEG", quality=quality) cache[hash] = screendump_filename except NameError: pass os.unlink(temp_filename)
def _take_screendumps(test, params, env): global _screendump_thread_termination_event temp_dir = test.debugdir if params.get("screendump_temp_dir"): temp_dir = virt_utils.get_path(test.bindir, params.get("screendump_temp_dir")) try: os.makedirs(temp_dir) except OSError: pass temp_filename = os.path.join( temp_dir, "scrdump-%s.ppm" % virt_utils.generate_random_string(6)) delay = float(params.get("screendump_delay", 5)) quality = int(params.get("screendump_quality", 30)) cache = {} counter = {} while True: for vm in env.get_all_vms(): if vm not in counter.keys(): counter[vm] = 0 if not vm.is_alive(): continue try: vm.screendump(filename=temp_filename, debug=False) except kvm_monitor.MonitorError, e: logging.warn(e) continue except AttributeError, e: continue if not os.path.exists(temp_filename): logging.warn("VM '%s' failed to produce a screendump", vm.name) continue if not ppm_utils.image_verify_ppm_file(temp_filename): logging.warn("VM '%s' produced an invalid screendump", vm.name) os.unlink(temp_filename) continue screendump_dir = os.path.join(test.debugdir, "screendumps_%s" % vm.name) try: os.makedirs(screendump_dir) except OSError: pass counter[vm] += 1 screendump_filename = os.path.join(screendump_dir, "%04d.jpg" % counter[vm]) hash = utils.hash_file(temp_filename) if hash in cache: try: os.link(cache[hash], screendump_filename) except OSError: pass else: try: try: image = PIL.Image.open(temp_filename) image.save(screendump_filename, format="JPEG", quality=quality) cache[hash] = screendump_filename except IOError, error_detail: logging.warning( "VM '%s' failed to produce a " "screendump: %s", vm.name, error_detail) # Decrement the counter as we in fact failed to # produce a converted screendump counter[vm] -= 1 except NameError: pass os.unlink(temp_filename)
def run_migration_with_file_transfer(test, params, env): """ KVM migration test: 1) Get a live VM and clone it. 2) Verify that the source VM supports migration. If it does, proceed with the test. 3) Transfer file from host to guest. 4) Repeatedly migrate VM and wait until transfer's finished. 5) Transfer file from guest back to host. 6) Repeatedly migrate VM and wait until transfer's finished. @param test: kvm test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() login_timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=login_timeout) mig_timeout = float(params.get("mig_timeout", "3600")) mig_protocol = params.get("migration_protocol", "tcp") mig_cancel_delay = int(params.get("mig_cancel") == "yes") * 2 host_path = "/tmp/file-%s" % kvm_utils.generate_random_string(6) host_path_returned = "%s-returned" % host_path guest_path = params.get("guest_path", "/tmp/file") file_size = params.get("file_size", "500") transfer_timeout = int(params.get("transfer_timeout", "240")) try: utils.run("dd if=/dev/urandom of=%s bs=1M count=%s" % (host_path, file_size)) def run_and_migrate(bg): bg.start() try: while bg.isAlive(): logging.info("File transfer not ended, starting a round of " "migration...") vm.migrate(mig_timeout, mig_protocol, mig_cancel_delay) except: # If something bad happened in the main thread, ignore # exceptions raised in the background thread bg.join(suppress_exception=True) raise else: bg.join() error.context("transferring file to guest while migrating", logging.info) bg = kvm_utils.Thread(vm.copy_files_to, (host_path, guest_path), dict(verbose=True, timeout=transfer_timeout)) run_and_migrate(bg) error.context("transferring file back to host while migrating", logging.info) bg = kvm_utils.Thread(vm.copy_files_from, (guest_path, host_path_returned), dict(verbose=True, timeout=transfer_timeout)) run_and_migrate(bg) # Make sure the returned file is identical to the original one error.context("comparing hashes", logging.info) orig_hash = client_utils.hash_file(host_path) returned_hash = client_utils.hash_file(host_path_returned) if orig_hash != returned_hash: raise error.TestFail("Returned file hash (%s) differs from " "original one (%s)" % (returned_hash, orig_hash)) error.context() finally: session.close() if os.path.isfile(host_path): os.remove(host_path) if os.path.isfile(host_path_returned): os.remove(host_path_returned)
def create(self, name=None, params=None, root_dir=None, timeout=5.0, migration_mode=None, mac_source=None): """ Start the VM by running a qemu command. All parameters are optional. If name, params or root_dir are not supplied, the respective values stored as class attributes are used. @param name: The name of the object @param params: A dict containing VM params @param root_dir: Base directory for relative filenames @param migration_mode: If supplied, start VM for incoming migration using this protocol (either 'tcp', 'unix' or 'exec') @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."' (e.g. 'gzip -c -d filename') if migration_mode is 'exec' @param mac_source: A VM object from which to copy MAC addresses. If not specified, new addresses will be generated. """ self.destroy() if name is not None: self.name = name if params is not None: self.params = params if root_dir is not None: self.root_dir = root_dir name = self.name params = self.params root_dir = self.root_dir # Verify the md5sum of the ISO image iso = params.get("cdrom") if iso: iso = kvm_utils.get_path(root_dir, iso) if not os.path.exists(iso): logging.error("ISO file not found: %s" % iso) return False compare = False if params.get("md5sum_1m"): logging.debug("Comparing expected MD5 sum with MD5 sum of " "first MB of ISO file...") actual_hash = utils.hash_file(iso, 1048576, method="md5") expected_hash = params.get("md5sum_1m") compare = True elif params.get("md5sum"): logging.debug("Comparing expected MD5 sum with MD5 sum of ISO " "file...") actual_hash = utils.hash_file(iso, method="md5") expected_hash = params.get("md5sum") compare = True elif params.get("sha1sum"): logging.debug("Comparing expected SHA1 sum with SHA1 sum of " "ISO file...") actual_hash = utils.hash_file(iso, method="sha1") expected_hash = params.get("sha1sum") compare = True if compare: if actual_hash == expected_hash: logging.debug("Hashes match") else: logging.error("Actual hash differs from expected one") return False # Make sure the following code is not executed by more than one thread # at the same time lockfile = open("/tmp/kvm-autotest-vm-create.lock", "w+") fcntl.lockf(lockfile, fcntl.LOCK_EX) try: # Handle port redirections redir_names = kvm_utils.get_sub_dict_names(params, "redirs") host_ports = kvm_utils.find_free_ports(5000, 6000, len(redir_names)) self.redirs = {} for i in range(len(redir_names)): redir_params = kvm_utils.get_sub_dict(params, redir_names[i]) guest_port = int(redir_params.get("guest_port")) self.redirs[guest_port] = host_ports[i] # Generate netdev IDs for all NICs self.netdev_id = [] for nic in kvm_utils.get_sub_dict_names(params, "nics"): self.netdev_id.append(kvm_utils.generate_random_id()) # Find available VNC port, if needed if params.get("display") == "vnc": self.vnc_port = kvm_utils.find_free_port(5900, 6100) # Find random UUID if specified 'uuid = random' in config file if params.get("uuid") == "random": f = open("/proc/sys/kernel/random/uuid") self.uuid = f.read().strip() f.close() # Generate or copy MAC addresses for all NICs num_nics = len(kvm_utils.get_sub_dict_names(params, "nics")) for vlan in range(num_nics): nic_name = kvm_utils.get_sub_dict_names(params, "nics")[vlan] nic_params = kvm_utils.get_sub_dict(params, nic_name) if nic_params.get("nic_mac", None): mac = nic_params.get("nic_mac") kvm_utils.set_mac_address(self.instance, vlan, mac) else: mac = mac_source and mac_source.get_mac_address(vlan) if mac: kvm_utils.set_mac_address(self.instance, vlan, mac) else: kvm_utils.generate_mac_address(self.instance, vlan) # Assign a PCI assignable device self.pci_assignable = None pa_type = params.get("pci_assignable") if pa_type in ["vf", "pf", "mixed"]: pa_devices_requested = params.get("devices_requested") # Virtual Functions (VF) assignable devices if pa_type == "vf": self.pci_assignable = kvm_utils.PciAssignable( type=pa_type, driver=params.get("driver"), driver_option=params.get("driver_option"), devices_requested=pa_devices_requested) # Physical NIC (PF) assignable devices elif pa_type == "pf": self.pci_assignable = kvm_utils.PciAssignable( type=pa_type, names=params.get("device_names"), devices_requested=pa_devices_requested) # Working with both VF and PF elif pa_type == "mixed": self.pci_assignable = kvm_utils.PciAssignable( type=pa_type, driver=params.get("driver"), driver_option=params.get("driver_option"), names=params.get("device_names"), devices_requested=pa_devices_requested) self.pa_pci_ids = self.pci_assignable.request_devs() if self.pa_pci_ids: logging.debug("Successfuly assigned devices: %s", self.pa_pci_ids) else: logging.error("No PCI assignable devices were assigned " "and 'pci_assignable' is defined to %s " "on your config file. Aborting VM creation.", pa_type) return False elif pa_type and pa_type != "no": logging.warn("Unsupported pci_assignable type: %s", pa_type) # Make qemu command qemu_command = self.make_qemu_command() # Add migration parameters if required if migration_mode == "tcp": self.migration_port = kvm_utils.find_free_port(5200, 6000) qemu_command += " -incoming tcp:0:%d" % self.migration_port elif migration_mode == "unix": self.migration_file = "/tmp/migration-unix-%s" % self.instance qemu_command += " -incoming unix:%s" % self.migration_file elif migration_mode == "exec": self.migration_port = kvm_utils.find_free_port(5200, 6000) qemu_command += (' -incoming "exec:nc -l %s"' % self.migration_port) logging.debug("Running qemu command:\n%s", qemu_command) self.process = kvm_subprocess.run_bg(qemu_command, None, logging.debug, "(qemu) ") # Make sure the process was started successfully if not self.process.is_alive(): logging.error("VM could not be created; " "qemu command failed:\n%s" % qemu_command) logging.error("Status: %s" % self.process.get_status()) logging.error("Output:" + kvm_utils.format_str_for_message( self.process.get_output())) self.destroy() return False # Establish monitor connections self.monitors = [] for monitor_name in kvm_utils.get_sub_dict_names(params, "monitors"): monitor_params = kvm_utils.get_sub_dict(params, monitor_name) # Wait for monitor connection to succeed end_time = time.time() + timeout while time.time() < end_time: try: if monitor_params.get("monitor_type") == "qmp": # Add a QMP monitor monitor = kvm_monitor.QMPMonitor( monitor_name, self.get_monitor_filename(monitor_name)) else: # Add a "human" monitor monitor = kvm_monitor.HumanMonitor( monitor_name, self.get_monitor_filename(monitor_name)) except kvm_monitor.MonitorError, e: logging.warn(e) else: if monitor.is_responsive(): break time.sleep(1) else: logging.error("Could not connect to monitor '%s'" % monitor_name) self.destroy() return False # Add this monitor to the list self.monitors += [monitor] # Get the output so far, to see if we have any problems with # KVM modules or with hugepage setup. output = self.process.get_output() if re.search("Could not initialize KVM", output, re.IGNORECASE): logging.error("Could not initialize KVM; " "qemu command:\n%s" % qemu_command) logging.error("Output:" + kvm_utils.format_str_for_message( self.process.get_output())) self.destroy() return False if "alloc_mem_area" in output: logging.error("Could not allocate hugepage memory; " "qemu command:\n%s" % qemu_command) logging.error("Output:" + kvm_utils.format_str_for_message( self.process.get_output())) self.destroy() return False logging.debug("VM appears to be alive with PID %s", self.get_pid()) # Establish a session with the serial console -- requires a version # of netcat that supports -U self.serial_console = kvm_subprocess.ShellSession( "nc -U %s" % self.get_serial_console_filename(), auto_close=False, output_func=kvm_utils.log_line, output_params=("serial-%s.log" % name,)) return True
def run_file_transfer(test, params, env): """ Test ethrnet device function by ethtool 1) Boot up a VM. 2) Create a large file by dd on host. 3) Copy this file from host to guest. 4) Copy this file from guest to host. 5) Check if file transfers ended good. @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() login_timeout = int(params.get("login_timeout", 360)) session = vm.wait_for_login(timeout=login_timeout) dir_name = test.tmpdir transfer_timeout = int(params.get("transfer_timeout")) transfer_type = params.get("transfer_type") tmp_dir = params.get("tmp_dir", "/tmp/") clean_cmd = params.get("clean_cmd", "rm -f") filesize = int(params.get("filesize", 4000)) count = int(filesize / 10) if count == 0: count = 1 host_path = os.path.join(dir_name, "tmp-%s" % kvm_utils.generate_random_string(8)) host_path2 = host_path + ".2" cmd = "dd if=/dev/zero of=%s bs=10M count=%d" % (host_path, count) guest_path = (tmp_dir + "file_transfer-%s" % kvm_utils.generate_random_string(8)) try: logging.info("Creating %dMB file on host", filesize) utils.run(cmd) if transfer_type == "remote": logging.info("Transfering file host -> guest, timeout: %ss", transfer_timeout) t_begin = time.time() vm.copy_files_to(host_path, guest_path, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) logging.info( "File transfer host -> guest succeed, " "estimated throughput: %.2fMB/s", throughput) logging.info("Transfering file guest -> host, timeout: %ss", transfer_timeout) t_begin = time.time() vm.copy_files_from(guest_path, host_path2, timeout=transfer_timeout) t_end = time.time() throughput = filesize / (t_end - t_begin) logging.info( "File transfer guest -> host succeed, " "estimated throughput: %.2fMB/s", throughput) else: raise error.TestError("Unknown test file transfer mode %s" % transfer_type) if (utils.hash_file(host_path, method="md5") != utils.hash_file( host_path2, method="md5")): raise error.TestFail("File changed after transfer host -> guest " "and guest -> host") finally: logging.info('Cleaning temp file on guest') session.cmd("rm -rf %s" % guest_path) logging.info('Cleaning temp files on host') try: os.remove(host_path) os.remove(host_path2) except OSError: pass session.close()
def run_vmstop(test, params, env): """ KVM guest stop test: 1) Log into a guest 2) Copy a file into guest 3) Stop guest 4) Check the status through monitor 5) Check the session 6) Migrat the vm to a file twice and compare them. @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 = float(params.get("login_timeout", 240)) session = vm.wait_for_login(timeout=timeout) save_path = params.get("save_path", "/tmp") clean_save = params.get("clean_save") == "yes" save1 = os.path.join(save_path, "save1") save2 = os.path.join(save_path, "save2") guest_path = params.get("guest_path", "/tmp") file_size = params.get("file_size", "1000") try: utils.run("dd if=/dev/zero of=/tmp/file bs=1M count=%s" % file_size) # Transfer file from host to guest, we didn't expect the finish of # transfer, we just let it to be a kind of stress in guest. bg = utils.InterruptedThread(vm.copy_files_to, ("/tmp/file", guest_path), dict(verbose=True, timeout=60)) logging.info("Start the background transfer") bg.start() try: # wait for the transfer start time.sleep(5) logging.info("Stop the VM") vm.monitor.cmd("stop") # check with monitor logging.info("Check the status through monitor") if not vm.monitor.verify_status("paused"): status = str(vm.monitor.info("status")) raise error.TestFail("Guest did not pause after sending stop," " guest status is %s" % status) # check through session logging.info("Check the session") if session.is_responsive(): raise error.TestFail("Session still alive after sending stop") # Check with the migration file logging.info("Save and check the state files") for p in [save1, save2]: vm.save_to_file(p) time.sleep(1) if not os.path.isfile(p): raise error.TestFail("VM failed to save state file %s" % p) # Fail if we see deltas md5_save1 = utils.hash_file(save1) md5_save2 = utils.hash_file(save2) if md5_save1 != md5_save2: raise error.TestFail("The produced state files differ") finally: bg.join(suppress_exception=True) finally: session.close() if clean_save: logging.debug("Clean the state files") if os.path.isfile(save1): os.remove(save1) if os.path.isfile(save2): os.remove(save2) vm.monitor.cmd("cont")