diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am index d782a28bfd..b04d1261c5 100644 --- a/examples/python/Makefile.am +++ b/examples/python/Makefile.am @@ -1,6 +1,7 @@ -## Copyright (C) 2005-2011 Red Hat, Inc. +## Copyright (C) 2005-2012 Red Hat, Inc. ## See COPYING.LIB for the License of this software EXTRA_DIST= \ README \ + consolecallback.py \ dominfo.py domrestore.py domsave.py domstart.py esxlist.py diff --git a/examples/python/consolecallback.py b/examples/python/consolecallback.py new file mode 100644 index 0000000000..23316ce8f6 --- /dev/null +++ b/examples/python/consolecallback.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# consolecallback - provide a persistent console that survives guest reboots + +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 == 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()