def postprocess(test, params, env): """ Postprocess all VMs and images according to the instructions in params. @param test: An Autotest test object. @param params: Dict containing all VM and image parameters. @param env: The environment (a dict-like object). """ process(test, params, env, postprocess_image, postprocess_vm) # Should we convert PPM files to PNG format? if params.get("convert_ppm_files_to_png") == "yes": logging.debug("'convert_ppm_files_to_png' specified; converting PPM" " files to PNG format...") mogrify_cmd = "mogrify -format png %s" % os.path.join(test.debugdir, "*.ppm") kvm_subprocess.run_fg(mogrify_cmd, logging.debug, "(mogrify) ", timeout=30.0) # Should we keep the PPM files? if params.get("keep_ppm_files") != "yes": logging.debug("'keep_ppm_files' not specified; removing all PPM files" " from debug dir...") rm_cmd = "rm -vf %s" % os.path.join(test.debugdir, "*.ppm") kvm_subprocess.run_fg(rm_cmd, logging.debug, "(rm) ", timeout=5.0) # Execute any post_commands if params.get("post_command"): process_command( test, params, env, params.get("post_command"), int(params.get("post_command_timeout", "600")), params.get("post_command_noncritical") == "yes", )
def run_pxe(test, params, env): """ PXE test: 1) Snoop the tftp packet in the tap device. 2) Wait for some seconds. 3) Check whether we could capture TFTP packets. @param test: KVM test object. @param params: Dictionary with the test parameters. @param env: Dictionary with test environment. """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = int(params.get("pxe_timeout", 60)) logging.info("Try to boot from PXE") output = kvm_subprocess.run_fg("tcpdump -nli %s" % vm.get_ifname(), logging.debug, "(pxe capture) ", timeout)[1] logging.info("Analyzing the tcpdump result...") if not "tftp" in output: raise error.TestFail("Couldn't find any TFTP packets after %s seconds" % timeout) logging.info("Found TFTP packet")
def process_command(test, params, env, command, command_timeout, command_noncritical): """ Pre- or post- custom commands to be executed before/after a test is run @param test: An Autotest test object. @param params: A dict containing all VM and image parameters. @param env: The environment (a dict-like object). @param command: Command to be run. @param command_timeout: Timeout for command execution. @param command_noncritical: If True test will not fail if command fails. """ # Export environment vars for k in params.keys(): os.putenv("KVM_TEST_%s" % k, str(params[k])) # Execute command logging.info("Executing command '%s'..." % command) (status, output) = kvm_subprocess.run_fg("cd %s; %s" % (test.bindir, command), logging.debug, "(command) ", timeout=command_timeout) if status != 0: logging.warn("Custom processing command failed: '%s'" % command) if not command_noncritical: raise error.TestError("Custom processing command failed")
def create_image(params, qemu_img_path, image_dir): """ Create an image using qemu_image. @param params: Dictionary containing the test parameters. @param qemu_img_path: The path of the qemu-img binary @param image_dir: The directory where the image is to be located @note: params should contain: image_name -- the name of the image file, without extension image_format -- the format of the image (qcow2, raw etc) image_size -- the requested size of the image (a string qemu-img can understand, such as '10G') """ qemu_img_cmd = qemu_img_path qemu_img_cmd += " create" format = params.get("image_format", "qcow2") qemu_img_cmd += " -f %s" % format image_filename = get_image_filename(params, image_dir) qemu_img_cmd += " %s" % image_filename size = params.get("image_size", "10G") qemu_img_cmd += " %s" % size logging.debug("Running qemu-img command:\n%s" % qemu_img_cmd) (status, output) = kvm_subprocess.run_fg(qemu_img_cmd, logging.debug, "(qemu-img) ", timeout=30) if status is None: logging.error("Timeout elapsed while waiting for qemu-img command " "to complete:\n%s" % qemu_img_cmd) return None elif status != 0: logging.error("Could not create image; " "qemu-img command failed:\n%s" % qemu_img_cmd) logging.error("Status: %s" % status) logging.error("Output:" + kvm_utils.format_str_for_message(output)) return None if not os.path.exists(image_filename): logging.error("Image could not be created for some reason; " "qemu-img command:\n%s" % qemu_img_cmd) return None logging.info("Image created in %s" % image_filename) return image_filename
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. """ # Helper functions def copy_if_size_differs(vm, local_path, remote_path): """ Copy a file to a guest if it doesn't exist or if its size differs. @param vm: VM object @param local_path: Local path @param remote_path: Remote path """ copy = False output = session.get_command_output("ls -l %s" % remote_path) if ("such file" in output or int(output.split()[4]) != os.path.getsize(local_path)): basename = os.path.basename(local_path) logging.info("Copying %s to guest (file is missing or has a " "different size)..." % basename) if not vm.copy_files_to(local_path, remote_path): raise error.TestFail("Could not copy %s to guest" % basename) def extract(vm, remote_path, dest_dir="."): """ Extract a .tar.bz2 file on the guest. @param vm: VM object @param remote_path: Remote file path @param dest_dir: Destination dir for the contents """ basename = os.path.basename(remote_path) logging.info("Extracting %s..." % basename) status = session.get_command_status("tar xfj %s -C %s" % (remote_path, dest_dir)) if status != 0: raise error.TestFail("Could not extract %s" % basename) vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) session = kvm_test_utils.wait_for_login(vm) # Collect test parameters 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) # Copy autotest.tar.bz2 copy_if_size_differs(vm, tarred_autotest_path, "autotest.tar.bz2") # Copy <test_name>.tar.bz2 copy_if_size_differs(vm, tarred_test_path, test_name + ".tar.bz2") # Extract autotest.tar.bz2 extract(vm, "autotest.tar.bz2") # mkdir autotest/tests session.sendline("mkdir autotest/tests") # Extract <test_name>.tar.bz2 into autotest/tests extract(vm, test_name + ".tar.bz2", "autotest/tests") # Copy 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.copy_files_to(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.sendline("rm -rf results/*") session.read_up_to_prompt() logging.info("---------------- Test output ----------------") status = session.get_command_status("bin/autotest control", timeout=test_timeout, print_func=logging.info) logging.info("---------------- End of test output ----------------") if status is None: 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") results = scan_results.parse_results(output) session.close # 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.copy_files_from("autotest/results/default/*", guest_results_dir): logging.error("Could not copy results back from guest") # Report test results logging.info("Results (test, status, duration, info):") for result in results: logging.info(str(result)) # Make a list of FAIL/ERROR/ABORT results (make sure FAIL results appear # before ERROR results, and ERROR results appear before ABORT results) bad_results = [r for r in results if r[1] == "FAIL"] bad_results += [r for r in results if r[1] == "ERROR"] bad_results += [r for r in results if r[1] == "ABORT"] # Fail the test if necessary if not results: raise error.TestFail("Test '%s' did not produce any recognizable " "results" % test_name) if bad_results: result = bad_results[0] raise error.TestFail("Test '%s' ended with %s (reason: '%s')" % (result[0], result[1], result[3]))
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)
def barrier_2(vm, words, params, debug_dir, data_scrdump_filename, current_step_num): if len(words) < 7: logging.error("Bad barrier_2 command line") return False cmd, dx, dy, x1, y1, md5sum, timeout = words[:7] dx, dy, x1, y1, timeout = map(int, [dx, dy, x1, y1, timeout]) # Timeout/5 is the time it took stepmaker to complete this step. # Divide that number by 10 to poll 10 times, just in case # current machine is stronger then the "stepmaker machine". # Limit to 1 (min) and 10 (max) seconds between polls. sleep_duration = float(timeout) / 50.0 if sleep_duration < 1.0: sleep_duration = 1.0 if sleep_duration > 10.0: sleep_duration = 10.0 scrdump_filename = os.path.join(debug_dir, "scrdump.ppm") cropped_scrdump_filename = os.path.join(debug_dir, "cropped_scrdump.ppm") expected_scrdump_filename = os.path.join(debug_dir, "scrdump_expected.ppm") expected_cropped_scrdump_filename = os.path.join(debug_dir, "cropped_scrdump_expected.ppm") comparison_filename = os.path.join(debug_dir, "comparison.ppm") fail_if_stuck_for = params.get("fail_if_stuck_for") if fail_if_stuck_for: fail_if_stuck_for = float(fail_if_stuck_for) else: fail_if_stuck_for = 1e308 stuck_detection_history = params.get("stuck_detection_history") if stuck_detection_history: stuck_detection_history = int(stuck_detection_history) else: stuck_detection_history = 2 keep_screendump_history = params.get("keep_screendump_history") == "yes" if keep_screendump_history: keep_all_history = params.get("keep_all_history") == "yes" history_dir = os.path.join(debug_dir, "barrier_history") end_time = time.time() + timeout end_time_stuck = time.time() + fail_if_stuck_for start_time = time.time() prev_whole_image_md5sums = [] failure_message = None # Main loop while True: # Check for timeouts if time.time() > end_time: failure_message = "regular timeout" break if time.time() > end_time_stuck: failure_message = "guest is stuck" break # Make sure vm is alive if not vm.is_alive(): failure_message = "VM is dead" break # Request screendump (status, output) = vm.send_monitor_cmd("screendump %s" % scrdump_filename) if status: logging.error("Could not fetch screendump") continue # Make sure image is valid if not ppm_utils.image_verify_ppm_file(scrdump_filename): failure_message = "got invalid screendump" break # Read image file (w, h, data) = ppm_utils.image_read_from_ppm_file(scrdump_filename) # Compute md5sum of whole image whole_image_md5sum = ppm_utils.image_md5sum(w, h, data) # Write screendump to history_dir (as JPG) if requested # and if the screendump differs from the previous one if (keep_screendump_history and whole_image_md5sum not in prev_whole_image_md5sums[:1]): try: os.makedirs(history_dir) except: pass history_scrdump_filename = os.path.join(history_dir, "scrdump-step_%s-%s.jpg" % (current_step_num, time.strftime("%Y%m%d-%H%M%S"))) kvm_subprocess.run_fg("convert -quality 30 %s %s" % (scrdump_filename, history_scrdump_filename), logging.debug, "(convert) ", timeout=30) # Compare md5sum of barrier region with the expected md5sum calced_md5sum = ppm_utils.get_region_md5sum(w, h, data, x1, y1, dx, dy, cropped_scrdump_filename) if calced_md5sum == md5sum: # Success -- remove screendump history unless requested not to if keep_screendump_history and not keep_all_history: kvm_subprocess.run_fg("rm -rvf %s" % history_dir, logging.debug, "(rm) ", timeout=30) # Report success return True # Insert image md5sum into queue of last seen images: # If md5sum is already in queue... if whole_image_md5sum in prev_whole_image_md5sums: # Remove md5sum from queue prev_whole_image_md5sums.remove(whole_image_md5sum) else: # Otherwise extend 'stuck' timeout end_time_stuck = time.time() + fail_if_stuck_for # Insert md5sum at beginning of queue prev_whole_image_md5sums.insert(0, whole_image_md5sum) # Limit queue length to stuck_detection_history prev_whole_image_md5sums = \ prev_whole_image_md5sums[:stuck_detection_history] # Sleep for a while time.sleep(sleep_duration) # Failure message = ("Barrier failed at step %s after %.2f seconds (%s)" % (current_step_num, time.time() - start_time, failure_message)) # What should we do with this failure? if words[-1] == "optional": logging.info(message) return False else: # Collect information and put it in debug_dir if data_scrdump_filename and os.path.exists(data_scrdump_filename): # Read expected screendump image (ew, eh, edata) = \ ppm_utils.image_read_from_ppm_file(data_scrdump_filename) # Write it in debug_dir ppm_utils.image_write_to_ppm_file(expected_scrdump_filename, ew, eh, edata) # Write the cropped version as well ppm_utils.get_region_md5sum(ew, eh, edata, x1, y1, dx, dy, expected_cropped_scrdump_filename) # Perform comparison (w, h, data) = ppm_utils.image_read_from_ppm_file(scrdump_filename) if w == ew and h == eh: (w, h, data) = ppm_utils.image_comparison(w, h, data, edata) ppm_utils.image_write_to_ppm_file(comparison_filename, w, h, data) # Print error messages and fail the test long_message = message + "\n(see analysis at %s)" % debug_dir logging.error(long_message) raise error.TestFail, message