def preprocess_vm(test, params, env, name): """ Preprocess a single VM object according to the instructions in params. Start the VM if requested and get a screendump. @param test: An Autotest test object. @param params: A dict containing VM preprocessing parameters. @param env: The environment (a dict-like object). @param name: The name of the VM object. """ logging.debug("Preprocessing VM '%s'..." % name) vm = kvm_utils.env_get_vm(env, name) if vm: logging.debug("VM object found in environment") else: logging.debug("VM object does not exist; creating it") vm = kvm_vm.VM(name, params, test.bindir, env.get("address_cache")) kvm_utils.env_register_vm(env, name, vm) start_vm = False migration_mode = params.get("migration_mode", None) if params.get("restart_vm") == "yes": logging.debug("'restart_vm' specified; (re)starting VM...") start_vm = True elif params.get("start_vm") == "yes": if not vm.is_alive(): logging.debug("VM is not alive; starting it...") start_vm = True elif vm.make_qemu_command() != vm.make_qemu_command(name, params, test.bindir): logging.debug("VM's qemu command differs from requested one; " "restarting it...") start_vm = True elif migration_mode is not None: logging.debug("Starting VM on migration incoming mode...") start_vm = True if start_vm: if migration_mode is not None: if not vm.create(name, params, test.bindir, migration_mode=migration_mode): raise error.TestError("Could not start VM for migration") else: # Start the VM (or restart it if it's already up) if not vm.create(name, params, test.bindir): raise error.TestError("Could not start VM") else: # Don't start the VM, just update its params vm.params = params scrdump_filename = os.path.join(test.debugdir, "pre_%s.ppm" % name) try: if vm.monitor: vm.monitor.screendump(scrdump_filename) except kvm_monitor.MonitorError, e: logging.warn(e)
def preprocess_vm(test, params, env, name): """ Preprocess a single VM object according to the instructions in params. Start the VM if requested and get a screendump. @param test: An Autotest test object. @param params: A dict containing VM preprocessing parameters. @param env: The environment (a dict-like object). @param name: The name of the VM object. """ qemu_path = os.path.join(test.bindir, "qemu") image_dir = os.path.join(test.bindir, "images") iso_dir = os.path.join(test.bindir, "isos") logging.debug("Preprocessing VM '%s'..." % name) vm = kvm_utils.env_get_vm(env, name) if vm: logging.debug("VM object found in environment") else: logging.debug("VM object does not exist; creating it") vm = kvm_vm.VM(name, params, qemu_path, image_dir, iso_dir) kvm_utils.env_register_vm(env, name, vm) start_vm = False for_migration = False if params.get("start_vm_for_migration") == "yes": logging.debug("'start_vm_for_migration' specified; (re)starting VM with" " -incoming option...") start_vm = True for_migration = True elif params.get("restart_vm") == "yes": logging.debug("'restart_vm' specified; (re)starting VM...") start_vm = True elif params.get("start_vm") == "yes": if not vm.is_alive(): logging.debug("VM is not alive; starting it...") start_vm = True elif vm.make_qemu_command() != vm.make_qemu_command(name, params, qemu_path, image_dir, iso_dir): logging.debug("VM's qemu command differs from requested one; " "restarting it...") start_vm = True if start_vm: if not vm.create(name, params, qemu_path, image_dir, iso_dir, for_migration): message = "Could not start VM" logging.error(message) raise error.TestError(message) scrdump_filename = os.path.join(test.debugdir, "pre_%s.ppm" % name) vm.send_monitor_cmd("screendump %s" % scrdump_filename)
def run_stress_boot(tests, params, env): """ Boots VMs until one of them becomes unresponsive, and records the maximum number of VMs successfully started: 1) boot the first vm 2) boot the second vm cloned from the first vm, check whether it boots up and all booted vms can ssh-login 3) go on until cannot create VM anymore or cannot allocate memory for VM @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ # boot the first vm vm = kvm_utils.env_get_vm(env, params.get("main_vm")) if not vm: raise error.TestError("VM object not found in environment") if not vm.is_alive(): raise error.TestError("VM seems to be dead; Test requires a living VM") logging.info("Waiting for first guest to be up...") session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2) if not session: raise error.TestFail("Could not log into first guest") num = 2 vms = [] sessions = [session] # boot the VMs while num <= int(params.get("max_vms")): try: vm_name = "vm" + str(num) # clone vm according to the first one vm_params = params.copy() vm_params["image_snapshot"] = "yes" vm_params["kill_vm"] = "yes" vm_params["kill_vm_gracefully"] = "no" curr_vm = vm.clone(vm_name, vm_params) kvm_utils.env_register_vm(env, vm_name, curr_vm) params["vms"] += " " + vm_name # vms.append(curr_vm) logging.info("Booting guest #%d" % num) if not curr_vm.create(): raise error.TestFail("Cannot create VM #%d" % num) curr_vm_session = kvm_utils.wait_for(curr_vm.ssh_login, 240, 0, 2) if not curr_vm_session: raise error.TestFail("Could not log into guest #%d" % num) logging.info("Guest #%d boots up successfully" % num) sessions.append(curr_vm_session) # check whether all previous ssh sessions are responsive for i, vm_session in enumerate(sessions): if vm_session.get_command_status(params.get("alive_test_cmd")): raise error.TestFail("Session #%d is not responsive" % i) num += 1 except (error.TestFail, OSError): for se in sessions: se.close() logging.info("Total number booted: %d" % (num - 1)) raise else: for se in sessions: se.close() logging.info("Total number booted: %d" % (num - 1))
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 kvm_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': if not dest_vm.create(migration_mode=mig_protocol, mac_source=vm): raise error.TestError("Could not create dest 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 kvm_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: 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 "paused" in dest_vm.monitor.info("status"): 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): kvm_utils.env_register_vm(env, vm.name, dest_vm) # Return the new cloned VM if dest_host == 'localhost': return dest_vm else: return vm
def run_stress_boot(tests, params, env): """ Boots VMs until one of them becomes unresponsive, and records the maximum number of VMs successfully started: 1) boot the first vm 2) boot the second vm cloned from the first vm, check whether it boots up and all booted vms respond to shell commands 3) go on until cannot create VM anymore or cannot allocate memory for VM @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ # boot the first vm vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) logging.info("Waiting for first guest to be up...") session = kvm_utils.wait_for(vm.remote_login, 240, 0, 2) if not session: raise error.TestFail("Could not log into first guest") num = 2 sessions = [session] address_index = int(params.get("clone_address_index_base", 10)) # boot the VMs while num <= int(params.get("max_vms")): try: vm_name = "vm" + str(num) # clone vm according to the first one vm_params = vm.get_params().copy() vm_params["address_index"] = str(address_index) curr_vm = vm.clone(vm_name, vm_params) kvm_utils.env_register_vm(env, vm_name, curr_vm) params['vms'] += " " + vm_name logging.info("Booting guest #%d" % num) if not curr_vm.create(): raise error.TestFail("Cannot create VM #%d" % num) curr_vm_session = kvm_utils.wait_for(curr_vm.remote_login, 240, 0, 2) if not curr_vm_session: raise error.TestFail("Could not log into guest #%d" % num) logging.info("Guest #%d boots up successfully" % num) sessions.append(curr_vm_session) # check whether all previous shell sessions are responsive for i, se in enumerate(sessions): if se.get_command_status(params.get("alive_test_cmd")) != 0: raise error.TestFail("Session #%d is not responsive" % i) num += 1 address_index += 1 except (error.TestFail, OSError): for se in sessions: se.close() logging.info("Total number booted: %d" % (num - 1)) raise else: for se in sessions: se.close() logging.info("Total number booted: %d" % (num -1))
def run_migration(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) Send a migration command to the source VM and wait until it's finished. 4) Kill off the source VM. 3) Log into the destination VM after the migration is finished. 4) Compare the output of a reference command executed on the source with the output of the same command on the destination machine. @param test: kvm test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) # See if migration is supported s, o = vm.send_monitor_cmd("help info") if not "info migrate" in o: raise error.TestError("Migration is not supported") # Log into guest and get the output of migration_test_command session = kvm_test_utils.wait_for_login(vm) migration_test_command = params.get("migration_test_command") reference_output = session.get_command_output(migration_test_command) session.close() # Clone the main VM and ask it to wait for incoming migration dest_vm = vm.clone() dest_vm.create(for_migration=True) try: # Define the migration command cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port logging.debug("Migration command: %s" % cmd) # Migrate s, o = vm.send_monitor_cmd(cmd) if s: logging.error("Migration command failed (command: %r, output: %r)" % (cmd, o)) raise error.TestFail("Migration command failed") # Define some helper functions def mig_finished(): s, o = vm.send_monitor_cmd("info migrate") return s == 0 and not "Migration status: active" in o def mig_succeeded(): s, o = vm.send_monitor_cmd("info migrate") return s == 0 and "Migration status: completed" in o def mig_failed(): s, o = vm.send_monitor_cmd("info migrate") return s == 0 and "Migration status: failed" in o # Wait for migration to finish if not kvm_utils.wait_for(mig_finished, 90, 2, 2, "Waiting for migration to finish..."): raise error.TestFail("Timeout elapsed while waiting for migration " "to finish") # 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") # Kill the source VM vm.destroy(gracefully=False) # Replace the source VM with the new cloned VM kvm_utils.env_register_vm(env, params.get("main_vm"), dest_vm) except: dest_vm.destroy(gracefully=False) raise # Log into guest and get the output of migration_test_command logging.info("Logging into guest after migration...") session = dest_vm.remote_login() if not session: raise error.TestFail("Could not log into guest after migration") logging.info("Logged in after migration") output = session.get_command_output(migration_test_command) session.close() # Compare output to reference output if output != reference_output: logging.info("Command output before migration differs from command " "output after migration") logging.info("Command: %s" % params.get("migration_test_command")) logging.info("Output before:" + kvm_utils.format_str_for_message(reference_output)) logging.info("Output after:" + kvm_utils.format_str_for_message(output)) raise error.TestFail("Command produced different output before and " "after migration")
except: raise error.TestFail("Could not get PID of %s" % (vm_name)) # Creating other guest systems for i in range(1, vmsc): vm_name = "vm" + str(i + 1) params['pid_' + vm_name] = kvm_utils.generate_tmp_file_name(vm_name, 'pid') params['extra_params_' + vm_name] = params.get('extra_params') params['extra_params_' + vm_name] += (" -pidfile %s" % (params.get('pid_' + vm_name))) params['extra_params'] = params.get('extra_params_' + vm_name) # Last VM is later used to run more allocators simultaneously lvms.append(lvms[0].clone(vm_name, params)) kvm_utils.env_register_vm(env, vm_name, lvms[i]) params['vms'] += " " + vm_name logging.debug("Booting guest %s" % lvms[i].name) if not lvms[i].create(): raise error.TestFail("Cannot create VM %s" % lvms[i].name) if not lvms[i].is_alive(): raise error.TestError("VM %s seems to be dead; Test requires a" "living VM" % lvms[i].name) lsessions.append(kvm_utils.wait_for(lvms[i].remote_login, 360, 0, 2)) if not lsessions[i]: raise error.TestFail("Could not log into guest %s" % lvms[i].name) try: tmp = open(params.get('pid_' + vm_name), 'r')