All of lore.kernel.org
 help / color / mirror / Atom feed
* [KVM-AUTOTEST PATCH 1/5] KVM test: kvm_subprocess: raise exceptions in kvm_shell_session and kvm_expect
@ 2010-10-26 16:49 Michael Goldish
  2010-10-26 16:49 ` [KVM-AUTOTEST PATCH 2/5] KVM test: kvm_monitor.py: store attributes in QMPCmdError Michael Goldish
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Goldish @ 2010-10-26 16:49 UTC (permalink / raw)
  To: autotest, kvm; +Cc: Michael Goldish

- Instead of relying solely on returned values, raise exceptions when something
  goes wrong in any of the variants of get_command_status_output() and
  read_until_output_matches().

- Introduce cmd() which executes a command and raises an exception if the
  command's exit status is nonzero (in addition to the exceptions raised by
  get_command_status_output()).  If the exit status is zero, cmd() returns the
  command's output.

- Modify all tests to account for these changes:
  * When cmd() is appropriate, use it.
  * When the command is not required to succeed, use get_command_output().
  * Otherwise leave code as it is or wrap it in try..except to catch the new
    exceptions.

- Set auto_close=True by default for kvm_expect (like it is set for
  kvm_shell_session).  Otherwise, an unhandled exception might leave a
  kvm_expect session open forever.

Signed-off-by: Michael Goldish <mgoldish@redhat.com>
---
 client/tests/kvm/kvm_subprocess.py            |  321 +++++++++++++++++--------
 client/tests/kvm/kvm_test_utils.py            |   75 +++---
 client/tests/kvm/kvm_utils.py                 |  119 +++++-----
 client/tests/kvm/kvm_vm.py                    |   10 +-
 client/tests/kvm/tests/ethtool.py             |   17 +-
 client/tests/kvm/tests/file_transfer.py       |    5 +-
 client/tests/kvm/tests/guest_test.py          |   24 +--
 client/tests/kvm/tests/iofuzz.py              |   18 +-
 client/tests/kvm/tests/ioquit.py              |    9 +-
 client/tests/kvm/tests/jumbo.py               |    6 +-
 client/tests/kvm/tests/ksm_overcommit.py      |   16 +-
 client/tests/kvm/tests/linux_s3.py            |    9 +-
 client/tests/kvm/tests/mac_change.py          |    6 +-
 client/tests/kvm/tests/migration.py           |    8 +-
 client/tests/kvm/tests/multicast.py           |   10 +-
 client/tests/kvm/tests/netperf.py             |   13 +-
 client/tests/kvm/tests/nic_promisc.py         |   16 +-
 client/tests/kvm/tests/nicdriver_unload.py    |   16 +-
 client/tests/kvm/tests/pci_hotplug.py         |   10 +-
 client/tests/kvm/tests/stress_boot.py         |    4 +-
 client/tests/kvm/tests/virtio_console.py      |    4 +-
 client/tests/kvm/tests/vlan.py                |   34 +--
 client/tests/kvm/tests/whql_client_install.py |   21 +-
 client/tests/kvm/tests/whql_submission.py     |   22 +-
 24 files changed, 426 insertions(+), 367 deletions(-)

diff --git a/client/tests/kvm/kvm_subprocess.py b/client/tests/kvm/kvm_subprocess.py
index 8321bb3..c92910c 100755
--- a/client/tests/kvm/kvm_subprocess.py
+++ b/client/tests/kvm/kvm_subprocess.py
@@ -189,6 +189,88 @@ import subprocess, time, signal, re, threading, logging
 import common, kvm_utils
 
 
+class ExpectError(Exception):
+    def __init__(self, patterns, output):
+        Exception.__init__(self, patterns, output)
+        self.patterns = patterns
+        self.output = output
+
+    def _pattern_str(self):
+        if len(self.patterns) == 1:
+            return "pattern %r" % self.patterns[0]
+        else:
+            return "patterns %r" % self.patterns
+
+    def __str__(self):
+        return ("Unknown error occurred while looking for %s (output: %r)" %
+                (self._pattern_str(), self.output))
+
+
+class ExpectTimeoutError(ExpectError):
+    def __str__(self):
+        return ("Timeout expired while looking for %s (output: %r)" %
+                (self._pattern_str(), self.output))
+
+
+class ExpectProcessTerminatedError(ExpectError):
+    def __init__(self, patterns, status, output):
+        ExpectError.__init__(self, patterns, output)
+        self.status = status
+
+    def __str__(self):
+        return ("Process terminated while looking for %s (status: %s, output: "
+                "%r)" % (self._pattern_str(), self.status, self.output))
+
+
+class ShellError(Exception):
+    def __init__(self, cmd, output):
+        Exception.__init__(self, cmd, output)
+        self.cmd = cmd
+        self.output = output
+
+    def __str__(self):
+        return ("Could not execute shell command %r (output: %r)" %
+                (self.cmd, self.output))
+
+
+class ShellTimeoutError(ShellError):
+    def __str__(self):
+        return ("Timeout expired while waiting for shell command %r to "
+                "complete (output: %r)" % (self.cmd, self.output))
+
+
+class ShellProcessTerminatedError(ShellError):
+    # Raised when the shell process itself (e.g. ssh, netcat, telnet)
+    # terminates unexpectedly
+    def __init__(self, cmd, status, output):
+        ShellError.__init__(self, cmd, output)
+        self.status = status
+
+    def __str__(self):
+        return ("Shell process terminated while waiting for command %r to "
+                "complete (status: %s, output: %r)" %
+                (self.cmd, self.status, self.output))
+
+
+class ShellCmdError(ShellError):
+    # Raised when a command executed in a shell terminates with a nonzero
+    # exit code (status)
+    def __init__(self, cmd, status, output):
+        ShellError.__init__(self, cmd, output)
+        self.status = status
+
+    def __str__(self):
+        return ("Shell command %r failed with status %d (output: %r)" %
+                (self.cmd, self.status, self.output))
+
+
+class ShellStatusError(ShellError):
+    # Raised when the command's exit status cannot be obtained
+    def __str__(self):
+        return ("Could not get exit status of command %r (output: %r)" %
+                (self.cmd, self.output))
+
+
 def run_bg(command, termination_func=None, output_func=None, output_prefix="",
            timeout=1.0):
     """
@@ -773,7 +855,7 @@ class kvm_expect(kvm_tail):
     It also provides all of kvm_tail's functionality.
     """
 
-    def __init__(self, command=None, id=None, auto_close=False, echo=False,
+    def __init__(self, command=None, id=None, auto_close=True, echo=False,
                  linesep="\n", termination_func=None, termination_params=(),
                  output_func=None, output_params=(), output_prefix=""):
         """
@@ -876,13 +958,14 @@ class kvm_expect(kvm_tail):
         @param internal_timeout: The timeout to pass to read_nonblocking
         @param print_func: A function to be used to print the data being read
                 (should take a string parameter)
-        @return: Tuple containing the match index (or None if no match was
-                found) and the data read so far.
+        @return: Tuple containing the match index and the data read so far
+        @raise ExpectTimeoutError: Raised if timeout expires
+        @raise ExpectProcessTerminatedError: Raised if the child process
+                terminates while waiting for output
+        @raise ExpectError: Raised if an unknown error occurs
         """
-        match = None
-        data = ""
-
         fd = self._get_fd("expect")
+        o = ""
         end_time = time.time() + timeout
         while True:
             try:
@@ -890,38 +973,28 @@ class kvm_expect(kvm_tail):
                                         max(0, end_time - time.time()))
             except (select.error, TypeError):
                 break
-            if fd not in r:
-                break
+            if not r:
+                raise ExpectTimeoutError(patterns, o)
             # Read data from child
-            newdata = self.read_nonblocking(internal_timeout)
+            data = self.read_nonblocking(internal_timeout)
+            if not data:
+                break
             # Print it if necessary
-            if print_func and newdata:
-                str = newdata
-                if str.endswith("\n"):
-                    str = str[:-1]
-                for line in str.split("\n"):
+            if print_func:
+                for line in data.splitlines():
                     print_func(line)
-            data += newdata
-
-            done = False
             # Look for patterns
-            match = self.match_patterns(filter(data), patterns)
+            o += data
+            match = self.match_patterns(filter(o), patterns)
             if match is not None:
-                done = True
-            # Check if child has died
-            if not self.is_alive():
-                logging.debug("Process terminated with status %s" %
-                              self.get_status())
-                done = True
-            # Are we done?
-            if done: break
-
-        # Print some debugging info
-        if match is None and (self.is_alive() or self.get_status() != 0):
-            logging.debug("Timeout elapsed or process terminated. Output:" +
-                          kvm_utils.format_str_for_message(data.strip()))
+                return match, o
 
-        return (match, data)
+        # Check if the child has terminated
+        if kvm_utils.wait_for(lambda: not self.is_alive(), 5, 0, 0.1):
+            raise ExpectProcessTerminatedError(patterns, self.get_status(), o)
+        else:
+            # This shouldn't happen
+            raise ExpectError(patterns, o)
 
 
     def read_until_last_word_matches(self, patterns, timeout=30.0,
@@ -936,8 +1009,11 @@ class kvm_expect(kvm_tail):
         @param internal_timeout: The timeout to pass to read_nonblocking
         @param print_func: A function to be used to print the data being read
                 (should take a string parameter)
-        @return: A tuple containing the match index (or None if no match was
-                found) and the data read so far.
+        @return: A tuple containing the match index and the data read so far
+        @raise ExpectTimeoutError: Raised if timeout expires
+        @raise ExpectProcessTerminatedError: Raised if the child process
+                terminates while waiting for output
+        @raise ExpectError: Raised if an unknown error occurs
         """
         def get_last_word(str):
             if str:
@@ -967,6 +1043,11 @@ class kvm_expect(kvm_tail):
         @param internal_timeout: The timeout to pass to read_nonblocking
         @param print_func: A function to be used to print the data being read
                 (should take a string parameter)
+        @return: A tuple containing the match index and the data read so far
+        @raise ExpectTimeoutError: Raised if timeout expires
+        @raise ExpectProcessTerminatedError: Raised if the child process
+                terminates while waiting for output
+        @raise ExpectError: Raised if an unknown error occurs
         """
         def get_last_nonempty_line(str):
             nonempty_lines = [l for l in str.splitlines() if l.strip()]
@@ -1101,31 +1182,34 @@ class kvm_shell_session(kvm_expect):
         @param print_func: A function to be used to print the data being
                 read (should take a string parameter)
 
-        @return: A tuple containing True/False indicating whether the prompt
-                was found, and the data read so far.
+        @return: The data read so far
+        @raise ExpectTimeoutError: Raised if timeout expires
+        @raise ExpectProcessTerminatedError: Raised if the shell process
+                terminates while waiting for output
+        @raise ExpectError: Raised if an unknown error occurs
         """
-        (match, output) = self.read_until_last_line_matches([self.prompt],
-                                                            timeout,
-                                                            internal_timeout,
-                                                            print_func)
-        return (match is not None, output)
+        m, o = self.read_until_last_line_matches([self.prompt], timeout,
+                                                 internal_timeout, print_func)
+        return o
 
 
-    def get_command_status_output(self, command, timeout=30.0,
-                                  internal_timeout=None, print_func=None):
+    def get_command_output(self, cmd, timeout=30.0, internal_timeout=None,
+                           print_func=None):
         """
-        Send a command and return its exit status and output.
+        Send a command and return its output.
 
-        @param command: Command to send (must not contain newline characters)
-        @param timeout: The duration (in seconds) to wait until a match is
-                found
+        @param cmd: Command to send (must not contain newline characters)
+        @param timeout: The duration (in seconds) to wait for the prompt to
+                return
         @param internal_timeout: The timeout to pass to read_nonblocking
         @param print_func: A function to be used to print the data being read
                 (should take a string parameter)
 
-        @return: A tuple (status, output) where status is the exit status or
-                None if no exit status is available (e.g. timeout elapsed), and
-                output is the output of command.
+        @return: The output of cmd
+        @raise ShellTimeoutError: Raised if timeout expires
+        @raise ShellProcessTerminatedError: Raised if the shell process
+                terminates while waiting for output
+        @raise ShellError: Raised if an unknown error occurs
         """
         def remove_command_echo(str, cmd):
             if str and str.splitlines()[0] == cmd:
@@ -1135,79 +1219,108 @@ class kvm_shell_session(kvm_expect):
         def remove_last_nonempty_line(str):
             return "".join(str.rstrip().splitlines(True)[:-1])
 
-        # Print some debugging info
-        logging.debug("Sending command: %s" % command)
-
-        # Read everything that's waiting to be read
+        logging.debug("Sending command: %s" % cmd)
         self.read_nonblocking(timeout=0)
+        self.sendline(cmd)
+        try:
+            o = self.read_up_to_prompt(timeout, internal_timeout, print_func)
+        except ExpectError, e:
+            o = remove_command_echo(e.output, cmd)
+            if isinstance(e, ExpectTimeoutError):
+                raise ShellTimeoutError(cmd, o)
+            elif isinstance(e, ExpectProcessTerminatedError):
+                raise ShellProcessTerminatedError(cmd, e.status, o)
+            else:
+                raise ShellError(cmd, o)
 
-        # Send the command and get its output
-        self.sendline(command)
-        (match, output) = self.read_up_to_prompt(timeout, internal_timeout,
-                                                 print_func)
-        # Remove the echoed command from the output
-        output = remove_command_echo(output, command)
-        # If the prompt was not found, return the output so far
-        if not match:
-            return (None, output)
-        # Remove the final shell prompt from the output
-        output = remove_last_nonempty_line(output)
-
-        # Send the 'echo ...' command to get the last exit status
-        self.sendline(self.status_test_command)
-        (match, status) = self.read_up_to_prompt(10.0, internal_timeout)
-        if not match:
-            return (None, output)
-        status = remove_command_echo(status, self.status_test_command)
-        status = remove_last_nonempty_line(status)
-        # Get the first line consisting of digits only
-        digit_lines = [l for l in status.splitlines() if l.strip().isdigit()]
-        if not digit_lines:
-            return (None, output)
-        status = int(digit_lines[0].strip())
+        # Remove the echoed command and the final shell prompt
+        return remove_last_nonempty_line(remove_command_echo(o, cmd))
+
+
+    def get_command_status_output(self, cmd, timeout=30.0,
+                                  internal_timeout=None, print_func=None):
+        """
+        Send a command and return its exit status and output.
+
+        @param cmd: Command to send (must not contain newline characters)
+        @param timeout: The duration (in seconds) to wait for the prompt to
+                return
+        @param internal_timeout: The timeout to pass to read_nonblocking
+        @param print_func: A function to be used to print the data being read
+                (should take a string parameter)
 
-        # Print some debugging info
-        if status != 0:
-            logging.debug("Command failed; status: %d, output:%s", status,
-                          kvm_utils.format_str_for_message(output.strip()))
+        @return: A tuple (status, output) where status is the exit status and
+                output is the output of cmd
+        @raise ShellTimeoutError: Raised if timeout expires
+        @raise ShellProcessTerminatedError: Raised if the shell process
+                terminates while waiting for output
+        @raise ShellStatusError: Raised if the exit status cannot be obtained
+        @raise ShellError: Raised if an unknown error occurs
+        """
+        o = self.get_command_output(cmd, timeout, internal_timeout, print_func)
+        try:
+            # Send the 'echo $?' (or equivalent) command to get the exit status
+            s = self.get_command_output(self.status_test_command, 10,
+                                        internal_timeout)
+        except ShellError:
+            raise ShellStatusError(cmd, o)
 
-        return (status, output)
+        # Get the first line consisting of digits only
+        digit_lines = [l for l in s.splitlines() if l.strip().isdigit()]
+        if digit_lines:
+            return int(digit_lines[0].strip()), o
+        else:
+            raise ShellStatusError(cmd, o)
 
 
-    def get_command_status(self, command, timeout=30.0, internal_timeout=None,
+    def get_command_status(self, cmd, timeout=30.0, internal_timeout=None,
                            print_func=None):
         """
         Send a command and return its exit status.
 
-        @param command: Command to send
-        @param timeout: The duration (in seconds) to wait until a match is
-                found
+        @param cmd: Command to send (must not contain newline characters)
+        @param timeout: The duration (in seconds) to wait for the prompt to
+                return
         @param internal_timeout: The timeout to pass to read_nonblocking
         @param print_func: A function to be used to print the data being read
                 (should take a string parameter)
 
-        @return: Exit status or None if no exit status is available (e.g.
-                timeout elapsed).
+        @return: The exit status of cmd
+        @raise ShellTimeoutError: Raised if timeout expires
+        @raise ShellProcessTerminatedError: Raised if the shell process
+                terminates while waiting for output
+        @raise ShellStatusError: Raised if the exit status cannot be obtained
+        @raise ShellError: Raised if an unknown error occurs
         """
-        (status, output) = self.get_command_status_output(command, timeout,
-                                                          internal_timeout,
-                                                          print_func)
-        return status
+        s, o = self.get_command_status_output(cmd, timeout, internal_timeout,
+                                              print_func)
+        return s
 
 
-    def get_command_output(self, command, timeout=30.0, internal_timeout=None,
-                           print_func=None):
+    def cmd(self, cmd, timeout=30.0, internal_timeout=None, print_func=None):
         """
-        Send a command and return its output.
+        Send a command and return its output. If the command's exit status is
+        nonzero, raise an exception.
 
-        @param command: Command to send
-        @param timeout: The duration (in seconds) to wait until a match is
-                found
+        @param cmd: Command to send (must not contain newline characters)
+        @param timeout: The duration (in seconds) to wait for the prompt to
+                return
         @param internal_timeout: The timeout to pass to read_nonblocking
         @param print_func: A function to be used to print the data being read
                 (should take a string parameter)
-        """
-        (status, output) = self.get_command_status_output(command, timeout,
-                                                          internal_timeout,
-                                                          print_func)
-        return output
+
+        @return: The output of cmd
+        @raise ShellTimeoutError: Raised if timeout expires
+        @raise ShellProcessTerminatedError: Raised if the shell process
+                terminates while waiting for output
+        @raise ShellError: Raised if the exit status cannot be obtained or if
+                an unknown error occurs
+        @raise ShellStatusError: Raised if the exit status cannot be obtained
+        @raise ShellError: Raised if an unknown error occurs
+        @raise ShellCmdError: Raised if the exit status is nonzero
+        """
+        s, o = self.get_command_status_output(cmd, timeout, internal_timeout,
+                                              print_func)
+        if s != 0:
+            raise ShellCmdError(cmd, s, o)
+        return o
diff --git a/client/tests/kvm/kvm_test_utils.py b/client/tests/kvm/kvm_test_utils.py
index a3b182b..c5f44b4 100644
--- a/client/tests/kvm/kvm_test_utils.py
+++ b/client/tests/kvm/kvm_test_utils.py
@@ -260,10 +260,7 @@ def get_time(session, time_command, time_filter_re, time_format):
     """
     if len(re.findall("ntpdate|w32tm", time_command)) == 0:
         host_time = time.time()
-        session.sendline(time_command)
-        (match, s) = session.read_up_to_prompt()
-        if not match:
-            raise error.TestError("Could not get guest time")
+        s = session.get_command_output(time_command)
 
         try:
             s = re.findall(time_filter_re, s)[0]
@@ -277,9 +274,7 @@ def get_time(session, time_command, time_filter_re, time_format):
 
         guest_time = time.mktime(time.strptime(s, time_format))
     else:
-        s , o = session.get_command_status_output(time_command)
-        if s != 0:
-            raise error.TestError("Could not get guest time")
+        o = session.cmd(time_command)
         if re.match('ntpdate', time_command):
             offset = re.findall('offset (.*) sec',o)[0]
             host_main, host_mantissa = re.findall(time_filter_re, o)[0]
@@ -389,10 +384,7 @@ def run_autotest(vm, session, control_path, timeout, outputdir):
         basename = os.path.basename(remote_path)
         logging.info("Extracting %s...", basename)
         e_cmd = "tar xjvf %s -C %s" % (remote_path, dest_dir)
-        s, o = session.get_command_status_output(e_cmd, timeout=120)
-        if s != 0:
-            logging.error("Uncompress output:\n%s", o)
-            raise error.TestFail("Failed to extract %s on guest" % basename)
+        session.cmd(e_cmd, timeout=120)
 
 
     def get_results():
@@ -462,26 +454,32 @@ def run_autotest(vm, session, control_path, timeout, outputdir):
     # Run the test
     logging.info("Running autotest control file %s on guest, timeout %ss",
                  os.path.basename(control_path), timeout)
-    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:
-        if not vm.is_alive():
-            raise error.TestError("Autotest job on guest failed "
-                                  "(VM terminated during job)")
-        if not session.is_alive():
+    session.cmd("cd %s" % autotest_path)
+    try:
+        session.cmd("rm -f control.state")
+        session.cmd("rm -rf results/*")
+    except kvm_subprocess.ShellError:
+        pass
+    try:
+        try:
+            logging.info("---------------- Test output ----------------")
+            session.get_command_output("bin/autotest control", timeout=timeout,
+                                       print_func=logging.info)
+        finally:
+            logging.info("------------- End of test output ------------")
+    except kvm_subprocess.ShellTimeoutError:
+        if vm.is_alive():
             get_results()
+            get_results_summary()
+            raise error.TestError("Timeout elapsed while waiting for job to "
+                                  "complete")
+        else:
             raise error.TestError("Autotest job on guest failed "
-                                  "(Remote session terminated during job)")
+                                  "(VM terminated during job)")
+    except kvm_subprocess.ShellProcessTerminatedError:
         get_results()
-        get_results_summary()
-        raise error.TestError("Timeout elapsed while waiting for job to "
-                              "complete")
+        raise error.TestError("Autotest job on guest failed "
+                              "(Remote session terminated during job)")
 
     results = get_results_summary()
     get_results()
@@ -543,21 +541,24 @@ def raw_ping(command, timeout, session, output_func):
         process.close()
         return status, output
     else:
-        session.sendline(command)
-        status, output = session.read_up_to_prompt(timeout=timeout,
-                                                   print_func=output_func)
-        if not status:
+        try:
+            output = session.get_command_output(command, timeout=timeout,
+                                                print_func=output_func)
+        except kvm_subprocess.ShellTimeoutError:
             # Send ctrl+c (SIGINT) through ssh session
             session.send("\003")
-            status, output2 = session.read_up_to_prompt(print_func=output_func)
-            output += output2
-            if not status:
+            try:
+                output2 = session.read_up_to_prompt(print_func=output_func)
+                output += output2
+            except kvm_subprocess.ExpectTimeoutError, e:
+                output += e.output
                 # We also need to use this session to query the return value
                 session.send("\003")
 
         session.sendline(session.status_test_command)
-        s2, o2 = session.read_up_to_prompt()
-        if not s2:
+        try:
+            o2 = session.read_up_to_prompt()
+        except kvm_subprocess.ExpectError:
             status = -1
         else:
             try:
diff --git a/client/tests/kvm/kvm_utils.py b/client/tests/kvm/kvm_utils.py
index f749f8d..c87e908 100644
--- a/client/tests/kvm/kvm_utils.py
+++ b/client/tests/kvm/kvm_utils.py
@@ -451,48 +451,52 @@ def _remote_login(session, username, password, prompt, timeout=10):
     login_prompt_count = 0
 
     while True:
-        (match, text) = session.read_until_last_line_matches(
+        try:
+            match, text = session.read_until_last_line_matches(
                 [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"[Ll]ogin:\s*$",
                  r"[Cc]onnection.*closed", r"[Cc]onnection.*refused",
                  r"[Pp]lease wait", prompt],
-                 timeout=timeout, internal_timeout=0.5)
-        if match == 0:  # "Are you sure you want to continue connecting"
-            logging.debug("Got 'Are you sure...'; sending 'yes'")
-            session.sendline("yes")
-            continue
-        elif match == 1:  # "password:"
-            if password_prompt_count == 0:
-                logging.debug("Got password prompt; sending '%s'" % password)
-                session.sendline(password)
-                password_prompt_count += 1
+                timeout=timeout, internal_timeout=0.5)
+            if match == 0:  # "Are you sure you want to continue connecting"
+                logging.debug("Got 'Are you sure...'; sending 'yes'")
+                session.sendline("yes")
                 continue
-            else:
-                logging.debug("Got password prompt again")
+            elif match == 1:  # "password:"
+                if password_prompt_count == 0:
+                    logging.debug("Got password prompt; sending '%s'" % password)
+                    session.sendline(password)
+                    password_prompt_count += 1
+                    continue
+                else:
+                    logging.debug("Got password prompt again")
+                    return False
+            elif match == 2:  # "login:"
+                if login_prompt_count == 0:
+                    logging.debug("Got username prompt; sending '%s'" % username)
+                    session.sendline(username)
+                    login_prompt_count += 1
+                    continue
+                else:
+                    logging.debug("Got username prompt again")
+                    return False
+            elif match == 3:  # "Connection closed"
+                logging.debug("Got 'Connection closed'")
                 return False
-        elif match == 2:  # "login:"
-            if login_prompt_count == 0:
-                logging.debug("Got username prompt; sending '%s'" % username)
-                session.sendline(username)
-                login_prompt_count += 1
-                continue
-            else:
-                logging.debug("Got username prompt again")
+            elif match == 4:  # "Connection refused"
+                logging.debug("Got 'Connection refused'")
                 return False
-        elif match == 3:  # "Connection closed"
-            logging.debug("Got 'Connection closed'")
-            return False
-        elif match == 4:  # "Connection refused"
-            logging.debug("Got 'Connection refused'")
+            elif match == 5:  # "Please wait"
+                logging.debug("Got 'Please wait'")
+                timeout = 30
+                continue
+            elif match == 6:  # prompt
+                logging.debug("Got shell prompt -- logged in")
+                return True
+        except kvm_subprocess.ExpectTimeoutError, e:
+            logging.debug("Timeout elapsed (output so far: %r)" % e.output)
             return False
-        elif match == 5:  # "Please wait"
-            logging.debug("Got 'Please wait'")
-            timeout = 30
-            continue
-        elif match == 6:  # prompt
-            logging.debug("Got shell prompt -- logged in")
-            return session
-        else:  # match == None
-            logging.debug("Timeout elapsed or process terminated")
+        except kvm_subprocess.ExpectProcessTerminatedError, e:
+            logging.debug("Process terminated (output so far: %r)" % e.output)
             return False
 
 
@@ -519,34 +523,33 @@ def _remote_scp(session, password, transfer_timeout=600, login_timeout=10):
     timeout = login_timeout
 
     while True:
-        (match, text) = session.read_until_last_line_matches(
+        try:
+            match, text = session.read_until_last_line_matches(
                 [r"[Aa]re you sure", r"[Pp]assword:\s*$", r"lost connection"],
                 timeout=timeout, internal_timeout=0.5)
-        if match == 0:  # "Are you sure you want to continue connecting"
-            logging.debug("Got 'Are you sure...'; sending 'yes'")
-            session.sendline("yes")
-            continue
-        elif match == 1:  # "password:"
-            if password_prompt_count == 0:
-                logging.debug("Got password prompt; sending '%s'" % password)
-                session.sendline(password)
-                password_prompt_count += 1
-                timeout = transfer_timeout
+            if match == 0:  # "Are you sure you want to continue connecting"
+                logging.debug("Got 'Are you sure...'; sending 'yes'")
+                session.sendline("yes")
                 continue
-            else:
-                logging.debug("Got password prompt again")
+            elif match == 1:  # "password:"
+                if password_prompt_count == 0:
+                    logging.debug("Got password prompt; sending '%s'" % password)
+                    session.sendline(password)
+                    password_prompt_count += 1
+                    timeout = transfer_timeout
+                    continue
+                else:
+                    logging.debug("Got password prompt again")
+                    return False
+            elif match == 2:  # "lost connection"
+                logging.debug("Got 'lost connection'")
                 return False
-        elif match == 2:  # "lost connection"
-            logging.debug("Got 'lost connection'")
+        except kvm_subprocess.ExpectTimeoutError, e:
+            logging.debug("Timeout expired")
             return False
-        else:  # match == None
-            if session.is_alive():
-                logging.debug("Timeout expired")
-                return False
-            else:
-                status = session.get_status()
-                logging.debug("SCP process terminated with status %s", status)
-                return status == 0
+        except kvm_subprocess.ExpectProcessTerminatedError, e:
+            logging.debug("SCP process terminated with status %s", e.status)
+            return e.status == 0
 
 
 def remote_login(client, host, port, username, password, prompt, linesep="\n",
diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py
index a860437..267b45b 100755
--- a/client/tests/kvm/kvm_vm.py
+++ b/client/tests/kvm/kvm_vm.py
@@ -1213,11 +1213,7 @@ class VM:
         if not session:
             return None
         try:
-            cmd = self.params.get("cpu_chk_cmd")
-            s, count = session.get_command_status_output(cmd)
-            if s == 0:
-                return int(count)
-            return None
+            return int(session.cmd(self.params.get("cpu_chk_cmd")))
         finally:
             session.close()
 
@@ -1235,9 +1231,7 @@ class VM:
         try:
             if not cmd:
                 cmd = self.params.get("mem_chk_cmd")
-            s, mem_str = session.get_command_status_output(cmd)
-            if s != 0:
-                return None
+            mem_str = session.cmd(cmd)
             mem = re.findall("([0-9]+)", mem_str)
             mem_size = 0
             for m in mem:
diff --git a/client/tests/kvm/tests/ethtool.py b/client/tests/kvm/tests/ethtool.py
index 56b1c70..b93c5a1 100644
--- a/client/tests/kvm/tests/ethtool.py
+++ b/client/tests/kvm/tests/ethtool.py
@@ -1,7 +1,7 @@
 import logging, commands, re
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
-import kvm_test_utils, kvm_utils
+import kvm_test_utils, kvm_utils, kvm_subprocess
 
 def run_ethtool(test, params, env):
     """
@@ -32,7 +32,7 @@ def run_ethtool(test, params, env):
             'gro': 'generic.*receive.*offload',
             'lro': 'large.*receive.*offload',
             }
-        s, o = session.get_command_status_output("ethtool -k %s" % ethname)
+        o = session.cmd("ethtool -k %s" % ethname)
         try:
             return re.findall("%s: (.*)" % feature_pattern.get(type), o)[0]
         except IndexError:
@@ -92,13 +92,13 @@ def run_ethtool(test, params, env):
         @param src: Source host of transfer file
         @return: Tuple (status, error msg/tcpdump result)
         """
-        session2.get_command_status("rm -rf %s" % filename)
-        dd_cmd = "dd if=/dev/urandom of=%s bs=1M count=%s" % (filename,
-                                                   params.get("filesize"))
+        session2.get_command_output("rm -rf %s" % filename)
+        dd_cmd = ("dd if=/dev/urandom of=%s bs=1M count=%s" %
+                  (filename, params.get("filesize")))
         logging.info("Creat file in source host, cmd: %s" % dd_cmd)
         tcpdump_cmd = "tcpdump -lep -s 0 tcp -vv port ssh"
         if src == "guest":
-            s = session.get_command_status(dd_cmd, timeout=360)
+            session.get_command_output(dd_cmd, timeout=360)
             tcpdump_cmd += " and src %s" % guest_ip
             copy_files_fun = vm.copy_files_from
         else:
@@ -125,8 +125,9 @@ def run_ethtool(test, params, env):
         logging.info("Transfer file completed")
         if session.get_command_status("killall tcpdump") != 0:
             return (False, "Could not kill all tcpdump process")
-        s, tcpdump_string = session2.read_up_to_prompt(timeout=60)
-        if not s:
+        try:
+            tcpdump_string = session2.read_up_to_prompt(timeout=60)
+        except kvm_subprocess.ExpectError:
             return (False, "Fail to read tcpdump's output")
 
         if not compare_md5sum(filename):
diff --git a/client/tests/kvm/tests/file_transfer.py b/client/tests/kvm/tests/file_transfer.py
index e872bed..afe4173 100644
--- a/client/tests/kvm/tests/file_transfer.py
+++ b/client/tests/kvm/tests/file_transfer.py
@@ -80,10 +80,7 @@ def run_file_transfer(test, params, env):
     finally:
         logging.info('Cleaning temp file on guest')
         clean_cmd += " %s" % guest_path
-        s, o = session.get_command_status_output(clean_cmd)
-        if s:
-            logging.warning("Failed to clean remote file %s, output:%s",
-                            guest_path, o)
+        session.cmd(clean_cmd)
         logging.info('Cleaning temp files on host')
         os.remove('%s/a.out' % dir)
         os.remove('%s/c.out' % dir)
diff --git a/client/tests/kvm/tests/guest_test.py b/client/tests/kvm/tests/guest_test.py
index b6bebc7..da38afd 100644
--- a/client/tests/kvm/tests/guest_test.py
+++ b/client/tests/kvm/tests/guest_test.py
@@ -48,14 +48,12 @@ def run_guest_test(test, params, env):
             # Change dir to dst_rsc_dir, and remove the guest script dir there
             rm_cmd = "cd %s && (rmdir /s /q %s || del /s /q %s)" % \
                      (dst_rsc_dir, rsc_dir, rsc_dir)
-            if session.get_command_status(rm_cmd, timeout=test_timeout) != 0:
-                raise error.TestFail("Remove %s failed." % rsc_dir)
+            session.cmd(rm_cmd, timeout=test_timeout)
             logging.debug("Clean directory succeeded.")
 
             # then download the resource.
             rsc_cmd = "cd %s && %s %s" %(dst_rsc_dir, download_cmd, rsc_server)
-            if session.get_command_status(rsc_cmd, timeout=test_timeout) != 0:
-                raise error.TestFail("Download test resource failed.")
+            session.cmd(rsc_cmd, timeout=test_timeout)
             logging.info("Download resource finished.")
         else:
             session.get_command_output("del %s" % dst_rsc_path,
@@ -63,19 +61,13 @@ def run_guest_test(test, params, env):
             script_path = kvm_utils.get_path(test.bindir, script)
             vm.copy_files_to(script_path, dst_rsc_path, timeout=60)
 
-        command = "cmd /c %s %s %s" %(interpreter, dst_rsc_path, script_params)
+        cmd = "cmd /c %s %s %s" %(interpreter, dst_rsc_path, script_params)
 
-        logging.info("---------------- Script output ----------------")
-        status = session.get_command_status(command,
-                                            print_func=logging.info,
-                                            timeout=test_timeout)
-        logging.info("---------------- End of script output ----------------")
-
-        if status is None:
-            raise error.TestFail("Timeout expired before script execution "
-                                 "completed (or something weird happened)")
-        if status != 0:
-            raise error.TestFail("Script execution failed")
+        try:
+            logging.info("------------ Script output ------------")
+            session.cmd(cmd, print_func=logging.info, timeout=test_timeout)
+        finally:
+            logging.info("------------ End of script output ------------")
 
         if reboot == "yes":
             logging.debug("Rebooting guest after test ...")
diff --git a/client/tests/kvm/tests/iofuzz.py b/client/tests/kvm/tests/iofuzz.py
index 45a0eb9..77f4761 100644
--- a/client/tests/kvm/tests/iofuzz.py
+++ b/client/tests/kvm/tests/iofuzz.py
@@ -33,11 +33,10 @@ def run_iofuzz(test, params, env):
         logging.debug("outb(0x%x, 0x%x)", port, data)
         outb_cmd = ("echo -e '\\%s' | dd of=/dev/port seek=%d bs=1 count=1" %
                     (oct(data), port))
-        s, o = session.get_command_status_output(outb_cmd)
-        if s is None:
-            logging.debug("Command did not return")
-        if s != 0:
-            logging.debug("Command returned status %s", s)
+        try:
+            session.cmd(outb_cmd)
+        except kvm_subprocess.ShellError, e:
+            logging.debug(e)
 
 
     def inb(session, port):
@@ -49,11 +48,10 @@ def run_iofuzz(test, params, env):
         """
         logging.debug("inb(0x%x)", port)
         inb_cmd = "dd if=/dev/port seek=%d of=/dev/null bs=1 count=1" % port
-        s, o = session.get_command_status_output(inb_cmd)
-        if s is None:
-            logging.debug("Command did not return")
-        if s != 0:
-            logging.debug("Command returned status %s", s)
+        try:
+            session.cmd(inb_cmd)
+        except kvm_subprocess.ShellError, e:
+            logging.debug(e)
 
 
     def fuzz(session, inst_list):
diff --git a/client/tests/kvm/tests/ioquit.py b/client/tests/kvm/tests/ioquit.py
index 8126139..bdccd78 100644
--- a/client/tests/kvm/tests/ioquit.py
+++ b/client/tests/kvm/tests/ioquit.py
@@ -20,16 +20,13 @@ def run_ioquit(test, params, env):
     try:
         bg_cmd = params.get("background_cmd")
         logging.info("Add IO workload for guest OS.")
-        (s, o) = session.get_command_status_output(bg_cmd, timeout=60)
+        session.get_command_output(bg_cmd, timeout=60)
         check_cmd = params.get("check_cmd")
-        (s, o) = session2.get_command_status_output(check_cmd, timeout=60)
-        if s:
-            raise error.TestError("Fail to add IO workload for Guest OS")
+        session2.cmd(check_cmd, timeout=60)
 
         logging.info("Sleep for a while")
         time.sleep(random.randrange(30,100))
-        (s, o) = session2.get_command_status_output(check_cmd, timeout=60)
-        if s:
+        if session2.get_command_status(check_cmd, timeout=60) != 0:
             logging.info("IO workload finished before the VM was killed")
         logging.info("Kill the virtual machine")
         vm.process.close()
diff --git a/client/tests/kvm/tests/jumbo.py b/client/tests/kvm/tests/jumbo.py
index 2c91c83..1fbce8b 100644
--- a/client/tests/kvm/tests/jumbo.py
+++ b/client/tests/kvm/tests/jumbo.py
@@ -40,11 +40,7 @@ def run_jumbo(test, params, env):
 
         logging.info("Changing the MTU of guest ...")
         guest_mtu_cmd = "ifconfig %s mtu %s" % (ethname , mtu)
-        s, o = session.get_command_status_output(guest_mtu_cmd)
-        if s != 0:
-            logging.error(o)
-            raise error.TestError("Fail to set the MTU of guest NIC: %s" %
-                                  ethname)
+        session.cmd(guest_mtu_cmd)
 
         logging.info("Chaning the MTU of host tap ...")
         host_mtu_cmd = "ifconfig %s mtu %s" % (ifname, mtu)
diff --git a/client/tests/kvm/tests/ksm_overcommit.py b/client/tests/kvm/tests/ksm_overcommit.py
index dd4a30d..dbd05dc 100644
--- a/client/tests/kvm/tests/ksm_overcommit.py
+++ b/client/tests/kvm/tests/ksm_overcommit.py
@@ -29,7 +29,7 @@ def run_ksm_overcommit(test, params, env):
         session.sendline("python /tmp/allocator.py")
         (match, data) = session.read_until_last_line_matches(["PASS:", "FAIL:"],
                                                              timeout)
-        if match == 1 or match is None:
+        if match != 0:
             raise error.TestFail("Command allocator.py on guest %s failed.\n"
                                  "return code: %s\n output:\n%s" %
                                  (vm.name, match, data))
@@ -52,7 +52,7 @@ def run_ksm_overcommit(test, params, env):
         session.sendline(command)
         (match, data) = session.read_until_last_line_matches(["PASS:","FAIL:"],
                                                              timeout)
-        if match == 1 or match is None:
+        if match != 0:
             raise error.TestFail("Failed to execute '%s' on allocator.py, "
                                  "vm: %s, output:\n%s" %
                                  (command, vm.name, data))
@@ -80,9 +80,7 @@ def run_ksm_overcommit(test, params, env):
             vm = lvms[lsessions.index(session)]
 
             logging.debug("Turning off swap on vm %s" % vm.name)
-            ret = session.get_command_status("swapoff -a", timeout=300)
-            if ret is None or ret:
-                raise error.TestFail("Failed to swapoff on VM %s" % vm.name)
+            session.cmd("swapoff -a", timeout=300)
 
             # Start the allocator
             _start_allocator(vm, session, 60 * perf_ratio)
@@ -232,7 +230,7 @@ def run_ksm_overcommit(test, params, env):
                            (mem / 200 * 50 * perf_ratio))
         logging.debug(kvm_test_utils.get_memory_info([lvms[last_vm]]))
 
-        (status, data) = lsessions[i].get_command_status_output("die()", 20)
+        lsessions[i].get_command_output("die()", 20)
         lvms[last_vm].destroy(gracefully = False)
         logging.info("Phase 3b: PASS")
 
@@ -253,9 +251,7 @@ def run_ksm_overcommit(test, params, env):
                 raise error.TestFail("Could not log into guest %s" %
                                      vm.name)
 
-        ret = session.get_command_status("swapoff -a", timeout=300)
-        if ret != 0:
-            raise error.TestFail("Failed to turn off swap on %s" % vm.name)
+        session.cmd("swapoff -a", timeout=300)
 
         for i in range(0, max_alloc):
             # Start the allocator
@@ -360,7 +356,7 @@ def run_ksm_overcommit(test, params, env):
 
         logging.debug("Cleaning up...")
         for i in range(0, max_alloc):
-            lsessions[i].get_command_status_output("die()", 20)
+            lsessions[i].get_command_output("die()", 20)
         session.close()
         vm.destroy(gracefully = False)
 
diff --git a/client/tests/kvm/tests/linux_s3.py b/client/tests/kvm/tests/linux_s3.py
index 4a782b8..55acea3 100644
--- a/client/tests/kvm/tests/linux_s3.py
+++ b/client/tests/kvm/tests/linux_s3.py
@@ -16,10 +16,7 @@ def run_linux_s3(test, params, env):
     session = kvm_test_utils.wait_for_login(vm, timeout=timeout)
 
     logging.info("Checking that VM supports S3")
-    status = session.get_command_status("grep -q mem /sys/power/state")
-    if status == None:
-        logging.error("Failed to check if S3 exists")
-    elif status != 0:
+    if session.get_command_status("grep -q mem /sys/power/state") != 0:
         raise error.TestFail("Guest does not support S3")
 
     logging.info("Waiting for a while for X to start")
@@ -38,9 +35,7 @@ def run_linux_s3(test, params, env):
     command = "chvt %s && echo mem > /sys/power/state && chvt %s" % (dst_tty,
                                                                      src_tty)
     suspend_timeout = 120 + int(params.get("smp")) * 60
-    status = session.get_command_status(command, timeout=suspend_timeout)
-    if status != 0:
-        raise error.TestFail("Suspend to mem failed")
+    session.cmd(command, timeout=suspend_timeout)
 
     logging.info("VM resumed after S3")
 
diff --git a/client/tests/kvm/tests/mac_change.py b/client/tests/kvm/tests/mac_change.py
index c614e15..8e6c7d0 100644
--- a/client/tests/kvm/tests/mac_change.py
+++ b/client/tests/kvm/tests/mac_change.py
@@ -35,13 +35,11 @@ def run_mac_change(test, params, env):
     logging.info("Changing MAC address to %s", new_mac)
     change_cmd = ("ifconfig %s down && ifconfig %s hw ether %s && "
                   "ifconfig %s up" % (interface, interface, new_mac, interface))
-    if session.get_command_status(change_cmd) != 0:
-        raise error.TestFail("Fail to send mac_change command")
+    session.cmd(change_cmd)
 
     # Verify whether MAC address was changed to the new one
     logging.info("Verifying the new mac address")
-    if session.get_command_status("ifconfig | grep -i %s" % new_mac) != 0:
-        raise error.TestFail("Fail to change MAC address")
+    session.cmd("ifconfig | grep -i %s" % new_mac)
 
     # Restart `dhclient' to regain IP for new mac address
     logging.info("Restart the network to gain new IP")
diff --git a/client/tests/kvm/tests/migration.py b/client/tests/kvm/tests/migration.py
index d6f4b11..513b500 100644
--- a/client/tests/kvm/tests/migration.py
+++ b/client/tests/kvm/tests/migration.py
@@ -42,9 +42,7 @@ def run_migration(test, params, env):
 
     try:
         check_command = params.get("migration_bg_check_command", "")
-        if session2.get_command_status(check_command, timeout=30) != 0:
-            raise error.TestError("Could not start background process '%s'" %
-                                  background_command)
+        session2.cmd(check_command, timeout=30)
         session2.close()
 
         # Migrate the VM
@@ -59,9 +57,7 @@ def run_migration(test, params, env):
         logging.info("Logged in after migration")
 
         # Make sure the background process is still running
-        if session2.get_command_status(check_command, timeout=30) != 0:
-            raise error.TestFail("Could not find running background process "
-                                 "after migration: '%s'" % background_command)
+        session2.cmd(check_command, timeout=30)
 
         # Get the output of migration_test_command
         output = session2.get_command_output(test_command)
diff --git a/client/tests/kvm/tests/multicast.py b/client/tests/kvm/tests/multicast.py
index a47779a..4a1b4f5 100644
--- a/client/tests/kvm/tests/multicast.py
+++ b/client/tests/kvm/tests/multicast.py
@@ -1,7 +1,7 @@
 import logging, os, re
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
-import kvm_test_utils
+import kvm_test_utils, kvm_subprocess
 
 
 def run_multicast(test, params, env):
@@ -23,10 +23,10 @@ def run_multicast(test, params, env):
                                   timeout=int(params.get("login_timeout", 360)))
 
     def run_guest(cmd):
-        s, o = session.get_command_status_output(cmd)
-        if s:
-            logging.warning('Command %s executed in guest returned exit code '
-                            '%s, output: %s', cmd, s, o.strip())
+        try:
+            session.cmd(cmd)
+        except kvm_subprocess.ShellError, e:
+            logging.warn(e)
 
     def run_host_guest(cmd):
         run_guest(cmd)
diff --git a/client/tests/kvm/tests/netperf.py b/client/tests/kvm/tests/netperf.py
index dc21e0f..64ff4c6 100644
--- a/client/tests/kvm/tests/netperf.py
+++ b/client/tests/kvm/tests/netperf.py
@@ -1,7 +1,7 @@
 import logging, commands, os
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
-import kvm_test_utils
+import kvm_test_utils, kvm_subprocess
 
 def run_netperf(test, params, env):
     """
@@ -32,14 +32,13 @@ def run_netperf(test, params, env):
         if not vm.copy_files_to(os.path.join(netperf_dir, i), "/tmp"):
             raise error.TestError("Could not copy file %s to guest" % i)
 
-    if session.get_command_status(firewall_flush):
+    try:
+        session.cmd(firewall_flush):
+    except kvm_subprocess.ShellError:
         logging.warning("Could not flush firewall rules on guest")
 
-    if session.get_command_status(setup_cmd % "/tmp", timeout=200):
-        raise error.TestFail("Fail to setup netperf on guest")
-
-    if session.get_command_status(params.get("netserver_cmd") % "/tmp"):
-        raise error.TestFail("Fail to start netperf server on guest")
+    session.cmd(setup_cmd % "/tmp", timeout=200)
+    session.cmd(params.get("netserver_cmd") % "/tmp")
 
     try:
         logging.info("Setup and run netperf client on host")
diff --git a/client/tests/kvm/tests/nic_promisc.py b/client/tests/kvm/tests/nic_promisc.py
index 99bbf8c..95f43ec 100644
--- a/client/tests/kvm/tests/nic_promisc.py
+++ b/client/tests/kvm/tests/nic_promisc.py
@@ -29,13 +29,8 @@ def run_nic_promisc(test, params, env):
         raise error.TestFail("Could not log into guest '%s'" % vm.name)
 
     def compare(filename):
-        cmd = "md5sum %s" % filename
         md5_host = utils.hash_file(filename, method="md5")
-        rc_guest, md5_guest = session.get_command_status_output(cmd)
-        if rc_guest:
-            logging.debug("Could not get MD5 hash for file %s on guest,"
-                          "output: %s", filename, md5_guest)
-            return False
+        md5_guest = session.cmd("md5sum %s" % filename)
         md5_guest = md5_guest.split()[0]
         if md5_host != md5_guest:
             logging.error("MD5 hash mismatch between file %s "
@@ -72,10 +67,7 @@ def run_nic_promisc(test, params, env):
                 success_counter += 1
 
             logging.info("Create %s bytes file on guest" % size)
-            if session.get_command_status(dd_cmd % (filename, int(size)),
-                                                    timeout=100) != 0:
-                logging.error("Create file on guest failed")
-                continue
+            session.cmd(dd_cmd % (filename, int(size)), timeout=100)
 
             logging.info("Transfer file from guest to host")
             if not vm.copy_files_from(filename, filename):
@@ -90,12 +82,12 @@ def run_nic_promisc(test, params, env):
             logging.info("Clean temporary files")
             cmd = "rm -f %s" % filename
             utils.run(cmd)
-            session.get_command_status(cmd)
+            session.get_command_output(cmd)
 
     finally:
         logging.info("Restore the %s to the nonpromisc mode", ethname)
         session2.close()
-        session.get_command_status("ip link set %s promisc off" % ethname)
+        session.get_command_output("ip link set %s promisc off" % ethname)
         session.close()
 
     if success_counter != 2 * len(file_size):
diff --git a/client/tests/kvm/tests/nicdriver_unload.py b/client/tests/kvm/tests/nicdriver_unload.py
index 47318ba..cc0879c 100644
--- a/client/tests/kvm/tests/nicdriver_unload.py
+++ b/client/tests/kvm/tests/nicdriver_unload.py
@@ -28,9 +28,7 @@ def run_nicdriver_unload(test, params, env):
 
     ethname = kvm_test_utils.get_linux_ifname(session, vm.get_mac_address(0))
     sys_path = "/sys/class/net/%s/device/driver" % (ethname)
-    s, o = session.get_command_status_output('readlink -e %s' % sys_path)
-    if s:
-        raise error.TestError("Could not find driver name")
+    o = session.cmd("readlink -e %s" % sys_path)
     driver = os.path.basename(o.strip())
     logging.info("driver is %s", driver)
 
@@ -45,12 +43,8 @@ def run_nicdriver_unload(test, params, env):
                 logging.debug("Failed to transfer file %s", remote_file)
 
     def compare(origin_file, receive_file):
-        cmd = "md5sum %s"
         check_sum1 = utils.hash_file(origin_file, method="md5")
-        s, output2 = session.get_command_status_output(cmd % receive_file)
-        if s != 0:
-            logging.error("Could not get md5sum of receive_file")
-            return False
+        output2 = session.cmd("md5sum %s" % receive_file)
         check_sum2 = output2.strip().split()[0]
         logging.debug("original file md5: %s, received file md5: %s",
                       check_sum1, check_sum2)
@@ -77,9 +71,11 @@ def run_nicdriver_unload(test, params, env):
         logging.info("Unload/load NIC driver repeatedly in guest...")
         while True:
             logging.debug("Try to unload/load nic drive once")
-            if session2.get_command_status(unload_load_cmd, timeout=120) != 0:
+            try:
+                session2.cmd(unload_load_cmd, timeout=120)
+            except:
                 session.get_command_output("rm -rf /tmp/Thread-*")
-                raise error.TestFail("Unload/load nic driver failed")
+                raise
             pid, s = os.waitpid(pid, os.WNOHANG)
             status = os.WEXITSTATUS(s)
             if (pid, status) != (0, 0):
diff --git a/client/tests/kvm/tests/pci_hotplug.py b/client/tests/kvm/tests/pci_hotplug.py
index 55cf666..1b38927 100644
--- a/client/tests/kvm/tests/pci_hotplug.py
+++ b/client/tests/kvm/tests/pci_hotplug.py
@@ -26,8 +26,7 @@ def run_pci_hotplug(test, params, env):
     # Modprobe the module if specified in config file
     module = params.get("modprobe_module")
     if module:
-        if session.get_command_status("modprobe %s" % module):
-            raise error.TestError("Modprobe module '%s' failed" % module)
+        session.cmd("modprobe %s" % module)
 
     # Get output of command 'info pci' as reference
     info_pci_ref = vm.monitor.info("pci")
@@ -152,10 +151,11 @@ def run_pci_hotplug(test, params, env):
                                   params.get("find_pci_cmd")))
 
         # Test the newly added device
-        s, o = session.get_command_status_output(params.get("pci_test_cmd"))
-        if s != 0:
+        try:
+            session.cmd(params.get("pci_test_cmd"))
+        except kvm_subprocess.ShellError, e:
             raise error.TestFail("Check for %s device failed after PCI "
-                                 "hotplug. Output: %r" % (test_type, o))
+                                 "hotplug. Output: %r" % (test_type, e.output))
 
         session.close()
 
diff --git a/client/tests/kvm/tests/stress_boot.py b/client/tests/kvm/tests/stress_boot.py
index b7916b4..13dc944 100644
--- a/client/tests/kvm/tests/stress_boot.py
+++ b/client/tests/kvm/tests/stress_boot.py
@@ -51,7 +51,9 @@ def run_stress_boot(tests, params, env):
 
             # check whether all previous shell sessions are responsive
             for i, se in enumerate(sessions):
-                if se.get_command_status(params.get("alive_test_cmd")) != 0:
+                try:
+                    se.cmd(params.get("alive_test_cmd"))
+                except kvm_subprocess.ShellError:
                     raise error.TestFail("Session #%d is not responsive" % i)
             num += 1
 
diff --git a/client/tests/kvm/tests/virtio_console.py b/client/tests/kvm/tests/virtio_console.py
index 008ec63..57114e3 100644
--- a/client/tests/kvm/tests/virtio_console.py
+++ b/client/tests/kvm/tests/virtio_console.py
@@ -366,7 +366,7 @@ def run_virtio_console(test, params, env):
                        "echo -n 'FAIL: Compile virtio_guest failed'")
         (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:"],
                                                            timeout)
-        if match == 1 or match is None:
+        if match != 0:
             raise error.TestFail("Command console_switch.py on guest %s failed."
                                  "\nreturn code: %s\n output:\n%s" %
                                  (vm[0].name, match, data))
@@ -376,7 +376,7 @@ def run_virtio_console(test, params, env):
                        "echo -n 'FAIL: virtio_guest failed'")
         (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:"],
                                                            timeout)
-        if match == 1 or match is None:
+        if match != 0:
             raise error.TestFail("Command console_switch.py on guest %s failed."
                                  "\nreturn code: %s\n output:\n%s" %
                                  (vm[0].name, match, data))
diff --git a/client/tests/kvm/tests/vlan.py b/client/tests/kvm/tests/vlan.py
index f41ea6a..8641c23 100644
--- a/client/tests/kvm/tests/vlan.py
+++ b/client/tests/kvm/tests/vlan.py
@@ -1,6 +1,6 @@
 import logging, time, re
 from autotest_lib.client.common_lib import error
-import kvm_test_utils, kvm_utils
+import kvm_test_utils, kvm_utils, kvm_subprocess
 
 def run_vlan(test, params, env):
     """
@@ -35,18 +35,15 @@ def run_vlan(test, params, env):
     vm.append(kvm_test_utils.get_living_vm(env, "vm2"))
 
     def add_vlan(session, id, iface="eth0"):
-        if session.get_command_status("vconfig add %s %s" % (iface, id)) != 0:
-            raise error.TestError("Fail to add %s.%s" % (iface, id))
+        session.cmd("vconfig add %s %s" % (iface, id))
 
     def set_ip_vlan(session, id, ip, iface="eth0"):
         iface = "%s.%s" % (iface, id)
-        if session.get_command_status("ifconfig %s %s" % (iface, ip)) != 0:
-            raise error.TestError("Fail to configure ip for %s" % iface)
+        session.cmd("ifconfig %s %s" % (iface, ip))
 
     def set_arp_ignore(session, iface="eth0"):
         ignore_cmd = "echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore"
-        if session.get_command_status(ignore_cmd) != 0:
-            raise error.TestError("Fail to set arp_ignore of %s" % session)
+        session.cmd(ignore_cmd)
 
     def rem_vlan(session, id, iface="eth0"):
         rem_vlan_cmd = "if [[ -e /proc/net/vlan/%s ]];then vconfig rem %s;fi"
@@ -65,11 +62,12 @@ def run_vlan(test, params, env):
         time.sleep(2)
         #send file from src to dst
         send_cmd = send_cmd % (vlan_ip[dst], str(nc_port), "file")
-        if session[src].get_command_status(send_cmd, timeout = 60) != 0:
+        if session[src].get_command_status(send_cmd, timeout=60) != 0:
             raise error.TestFail ("Fail to send file"
                                     " from vm%s to vm%s" % (src+1, dst+1))
-        s, o = session[dst].read_up_to_prompt(timeout=60)
-        if s != True:
+        try:
+            session[dst].read_up_to_prompt(timeout=60)
+        except kvm_subprocess.ExpectError:
             raise error.TestFail ("Fail to receive file"
                                     " from vm%s to vm%s" % (src+1, dst+1))
         #check MD5 message digest of receive file in dst
@@ -81,7 +79,7 @@ def run_vlan(test, params, env):
             logging.info("digest_origin is  %s" % digest_origin[src])
             logging.info("digest_receive is %s" % digest_receive)
             raise error.TestFail("File transfered differ from origin")
-        session[dst].get_command_status("rm -f receive")
+        session[dst].get_command_output("rm -f receive")
 
     for i in range(2):
         session.append(kvm_test_utils.wait_for_login(vm[i],
@@ -97,22 +95,16 @@ def run_vlan(test, params, env):
 
         #produce sized file in vm
         dd_cmd = "dd if=/dev/urandom of=file bs=1024k count=%s"
-        if session[i].get_command_status(dd_cmd % file_size) != 0:
-            raise error.TestFail("File producing failed")
+        session[i].cmd(dd_cmd % file_size)
         #record MD5 message digest of file
-        s, output =session[i].get_command_status_output("md5sum file",
-                                                        timeout=60)
-        if s != 0:
-            raise error.TestFail("File MD5_checking failed" )
+        output = session[i].cmd("md5sum file", timeout=60)
         digest_origin.append(re.findall(r'(\w+)', output)[0])
 
         #stop firewall in vm
-        session[i].get_command_status("/etc/init.d/iptables stop")
+        session[i].get_command_output("/etc/init.d/iptables stop")
 
         #load 8021q module for vconfig
-        load_8021q_cmd = "modprobe 8021q"
-        if session[i].get_command_status(load_8021q_cmd) != 0:
-            raise error.TestError("Fail to load 8021q module on VM%s" % i)
+        session[i].cmd("modprobe 8021q")
 
     try:
         for i in range(2):
diff --git a/client/tests/kvm/tests/whql_client_install.py b/client/tests/kvm/tests/whql_client_install.py
index 84b91bc..52daa31 100644
--- a/client/tests/kvm/tests/whql_client_install.py
+++ b/client/tests/kvm/tests/whql_client_install.py
@@ -50,6 +50,7 @@ def run_whql_client_install(test, params, env):
     server_session = kvm_utils.remote_login("nc", server_address,
                                             server_shell_port, "", "",
                                             session.prompt, session.linesep)
+    server_session.set_status_test_command(session.status_test_command)
 
     # Get server and client information
     cmd = "echo %computername%"
@@ -67,10 +68,10 @@ def run_whql_client_install(test, params, env):
         server_dns_suffix = ""
 
     # Delete the client machine from the server's data store (if it's there)
-    server_session.get_command_output("cd %s" % server_studio_path)
+    server_session.cmd("cd %s" % server_studio_path)
     cmd = "%s %s %s" % (os.path.basename(dsso_delete_machine_binary),
                         server_name, client_name)
-    server_session.get_command_output(cmd, print_func=logging.info)
+    server_session.cmd(cmd, print_func=logging.info)
     server_session.close()
 
     # Rename the client machine
@@ -78,21 +79,18 @@ def run_whql_client_install(test, params, env):
     logging.info("Renaming client machine to '%s'" % client_name)
     cmd = ('wmic computersystem where name="%%computername%%" rename name="%s"'
            % client_name)
-    if session.get_command_status(cmd, timeout=600) != 0:
-        raise error.TestError("Could not rename the client machine")
+    session.cmd(cmd, timeout=600)
 
     # Join the server's workgroup
     logging.info("Joining workgroup '%s'" % server_workgroup)
     cmd = ('wmic computersystem where name="%%computername%%" call '
            'joindomainorworkgroup name="%s"' % server_workgroup)
-    if session.get_command_status(cmd, timeout=600) != 0:
-        raise error.TestError("Could not change the client's workgroup")
+    session.cmd(cmd, timeout=600)
 
     # Set the client machine's DNS suffix
     logging.info("Setting DNS suffix to '%s'" % server_dns_suffix)
     cmd = 'reg add %s /v Domain /d "%s" /f' % (regkey, server_dns_suffix)
-    if session.get_command_status(cmd, timeout=300) != 0:
-        raise error.TestError("Could not set the client's DNS suffix")
+    session.cmd(cmd, timeout=300)
 
     # Reboot
     session = kvm_test_utils.reboot(vm, session)
@@ -103,8 +101,7 @@ def run_whql_client_install(test, params, env):
                                          server_password)
     end_time = time.time() + 120
     while time.time() < end_time:
-        s = session.get_command_status(cmd)
-        if s == 0:
+        if session.get_command_status(cmd) == 0:
             break
         time.sleep(5)
     else:
@@ -114,7 +111,5 @@ def run_whql_client_install(test, params, env):
     # Install
     logging.info("Installing DTM client (timeout=%ds)", install_timeout)
     install_cmd = r"cmd /c \\%s\%s" % (server_name, install_cmd.lstrip("\\"))
-    if session.get_command_status(install_cmd, timeout=install_timeout) != 0:
-        raise error.TestError("Client installation failed")
-
+    session.cmd(install_cmd, timeout=install_timeout)
     session.close()
diff --git a/client/tests/kvm/tests/whql_submission.py b/client/tests/kvm/tests/whql_submission.py
index 1fe27c9..3930954 100644
--- a/client/tests/kvm/tests/whql_submission.py
+++ b/client/tests/kvm/tests/whql_submission.py
@@ -50,6 +50,7 @@ def run_whql_submission(test, params, env):
     server_session = kvm_utils.remote_login("nc", server_address,
                                             server_shell_port, "", "",
                                             session.prompt, session.linesep)
+    server_session.set_status_test_command(session.status_test_command)
 
     # Get the computer names of the server and client
     cmd = "echo %computername%"
@@ -58,7 +59,7 @@ def run_whql_submission(test, params, env):
     session.close()
 
     # Run the automation program on the server
-    server_session.get_command_output("cd %s" % server_studio_path)
+    server_session.cmd("cd %s" % server_studio_path)
     cmd = "%s %s %s %s %s %s" % (os.path.basename(dsso_test_binary),
                                  server_name,
                                  client_name,
@@ -78,8 +79,8 @@ 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:")
@@ -108,10 +109,15 @@ def run_whql_submission(test, params, env):
     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
@@ -167,7 +173,7 @@ def run_whql_submission(test, params, env):
     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:
+    if not done:
         vm.destroy()
         raise error.TestFail("The automation program did not terminate "
                              "on time")
-- 
1.5.5.6


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-10-27 12:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <2034814473.1590591288159137734.JavaMail.root@zmail04.collab.prod.int.phx2.redhat.com>
2010-10-27  5:59 ` [KVM-AUTOTEST PATCH 4/5] KVM test: kvm_subprocess: rename get_command_status_output() and friends Feng Yang
2010-10-27  9:10   ` Michael Goldish
2010-10-27 12:04   ` [Autotest] " Lucas Meneghel Rodrigues
2010-10-26 16:49 [KVM-AUTOTEST PATCH 1/5] KVM test: kvm_subprocess: raise exceptions in kvm_shell_session and kvm_expect Michael Goldish
2010-10-26 16:49 ` [KVM-AUTOTEST PATCH 2/5] KVM test: kvm_monitor.py: store attributes in QMPCmdError Michael Goldish
2010-10-26 16:49   ` [KVM-AUTOTEST PATCH 3/5] KVM test: add utility functions start_windows_service() and stop_windows_service() Michael Goldish
2010-10-26 16:49     ` [KVM-AUTOTEST PATCH 4/5] KVM test: kvm_subprocess: rename get_command_status_output() and friends Michael Goldish

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.