def run_yum_update(test, params, env): """ Runs yum update and yum update kernel on the remote host (yum enabled hosts only). @param test: kvm test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ vm = kvm_utils.env_get_vm(env, params.get("main_vm")) if not vm: message = "VM object not found in environment" logging.error(message) raise error.TestError(message) if not vm.is_alive(): message = "VM seems to be dead; Test requires a living VM" logging.error(message) raise error.TestError(message) logging.info("Logging into guest...") session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2) if not session: message = "Could not log into guest" logging.error(message) raise error.TestFail(message) logging.info("Logged in") internal_yum_update(session, "yum update", params.get("ssh_prompt"), 600) internal_yum_update(session, "yum update kernel", params.get("ssh_prompt"), 600) session.close()
def run_shutdown(test, params, env): """ KVM shutdown test: 1) Log into a guest 2) Send a shutdown command to the guest 3) Wait until it's down @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment """ 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 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 guest") logging.info("Logged in") # Send the VM's shutdown command session.sendline(vm.get_params().get("cmd_shutdown")) session.close() logging.info("Shutdown command sent; waiting for guest to go down...") if not kvm_utils.wait_for(vm.is_dead, 240, 0, 1): raise error.TestFail("Guest refuses to go down") logging.info("Guest is down")
def postprocess_vm(test, params, env, name): """ Postprocess a single VM object according to the instructions in params. Kill the VM if requested and get a screendump. @param test: An Autotest test object. @param params: A dict containing VM postprocessing parameters. @param env: The environment (a dict-like object). @param name: The name of the VM object. """ logging.debug("Postprocessing 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 in environment") return scrdump_filename = os.path.join(test.debugdir, "post_%s.ppm" % name) vm.send_monitor_cmd("screendump %s" % scrdump_filename) if params.get("kill_vm") == "yes": if not kvm_utils.wait_for(vm.is_dead, float(params.get("kill_vm_timeout", 0)), 0.0, 1.0, "Waiting for VM to kill itself..."): logging.debug("'kill_vm' specified; killing VM...") vm.destroy(gracefully = params.get("kill_vm_gracefully") == "yes")
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 run_linux_s3(test, params, env): """ Suspend a guest Linux OS to memory. @param test: kvm test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ 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 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 guest") logging.info("Logged in") logging.info("Checking that VM supports S3") status = session.get_command_status("grep -q mem /sys/power/state") if status == None: logging.error("Failed to check if S3 exists") elif status != 0: raise error.TestFail("Guest does not support S3") logging.info("Waiting for a while for X to start") time.sleep(10) src_tty = session.get_command_output("fgconsole").strip() logging.info("Current virtual terminal is %s" % src_tty) if src_tty not in map(str, range(1, 10)): raise error.TestFail("Got a strange current vt (%s)" % src_tty) dst_tty = "1" if src_tty == "1": dst_tty = "2" logging.info("Putting VM into S3") command = "chvt %s && echo mem > /sys/power/state && chvt %s" % (dst_tty, src_tty) status = session.get_command_status(command, timeout=120) if status != 0: raise error.TestFail("Suspend to mem failed") logging.info("VM resumed after S3") session.close()
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 get_living_vm(env, vm_name): """ Get a VM object from the environment and make sure it's alive. @param env: Dictionary with test environment. @param vm_name: Name of the desired VM object. @return: A VM object. """ vm = kvm_utils.env_get_vm(env, vm_name) if not vm: raise error.TestError("VM '%s' not found in environment" % vm_name) if not vm.is_alive(): raise error.TestError("VM '%s' seems to be dead; test requires a " "living VM" % vm_name) return vm
def run_stepmaker(test, params, env): 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; Step Maker requires a" " living VM") steps_filename = params.get("steps") if not steps_filename: raise error.TestError("Steps filename not specified") steps_filename = os.path.join(test.bindir, "steps", steps_filename) if os.path.exists(steps_filename): raise error.TestError("Steps file %s already exists" % steps_filename) StepMaker(vm, steps_filename, test.debugdir, params) gtk.main()
def run_boot(test, params, env): """ KVM reboot test: 1) Log into a guest 2) Send a reboot command to the guest 3) Wait until it's up. 4) Log into the guest to verify it's up again. @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ 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 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 guest") logging.info("Logged in") if params.get("reboot") == "yes": # Send the VM's reboot command session.sendline(vm.get_params().get("cmd_reboot")) logging.info("Reboot command sent; waiting for guest to go down...") if not kvm_utils.wait_for(lambda: not session.is_responsive(), 120, 0, 1): raise error.TestFail("Guest refuses to go down") session.close() logging.info("Guest is down; waiting for it to go up again...") session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2) if not session: raise error.TestFail("Could not log into guest after reboot") logging.info("Guest is up again") session.close()
def postprocess_vm(test, params, env, name): """ Postprocess a single VM object according to the instructions in params. Kill the VM if requested and get a screendump. @param test: An Autotest test object. @param params: A dict containing VM postprocessing parameters. @param env: The environment (a dict-like object). @param name: The name of the VM object. """ logging.debug("Postprocessing 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 in environment") return scrdump_filename = os.path.join(test.debugdir, "post_%s.ppm" % name) try: if vm.monitor: vm.monitor.screendump(scrdump_filename) except kvm_monitor.MonitorError, e: logging.warn(e)
def run_migration(test, params, env): """ KVM migration test: 1) Get two live VMs. One will be the 'source', the other will be the 'destination'. 2) Verify if 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. """ src_vm_name = params.get("migration_src") vm = kvm_utils.env_get_vm(env, src_vm_name) if not vm: raise error.TestError("VM '%s' not found in environment" % src_vm_name) if not vm.is_alive(): raise error.TestError("VM '%s' seems to be dead; Test requires a" " living VM" % src_vm_name) dest_vm_name = params.get("migration_dst") dest_vm = kvm_utils.env_get_vm(env, dest_vm_name) if not dest_vm: raise error.TestError("VM '%s' not found in environment" % dest_vm_name) if not dest_vm.is_alive(): raise error.TestError("VM '%s' seems to be dead; Test requires a" " living VM" % dest_vm_name) pre_scrdump_filename = os.path.join(test.debugdir, "migration_pre.ppm") post_scrdump_filename = os.path.join(test.debugdir, "migration_post.ppm") # 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 logging.info("Waiting for 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 guest") logging.info("Logged in") reference_output = session.get_command_output(params.get("migration_test_" "command")) session.close() # 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") if s: return False if "Migration status: active" in o: return False return True def mig_succeeded(): s, o = vm.send_monitor_cmd("info migrate") if s == 0 and "Migration status: completed" in o: return True return False def mig_failed(): s, o = vm.send_monitor_cmd("info migrate") if s == 0 and "Migration status: failed" in o: return True return False # 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") else: if mig_failed(): message = "Migration failed" else: message = "Migration ended with unknown status" raise error.TestFail(message) # Get 'post' screendump dest_vm.send_monitor_cmd("screendump %s" % post_scrdump_filename) # Get 'pre' screendump vm.send_monitor_cmd("screendump %s" % pre_scrdump_filename) # Kill the source VM vm.send_monitor_cmd("quit", block=False) # Hack: it seems that the first attempt to communicate with the SSH port # following migration always fails (or succeeds after a very long time). # So just connect to the port once so the following call to ssh_login # succeeds. dest_vm.is_sshd_running(timeout=0.0) # Log into guest and get the output of migration_test_command logging.info("Logging into guest after migration...") session = dest_vm.ssh_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(params.get("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")
def run_timedrift(test, params, env): """ Time drift test (mainly for Windows guests): 1) Log into a guest. 2) Take a time reading from the guest and host. 3) Run load on the guest and host. 4) Take a second time reading. 5) Stop the load and rest for a while. 6) Take a third time reading. 7) If the drift immediately after load is higher than a user- specified value (in %), fail. If the drift after the rest period is higher than a user-specified value, fail. @param test: KVM test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ 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 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 guest") logging.info("Logged in") # Collect test parameters: # Command to run to get the current time time_command = params.get("time_command") # Filter which should match a string to be passed to time.strptime() time_filter_re = params.get("time_filter_re") # Time format for time.strptime() time_format = params.get("time_format") guest_load_command = params.get("guest_load_command") guest_load_stop_command = params.get("guest_load_stop_command") host_load_command = params.get("host_load_command") guest_load_instances = int(params.get("guest_load_instances", "1")) host_load_instances = int(params.get("host_load_instances", "0")) # CPU affinity mask for taskset cpu_mask = params.get("cpu_mask", "0xFF") load_duration = float(params.get("load_duration", "30")) rest_duration = float(params.get("rest_duration", "10")) drift_threshold = float(params.get("drift_threshold", "200")) drift_threshold_after_rest = float(params.get("drift_threshold_after_rest", "200")) guest_load_sessions = [] host_load_sessions = [] # Remember the VM's previous CPU affinity prev_cpu_mask = commands.getoutput("taskset -p %s" % vm.get_pid()) prev_cpu_mask = prev_cpu_mask.split()[-1] # Set the VM's CPU affinity commands.getoutput("taskset -p %s %s" % (cpu_mask, vm.get_pid())) try: # Get time before load host_time_0 = time.time() session.sendline(time_command) (match, s) = session.read_up_to_prompt() s = re.findall(time_filter_re, s)[0] guest_time_0 = time.mktime(time.strptime(s, time_format)) # Run some load on the guest logging.info("Starting load on guest...") for i in range(guest_load_instances): load_session = vm.ssh_login() if not load_session: raise error.TestFail("Could not log into guest") load_session.set_output_prefix("(guest load %d) " % i) load_session.set_output_func(logging.debug) load_session.sendline(guest_load_command) guest_load_sessions.append(load_session) # Run some load on the host logging.info("Starting load on host...") for i in range(host_load_instances): host_load_sessions.append( kvm_subprocess.run_bg( host_load_command, output_func=logging.debug, output_prefix="(host load %d) " % i, timeout=0.5 ) ) # Set the CPU affinity of the shell running the load process pid = host_load_sessions[-1].get_shell_pid() commands.getoutput("taskset -p %s %s" % (cpu_mask, pid)) # Try setting the CPU affinity of the load process itself pid = host_load_sessions[-1].get_pid() if pid: commands.getoutput("taskset -p %s %s" % (cpu_mask, pid)) # Sleep for a while (during load) logging.info("Sleeping for %s seconds..." % load_duration) time.sleep(load_duration) # Get time delta after load host_time_1 = time.time() session.sendline(time_command) (match, s) = session.read_up_to_prompt() s = re.findall(time_filter_re, s)[0] guest_time_1 = time.mktime(time.strptime(s, time_format)) # Report results host_delta = host_time_1 - host_time_0 guest_delta = guest_time_1 - guest_time_0 drift = 100.0 * (host_delta - guest_delta) / host_delta logging.info("Host duration: %.2f" % host_delta) logging.info("Guest duration: %.2f" % guest_delta) logging.info("Drift: %.2f%%" % drift) finally: logging.info("Cleaning up...") # Restore the VM's CPU affinity commands.getoutput("taskset -p %s %s" % (prev_cpu_mask, vm.get_pid())) # Stop the guest load if guest_load_stop_command: session.get_command_output(guest_load_stop_command) # Close all load shell sessions for load_session in guest_load_sessions: load_session.close() for load_session in host_load_sessions: load_session.close() # Sleep again (rest) logging.info("Sleeping for %s seconds..." % rest_duration) time.sleep(rest_duration) # Get time after rest host_time_2 = time.time() session.sendline(time_command) (match, s) = session.read_up_to_prompt() s = re.findall(time_filter_re, s)[0] guest_time_2 = time.mktime(time.strptime(s, time_format)) # Report results host_delta_total = host_time_2 - host_time_0 guest_delta_total = guest_time_2 - guest_time_0 drift_total = 100.0 * (host_delta_total - guest_delta_total) / host_delta logging.info("Total host duration including rest: %.2f" % host_delta_total) logging.info("Total guest duration including rest: %.2f" % guest_delta_total) logging.info("Total drift after rest: %.2f%%" % drift_total) # Fail the test if necessary if drift > drift_threshold: raise error.TestFail("Time drift too large: %.2f%%" % drift) if drift > drift_threshold_after_rest: raise error.TestFail("Time drift too large after rest period: %.2f%%" % drift_total) session.close()
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 _vm_create(no_console=3, no_serialport=3): """ Creates the VM and connects the specified number of consoles and serial ports. Ports are allocated by 2 per 1 virtio-serial-pci device starting with console. (3+2 => CC|CS|S; 0+2 => SS; 3+4 => CC|CS|SS|S, ...) This way it's easy to test communication on the same or different virtio-serial-pci device. Further in tests the consoles are being picked always from the first available one (3+2: 2xC => CC|cs|s <communication on the same PCI>; 2xC,1xS => CC|cS|s <communication between 2 PCI devs) @param no_console: Number of desired virtconsoles. @param no_serialport: Number of desired virtserialports. @return: Tuple with (guest information, consoles information) guest informations = [vm, session, tmp_dir] consoles informations = [consoles[], serialports[]] """ consoles = [] serialports = [] tmp_dir = tempfile.mkdtemp(prefix="virtio-console-", dir="/tmp/") if not params.get('extra_params'): params['extra_params'] = '' for i in range(0, no_console): # Spread consoles between multiple PCI devices (2 per a dev) if not i % 2: pci = "virtio-serial-pci%d" % (i / 2) params['extra_params'] += (" -device virtio-serial-pci,id=" + pci) pci += ".0" params['extra_params'] += (" -chardev socket,path=%s/%d,id=vc%d," "server,nowait" % (tmp_dir, i, i)) params['extra_params'] += (" -device virtconsole,chardev=vc%d," "name=console-%d,id=c%d,bus=%s" % (i, i, i, pci)) for i in range(no_console, no_console + no_serialport): # Spread seroal ports between multiple PCI devices (2 per a dev) if not i % 2: pci = "virtio-serial-pci%d" % (i / 2) params['extra_params'] += (" -device virtio-serial-pci,id=" + pci) pci += ".0" params['extra_params'] += (" -chardev socket,path=%s/%d,id=vs%d," "server,nowait" % (tmp_dir, i, i)) params['extra_params'] += (" -device virtserialport,chardev=vs%d," "name=serialport-%d,id=p%d,bus=%s" % (i, i, i, pci)) logging.debug("Booting first guest %s", params.get("main_vm")) kvm_preprocessing.preprocess_vm(test, params, env, params.get("main_vm")) vm = kvm_utils.env_get_vm(env, params.get("main_vm")) session = kvm_test_utils.wait_for_login(vm, 0, float(params.get("boot_timeout", 240)), 0, 2) # connect the sockets for i in range(0, no_console): consoles.append(Port(None ,"console-%d" % i, "yes", "%s/%d" % (tmp_dir, i))) for i in range(no_console, no_console + no_serialport): serialports.append(Port(None ,"serialport-%d" % i, "no", "%s/%d" % (tmp_dir, i))) return [vm, session, tmp_dir], [consoles, serialports]
def run_autotest(test, params, env): """ Run an autotest test inside a guest. @param test: kvm test object. @param params: Dictionary with test parameters. @param env: Dictionary with the test environment. """ 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("Logging into guest...") session = kvm_utils.wait_for(vm.ssh_login, 240, 0, 2) if not session: raise error.TestFail("Could not log into guest") logging.info("Logged in") # Collect some info test_name = params.get("test_name") test_timeout = int(params.get("test_timeout", 300)) test_control_file = params.get("test_control_file", "control") tarred_autotest_path = "/tmp/autotest.tar.bz2" tarred_test_path = "/tmp/%s.tar.bz2" % test_name # tar the contents of bindir/autotest cmd = "cd %s; tar cvjf %s autotest/*" cmd += " --exclude=autotest/tests" cmd += " --exclude=autotest/results" cmd += " --exclude=autotest/tmp" cmd += " --exclude=autotest/control" cmd += " --exclude=*.pyc" cmd += " --exclude=*.svn" cmd += " --exclude=*.git" kvm_subprocess.run_fg(cmd % (test.bindir, tarred_autotest_path), timeout=30) # tar the contents of bindir/autotest/tests/<test_name> cmd = "cd %s; tar cvjf %s %s/*" cmd += " --exclude=*.pyc" cmd += " --exclude=*.svn" cmd += " --exclude=*.git" kvm_subprocess.run_fg( cmd % (os.path.join(test.bindir, "autotest", "tests"), tarred_test_path, test_name), timeout=30 ) # Check if we need to copy autotest.tar.bz2 copy = False output = session.get_command_output("ls -l autotest.tar.bz2") if "such file" in output: copy = True else: size = int(output.split()[4]) if size != os.path.getsize(tarred_autotest_path): copy = True # Perform the copy if copy: logging.info("Copying autotest.tar.bz2 to guest" " (file is missing or has a different size)...") if not vm.scp_to_remote(tarred_autotest_path, ""): raise error.TestFail("Could not copy autotest.tar.bz2 to guest") # Check if we need to copy <test_name>.tar.bz2 copy = False output = session.get_command_output("ls -l %s.tar.bz2" % test_name) if "such file" in output: copy = True else: size = int(output.split()[4]) if size != os.path.getsize(tarred_test_path): copy = True # Perform the copy if copy: logging.info("Copying %s.tar.bz2 to guest (file is missing or has a" " different size)..." % test_name) if not vm.scp_to_remote(tarred_test_path, ""): raise error.TestFail("Could not copy %s.tar.bz2 to guest" % test_name) # Extract autotest.tar.bz2 logging.info("Extracting autotest.tar.bz2...") status = session.get_command_status("tar xvfj autotest.tar.bz2") if status != 0: raise error.TestFail("Could not extract autotest.tar.bz2") # mkdir autotest/tests session.sendline("mkdir autotest/tests") # Extract <test_name>.tar.bz2 into autotest/tests logging.info("Extracting %s.tar.bz2..." % test_name) status = session.get_command_status("tar xvfj %s.tar.bz2 -C " "autotest/tests" % test_name) if status != 0: raise error.TestFail("Could not extract %s.tar.bz2" % test_name) # Cleaning up old remaining results session.sendline("rm -rf autotest/results/*") # Copying the selected control file (located inside # test.bindir/autotest_control to the autotest dir control_file_path = os.path.join(test.bindir, "autotest_control", test_control_file) if not vm.scp_to_remote(control_file_path, "autotest/control"): raise error.TestFail("Could not copy the test control file to guest") # Run the test logging.info("Running test '%s'..." % test_name) session.sendline("cd autotest") session.sendline("rm -f control.state") session.read_up_to_prompt() session.sendline("bin/autotest control") logging.info("---------------- Test output ----------------") match = session.read_up_to_prompt(timeout=test_timeout, print_func=logging.info)[0] logging.info("---------------- End of test output ----------------") if not match: raise error.TestFail("Timeout elapsed while waiting for test to " "complete") # Get the results generated by autotest output = session.get_command_output("cat results/*/status") # Parse test results result_list = scan_results.parse_results(output) # Report test results and check for FAIL/ERROR status logging.info("Results (test, status, duration, info):") status_error = False status_fail = False if result_list == []: status_fail = True message_fail = "Test '%s' did not produce any recognizable " "results" % test_name for result in result_list: logging.info(str(result)) if result[1] == "FAIL": status_fail = True message_fail = "Test '%s' ended with FAIL " "(info: '%s')" % (result[0], result[3]) if result[1] == "ERROR": status_error = True message_error = "Test '%s' ended with ERROR " "(info: '%s')" % (result[0], result[3]) if result[1] == "ABORT": status_error = True message_error = "Test '%s' ended with ABORT " "(info: '%s')" % (result[0], result[3]) # Copy test results to the local bindir/guest_results logging.info("Copying results back from guest...") guest_results_dir = os.path.join(test.outputdir, "guest_results") if not os.path.exists(guest_results_dir): os.mkdir(guest_results_dir) if not vm.scp_from_remote("autotest/results/default/*", guest_results_dir): logging.error("Could not copy results back from guest") # Fail the test if necessary if status_fail: raise error.TestFail(message_fail) elif status_error: raise error.TestError(message_error)
params['pid_' + vm_name] = kvm_utils.generate_tmp_file_name(vm_name, 'pid') if not params.get('extra_params'): params['extra_params'] = ' ' 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) # ksm_size: amount of memory used by allocator ksm_size = mem - guest_reserve logging.debug("Memory used by allocator on guests = %dM" % (ksm_size)) # Creating the first guest kvm_preprocessing.preprocess_vm(test, params, env, vm_name) lvms.append(kvm_utils.env_get_vm(env, vm_name)) if not lvms[0]: raise error.TestError("VM object not found in environment") if not lvms[0].is_alive(): raise error.TestError("VM seems to be dead; Test requires a living " "VM") logging.debug("Booting first guest %s", lvms[0].name) lsessions.append(kvm_utils.wait_for(lvms[0].remote_login, 360, 0, 2)) if not lsessions[0]: raise error.TestFail("Could not log into first guest") # Associate vm PID try: tmp = open(params.get('pid_' + vm_name), 'r') params['pid_' + vm_name] = int(tmp.readline())
def run_steps(test, params, env): 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(): e_msg = "VM seems to be dead. Guestwizard requires a living VM" raise error.TestError(e_msg) steps_filename = params.get("steps") if not steps_filename: raise error.TestError("Steps filename not specified") steps_filename = kvm_utils.get_path(test.bindir, steps_filename) if not os.path.exists(steps_filename): raise error.TestError("Steps file not found: %s" % steps_filename) sf = open(steps_filename, "r") lines = sf.readlines() sf.close() vm.monitor.cmd("cont") current_step_num = 0 current_screendump = None skip_current_step = False # Iterate over the lines in the file for line in lines: line = line.strip() if not line: continue logging.info(line) if line.startswith("#"): continue words = line.split() if words[0] == "step": current_step_num += 1 current_screendump = None skip_current_step = False elif words[0] == "screendump": current_screendump = words[1] elif skip_current_step: continue elif words[0] == "sleep": timeout_multiplier = float(params.get("timeout_multiplier") or 1) time.sleep(float(words[1]) * timeout_multiplier) elif words[0] == "key": vm.send_key(words[1]) elif words[0] == "var": if not handle_var(vm, params, words[1]): logging.error("Variable not defined: %s" % words[1]) elif words[0] == "barrier_2": if current_screendump: scrdump_filename = os.path.join( ppm_utils.get_data_dir(steps_filename), current_screendump) else: scrdump_filename = None if not barrier_2(vm, words, params, test.debugdir, scrdump_filename, current_step_num): skip_current_step = True else: vm.send_key(words[0])
def run_unittest(test, params, env): """ KVM RHEL-6 style unit test: 1) Resume a stopped VM 2) Wait for VM to terminate 3) If qemu exited with code = 0, the unittest passed. Otherwise, it failed 4) Collect all logs generated @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment """ unittest_dir = os.path.join(test.bindir, 'unittests') if not os.path.isdir(unittest_dir): raise error.TestError("No unittest dir %s available (did you run the " "build test first?)" % unittest_dir) os.chdir(unittest_dir) unittest_list = glob.glob('*.flat') if not unittest_list: raise error.TestError("No unittest files available (did you run the " "build test first?)") logging.debug('Flat file list: %s', unittest_list) unittest_cfg = os.path.join(unittest_dir, 'unittests.cfg') parser = ConfigParser.ConfigParser() parser.read(unittest_cfg) test_list = parser.sections() if not test_list: raise error.TestError("No tests listed on config file %s" % unittest_cfg) logging.debug('Unit test list: %s' % test_list) if params.get('test_list', None): test_list = kvm_utils.get_sub_dict_names(params, 'test_list') logging.info('Original test list overriden by user') logging.info('User defined unit test list: %s' % test_list) nfail = 0 tests_failed = [] timeout = int(params.get('unittest_timeout', 600)) extra_params_original = params['extra_params'] for t in test_list: logging.info('Running %s', t) file = None if parser.has_option(t, 'file'): file = parser.get(t, 'file') if file is None: nfail += 1 tests_failed.append(t) logging.error('Unittest config file %s has section %s but no ' 'mandatory option file' % (unittest_cfg, t)) continue if file not in unittest_list: nfail += 1 tests_failed.append(t) logging.error('Unittest file %s referenced in config file %s but ' 'was not find under the unittest dir' % (file, unittest_cfg)) continue smp = None if parser.has_option(t, 'smp'): smp = int(parser.get(t, 'smp')) params['smp'] = smp extra_params = None if parser.has_option(t, 'extra_params'): extra_params = parser.get(t, 'extra_params') params['extra_params'] += ' %s' % extra_params vm_name = params.get("main_vm") params['kernel'] = os.path.join(unittest_dir, file) testlog_path = os.path.join(test.debugdir, "%s.log" % t) try: try: vm_name = params.get('main_vm') kvm_preprocessing.preprocess_vm(test, params, env, vm_name) vm = kvm_utils.env_get_vm(env, vm_name) vm.create() vm.monitor.cmd("cont") logging.info("Waiting for unittest %s to complete, timeout %s, " "output in %s", t, timeout, vm.get_testlog_filename()) if not kvm_utils.wait_for(vm.is_dead, timeout): raise error.TestFail("Timeout elapsed (%ss)" % timeout) # Check qemu's exit status status = vm.process.get_status() if status != 0: nfail += 1 tests_failed.append(t) logging.error("Unit test %s failed", t) except Exception, e: nfail += 1 tests_failed.append(t) logging.error('Exception happened during %s: %s', t, str(e)) finally: try: shutil.copy(vm.get_testlog_filename(), testlog_path) logging.info("Unit test log collected and available under %s", testlog_path) except NameError, IOError: logging.error("Not possible to collect logs") # Restore the extra params so other tests can run normally params['extra_params'] = extra_params_original