commit 93ff325ffb5ccd11661301f3b724f291c23cebec
Author: W. David Ashley <w.david.ashley(a)gmail.com>
Date: Fri Aug 14 13:26:59 2015 -0500
Events chapter
- started work on the events chapter
- added example 1
en-US/Event_Handling.xml | 28 +++++++++++-
en-US/extras/Events-Example-1.py | 89 ++++++++++++++++++++++++++++++++++++++
2 files changed, 115 insertions(+), 2 deletions(-)
---
diff --git a/en-US/Event_Handling.xml b/en-US/Event_Handling.xml
index 52a2085..96326ea 100644
--- a/en-US/Event_Handling.xml
+++ b/en-US/Event_Handling.xml
@@ -3,9 +3,33 @@
<!ENTITY % BOOK_ENTITIES SYSTEM
"Libvirt_Application_Development_Guide_Using_Python.ent">
%BOOK_ENTITIES;
]>
-<chapter
id="libvirt_application_development_guide_using_python-Event_Handling">
+<chapter
id="libvirt_application_development_guide_using_python-Events_and_Timers">
<title>Event Handling</title>
<para>
- TBD
+ The Python libvirt module provides a complete interface for handling both events
and timers.
+ Both event and timer handling are invoked through a function interface as opposed
to a
+ class/method interface. This makes it easier to integrate the interface into
either a graphical
+ or console program.
</para>
+ <section
id="libvirt_application_development_guide_using_python-Event_Handling">
+ <title>Event Handling</title>
+ <para>
+ The Python libvirt module supplies a framework for event handling. While this
is most useful
+ for graphical programs, it can also be used for console programs to provide a
consistent user
+ interface and control the processing of console events.
+ </para>
+ <para>
+ Event handling is done through the functions
<literal>virEventAddHandle</literal>,
+ <literal>virEventRegisterDefaultImpl</literal>,
<literal>virEventRegisterImpl</literal>,
+ <literal>virEventRemoveHandle</literal>,
<literal>virEventRunDefaultImpl</literal>,
+ and <literal>virEventUpdateHandle</literal>.
+ </para>
+ <para>
+ An example program that uses most of these functions follows:
+ </para>
+ <example id="Events-example_1">
+ <title>Provide a persistent console that survives guest
reboots</title>
+ <programlisting language="Python"><xi:include
href="extras/Events-Example-1.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
</chapter>
diff --git a/en-US/extras/Events-Example-1.py b/en-US/extras/Events-Example-1.py
new file mode 100644
index 0000000..a1fedc0
--- /dev/null
+++ b/en-US/extras/Events-Example-1.py
@@ -0,0 +1,89 @@
+# Example-1.py
+# consolecallback - provide a persistent console that survives guest reboots
+from __future__ import print_function
+
+import sys, os, logging, libvirt, tty, termios, atexit
+
+def reset_term():
+ termios.tcsetattr(0, termios.TCSADRAIN, attrs)
+
+def error_handler(unused, error):
+ # The console stream errors on VM shutdown; we don't care
+ if (error[0] == libvirt.VIR_ERR_RPC and
+ error[1] == libvirt.VIR_FROM_STREAMS):
+ return
+ logging.warn(error)
+
+class Console(object):
+ def __init__(self, uri, uuid):
+ self.uri = uri
+ self.uuid = uuid
+ self.connection = libvirt.open(uri)
+ self.domain = self.connection.lookupByUUIDString(uuid)
+ self.state = self.domain.state(0)
+ self.connection.domainEventRegister(lifecycle_callback, self)
+ self.stream = None
+ self.run_console = True
+ logging.info("%s initial state %d, reason %d",
+ self.uuid, self.state[0], self.state[1])
+
+def check_console(console):
+ if (console.state[0] == libvirt.VIR_DOMAIN_RUNNING or
+ console.state[0] == libvirt.VIR_DOMAIN_PAUSED):
+ if console.stream is None:
+ console.stream = console.connection.newStream(libvirt.VIR_STREAM_NONBLOCK)
+ console.domain.openConsole(None, console.stream, 0)
+ console.stream.eventAddCallback(libvirt.VIR_STREAM_EVENT_READABLE,
stream_callback, console)
+ else:
+ if console.stream:
+ console.stream.eventRemoveCallback()
+ console.stream = None
+
+ return console.run_console
+
+def stdin_callback(watch, fd, events, console):
+ readbuf = os.read(fd, 1024)
+ if readbuf.startswith(""):
+ console.run_console = False
+ return
+ if console.stream:
+ console.stream.send(readbuf)
+
+def stream_callback(stream, events, console):
+ try:
+ received_data = console.stream.recv(1024)
+ except:
+ return
+ os.write(0, received_data)
+
+def lifecycle_callback (connection, domain, event, detail, console):
+ console.state = console.domain.state(0)
+ logging.info("%s transitioned to state %d, reason %d",
+ console.uuid, console.state[0], console.state[1])
+
+# main
+if len(sys.argv) != 3:
+ print("Usage:", sys.argv[0], "URI UUID")
+ print("for example:", sys.argv[0], "'qemu:///system'
'32ad945f-7e78-c33a-e96d-39f25e025d81'")
+ sys.exit(1)
+
+uri = sys.argv[1]
+uuid = sys.argv[2]
+
+print("Escape character is ^]")
+logging.basicConfig(filename='msg.log', level=logging.DEBUG)
+logging.info("URI: %s", uri)
+logging.info("UUID: %s", uuid)
+
+libvirt.virEventRegisterDefaultImpl()
+libvirt.registerErrorHandler(error_handler, None)
+
+atexit.register(reset_term)
+attrs = termios.tcgetattr(0)
+tty.setraw(0)
+
+console = Console(uri, uuid)
+console.stdin_watch = libvirt.virEventAddHandle(0, libvirt.VIR_EVENT_HANDLE_READABLE,
stdin_callback, console)
+
+while check_console(console):
+ libvirt.virEventRunDefaultImpl()