- 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 v1: - Turn VM.monitor into a property Signed-off-by: Michael Goldish <mgoldish@xxxxxxxxxx> --- client/tests/kvm/kvm_preprocessing.py | 33 ++-- client/tests/kvm/kvm_test_utils.py | 35 +-- client/tests/kvm/kvm_vm.py | 236 +++++++++----------- client/tests/kvm/tests/balloon_check.py | 12 +- client/tests/kvm/tests/boot_savevm.py | 41 ++-- client/tests/kvm/tests/ksm_overcommit.py | 8 +- 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_base.cfg.sample | 7 +- 12 files changed, 241 insertions(+), 242 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 24e2bf5..c3b6b8a 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) @@ -119,21 +119,16 @@ def migrate(vm, env=None): """ # 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 + 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 - - # 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") + o = vm.monitor.info("migrate") + return "status: failed" in o # Clone the source VM and ask the clone to wait for incoming migration dest_vm = vm.clone() @@ -141,21 +136,15 @@ def migrate(vm, env=None): raise error.TestError("Could not create dest VM") try: - # Define the migration command - cmd = "migrate -d tcp:localhost:%d" % dest_vm.migration_port - logging.debug("Migrating with command: %s" % cmd) - # Migrate - s, o = vm.send_monitor_cmd(cmd) - if s: - logging.error("Migration command failed (command: %r, output: %r)" - % (cmd, o)) - raise error.TestFail("Migration command failed") + uri = "tcp:localhost:%d" % dest_vm.migration_port + logging.debug("Migrating to: %s" % uri) + o = vm.monitor.migrate(uri) # Wait for migration to finish if not kvm_utils.wait_for(mig_finished, 90, 2, 2, "Waiting for migration to finish..."): - raise error.TestFail("Timeout elapsed while waiting for migration " + raise error.TestFail("Timeout expired while waiting for migration " "to finish") # Report migration status diff --git a/client/tests/kvm/kvm_vm.py b/client/tests/kvm/kvm_vm.py index e40abb4..db5f8e0 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,25 +109,19 @@ 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 - # Find available monitor filename + # Find a unique identifier for this VM while True: - # A unique identifier for this VM self.instance = (time.strftime("%Y%m%d-%H%M%S-") + kvm_utils.generate_random_string(4)) - # Monitor - self.monitor_file_name = "/tmp/monitor-" + self.instance - # Test log for unit tests - self.testlog_file_name = "/tmp/testlog-" + self.instance - # Verify uniqueness - if True not in map(os.path.exists, [self.monitor_file_name, - self.testlog_file_name]): + if not glob.glob("/tmp/*%s" % self.instance): break @@ -203,9 +197,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 @@ -307,8 +304,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) @@ -410,7 +413,7 @@ class VM: qemu_cmd += add_uuid(help, params.get("uuid")) if params.get("testdev") == "yes": - qemu_cmd += add_testdev(help, self.testlog_file_name) + qemu_cmd += add_testdev(help, self.get_testlog_filename()) # If the PCI assignment step went OK, add each one of the PCI assigned # devices to the qemu command line. @@ -567,6 +570,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) @@ -576,11 +580,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. @@ -602,89 +631,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) - return (0, data) - - # Clean up before exiting - finally: - s.shutdown(socket.SHUT_RDWR) - s.close() - - def destroy(self, gracefully=True): """ Destroy the VM. @@ -721,15 +667,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 " @@ -743,29 +692,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() - for f in [self.monitor_file_name, self.testlog_file_name]: + 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 main 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): @@ -791,6 +754,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. @@ -988,12 +974,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 2d483c6..bbab95f 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: + 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/ksm_overcommit.py b/client/tests/kvm/tests/ksm_overcommit.py index 2b791f1..ddf1670 100644 --- a/client/tests/kvm/tests/ksm_overcommit.py +++ b/client/tests/kvm/tests/ksm_overcommit.py @@ -173,11 +173,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 @@ -188,12 +188,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/pci_hotplug.py b/client/tests/kvm/tests/pci_hotplug.py index d8f34f8..f50a67e 100644 --- a/client/tests/kvm/tests/pci_hotplug.py +++ b/client/tests/kvm/tests/pci_hotplug.py @@ -27,7 +27,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")) @@ -43,21 +43,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 af9613e..946760f 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): @@ -48,13 +48,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: @@ -65,25 +67,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) @@ -100,19 +105,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 8a252d9..3cbdd79 100644 --- a/client/tests/kvm/tests/shutdown.py +++ b/client/tests/kvm/tests/shutdown.py @@ -28,7 +28,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_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample index b302557..cabeb4a 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 -# 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.5.4.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html