Refactor autotest subtest into a utility function, so other KVM subtests can run autotest control files in hosts as part of their routine. This arrangement was made to accomodate the upcoming 'cpu_hotplug' test. Why not just do the non-autotest part on cpu_hotplug and make autotest.cpu_hotplug dependent on cpu_hotplug? Because: 1) autotest.cpu_hotplug is a valid test on its own, for any situations where smp > 1 on qemu virtual machines. 2) Adding cpus to qemu on the fly is pretty broken at the moment (qemu segfaults, no ETA to fix), so skip the autotest.cpu_hotplug test when the cpu_hotplug fails means we won't manage to run the autotest test at all. Why test feature that is not mature then? Because it is there anyway, and by the time it is functional, we'll already have a test for it :) Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx> --- client/tests/kvm/kvm_test_utils.py | 166 +++++++++++++++++++++++++++++++++++- client/tests/kvm/tests/autotest.py | 153 ++------------------------------- 2 files changed, 172 insertions(+), 147 deletions(-) diff --git a/client/tests/kvm/kvm_test_utils.py b/client/tests/kvm/kvm_test_utils.py index 02ec0cf..a581ca9 100644 --- a/client/tests/kvm/kvm_test_utils.py +++ b/client/tests/kvm/kvm_test_utils.py @@ -23,7 +23,7 @@ More specifically: import time, os, logging, re, commands from autotest_lib.client.common_lib import utils, error -import kvm_utils, kvm_vm, kvm_subprocess +import kvm_utils, kvm_vm, kvm_subprocess, scan_results def get_living_vm(env, vm_name): @@ -203,3 +203,167 @@ def get_time(session, time_command, time_filter_re, time_format): s = re.findall(time_filter_re, s)[0] guest_time = time.mktime(time.strptime(s, time_format)) return (host_time, guest_time) + + +def run_autotest(vm, session, control_path, timeout, test_name, outputdir): + """ + Run an autotest control file inside a guest (linux only utility). + + @param vm: VM object. + @param session: A shell session on the VM provided. + @param control: An autotest control file. + @param timeout: Timeout under which the autotest test must complete. + @param test_name: Autotest client test name. + @param outputdir: Path on host where we should copy the guest autotest + results to. + """ + 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 + basename = os.path.basename(local_path) + local_size = os.path.getsize(local_path) + output = session.get_command_output("ls -l %s" % remote_path) + if "such file" in output: + logging.info("Copying %s to guest (remote file is missing)" % + basename) + copy = True + else: + try: + remote_size = output.split()[4] + remote_size = int(remote_size) + except IndexError, ValueError: + logging.error("Check for remote path size %s returned %s. " + "Cannot process.", remote_path, output) + raise error.TestFail("Failed to check for %s (Guest died?)" % + remote_path) + if remote_size != local_size: + logging.debug("Copying %s to guest due to size mismatch" + "(remote size %s, local size %s)" % + (basename, remote_size, local_size)) + copy = True + + if copy: + if not vm.copy_files_to(local_path, remote_path): + raise error.TestFail("Could not copy %s to guest" % local_path) + + + def 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, output) = session.get_command_status_output( + "tar xjvf %s -C %s" % (remote_path, dest_dir)) + if status != 0: + logging.error("Uncompress output:\n%s" % output) + raise error.TestFail("Could not extract % on guest") + + if not os.path.isfile(control_path): + raise error.TestError("Invalid path to autotest control file: %s" % + control_path) + + tarred_autotest_path = "/tmp/autotest.tar.bz2" + tarred_test_path = "/tmp/%s.tar.bz2" % test_name + + # To avoid problems, let's make the test use the current AUTODIR + # (autotest client path) location + autotest_path = os.environ['AUTODIR'] + tests_path = os.path.join(autotest_path, 'tests') + test_path = os.path.join(tests_path, test_name) + + # tar the contents of bindir/autotest + cmd = "tar cvjf %s %s/*" % (tarred_autotest_path, autotest_path) + cmd += " --exclude=%s/tests" % autotest_path + cmd += " --exclude=%s/results" % autotest_path + cmd += " --exclude=%s/tmp" % autotest_path + cmd += " --exclude=%s/control" % autotest_path + cmd += " --exclude=*.pyc" + cmd += " --exclude=*.svn" + cmd += " --exclude=*.git" + utils.run(cmd) + + # tar the contents of bindir/autotest/tests/<test_name> + cmd = "tar cvjf %s %s/*" % (tarred_test_path, test_path) + cmd += " --exclude=*.pyc" + cmd += " --exclude=*.svn" + cmd += " --exclude=*.git" + utils.run(cmd) + + # Copy autotest.tar.bz2 + copy_if_size_differs(vm, tarred_autotest_path, tarred_autotest_path) + + # Copy <test_name>.tar.bz2 + copy_if_size_differs(vm, tarred_test_path, tarred_test_path) + + # Extract autotest.tar.bz2 + extract(vm, tarred_autotest_path, "/") + + # mkdir autotest/tests + session.get_command_output("mkdir -p %s" % tests_path) + + # Extract <test_name>.tar.bz2 into autotest/tests + extract(vm, tarred_test_path, "/") + + if not vm.copy_files_to(control_path, + os.path.join(autotest_path, 'control')): + raise error.TestFail("Could not copy the test control file to guest") + + # Run the test + logging.info("Running test '%s'..." % test_name) + session.get_command_output("cd %s" % autotest_path) + session.get_command_output("rm -f control.state") + session.get_command_output("rm -rf results/*") + logging.info("---------------- Test output ----------------") + status = session.get_command_status("bin/autotest control", + timeout=timeout, + print_func=logging.info) + logging.info("--------------End of test output ------------") + if status is None: + raise error.TestFail("Timeout elapsed while waiting for autotest 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(outputdir, "guest_autotest_results") + if not os.path.exists(guest_results_dir): + os.mkdir(guest_results_dir) + if not vm.copy_files_from("%s/results/default/*" % autotest_path, + 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])) + diff --git a/client/tests/kvm/tests/autotest.py b/client/tests/kvm/tests/autotest.py index f19a2ec..07dd0a9 100644 --- a/client/tests/kvm/tests/autotest.py +++ b/client/tests/kvm/tests/autotest.py @@ -1,7 +1,7 @@ import os, logging from autotest_lib.client.common_lib import error from autotest_lib.client.bin import utils -import kvm_subprocess, kvm_utils, kvm_test_utils, scan_results +import kvm_subprocess, kvm_utils, kvm_test_utils def run_autotest(test, params, env): @@ -12,155 +12,16 @@ def run_autotest(test, params, env): @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 - basename = os.path.basename(local_path) - output = session.get_command_output("ls -l %s" % remote_path) - local_size = os.path.getsize(local_path) - if "such file" in output: - logging.info("Copying %s to guest (remote file is missing)" % - basename) - copy = True - else: - remote_size = int(output.split()[4]) - if remote_size != local_size: - logging.info("Copying %s to guest due to size mismatch" - "(remote size %s, local size %s)" % (basename, - remote_size, - local_size)) - copy = True - - if copy: - if not vm.copy_files_to(local_path, remote_path): - raise error.TestFail("Could not copy %s to guest" % local_path) - - - def 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, output) = session.get_command_status_output( - "tar xjvf %s -C %s" % (remote_path, dest_dir)) - if status != 0: - raise error.TestFail("Could not extract %s, command output: %s" % - (basename, output)) - vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) session = kvm_test_utils.wait_for_login(vm) # Collect test parameters + timeout = int(params.get("test_timeout", 300)) 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 - - # To avoid problems, let's make the test use the current AUTODIR - # (autotest client path) location - autotest_path = os.environ['AUTODIR'] - tests_path = os.path.join(autotest_path, 'tests') - test_path = os.path.join(tests_path, test_name) - - # tar the contents of bindir/autotest - cmd = "tar cvjf %s %s/*" % (tarred_autotest_path, autotest_path) - cmd += " --exclude=%s/tests" % autotest_path - cmd += " --exclude=%s/results" % autotest_path - cmd += " --exclude=%s/tmp" % autotest_path - cmd += " --exclude=%s/control" % autotest_path - cmd += " --exclude=*.pyc" - cmd += " --exclude=*.svn" - cmd += " --exclude=*.git" - utils.run(cmd) - - # tar the contents of bindir/autotest/tests/<test_name> - cmd = "tar cvjf %s %s/*" % (tarred_test_path, test_path) - cmd += " --exclude=*.pyc" - cmd += " --exclude=*.svn" - cmd += " --exclude=*.git" - utils.run(cmd) - - # Copy autotest.tar.bz2 - copy_if_size_differs(vm, tarred_autotest_path, tarred_autotest_path) - - # Copy <test_name>.tar.bz2 - copy_if_size_differs(vm, tarred_test_path, tarred_test_path) - - # Extract autotest.tar.bz2 - extract(vm, tarred_autotest_path, "/") - - # mkdir autotest/tests - session.get_command_output("mkdir -p %s" % tests_path) - - # Extract <test_name>.tar.bz2 into autotest/tests - extract(vm, tarred_test_path, "/") - - # 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, - os.path.join(autotest_path, 'control')): - raise error.TestFail("Could not copy the test control file to guest") - - # Run the test - logging.info("Running test '%s'..." % test_name) - session.get_command_output("cd %s" % autotest_path) - session.get_command_output("rm -f control.state") - session.get_command_output("rm -rf results/*") - 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("%s/results/default/*" % autotest_path, - 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)) + control_path = os.path.join(test.bindir, "autotest_control", + params.get("test_control_file")) + outputdir = test.outputdir - # 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"] + kvm_test_utils.run_autotest(vm, session, control_path, timeout, test_name, + outputdir) - # 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])) -- 1.6.6 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html