Example #1
0
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",
        )
Example #2
0
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")
Example #3
0
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")
Example #4
0
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
Example #5
0
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]))
Example #6
0
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)
Example #7
0
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