diff mbox

[KVM-AUTOTEST,v3] KVM test: take frequent screendumps during all tests

Message ID 1269359532-7139-1-git-send-email-mgoldish@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Goldish March 23, 2010, 3:52 p.m. UTC
None
diff mbox

Patch

diff --git a/client/tests/kvm/kvm_preprocessing.py b/client/tests/kvm/kvm_preprocessing.py
index a92282a..b3fef9d 100644
--- a/client/tests/kvm/kvm_preprocessing.py
+++ b/client/tests/kvm/kvm_preprocessing.py
@@ -1,4 +1,4 @@ 
-import sys, os, time, commands, re, logging, signal, glob
+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
@@ -11,6 +11,10 @@  except ImportError:
                     'distro.')
 
 
+_screendump_thread = None
+_screendump_thread_termination_event = None
+
+
 def preprocess_image(test, params):
     """
     Preprocess a single QEMU image according to the instructions in params.
@@ -254,6 +258,15 @@  def preprocess(test, params, env):
     # Preprocess all VMs and images
     process(test, params, env, preprocess_image, preprocess_vm)
 
+    # Start the screendump thread
+    if params.get("take_regular_screendumps") == "yes":
+        logging.debug("Starting screendump thread")
+        global _screendump_thread, _screendump_thread_termination_event
+        _screendump_thread_termination_event = threading.Event()
+        _screendump_thread = threading.Thread(target=_take_screendumps,
+                                              args=(test, params, env))
+        _screendump_thread.start()
+
 
 def postprocess(test, params, env):
     """
@@ -263,8 +276,16 @@  def postprocess(test, params, env):
     @param params: Dict containing all VM and image parameters.
     @param env: The environment (a dict-like object).
     """
+    # Postprocess all VMs and images
     process(test, params, env, postprocess_image, postprocess_vm)
 
+    # Terminate the screendump thread
+    global _screendump_thread, _screendump_thread_termination_event
+    if _screendump_thread:
+        logging.debug("Terminating screendump thread...")
+        _screendump_thread_termination_event.set()
+        _screendump_thread.join(10)
+
     # Warn about corrupt PPM files
     for f in glob.glob(os.path.join(test.debugdir, "*.ppm")):
         if not ppm_utils.image_verify_ppm_file(f):
@@ -290,11 +311,13 @@  def postprocess(test, params, env):
         for f in glob.glob(os.path.join(test.debugdir, '*.ppm')):
             os.unlink(f)
 
-    # Execute any post_commands
-    if params.get("post_command"):
-        process_command(test, params, env, params.get("post_command"),
-                        int(params.get("post_command_timeout", "600")),
-                        params.get("post_command_noncritical") == "yes")
+    # Should we keep the screendump dirs?
+    if params.get("keep_screendumps") != "yes":
+        logging.debug("'keep_screendumps' not specified; removing screendump "
+                      "dirs...")
+        for d in glob.glob(os.path.join(test.debugdir, "screendumps_*")):
+            if os.path.isdir(d) and not os.path.islink(d):
+                shutil.rmtree(d, ignore_errors=True)
 
     # Kill all unresponsive VMs
     if params.get("kill_unresponsive_vms") == "yes":
@@ -318,6 +341,12 @@  def postprocess(test, params, env):
         env["tcpdump"].close()
         del env["tcpdump"]
 
+    # Execute any post_commands
+    if params.get("post_command"):
+        process_command(test, params, env, params.get("post_command"),
+                        int(params.get("post_command_timeout", "600")),
+                        params.get("post_command_noncritical") == "yes")
+
 
 def postprocess_on_error(test, params, env):
     """
@@ -343,3 +372,60 @@  def _update_address_cache(address_cache, line):
                           mac_address, address_cache.get("last_seen"))
             address_cache[mac_address] = address_cache.get("last_seen")
             del address_cache["last_seen"]
+
+
+def _take_screendumps(test, params, env):
+    global _screendump_thread_termination_event
+    temp_dir = test.debugdir
+    if params.get("screendump_temp_dir"):
+        temp_dir = kvm_utils.get_path(test.bindir,
+                                      params.get("screendump_temp_dir"))
+        try:
+            os.makedirs(temp_dir)
+        except OSError:
+            pass
+    temp_filename = os.path.join(temp_dir, "scrdump-%s.ppm" %
+                                 kvm_utils.generate_random_string(6))
+    delay = float(params.get("screendump_delay", 5))
+    quality = int(params.get("screendump_quality", 30))
+
+    cache = {}
+
+    while True:
+        for vm in kvm_utils.env_get_all_vms(env):
+            if vm.is_dead():
+                continue
+            vm.send_monitor_cmd("screendump %s" % temp_filename)
+            if not os.path.exists(temp_filename):
+                logging.warn("VM '%s' failed to produce a screendump", vm.name)
+                continue
+            if not ppm_utils.image_verify_ppm_file(temp_filename):
+                logging.warn("VM '%s' produced an invalid screendump", vm.name)
+                os.unlink(temp_filename)
+                continue
+            screendump_dir = os.path.join(test.debugdir,
+                                          "screendumps_%s" % vm.name)
+            try:
+                os.makedirs(screendump_dir)
+            except OSError:
+                pass
+            screendump_filename = os.path.join(screendump_dir,
+                    "%s_%s.jpg" % (vm.name,
+                                   time.strftime("%Y-%m-%d_%H-%M-%S")))
+            hash = utils.hash_file(temp_filename)
+            if hash in cache:
+                try:
+                    os.link(cache[hash], screendump_filename)
+                except OSError:
+                    pass
+            else:
+                try:
+                    image = PIL.Image.open(temp_filename)
+                    image.save(screendump_filename, format="JPEG", quality=quality)
+                    cache[hash] = screendump_filename
+                except NameError:
+                    pass
+            os.unlink(temp_filename)
+        if _screendump_thread_termination_event.isSet():
+            break
+        _screendump_thread_termination_event.wait(delay)
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index b13aec4..2a36687 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -10,13 +10,20 @@  main_vm = vm1
 
 # Some preprocessor/postprocessor params
 start_vm = yes
-convert_ppm_files_to_png_on_error = yes
-#keep_ppm_files = yes
-#keep_ppm_files_on_error = yes
 kill_vm = no
 kill_vm_gracefully = yes
 kill_unresponsive_vms = yes
 
+# Screendump specific stuff
+convert_ppm_files_to_png_on_error = yes
+#keep_ppm_files = yes
+#keep_ppm_files_on_error = yes
+take_regular_screendumps = yes
+keep_screendumps_on_error = yes
+screendump_delay = 5
+screendump_quality = 30
+screendump_temp_dir = /dev/shm
+
 # Some default VM params
 qemu_binary = qemu
 qemu_img_binary = qemu-img