Screendumps are taken regularly and converted to JPEG format.
They are stored in .../debug/screendumps_<VMname>/.
Requires python-imaging.

- Enabled by 'take_regular_screendumps = yes' (naming suggestions welcome).
- Delay between screendumps is controlled by 'screendump_delay' (default 5).
- Compression quality is controlled by 'screendump_quality' (default 30).
- It's probably a good idea to dump them to /dev/shm before converting them
  in order to minimize disk use.  This can be enabled by
  'screendump_temp_dir = /dev/shm' (commented out by default because I'm not
  sure /dev/shm is available on all machines.)
- Screendumps are removed unless 'keep_screendumps'['_on_error'] is 'yes'.
  The recommended setting when submitting jobs from autoserv is
  'keep_screendumps_on_error = yes', which means screendumps are kept only if
  the test fails.  Keeping all screendumps may use up all of the server's
  storage space.

This patch sets reasonable defaults in tests_base.cfg.sample.

(It also makes sure post_command is executed last in the postprocessing
procedure -- otherwise post_command failure can prevent other postprocessing
steps (like removing the screendump dirs) from taking place.)

Changes from v1:
Print debug messages when starting or terminating the screendump thread.

Signed-off-by: Michael Goldish <mgold...@redhat.com>
---
 client/tests/kvm/kvm_preprocessing.py  |   87 +++++++++++++++++++++++++++++--
 client/tests/kvm/tests_base.cfg.sample |   13 ++++-
 2 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/client/tests/kvm/kvm_preprocessing.py 
b/client/tests/kvm/kvm_preprocessing.py
index a92282a..774de3f 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,49 @@ 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))
+
+    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")))
+            try:
+                image = PIL.Image.open(temp_filename)
+                image.save(screendump_filename, format="JPEG", quality=quality)
+            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..1fd5b39 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
-- 
1.5.4.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to