summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2011-09-21 18:58:58 +0300
committerAlon Levy <alevy@redhat.com>2011-09-21 18:58:58 +0300
commitf2a2652e4c9499b67e6bc215f1bc626f3b2a2f16 (patch)
tree5c245cd781670d725bfc4f9f27e90030a083c70f
parent835e329a20166167b0c8d8764375b9edc7443130 (diff)
qmp helpers: --print-events, --reset-on-shutdown
-rwxr-xr-xqmp_helpers.py96
-rwxr-xr-xspice215
2 files changed, 110 insertions, 1 deletions
diff --git a/qmp_helpers.py b/qmp_helpers.py
new file mode 100755
index 0000000..f68aabc
--- /dev/null
+++ b/qmp_helpers.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+"""
+Various helpers for spice2, they all get a qmp port and connect to it,
+and do various helpful things.
+"""
+
+import qmp
+import os
+import atexit
+import time
+import copy
+
+def kill_proc(pid):
+ os.kill(pid, 3)
+ time.sleep(0.01)
+ try:
+ os.kill(pid, 3)
+ print "sleeping 1 second before terminating %s" % pid
+ time.sleep(1)
+ os.kill(pid, 15)
+ except OSError, e:
+ # already dead
+ pass
+
+def fork_and_handle(qmp_address, handlers):
+ """ qemu doesn't like multiple clients to it's qmp handler, so just do with
+ one """
+ print "connecting to %s" % repr(qmp_address)
+ pid = os.fork()
+ if pid != 0:
+ # parent
+ atexit.register(kill_proc, pid)
+ return pid
+ q = qmp.QEMUMonitorProtocol(qmp_address)
+ q.connect()
+ while True:
+ for e in q.get_events():
+ for handler in handlers:
+ handler(q, e)
+ q.clear_events()
+ time.sleep(0.1)
+
+def reset_on_shutdown():
+ """
+ {u'seconds': 1316615017, u'microseconds': 145684}: "{u'event': u'SHUTDOWN'}"
+ {u'seconds': 1316615017, u'microseconds': 157869}: "{u'event': u'STOP'}"
+ """
+ class ResetOnShutdownHandler(object):
+ def __init__(self):
+ self.next = self.wait_for_shutdown
+
+ def handler(self, q, event):
+ self.next(q, event)
+
+ def wait_for_shutdown(self, q, event):
+ if event['event'] == 'SHUTDOWN':
+ self.next = self.wait_for_stop
+
+ def wait_for_stop(self, q, event):
+ if event['event'] == 'STOP':
+ print "RESET_ON_SHUTDOWN: resetting and continuing machine"
+ q.cmd('system_reset')
+ q.cmd('cont')
+ return ResetOnShutdownHandler().handler
+
+def print_events():
+ def handler(q, orig_event, d={}):
+ # we will mangle the event, so make a copy of it
+ event = copy.deepcopy(orig_event)
+ timestamp_sec, timestamp_usec = event['timestamp']['seconds'], event['timestamp']['microseconds']
+ if not 'base' in d:
+ d['base'] = (timestamp_sec, timestamp_usec)
+ event_type = event['event']
+ del event['timestamp']
+ del event['event']
+ data = {}
+ if 'data' in event:
+ data = event['data']
+ del event['data']
+ print "%4d.%04d: %s%s" % (timestamp_sec - d['base'][0], timestamp_usec / 1000, event_type,
+ ' %r' % event if len(event) > 0 else '')
+ for k, v in data.items():
+ print " %12s: %r" % (k, v)
+ return handler
+
+def test_print_events(qmp_address):
+ print_events(qmp_address)
+ try:
+ while True:
+ time.sleep(10)
+ except:
+ pass
+
+if __name__ == '__main__':
+ import sys
+ test_print_events(sys.argv[1])
diff --git a/spice2 b/spice2
index 5a0200d..5a01f0e 100755
--- a/spice2
+++ b/spice2
@@ -12,6 +12,8 @@ import time
import shutil
import itertools
+import qmp_helpers
+
try:
import argparse
except:
@@ -753,7 +755,7 @@ def wait_for_port(port):
################################################################################
-
+default_qmp_port = 20000 # TODO - port allocation (=PortPromisedRange(20000, 100))
def parseargs():
""" Parse command line. Some of the parameters are pre populated:
@@ -1162,6 +1164,17 @@ def main():
os.setuid(args.uid)
os.setgid(args.gid)
test_process = start_process(args=cmdline, show_output=True)
+ # some qmp using apps require some forking
+ qmp_handlers = []
+ if args.qmp_port:
+ wait_for_port(args.qmp_port)
+ qmp_address = ('localhost', args.qmp_port)
+ if args.print_events:
+ qmp_handlers.append(qmp_helpers.print_events())
+ if args.reset_on_shutdown:
+ qmp_handlers.append(qmp_helpers.reset_on_shutdown())
+ if len(qmp_handlers) > 0:
+ qmp_helpers.fork_and_handle(qmp_address, qmp_handlers)
if args.xephyr:
display = xephyr_get_display()
else: