- Add new monitor definition syntax that allows definition of multiple
  monitors.
  Monitors are now defined like other objects in the config file:

      monitors = MyMonitor SomeOtherMonitor YetAnotherMonitor   # defines 3 
monitors
      monitor_type = human                    # default for all monitors
      monitor_type_SomeOtherMonitor = qmp     # applies only to SomeOtherMonitor
      monitor_type_YetAnotherMonitor = qmp    # applies only to 
YetAnotherMonitor
      main_monitor = MyMonitor                # defines the main monitor to use
                                              # in the test

- Use the new syntax in tests_base.cfg.sample.

- Establish monitor connections using kvm_monitor in VM.create().
  Store all monitors in self.monitors.  Store main monitor in
self.monitor.

- Replace calls to send_monitor_cmd() with appropriate calls to methods
  of self.monitor (the main monitor).

- For now, ignore the parameter screendump_verbose because currently
  monitor commands are always silent (when successful).

Changes from v2:
- Rebased against the latest upstream
- Corrected a few bugs left on tests

Changes from v1:
- Turn VM.monitor into a property

Signed-off-by: Michael Goldish <[email protected]>
Signed-off-by: Lucas Meneghel Rodrigues <[email protected]>
---
 client/tests/kvm/kvm_preprocessing.py              |   33 ++--
 client/tests/kvm/kvm_test_utils.py                 |  135 ++++--------
 client/tests/kvm/kvm_vm.py                         |  238 ++++++++++----------
 client/tests/kvm/tests/balloon_check.py            |   12 +-
 client/tests/kvm/tests/boot_savevm.py              |   41 ++--
 client/tests/kvm/tests/build.py                    |    1 -
 client/tests/kvm/tests/guest_s4.py                 |    2 +-
 client/tests/kvm/tests/ksm_overcommit.py           |    8 +-
 client/tests/kvm/tests/migration.py                |    2 +-
 client/tests/kvm/tests/pci_hotplug.py              |   13 +-
 client/tests/kvm/tests/physical_resources_check.py |   40 ++--
 client/tests/kvm/tests/shutdown.py                 |    2 +-
 client/tests/kvm/tests/stepmaker.py                |   44 ++--
 client/tests/kvm/tests/steps.py                    |   12 +-
 client/tests/kvm/tests/timedrift_with_stop.py      |    8 +-
 client/tests/kvm/tests/vlan_tag.py                 |    2 +-
 client/tests/kvm/tests_base.cfg.sample             |    7 +-
 17 files changed, 284 insertions(+), 316 deletions(-)

diff --git a/client/tests/kvm/kvm_preprocessing.py 
b/client/tests/kvm/kvm_preprocessing.py
index 76c8268..ee3e9b2 100644
--- a/client/tests/kvm/kvm_preprocessing.py
+++ b/client/tests/kvm/kvm_preprocessing.py
@@ -1,7 +1,7 @@
 import sys, os, time, commands, re, logging, signal, glob, threading, shutil
 from autotest_lib.client.bin import test, utils
 from autotest_lib.client.common_lib import error
-import kvm_vm, kvm_utils, kvm_subprocess, ppm_utils
+import kvm_vm, kvm_utils, kvm_subprocess, kvm_monitor, ppm_utils
 try:
     import PIL.Image
 except ImportError:
@@ -83,7 +83,11 @@ def preprocess_vm(test, params, env, name):
         raise error.TestError("Could not start VM")
 
     scrdump_filename = os.path.join(test.debugdir, "pre_%s.ppm" % name)
-    vm.send_monitor_cmd("screendump %s" % scrdump_filename)
+    try:
+        if vm.monitor:
+            vm.monitor.screendump(scrdump_filename)
+    except kvm_monitor.MonitorError, e:
+        logging.warn(e)
 
 
 def postprocess_image(test, params):
@@ -117,7 +121,11 @@ def postprocess_vm(test, params, env, name):
         return
 
     scrdump_filename = os.path.join(test.debugdir, "post_%s.ppm" % name)
-    vm.send_monitor_cmd("screendump %s" % scrdump_filename)
+    try:
+        if vm.monitor:
+            vm.monitor.screendump(scrdump_filename)
+    except kvm_monitor.MonitorError, e:
+        logging.warn(e)
 
     if params.get("kill_vm") == "yes":
         kill_vm_timeout = float(params.get("kill_vm_timeout", 0))
@@ -356,8 +364,9 @@ def postprocess(test, params, env):
         for vm in kvm_utils.env_get_all_vms(env):
             if not vm.is_dead():
                 logging.info("VM '%s' is alive.", vm.name)
-                logging.info("The monitor unix socket of '%s' is: %s",
-                             vm.name, vm.monitor_file_name)
+                for m in vm.monitors:
+                    logging.info("'%s' has a %s monitor unix socket at: %s",
+                                 vm.name, m.protocol, m.filename)
                 logging.info("The command line used to start '%s' was:\n%s",
                              vm.name, vm.make_qemu_command())
         raise error.JobError("Abort requested (%s)" % exc_string)
@@ -403,10 +412,6 @@ def _take_screendumps(test, params, env):
                                  kvm_utils.generate_random_string(6))
     delay = float(params.get("screendump_delay", 5))
     quality = int(params.get("screendump_quality", 30))
-    if params.get("screendump_verbose") == 'yes':
-        screendump_verbose = True
-    else:
-        screendump_verbose = False
 
     cache = {}
 
@@ -414,11 +419,11 @@ def _take_screendumps(test, params, env):
         for vm in kvm_utils.env_get_all_vms(env):
             if vm.is_dead():
                 continue
-            if screendump_verbose:
-                vm.send_monitor_cmd("screendump %s" % temp_filename)
-            else:
-                vm.send_monitor_cmd("screendump %s" % temp_filename,
-                                    verbose=False)
+            try:
+                vm.monitor.screendump(temp_filename)
+            except kvm_monitor.MonitorError, e:
+                logging.warn(e)
+                continue
             if not os.path.exists(temp_filename):
                 logging.warn("VM '%s' failed to produce a screendump", vm.name)
                 continue
diff --git a/client/tests/kvm/kvm_test_utils.py 
b/client/tests/kvm/kvm_test_utils.py
index 77015f0..760a462 100644
--- a/client/tests/kvm/kvm_test_utils.py
+++ b/client/tests/kvm/kvm_test_utils.py
@@ -85,9 +85,9 @@ def reboot(vm, session, method="shell", 
sleep_before_reset=10, nic_index=0,
         # Sleep for a while before sending the command
         time.sleep(sleep_before_reset)
         # Send a system_reset monitor command
-        vm.send_monitor_cmd("system_reset")
+        vm.monitor.cmd("system_reset")
         logging.info("Monitor command system_reset sent. Waiting for guest to "
-                     "go down")
+                     "go down...")
     else:
         logging.error("Unknown reboot method: %s", method)
 
@@ -121,90 +121,70 @@ def migrate(vm, env=None, mig_timeout=3600, 
mig_protocol="tcp",
     @param mig_cancel: Test migrate_cancel or not when protocol is tcp.
     @return: The post-migration VM.
     """
-    # Helper functions
     def mig_finished():
-        s, o = vm.send_monitor_cmd("info migrate")
-        return s == 0 and not "Migration status: active" in o
+        o = vm.monitor.info("migrate")
+        return "status: active" not in o
 
     def mig_succeeded():
-        s, o = vm.send_monitor_cmd("info migrate")
-        return s == 0 and "Migration status: completed" in o
-
-    def mig_canceled():
-        s, o = vm.send_monitor_cmd("info migrate")
-        return s == 0 and "Migration status: cancelled" in o
+        o = vm.monitor.info("migrate")
+        return "status: completed" in o
 
     def mig_failed():
-        s, o = vm.send_monitor_cmd("info migrate")
-        return s == 0 and "Migration status: failed" in o
+        o = vm.monitor.info("migrate")
+        return "status: failed" in o
+
+    def mig_cancelled():
+        o = vm.monitor.info("migrate")
+        return "Migration status: cancelled" in o
+
+    def wait_for_migration():
+        if not kvm_utils.wait_for(mig_finished, mig_timeout, 2, 2,
+                                  "Waiting for migration to finish..."):
+            raise error.TestFail("Timeout expired while waiting for migration "
+                                 "to finish")
 
-    # See if migration is supported
-    s, o = vm.send_monitor_cmd("help info")
-    if not "info migrate" in o:
-        raise error.TestError("Migration is not supported")
 
+    migration_file = os.path.join("/tmp/",
+                                  mig_protocol + 
time.strftime("%Y%m%d-%H%M%S"))
     if mig_protocol == "tcp":
         mig_extra_params = " -incoming tcp:0:%d"
     elif mig_protocol == "unix":
-        file = os.path.join("/tmp/", mig_protocol +
-                                     time.strftime("%Y%m%d-%H%M%S"))
         mig_extra_params = " -incoming unix:%s"
     elif mig_protocol == "exec":
-        file = os.path.join("/tmp/", mig_protocol +
-                                     time.strftime("%Y%m%d-%H%M%S"))
-        mig_extra_params = " -incoming \"exec: gzip -c -d %s\"" % file
-        mig_cmd = "migrate \"exec:gzip -c > %s\"" % file
-
-        vm.send_monitor_cmd("stop")
-        vm.send_monitor_cmd(mig_cmd, timeout=mig_timeout)
-        if not kvm_utils.wait_for(mig_finished, mig_timeout, 2, 2,
-                                  "Waiting for migration to finish..."):
-            raise error.TestFail("Timeout elapsed while waiting for migration "
-                                 "to finish")
+        # Exec is a little different from other migrate methods - first we
+        # ask the monitor the migration, then the vm state is dumped to a
+        # compressed file, then we start the dest vm with -incoming pointing
+        # to it
+        mig_extra_params = " -incoming \"exec: gzip -c -d %s\"" % 
migration_file
+        uri = "\"exec:gzip -c > %s\"" % migration_file
+        vm.monitor.cmd("stop")
+        o = vm.monitor.migrate(uri)
+        wait_for_migration()
 
     # Clone the source VM and ask the clone to wait for incoming migration
     dest_vm = vm.clone()
     if not dest_vm.create(extra_params=mig_extra_params):
         raise error.TestError("Could not create dest VM")
 
-    if mig_protocol == "tcp":
-        mig_cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port
-    elif mig_protocol == "unix":
-        mig_cmd = "migrate unix:%s" % dest_vm.migration_file
-
     try:
-        if mig_protocol != "exec":
-            logging.debug("Migrating with command: %s" % mig_cmd)
+        if mig_protocol == "tcp":
+            uri = "tcp:localhost:%d" % dest_vm.migration_port
+        elif mig_protocol == "unix":
+            uri = "unix:%s" % dest_vm.migration_file
 
-            # Migrate
-            s, o = vm.send_monitor_cmd(mig_cmd, timeout=mig_timeout)
-            if s:
-                logging.error("Migration command failed (command: %r, output:"
-                              " %r)"  % (mig_cmd, o))
-                raise error.TestFail("Migration command failed")
+        if mig_protocol != "exec":
+            o = vm.monitor.migrate(uri)
 
             if mig_protocol == "tcp" and mig_cancel:
-                # Sleep two seconds before send migrate_cancel command.
                 time.sleep(2)
-                s, o = vm.send_monitor_cmd("migrate_cancel")
-                if not kvm_utils.wait_for(mig_canceled, 60, 2, 2,
+                o = vm.monitor.cmd("migrate_cancel")
+                if not kvm_utils.wait_for(mig_cancelled, 60, 2, 2,
                                           "Waiting for migration cancel"):
                     raise error.TestFail("Fail to cancel migration")
-                s, o = dest_vm.send_monitor_cmd("info status")
-                if "paused" not in o:
-                    raise error.TestFail("Fail to cancel migration, dest VM"
-                                          "is not paused")
-                s, o = vm.send_monitor_cmd("info status")
-                if "running" not in o:
-                    raise error.TestFail("VM status is not running after"
-                                         " migration canceled")
+                dest_vm.destroy(gracefully=False)
                 return vm
 
-            # Wait for migration to finish
-            if not kvm_utils.wait_for(mig_finished, mig_timeout, 2, 2,
-                                      "Waiting for migration to finish..."):
-                raise error.TestFail("Timeout elapsed while waiting for "
-                                      "migration to finish")
+            wait_for_migration()
 
         # Report migration status
         if mig_succeeded():
@@ -214,13 +194,12 @@ def migrate(vm, env=None, mig_timeout=3600, 
mig_protocol="tcp",
         else:
             raise error.TestFail("Migration ended with unknown status")
 
-        if mig_protocol == "exec":
-            s, o = dest_vm.send_monitor_cmd("info status")
-            if "paused" in o:
-                logging.debug("Dest VM is in paused status")
-                dest_vm.send_monitor_cmd("c")
-            if os.path.exists(file):
-                os.remove(file)
+        o = dest_vm.monitor.info("status")
+        if "paused" in o:
+            logging.debug("Destination VM is paused, resuming it...")
+            dest_vm.monitor.cmd("cont")
+            if os.path.exists(migration_file):
+                os.remove(migration_file)
 
         # Kill the source VM
         vm.destroy(gracefully=False)
@@ -237,30 +216,6 @@ def migrate(vm, env=None, mig_timeout=3600, 
mig_protocol="tcp",
         raise
 
 
-def stop(vm):
-    """
-    Stop a running vm
-    """
-    s, o = vm.send_monitor_cmd("stop")
-    if s != 0:
-        raise error.TestError("Could not send the stop command")
-    s, o = vm.send_monitor_cmd("info status")
-    if "paused" not in o:
-        raise error.TestFail("VM does not stop afer send stop command")
-
-
-def cont(vm):
-    """
-    Continue a stopped vm
-    """
-    s, o = vm.send_monitor_cmd("cont")
-    if s != 0:
-        raise error.TestError("Could not send the cont command")
-    s, o = vm.send_monitor_cmd("info status")
-    if "running" not in o:
-        raise error.TestFail("VM still in paused status after sending cont")
-
-
 def get_time(session, time_command, time_filter_re, time_format):
     """
     Return the host time and guest time.  If the guest time cannot be fetched
diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py
index ed8e7a3..cb4666b 100755
--- a/client/tests/kvm/kvm_vm.py
+++ b/client/tests/kvm/kvm_vm.py
@@ -5,8 +5,8 @@ Utility classes and functions to handle Virtual Machine 
creation using qemu.
 @copyright: 2008-2009 Red Hat Inc.
 """
 
-import time, socket, os, logging, fcntl, re, commands
-import kvm_utils, kvm_subprocess
+import time, socket, os, logging, fcntl, re, commands, glob
+import kvm_utils, kvm_subprocess, kvm_monitor
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
 
@@ -109,24 +109,22 @@ class VM:
         self.redirs = {}
         self.vnc_port = 5900
         self.uuid = None
+        self.monitors = []
+        self.pci_assignable = None
 
         self.name = name
         self.params = params
         self.root_dir = root_dir
         self.address_cache = address_cache
-        self.pci_assignable = None
         self.netdev_id = []
         for nic in params.get("nics").split():
             self.netdev_id.append(kvm_utils.generate_random_string(4))
 
-        # Find available monitor filename
+        # Find a unique identifier for this VM
         while True:
-            # The monitor filename should be unique
             self.instance = (time.strftime("%Y%m%d-%H%M%S-") +
                              kvm_utils.generate_random_string(4))
-            self.monitor_file_name = os.path.join("/tmp",
-                                                  "monitor-" + self.instance)
-            if not os.path.exists(self.monitor_file_name):
+            if not glob.glob("/tmp/*%s" % self.instance):
                 break
 
 
@@ -202,9 +200,12 @@ class VM:
         def add_name(help, name):
             return " -name '%s'" % name
 
-        def add_unix_socket_monitor(help, filename):
+        def add_human_monitor(help, filename):
             return " -monitor unix:'%s',server,nowait" % filename
 
+        def add_qmp_monitor(help, filename):
+            return " -qmp unix:'%s',server,nowait" % filename
+
         def add_mem(help, mem):
             return " -m %s" % mem
 
@@ -304,8 +305,14 @@ class VM:
         qemu_cmd += qemu_binary
         # Add the VM's name
         qemu_cmd += add_name(help, name)
-        # Add the monitor socket parameter
-        qemu_cmd += add_unix_socket_monitor(help, self.monitor_file_name)
+        # Add monitors
+        for monitor_name in kvm_utils.get_sub_dict_names(params, "monitors"):
+            monitor_params = kvm_utils.get_sub_dict(params, monitor_name)
+            monitor_filename = self.get_monitor_filename(monitor_name)
+            if monitor_params.get("monitor_type") == "qmp":
+                qemu_cmd += add_qmp_monitor(help, monitor_filename)
+            else:
+                qemu_cmd += add_human_monitor(help, monitor_filename)
 
         for image_name in kvm_utils.get_sub_dict_names(params, "images"):
             image_params = kvm_utils.get_sub_dict(params, image_name)
@@ -565,6 +572,7 @@ class VM:
             self.process = kvm_subprocess.run_bg(qemu_command, None,
                                                  logging.debug, "(qemu) ")
 
+            # Make sure the process was started successfully
             if not self.process.is_alive():
                 logging.error("VM could not be created; "
                               "qemu command failed:\n%s" % qemu_command)
@@ -574,11 +582,36 @@ class VM:
                 self.destroy()
                 return False
 
-            if not kvm_utils.wait_for(self.is_alive, timeout, 0, 1):
-                logging.error("VM is not alive for some reason; "
-                              "qemu command:\n%s" % qemu_command)
-                self.destroy()
-                return False
+            # Establish monitor connections
+            self.monitors = []
+            for monitor_name in kvm_utils.get_sub_dict_names(params,
+                                                             "monitors"):
+                monitor_params = kvm_utils.get_sub_dict(params, monitor_name)
+                # Wait for monitor connection to succeed
+                end_time = time.time() + timeout
+                while time.time() < end_time:
+                    try:
+                        if monitor_params.get("monitor_type") == "qmp":
+                            # Add a QMP monitor: not implemented yet
+                            monitor = None
+                        else:
+                            # Add a "human" monitor
+                            monitor = kvm_monitor.HumanMonitor(
+                                monitor_name,
+                                self.get_monitor_filename(monitor_name))
+                    except kvm_monitor.MonitorError, e:
+                        logging.warn(e)
+                    else:
+                        if monitor and monitor.is_responsive():
+                            break
+                    time.sleep(1)
+                else:
+                    logging.error("Could not connect to monitor '%s'" %
+                                  monitor_name)
+                    self.destroy()
+                    return False
+                # Add this monitor to the list
+                self.monitors += [monitor]
 
             # Get the output so far, to see if we have any problems with
             # hugepage setup.
@@ -600,90 +633,6 @@ class VM:
             lockfile.close()
 
 
-    def send_monitor_cmd(self, command, block=True, timeout=20.0, 
verbose=True):
-        """
-        Send command to the QEMU monitor.
-
-        Connect to the VM's monitor socket and wait for the (qemu) prompt.
-        If block is True, read output from the socket until the (qemu) prompt
-        is found again, or until timeout expires.
-
-        Return a tuple containing an integer indicating success or failure,
-        and the data read so far. The integer is 0 on success and 1 on failure.
-        A failure is any of the following cases: connection to the socket
-        failed, or the first (qemu) prompt could not be found, or block is
-        True and the second prompt could not be found.
-
-        @param command: Command that will be sent to the monitor
-        @param block: Whether the output from the socket will be read until
-                the timeout expires
-        @param timeout: Timeout (seconds) before giving up on reading from
-                socket
-        """
-        def read_up_to_qemu_prompt(s, timeout):
-            """
-            Read data from socket s until the (qemu) prompt is found.
-
-            If the prompt is found before timeout expires, return a tuple
-            containing True and the data read. Otherwise return a tuple
-            containing False and the data read so far.
-
-            @param s: Socket object
-            @param timeout: Time (seconds) before giving up trying to get the
-                    qemu prompt.
-            """
-            o = ""
-            end_time = time.time() + timeout
-            while time.time() < end_time:
-                try:
-                    o += s.recv(1024)
-                    if o.splitlines()[-1].split()[-1] == "(qemu)":
-                        return (True, o)
-                except:
-                    time.sleep(0.01)
-            return (False, o)
-
-        # In certain conditions printing this debug output might be too much
-        # Just print it if verbose is enabled (True by default)
-        if verbose:
-            logging.debug("Sending monitor command: %s" % command)
-        # Connect to monitor
-        try:
-            s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            s.setblocking(False)
-            s.connect(self.monitor_file_name)
-        except:
-            logging.debug("Could not connect to monitor socket")
-            return (1, "")
-
-        # Send the command and get the resulting output
-        try:
-            status, data = read_up_to_qemu_prompt(s, timeout)
-            if not status:
-                logging.debug("Could not find (qemu) prompt; output so far:" +
-                              kvm_utils.format_str_for_message(data))
-                return (1, "")
-            # Send command
-            s.sendall(command + "\n")
-            # Receive command output
-            data = ""
-            if block:
-                status, data = read_up_to_qemu_prompt(s, timeout)
-                data = "\n".join(data.splitlines()[1:])
-                if not status:
-                    logging.debug("Could not find (qemu) prompt after command; 
"
-                                  "output so far:" +
-                                  kvm_utils.format_str_for_message(data))
-                    return (1, data)
-            data = "".join(data.rstrip().splitlines(True)[:-1])
-            return (0, data)
-
-        # Clean up before exiting
-        finally:
-            s.shutdown(socket.SHUT_RDWR)
-            s.close()
-
-
     def destroy(self, gracefully=True):
         """
         Destroy the VM.
@@ -720,15 +669,18 @@ class VM:
                     finally:
                         session.close()
 
-            # Try to destroy with a monitor command
-            logging.debug("Trying to kill VM with monitor command...")
-            status, output = self.send_monitor_cmd("quit", block=False)
-            # Was the command sent successfully?
-            if status == 0:
-                # Wait for the VM to be really dead
-                if kvm_utils.wait_for(self.is_dead, 5, 0.5, 0.5):
-                    logging.debug("VM is down")
-                    return
+            if self.monitor:
+                # Try to destroy with a monitor command
+                logging.debug("Trying to kill VM with monitor command...")
+                try:
+                    self.monitor.quit()
+                except kvm_monitor.MonitorError, e:
+                    logging.warn(e)
+                else:
+                    # Wait for the VM to be really dead
+                    if kvm_utils.wait_for(self.is_dead, 5, 0.5, 0.5):
+                        logging.debug("VM is down")
+                        return
 
             # If the VM isn't dead yet...
             logging.debug("Cannot quit normally; sending a kill to close the "
@@ -742,28 +694,43 @@ class VM:
             logging.error("Process %s is a zombie!" % self.process.get_pid())
 
         finally:
+            self.monitors = []
             if self.pci_assignable:
                 self.pci_assignable.release_devs()
             if self.process:
                 self.process.close()
-            try:
-                os.unlink(self.monitor_file_name)
-            except OSError:
-                pass
+            for f in ([self.get_testlog_filename()] +
+                      self.get_monitor_filenames()):
+                try:
+                    os.unlink(f)
+                except OSError:
+                    pass
+
+
+    @property
+    def monitor(self):
+        """
+        Return the main monitor object, selected by the parameter main_monitor.
+        If main_monitor isn't defined, return the first monitor.
+        If no monitors exist, or if main_monitor refers to a nonexistent
+        monitor, return None.
+        """
+        for m in self.monitors:
+            if m.name == self.params.get("main_monitor"):
+                return m
+        if self.monitors and not self.params.get("main_monitor"):
+            return self.monitors[0]
 
 
     def is_alive(self):
         """
-        Return True if the VM's monitor is responsive.
+        Return True if the VM is alive and its monitor is responsive.
         """
         # Check if the process is running
         if self.is_dead():
             return False
         # Try sending a monitor command
-        (status, output) = self.send_monitor_cmd("help")
-        if status:
-            return False
-        return True
+        return bool(self.monitor) and self.monitor.is_responsive()
 
 
     def is_dead(self):
@@ -789,6 +756,29 @@ class VM:
         return self.params
 
 
+    def get_monitor_filename(self, monitor_name):
+        """
+        Return the filename corresponding to a given monitor name.
+        """
+        return "/tmp/monitor-%s-%s" % (monitor_name, self.instance)
+
+
+    def get_monitor_filenames(self):
+        """
+        Return a list of all monitor filenames (as specified in the VM's
+        params).
+        """
+        return [self.get_monitor_filename(m) for m in
+                kvm_utils.get_sub_dict_names(self.params, "monitors")]
+
+
+    def get_testlog_filename(self):
+        """
+        Return the testlog filename.
+        """
+        return "/tmp/testlog-%s" % self.instance
+
+
     def get_address(self, index=0):
         """
         Return the address of a NIC of the guest, in host space.
@@ -986,12 +976,12 @@ class VM:
         # For compatibility with versions of QEMU that do not recognize all
         # key names: replace keyname with the hex value from the dict, which
         # QEMU will definitely accept
-        dict = { "comma": "0x33",
-                 "dot": "0x34",
-                 "slash": "0x35" }
-        for key in dict.keys():
-            keystr = keystr.replace(key, dict[key])
-        self.send_monitor_cmd("sendkey %s 1" % keystr)
+        dict = {"comma": "0x33",
+                "dot":   "0x34",
+                "slash": "0x35"}
+        for key, value in dict.items():
+            keystr = keystr.replace(key, value)
+        self.monitor.sendkey(keystr)
         time.sleep(0.2)
 
 
diff --git a/client/tests/kvm/tests/balloon_check.py 
b/client/tests/kvm/tests/balloon_check.py
index f33bda8..1ee05bf 100644
--- a/client/tests/kvm/tests/balloon_check.py
+++ b/client/tests/kvm/tests/balloon_check.py
@@ -1,6 +1,6 @@
 import re, string, logging, random, time
 from autotest_lib.client.common_lib import error
-import kvm_test_utils, kvm_utils
+import kvm_test_utils, kvm_utils, kvm_monitor
 
 def run_balloon_check(test, params, env):
     """
@@ -21,9 +21,10 @@ def run_balloon_check(test, params, env):
         @return: Number of failures occurred during operation.
         """
         fail = 0
-        status, output = vm.send_monitor_cmd("info balloon")
-        if status != 0:
-            logging.error("qemu monitor command failed: info balloon")
+        try:
+            output = vm.monitor.info("balloon")
+        except kvm_monitor.MonitorError, e:
+            logging.error(e)
             fail += 1
             return 0
         return int(re.findall("\d+", output)[0]), fail
@@ -39,7 +40,8 @@ def run_balloon_check(test, params, env):
         """
         fail = 0
         logging.info("Changing VM memory to %s", new_mem)
-        vm.send_monitor_cmd("balloon %s" % new_mem)
+        # This should be replaced by proper monitor method call
+        vm.monitor.cmd("balloon %s" % new_mem)
         time.sleep(20)
 
         ballooned_mem, cfail = check_ballooned_memory()
diff --git a/client/tests/kvm/tests/boot_savevm.py 
b/client/tests/kvm/tests/boot_savevm.py
index e8ea724..3305695 100644
--- a/client/tests/kvm/tests/boot_savevm.py
+++ b/client/tests/kvm/tests/boot_savevm.py
@@ -1,6 +1,6 @@
 import logging, time
 from autotest_lib.client.common_lib import error
-import kvm_subprocess, kvm_test_utils, kvm_utils
+import kvm_test_utils, kvm_utils, kvm_monitor
 
 def run_boot_savevm(test, params, env):
     """
@@ -23,23 +23,30 @@ def run_boot_savevm(test, params, env):
     while time.time() < end_time:
         time.sleep(savevm_delay)
 
-        s, o = vm.send_monitor_cmd("stop")
-        if s:
-            logging.error("stop failed: %r" % o)
-        s, o = vm.send_monitor_cmd("savevm 1")
-        if s:
-            logging.error("savevm failed: %r" % o)
-        s, o = vm.send_monitor_cmd("system_reset")
-        if s:
-            logging.error("system_reset: %r" % o)
-        s, o = vm.send_monitor_cmd("loadvm 1")
-        if s:
-            logging.error("loadvm failed: %r" % o)
-        s, o = vm.send_monitor_cmd("cont")
-        if s:
-            logging.error("cont failed: %r" % o)
+        try:
+            vm.monitor.cmd("stop")
+        except kvm_monitor.MonitorError, e:
+            logging.error(e)
+        try:
+            # This should be replaced by a proper monitor method call
+            vm.monitor.cmd("savevm 1")
+        except kvm_monitor.MonitorError, e:
+            logging.error(e)
+        try:
+            vm.monitor.cmd("system_reset")
+        except kvm_monitor.MonitorError, e:
+            logging.error(e)
+        try:
+            # This should be replaced by a proper monitor method call
+            vm.monitor.cmd("loadvm 1")
+        except kvm_monitor.MonitorError, e:
+            logging.error(e)
+        try:
+            vm.monitor.cmd("cont")
+        except kvm_monitor.MonitorError, e:
+            logging.error(e)
 
-         # Log in
+        # Log in
         if (time.time() > login_expire):
             login_expire = time.time() + savevm_login_delay
             logging.info("Logging in after loadvm...")
diff --git a/client/tests/kvm/tests/build.py b/client/tests/kvm/tests/build.py
index aaf8d3c..6814cfe 100644
--- a/client/tests/kvm/tests/build.py
+++ b/client/tests/kvm/tests/build.py
@@ -650,4 +650,3 @@ def run_build(test, params, env):
                               ' install mode: %s' % install_mode)
 
     installer.install()
-
diff --git a/client/tests/kvm/tests/guest_s4.py 
b/client/tests/kvm/tests/guest_s4.py
index 608d542..2eb035b 100644
--- a/client/tests/kvm/tests/guest_s4.py
+++ b/client/tests/kvm/tests/guest_s4.py
@@ -32,7 +32,7 @@ def run_guest_s4(test, params, env):
     time.sleep(5)
 
     # Get the second session to start S4
-    session = kvm_test_utils.wait_for_login(vm, timeout=timeout)
+    session2 = kvm_test_utils.wait_for_login(vm, timeout=timeout)
 
     # Make sure the background program is running as expected
     check_s4_cmd = params.get("check_s4_cmd")
diff --git a/client/tests/kvm/tests/ksm_overcommit.py 
b/client/tests/kvm/tests/ksm_overcommit.py
index f5bb212..2b49a65 100644
--- a/client/tests/kvm/tests/ksm_overcommit.py
+++ b/client/tests/kvm/tests/ksm_overcommit.py
@@ -189,11 +189,11 @@ def run_ksm_overcommit(test, params, env):
                     # We need to keep some memory for python to run.
                     if (free_mem < 64000) or (ksm_swap and
                                               free_mem < (450000 * 
perf_ratio)):
-                        vm.send_monitor_cmd('stop')
+                        vm.monitor.cmd("stop")
                         for j in range(0, i):
                             lvms[j].destroy(gracefully = False)
                         time.sleep(20)
-                        vm.send_monitor_cmd('c')
+                        vm.monitor.cmd("c")
                         logging.debug("Only %s free memory, killing %d guests" 
%
                                       (free_mem, (i-1)))
                         last_vm = i
@@ -204,12 +204,12 @@ def run_ksm_overcommit(test, params, env):
                 logging.debug("Only %s host free memory, killing %d guests" %
                               (free_mem, (i - 1)))
                 logging.debug("Stopping %s", vm.name)
-                vm.send_monitor_cmd('stop')
+                vm.monitor.cmd("stop")
                 for j in range(0, i):
                     logging.debug("Destroying %s", lvms[j].name)
                     lvms[j].destroy(gracefully = False)
                 time.sleep(20)
-                vm.send_monitor_cmd('c')
+                vm.monitor.cmd("c")
                 last_vm = i
 
             if last_vm != 0:
diff --git a/client/tests/kvm/tests/migration.py 
b/client/tests/kvm/tests/migration.py
index f64afe1..d6f4b11 100644
--- a/client/tests/kvm/tests/migration.py
+++ b/client/tests/kvm/tests/migration.py
@@ -38,7 +38,7 @@ def run_migration(test, params, env):
 
     # Start another session with the guest and make sure the background
     # process is running
-    session = kvm_test_utils.wait_for_login(vm, timeout=timeout)
+    session2 = kvm_test_utils.wait_for_login(vm, timeout=timeout)
 
     try:
         check_command = params.get("migration_bg_check_command", "")
diff --git a/client/tests/kvm/tests/pci_hotplug.py 
b/client/tests/kvm/tests/pci_hotplug.py
index 3063359..2c459d7 100644
--- a/client/tests/kvm/tests/pci_hotplug.py
+++ b/client/tests/kvm/tests/pci_hotplug.py
@@ -28,7 +28,7 @@ def run_pci_hotplug(test, params, env):
             raise error.TestError("Modprobe module '%s' failed" % module)
 
     # Get output of command 'info pci' as reference
-    s, info_pci_ref = vm.send_monitor_cmd("info pci")
+    info_pci_ref = vm.monitor.info("pci")
 
     # Get output of command as reference
     reference = session.get_command_output(params.get("reference_cmd"))
@@ -44,21 +44,22 @@ def run_pci_hotplug(test, params, env):
         pci_add_cmd = ("pci_add pci_addr=auto storage file=%s,if=%s" %
                        (image_filename, tested_model))
 
-    # Implement pci_add
-    s, add_output = vm.send_monitor_cmd(pci_add_cmd)
+    # Execute pci_add (should be replaced by a proper monitor method call)
+    add_output = vm.monitor.cmd(pci_add_cmd)
     if not "OK domain" in add_output:
         raise error.TestFail("Add device failed. Hypervisor command is: %s. "
                              "Output: %r" % (pci_add_cmd, add_output))
-    s, after_add = vm.send_monitor_cmd("info pci")
+    after_add = vm.monitor.info("pci")
 
     # Define a helper function to delete the device
     def pci_del(ignore_failure=False):
         slot_id = "0" + add_output.split(",")[2].split()[1]
         cmd = "pci_del pci_addr=%s" % slot_id
-        vm.send_monitor_cmd(cmd)
+        # This should be replaced by a proper monitor method call
+        vm.monitor.cmd(cmd)
 
         def device_removed():
-            s, after_del = vm.send_monitor_cmd("info pci")
+            after_del = vm.monitor.info("pci")
             return after_del != after_add
 
         if (not kvm_utils.wait_for(device_removed, 10, 0, 1)
diff --git a/client/tests/kvm/tests/physical_resources_check.py 
b/client/tests/kvm/tests/physical_resources_check.py
index 258713c..b5e156a 100644
--- a/client/tests/kvm/tests/physical_resources_check.py
+++ b/client/tests/kvm/tests/physical_resources_check.py
@@ -1,6 +1,6 @@
 import re, string, logging
 from autotest_lib.client.common_lib import error
-import kvm_test_utils, kvm_utils
+import kvm_test_utils, kvm_utils, kvm_monitor
 
 
 def run_physical_resources_check(test, params, env):
@@ -49,13 +49,15 @@ def run_physical_resources_check(test, params, env):
         logging.error("    Reported by OS: %s" % actual_mem)
 
     # Define a function for checking number of hard drivers & NICs
-    def check_num(devices, cmd, check_str):
+    def check_num(devices, info_cmd, check_str):
         f_fail = 0
         expected_num = kvm_utils.get_sub_dict_names(params, devices).__len__()
-        s, o = vm.send_monitor_cmd(cmd)
-        if s != 0:
+        try:
+            o = vm.monitor.info(info_cmd)
+        except kvm_monitor.MonitorError, e:
             f_fail += 1
-            logging.error("qemu monitor command failed: %s" % cmd)
+            logging.error(e)
+            logging.error("info/query monitor command failed (%s)", info_cmd)
 
         actual_num = string.count(o, check_str)
         if expected_num != actual_num:
@@ -66,25 +68,28 @@ def run_physical_resources_check(test, params, env):
         return expected_num, f_fail
 
     logging.info("Hard drive count check")
-    drives_num, f_fail = check_num("images", "info block", "type=hd")
+    drives_num, f_fail = check_num("images", "block", "type=hd")
     n_fail += f_fail
 
     logging.info("NIC count check")
-    nics_num, f_fail = check_num("nics", "info network", "model=")
+    nics_num, f_fail = check_num("nics", "network", "model=")
     n_fail += f_fail
 
     # Define a function for checking hard drives & NICs' model
-    def chk_fmt_model(device, fmt_model, cmd, str):
+    def chk_fmt_model(device, fmt_model, info_cmd, str):
         f_fail = 0
         devices = kvm_utils.get_sub_dict_names(params, device)
         for chk_device in devices:
             expected = kvm_utils.get_sub_dict(params, 
chk_device).get(fmt_model)
             if not expected:
                 expected = "rtl8139"
-            s, o = vm.send_monitor_cmd(cmd)
-            if s != 0:
+            try:
+                o = vm.monitor.info(info_cmd)
+            except kvm_monitor.MonitorError, e:
                 f_fail += 1
-                logging.error("qemu monitor command failed: %s" % cmd)
+                logging.error(e)
+                logging.error("info/query monitor command failed (%s)",
+                              info_cmd)
 
             device_found = re.findall(str, o)
             logging.debug("Found devices: %s" % device_found)
@@ -101,19 +106,20 @@ def run_physical_resources_check(test, params, env):
         return f_fail
 
     logging.info("NICs model check")
-    f_fail = chk_fmt_model("nics", "nic_model", "info network", "model=(.*),")
+    f_fail = chk_fmt_model("nics", "nic_model", "network", "model=(.*),")
     n_fail += f_fail
 
     logging.info("Drive format check")
-    f_fail = chk_fmt_model("images", "drive_format", "info block",
-                           "(.*)\: type=hd")
+    f_fail = chk_fmt_model("images", "drive_format", "block", "(.*)\: type=hd")
     n_fail += f_fail
 
     logging.info("Network card MAC check")
-    s, o = vm.send_monitor_cmd("info network")
-    if s != 0:
+    try:
+        o = vm.monitor.info("network")
+    except kvm_monitor.MonitorError, e:
         n_fail += 1
-        logging.error("qemu monitor command failed: info network")
+        logging.error(e)
+        logging.error("info/query monitor command failed (network)")
     found_mac_addresses = re.findall("macaddr=(.*)", o)
     logging.debug("Found MAC adresses: %s" % found_mac_addresses)
 
diff --git a/client/tests/kvm/tests/shutdown.py 
b/client/tests/kvm/tests/shutdown.py
index 795d9cf..bfc5477 100644
--- a/client/tests/kvm/tests/shutdown.py
+++ b/client/tests/kvm/tests/shutdown.py
@@ -29,7 +29,7 @@ def run_shutdown(test, params, env):
             # Sleep for a while -- give the guest a chance to finish booting
             time.sleep(float(params.get("sleep_before_powerdown", 10)))
             # Send a system_powerdown monitor command
-            vm.send_monitor_cmd("system_powerdown")
+            vm.monitor.cmd("system_powerdown")
             logging.info("system_powerdown monitor command sent; waiting for "
                          "guest to go down...")
 
diff --git a/client/tests/kvm/tests/stepmaker.py 
b/client/tests/kvm/tests/stepmaker.py
index 24060db..ee0ed92 100755
--- a/client/tests/kvm/tests/stepmaker.py
+++ b/client/tests/kvm/tests/stepmaker.py
@@ -10,7 +10,7 @@ Step file creator/editor.
 import pygtk, gtk, gobject, time, os, commands
 import common
 from autotest_lib.client.common_lib import error
-import kvm_utils, logging, ppm_utils, stepeditor
+import kvm_utils, logging, ppm_utils, stepeditor, kvm_monitor
 pygtk.require('2.0')
 
 
@@ -84,7 +84,7 @@ class StepMaker(stepeditor.StepMakerWindow):
 
 
     def destroy(self, widget):
-        self.vm.send_monitor_cmd("cont")
+        self.vm.monitor.cmd("cont")
         self.steps_file.close()
         self.vars_file.close()
         stepeditor.StepMakerWindow.destroy(self, widget)
@@ -112,7 +112,7 @@ class StepMaker(stepeditor.StepMakerWindow):
         # Start the screendump timer
         self.redirect_timer(100, self.update)
         # Resume the VM
-        self.vm.send_monitor_cmd("cont")
+        self.vm.monitor.cmd("cont")
 
 
     def switch_to_step_mode(self):
@@ -127,7 +127,7 @@ class StepMaker(stepeditor.StepMakerWindow):
         # Start the screendump timer
         self.redirect_timer()
         # Stop the VM
-        self.vm.send_monitor_cmd("stop")
+        self.vm.monitor.cmd("stop")
 
 
     # Events in step mode
@@ -137,10 +137,10 @@ class StepMaker(stepeditor.StepMakerWindow):
         if os.path.exists(self.screendump_filename):
             os.unlink(self.screendump_filename)
 
-        (status, output) = self.vm.send_monitor_cmd("screendump " +
-                                                    self.screendump_filename)
-        if status: # Failure
-            logging.info("Could not fetch screendump")
+        try:
+            self.vm.monitor.screendump(self.screendump_filename)
+        except kvm_monitor.MonitorError, e:
+            logging.warn(e)
         else:
             self.set_image_from_file(self.screendump_filename)
 
@@ -228,15 +228,14 @@ class StepMaker(stepeditor.StepMakerWindow):
                     continue
                 self.vm.send_string(val)
             elif words[0] == "mousemove":
-                self.vm.send_monitor_cmd("mouse_move %d %d" % (-8000,-8000))
+                self.vm.monitor.mouse_move(-8000, -8000)
                 time.sleep(0.5)
-                self.vm.send_monitor_cmd("mouse_move %s %s" % (words[1],
-                                                               words[2]))
+                self.vm.monitor.mouse_move(words[1], words[2])
                 time.sleep(0.5)
             elif words[0] == "mouseclick":
-                self.vm.send_monitor_cmd("mouse_button %s" % words[1])
+                self.vm.monitor.mouse_button(words[1])
                 time.sleep(0.1)
-                self.vm.send_monitor_cmd("mouse_button 0")
+                self.vm.monitor.mouse_button(0)
 
         # Remember the current time
         self.time_when_actions_completed = time.time()
@@ -267,7 +266,7 @@ class StepMaker(stepeditor.StepMakerWindow):
                 self.event_capture_button_release,
                 self.event_capture_scroll)
         self.redirect_timer(10, self.update_capture)
-        self.vm.send_monitor_cmd("cont")
+        self.vm.monitor.cmd("cont")
 
     # Events in mouse capture mode
 
@@ -280,11 +279,10 @@ class StepMaker(stepeditor.StepMakerWindow):
 
         delay = self.spin_latency.get_value() / 1000
         if (x, y) != (self.prev_x, self.prev_y):
-            self.vm.send_monitor_cmd("mouse_move %d %d" % (-8000, -8000))
+            self.vm.monitor.mouse_move(-8000, -8000)
             time.sleep(delay)
-            self.vm.send_monitor_cmd("mouse_move %d %d" %
-                                     (self.mouse_click_coords[0],
-                                      self.mouse_click_coords[1]))
+            self.vm.monitor.mouse_move(self.mouse_click_coords[0],
+                                       self.mouse_click_coords[1])
             time.sleep(delay)
 
         self.prev_x = x
@@ -293,10 +291,10 @@ class StepMaker(stepeditor.StepMakerWindow):
         if os.path.exists(self.screendump_filename):
             os.unlink(self.screendump_filename)
 
-        (status, output) = self.vm.send_monitor_cmd("screendump " +
-                                                    self.screendump_filename)
-        if status: # Failure
-            logging.info("Could not fetch screendump")
+        try:
+            self.vm.monitor.screendump(self.screendump_filename)
+        except kvm_monitor.MonitorError, e:
+            logging.warn(e)
         else:
             self.set_image_from_file(self.screendump_filename)
 
@@ -317,7 +315,7 @@ class StepMaker(stepeditor.StepMakerWindow):
                 None,
                 self.event_expose)
         self.redirect_timer()
-        self.vm.send_monitor_cmd("stop")
+        self.vm.monitor.cmd("stop")
         self.mouse_click_captured = True
         self.mouse_click_button = event.button
         self.set_image(self.image_width_backup, self.image_height_backup,
diff --git a/client/tests/kvm/tests/steps.py b/client/tests/kvm/tests/steps.py
index 8ebe7c1..6f782f5 100644
--- a/client/tests/kvm/tests/steps.py
+++ b/client/tests/kvm/tests/steps.py
@@ -6,7 +6,7 @@ Utilities to perform automatic guest installation using step 
files.
 
 import os, time, re, shutil, logging
 from autotest_lib.client.common_lib import utils, error
-import kvm_utils, ppm_utils, kvm_subprocess
+import kvm_utils, ppm_utils, kvm_subprocess, kvm_monitor
 try:
     import PIL.Image
 except ImportError:
@@ -85,10 +85,10 @@ def barrier_2(vm, words, params, debug_dir, 
data_scrdump_filename,
             break
 
         # Request screendump
-        (status, output) = vm.send_monitor_cmd("screendump %s" %
-                                               scrdump_filename)
-        if status:
-            logging.error("Could not fetch screendump")
+        try:
+            vm.monitor.screendump(scrdump_filename)
+        except kvm_monitor.MonitorError, e:
+            logging.warn(e)
             continue
 
         # Read image file
@@ -199,7 +199,7 @@ def run_steps(test, params, env):
     lines = sf.readlines()
     sf.close()
 
-    vm.send_monitor_cmd("cont")
+    vm.monitor.cmd("cont")
 
     current_step_num = 0
     current_screendump = None
diff --git a/client/tests/kvm/tests/timedrift_with_stop.py 
b/client/tests/kvm/tests/timedrift_with_stop.py
index b99dd40..fe98571 100644
--- a/client/tests/kvm/tests/timedrift_with_stop.py
+++ b/client/tests/kvm/tests/timedrift_with_stop.py
@@ -49,11 +49,11 @@ def run_timedrift_with_stop(test, params, env):
             # Run current iteration
             logging.info("Stop %s second: iteration %d of %d..." %
                          (stop_time, i + 1, stop_iterations))
-            
-            kvm_test_utils.stop(vm)
+
+            vm.monitor.cmd("stop")
             time.sleep(stop_time)
-            kvm_test_utils.cont(vm)
-            
+            vm.monitor.cmd("cont")
+
             # Get time after current iteration
             (ht1_, gt1_) = kvm_test_utils.get_time(session, time_command,
                                                    time_filter_re, time_format)
diff --git a/client/tests/kvm/tests/vlan_tag.py 
b/client/tests/kvm/tests/vlan_tag.py
index 32de6a9..cafd8fe 100644
--- a/client/tests/kvm/tests/vlan_tag.py
+++ b/client/tests/kvm/tests/vlan_tag.py
@@ -24,7 +24,7 @@ def run_vlan_tag(test, params, env):
     vm2 = kvm_test_utils.get_living_vm(env, "vm2")
 
     timeout = int(params.get("login_timeout", 360))
-    session = kvm_test_utils.wait_for_login(vm1, timeout=timeout)
+    session1 = kvm_test_utils.wait_for_login(vm1, timeout=timeout)
     session2 = kvm_test_utils.wait_for_login(vm2, timeout=timeout)
 
     try:
diff --git a/client/tests/kvm/tests_base.cfg.sample 
b/client/tests/kvm/tests_base.cfg.sample
index 18741d9..fc4fb0b 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -4,9 +4,11 @@
 vms = vm1
 images = image1
 nics = nic1
+monitors = humanmonitor1
 login_timeout = 360
-# Choose the main VM
+# Choose the main VM and monitor
 main_vm = vm1
+main_monitor = humanmonitor1
 
 # Some preprocessor/postprocessor params
 start_vm = yes
@@ -34,6 +36,9 @@ image_size = 10G
 shell_port = 22
 display = vnc
 
+# Monitor params
+monitor_type = human
+
 # Default scheduler params
 used_cpus = 1
 used_mem = 512
-- 
1.7.0.1

_______________________________________________
Autotest mailing list
[email protected]
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to