Index: client/tests/kvm/tests/whql_submission.py |
diff --git a/client/tests/kvm/tests/whql_submission.py b/client/tests/kvm/tests/whql_submission.py |
index 1fe27c9ed03413b55d4122113f0aef6e57a4dade..c3621c43945a322967dd7bbe82e8c042ceade02b 100644 |
--- a/client/tests/kvm/tests/whql_submission.py |
+++ b/client/tests/kvm/tests/whql_submission.py |
@@ -1,25 +1,38 @@ |
-import logging, time, os, re |
+import logging, os, re |
from autotest_lib.client.common_lib import error |
-import kvm_subprocess, kvm_test_utils, kvm_utils, rss_file_transfer |
+import kvm_subprocess, kvm_utils, rss_file_transfer |
def run_whql_submission(test, params, env): |
""" |
WHQL submission test: |
- 1) Log into the guest (the client machine) and into a DTM server machine |
+ 1) Log into the client machines and into a DTM server machine |
2) Copy the automation program binary (dsso_test_binary) to the server machine |
3) Run the automation program |
4) Pass the program all relevant parameters (e.g. device_data) |
5) Wait for the program to terminate |
6) Parse and report job results |
- (logs and HTML reports are placed in test.bindir) |
+ (logs and HTML reports are placed in test.debugdir) |
@param test: kvm test object |
@param params: Dictionary with the test parameters |
@param env: Dictionary with test environment. |
""" |
- vm = kvm_test_utils.get_living_vm(env, params.get("main_vm")) |
- session = kvm_test_utils.wait_for_login(vm, 0, 240) |
+ # Log into all client VMs |
+ login_timeout = int(params.get("login_timeout", 360)) |
+ vms = [] |
+ sessions = [] |
+ for vm_name in params.objects("vms"): |
+ vms.append(env.get_vm(vm_name)) |
+ vms[-1].verify_alive() |
+ sessions.append(vms[-1].wait_for_login(timeout=login_timeout)) |
+ |
+ # Make sure all NICs of all client VMs are up |
+ for vm in vms: |
+ nics = vm.params.objects("nics") |
+ for nic_index in range(len(nics)): |
+ s = vm.wait_for_login(nic_index, 600) |
+ s.close() |
# Collect parameters |
server_address = params.get("server_address") |
@@ -30,41 +43,61 @@ def run_whql_submission(test, params, env): |
dsso_test_binary = params.get("dsso_test_binary", |
"deps/whql_submission_15.exe") |
dsso_test_binary = kvm_utils.get_path(test.bindir, dsso_test_binary) |
- test_device = params.get("test_device") |
- job_filter = params.get("job_filter", ".*") |
+ dsso_delete_machine_binary = params.get("dsso_delete_machine_binary", |
+ "deps/whql_delete_machine_15.exe") |
+ dsso_delete_machine_binary = kvm_utils.get_path(test.bindir, |
+ dsso_delete_machine_binary) |
test_timeout = float(params.get("test_timeout", 600)) |
- wtt_services = params.get("wtt_services") |
- |
- # Restart WTT service(s) on the client |
- logging.info("Restarting WTT services on client") |
- for svc in wtt_services.split(): |
- kvm_test_utils.stop_windows_service(session, svc) |
- for svc in wtt_services.split(): |
- kvm_test_utils.start_windows_service(session, svc) |
- # Copy dsso_test_binary to the server |
- rss_file_transfer.upload(server_address, server_file_transfer_port, |
- dsso_test_binary, server_studio_path, timeout=60) |
+ # Copy dsso binaries to the server |
+ for filename in dsso_test_binary, dsso_delete_machine_binary: |
+ rss_file_transfer.upload(server_address, server_file_transfer_port, |
+ filename, server_studio_path, timeout=60) |
# Open a shell session with the server |
server_session = kvm_utils.remote_login("nc", server_address, |
server_shell_port, "", "", |
- session.prompt, session.linesep) |
+ sessions[0].prompt, |
+ sessions[0].linesep) |
+ server_session.set_status_test_command(sessions[0].status_test_command) |
- # Get the computer names of the server and client |
+ # Get the computer names of the server and clients |
cmd = "echo %computername%" |
- server_name = server_session.get_command_output(cmd).strip() |
- client_name = session.get_command_output(cmd).strip() |
- session.close() |
+ server_name = server_session.cmd_output(cmd).strip() |
+ client_names = [session.cmd_output(cmd).strip() for session in sessions] |
+ |
+ # Delete all client machines from the server's data store |
+ server_session.cmd("cd %s" % server_studio_path) |
+ for client_name in client_names: |
+ cmd = "%s %s %s" % (os.path.basename(dsso_delete_machine_binary), |
+ server_name, client_name) |
+ server_session.cmd(cmd, print_func=logging.debug) |
+ |
+ # Reboot the client machines |
+ sessions = kvm_utils.parallel((vm.reboot, (session,)) |
+ for vm, session in zip(vms, sessions)) |
+ |
+ # Check the NICs again |
+ for vm in vms: |
+ nics = vm.params.objects("nics") |
+ for nic_index in range(len(nics)): |
+ s = vm.wait_for_login(nic_index, 600) |
+ s.close() |
+ |
+ # Run whql_pre_command and close the sessions |
+ if params.get("whql_pre_command"): |
+ for session in sessions: |
+ session.cmd(params.get("whql_pre_command"), |
+ int(params.get("whql_pre_command_timeout", 600))) |
+ session.close() |
# Run the automation program on the server |
- server_session.get_command_output("cd %s" % server_studio_path) |
+ pool_name = "%s_pool" % client_names[0] |
+ submission_name = "%s_%s" % (client_names[0], |
+ params.get("submission_name")) |
cmd = "%s %s %s %s %s %s" % (os.path.basename(dsso_test_binary), |
- server_name, |
- client_name, |
- "%s_pool" % client_name, |
- "%s_submission" % client_name, |
- test_timeout) |
+ server_name, pool_name, submission_name, |
+ test_timeout, " ".join(client_names)) |
server_session.sendline(cmd) |
# Helper function: wait for a given prompt and raise an exception if an |
@@ -78,40 +111,69 @@ def run_whql_submission(test, params, env): |
if errors: |
raise error.TestError(errors[0]) |
else: |
- raise error.TestError("Error running automation program: could " |
- "not find '%s' prompt" % prompt) |
+ raise error.TestError("Error running automation program: " |
+ "could not find '%s' prompt" % prompt) |
# Tell the automation program which device to test |
find_prompt("Device to test:") |
- server_session.sendline(test_device) |
+ server_session.sendline(params.get("test_device")) |
# Tell the automation program which jobs to run |
find_prompt("Jobs to run:") |
- server_session.sendline(job_filter) |
+ server_session.sendline(params.get("job_filter", ".*")) |
- # Give the automation program all the device data supplied by the user |
+ # Set submission DeviceData |
find_prompt("DeviceData name:") |
- for dd in kvm_utils.get_sub_dict_names(params, "device_data"): |
- dd_params = kvm_utils.get_sub_dict(params, dd) |
+ for dd in params.objects("device_data"): |
+ dd_params = params.object_params(dd) |
if dd_params.get("dd_name") and dd_params.get("dd_data"): |
server_session.sendline(dd_params.get("dd_name")) |
server_session.sendline(dd_params.get("dd_data")) |
server_session.sendline() |
- # Give the automation program all the descriptor information supplied by |
- # the user |
+ # Set submission descriptors |
find_prompt("Descriptor path:") |
- for desc in kvm_utils.get_sub_dict_names(params, "descriptors"): |
- desc_params = kvm_utils.get_sub_dict(params, desc) |
+ for desc in params.objects("descriptors"): |
+ desc_params = params.object_params(desc) |
if desc_params.get("desc_path"): |
server_session.sendline(desc_params.get("desc_path")) |
server_session.sendline() |
+ # Set machine dimensions for each client machine |
+ for vm_name in params.objects("vms"): |
+ vm_params = params.object_params(vm_name) |
+ find_prompt(r"Dimension name\b.*:") |
+ for dp in vm_params.objects("dimensions"): |
+ dp_params = vm_params.object_params(dp) |
+ if dp_params.get("dim_name") and dp_params.get("dim_value"): |
+ server_session.sendline(dp_params.get("dim_name")) |
+ server_session.sendline(dp_params.get("dim_value")) |
+ server_session.sendline() |
+ |
+ # Set extra parameters for tests that require them (e.g. NDISTest) |
+ for vm_name in params.objects("vms"): |
+ vm_params = params.object_params(vm_name) |
+ find_prompt(r"Parameter name\b.*:") |
+ for dp in vm_params.objects("device_params"): |
+ dp_params = vm_params.object_params(dp) |
+ if dp_params.get("dp_name") and dp_params.get("dp_regex"): |
+ server_session.sendline(dp_params.get("dp_name")) |
+ server_session.sendline(dp_params.get("dp_regex")) |
+ # Make sure the prompt appears again (if the device isn't found |
+ # the automation program will terminate) |
+ find_prompt(r"Parameter name\b.*:") |
+ server_session.sendline() |
+ |
# Wait for the automation program to terminate |
- m, o = server_session.read_up_to_prompt(print_func=logging.info, |
- timeout=test_timeout + 300) |
- # (test_timeout + 300 is used here because the automation program is |
- # supposed to terminate cleanly on its own when test_timeout expires) |
+ try: |
+ o = server_session.read_up_to_prompt(print_func=logging.info, |
+ timeout=test_timeout + 300) |
+ # (test_timeout + 300 is used here because the automation program is |
+ # supposed to terminate cleanly on its own when test_timeout expires) |
+ done = True |
+ except kvm_subprocess.ExpectError, e: |
+ o = e.output |
+ done = False |
server_session.close() |
# Look for test results in the automation program's output |
@@ -151,38 +213,63 @@ def run_whql_submission(test, params, env): |
except (KeyError, OSError): |
pass |
- # Print result summary |
- logging.info("") |
- logging.info("Result summary:") |
- name_length = max(len(r.get("job", "")) for r in results) |
- fmt = "%%-6s %%-%ds %%-15s %%-8s %%-8s %%-8s %%-15s" % name_length |
- logging.info(fmt % ("ID", "Job", "Status", "Pass", "Fail", "NotRun", |
- "NotApplicable")) |
- logging.info(fmt % ("--", "---", "------", "----", "----", "------", |
- "-------------")) |
- for r in results: |
- logging.info(fmt % (r.get("id"), r.get("job"), r.get("status"), |
- r.get("pass"), r.get("fail"), r.get("notrun"), |
- r.get("notapplicable"))) |
- logging.info("(see logs and HTML reports in %s)" % test.debugdir) |
- |
- # Kill the VM and fail if the automation program did not terminate on time |
- if not m: |
- vm.destroy() |
+ # Print result summary (both to the regular logs and to a file named |
+ # 'summary' in test.debugdir) |
+ def print_summary_line(f, line): |
+ logging.info(line) |
+ f.write(line + "\n") |
+ if results: |
+ # Make sure all results have the required keys |
+ for r in results: |
+ r["id"] = str(r.get("id")) |
+ r["job"] = str(r.get("job")) |
+ r["status"] = str(r.get("status")) |
+ r["pass"] = int(r.get("pass", 0)) |
+ r["fail"] = int(r.get("fail", 0)) |
+ r["notrun"] = int(r.get("notrun", 0)) |
+ r["notapplicable"] = int(r.get("notapplicable", 0)) |
+ # Sort the results by failures and total test count in descending order |
+ results = [(r["fail"], |
+ r["pass"] + r["fail"] + r["notrun"] + r["notapplicable"], |
+ r) for r in results] |
+ results.sort(reverse=True) |
+ results = [r[-1] for r in results] |
+ # Print results |
+ logging.info("") |
+ logging.info("Result summary:") |
+ name_length = max(len(r["job"]) for r in results) |
+ fmt = "%%-6s %%-%ds %%-15s %%-8s %%-8s %%-8s %%-15s" % name_length |
+ f = open(os.path.join(test.debugdir, "summary"), "w") |
+ print_summary_line(f, fmt % ("ID", "Job", "Status", "Pass", "Fail", |
+ "NotRun", "NotApplicable")) |
+ print_summary_line(f, fmt % ("--", "---", "------", "----", "----", |
+ "------", "-------------")) |
+ for r in results: |
+ print_summary_line(f, fmt % (r["id"], r["job"], r["status"], |
+ r["pass"], r["fail"], r["notrun"], |
+ r["notapplicable"])) |
+ f.close() |
+ logging.info("(see logs and HTML reports in %s)", test.debugdir) |
+ |
+ # Kill the client VMs and fail if the automation program did not terminate |
+ # on time |
+ if not done: |
+ kvm_utils.parallel(vm.destroy for vm in vms) |
raise error.TestFail("The automation program did not terminate " |
"on time") |
- # Fail if there are failed or incomplete jobs (kill the VM if there are |
- # incomplete jobs) |
- failed_jobs = [r.get("job") for r in results |
- if r.get("status", "").lower() == "investigate"] |
- running_jobs = [r.get("job") for r in results |
- if r.get("status", "").lower() == "inprogress"] |
+ # Fail if there are failed or incomplete jobs (kill the client VMs if there |
+ # are incomplete jobs) |
+ failed_jobs = [r["job"] for r in results |
+ if r["status"].lower() == "investigate"] |
+ running_jobs = [r["job"] for r in results |
+ if r["status"].lower() == "inprogress"] |
errors = [] |
if failed_jobs: |
errors += ["Jobs failed: %s." % failed_jobs] |
if running_jobs: |
- vm.destroy() |
+ for vm in vms: |
+ vm.destroy() |
errors += ["Jobs did not complete on time: %s." % running_jobs] |
if errors: |
raise error.TestFail(" ".join(errors)) |