| 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 6fb5d83128a5990f1e2f6358dabe28ecf93562d8..1fe27c9ed03413b55d4122113f0aef6e57a4dade 100644
 | 
| --- a/client/tests/kvm/tests/whql_submission.py
 | 
| +++ b/client/tests/kvm/tests/whql_submission.py
 | 
| @@ -6,31 +6,20 @@ import kvm_subprocess, kvm_test_utils, kvm_utils, rss_file_transfer
 | 
|  def run_whql_submission(test, params, env):
 | 
|      """
 | 
|      WHQL submission test:
 | 
| -    1) Log into the client machines and into a DTM server machine
 | 
| +    1) Log into the guest (the client machine) 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.debugdir)
 | 
| +    (logs and HTML reports are placed in test.bindir)
 | 
|  
 | 
|      @param test: kvm test object
 | 
|      @param params: Dictionary with the test parameters
 | 
|      @param env: Dictionary with test environment.
 | 
|      """
 | 
| -    # Log into all client VMs
 | 
| -    vms = []
 | 
| -    sessions = []
 | 
| -    for vm_name in params.objects("vms"):
 | 
| -        vms.append(kvm_test_utils.get_living_vm(env, vm_name))
 | 
| -        sessions.append(kvm_test_utils.wait_for_login(vms[-1], 0, 240))
 | 
| -
 | 
| -    # Make sure all NICs of all client VMs are up
 | 
| -    for vm in vms:
 | 
| -        nics = kvm_utils.get_sub_dict_names(vm.params, "nics")
 | 
| -        for nic_index in range(len(nics)):
 | 
| -            s = kvm_test_utils.wait_for_login(vm, nic_index, 600)
 | 
| -            s.close()
 | 
| +    vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
 | 
| +    session = kvm_test_utils.wait_for_login(vm, 0, 240)
 | 
|  
 | 
|      # Collect parameters
 | 
|      server_address = params.get("server_address")
 | 
| @@ -41,61 +30,41 @@ 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)
 | 
| -    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_device = params.get("test_device")
 | 
| +    job_filter = params.get("job_filter", ".*")
 | 
|      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 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)
 | 
| +    # 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)
 | 
|  
 | 
|      # Open a shell session with the server
 | 
|      server_session = kvm_utils.remote_login("nc", server_address,
 | 
|                                              server_shell_port, "", "",
 | 
| -                                            sessions[0].prompt,
 | 
| -                                            sessions[0].linesep)
 | 
| -    server_session.set_status_test_command(sessions[0].status_test_command)
 | 
| +                                            session.prompt, session.linesep)
 | 
|  
 | 
| -    # Get the computer names of the server and clients
 | 
| +    # Get the computer names of the server and client
 | 
|      cmd = "echo %computername%"
 | 
| -    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((kvm_test_utils.reboot, (vm, session))
 | 
| -                                  for vm, session in zip(vms, sessions))
 | 
| -
 | 
| -    # Check the NICs again
 | 
| -    for vm in vms:
 | 
| -        nics = kvm_utils.get_sub_dict_names(vm.params, "nics")
 | 
| -        for nic_index in range(len(nics)):
 | 
| -            s = kvm_test_utils.wait_for_login(vm, 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()
 | 
| +    server_name = server_session.get_command_output(cmd).strip()
 | 
| +    client_name = session.get_command_output(cmd).strip()
 | 
| +    session.close()
 | 
|  
 | 
|      # Run the automation program on the server
 | 
| -    pool_name = "%s_pool" % client_names[0]
 | 
| -    submission_name = "%s_%s" % (client_names[0],
 | 
| -                                 params.get("submission_name"))
 | 
| +    server_session.get_command_output("cd %s" % server_studio_path)
 | 
|      cmd = "%s %s %s %s %s %s" % (os.path.basename(dsso_test_binary),
 | 
| -                                 server_name, pool_name, submission_name,
 | 
| -                                 test_timeout, " ".join(client_names))
 | 
| +                                 server_name,
 | 
| +                                 client_name,
 | 
| +                                 "%s_pool" % client_name,
 | 
| +                                 "%s_submission" % client_name,
 | 
| +                                 test_timeout)
 | 
|      server_session.sendline(cmd)
 | 
|  
 | 
|      # Helper function: wait for a given prompt and raise an exception if an
 | 
| @@ -109,69 +78,40 @@ 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(params.get("test_device"))
 | 
| +    server_session.sendline(test_device)
 | 
|  
 | 
|      # Tell the automation program which jobs to run
 | 
|      find_prompt("Jobs to run:")
 | 
| -    server_session.sendline(params.get("job_filter", ".*"))
 | 
| +    server_session.sendline(job_filter)
 | 
|  
 | 
| -    # Set submission DeviceData
 | 
| +    # Give the automation program all the device data supplied by the user
 | 
|      find_prompt("DeviceData name:")
 | 
| -    for dd in params.objects("device_data"):
 | 
| -        dd_params = params.object_params(dd)
 | 
| +    for dd in kvm_utils.get_sub_dict_names(params, "device_data"):
 | 
| +        dd_params = kvm_utils.get_sub_dict(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()
 | 
|  
 | 
| -    # Set submission descriptors
 | 
| +    # Give the automation program all the descriptor information supplied by
 | 
| +    # the user
 | 
|      find_prompt("Descriptor path:")
 | 
| -    for desc in params.objects("descriptors"):
 | 
| -        desc_params = params.object_params(desc)
 | 
| +    for desc in kvm_utils.get_sub_dict_names(params, "descriptors"):
 | 
| +        desc_params = kvm_utils.get_sub_dict(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
 | 
| -    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
 | 
| +    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)
 | 
|      server_session.close()
 | 
|  
 | 
|      # Look for test results in the automation program's output
 | 
| @@ -211,63 +151,38 @@ def run_whql_submission(test, params, env):
 | 
|                  except (KeyError, OSError):
 | 
|                      pass
 | 
|  
 | 
| -    # 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)
 | 
| +    # 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()
 | 
|          raise error.TestFail("The automation program did not terminate "
 | 
|                               "on time")
 | 
|  
 | 
| -    # 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"]
 | 
| +    # 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"]
 | 
|      errors = []
 | 
|      if failed_jobs:
 | 
|          errors += ["Jobs failed: %s." % failed_jobs]
 | 
|      if running_jobs:
 | 
| -        for vm in vms:
 | 
| -            vm.destroy()
 | 
| +        vm.destroy()
 | 
|          errors += ["Jobs did not complete on time: %s." % running_jobs]
 | 
|      if errors:
 | 
|          raise error.TestFail(" ".join(errors))
 | 
| 
 |