Handle libvirt events in qubesd

This is required to get shutdown notification, when it wasn't initiated
by qubesd (for example 'poweroff' command inside of VM).
Libvirt event loop implementation must be registered before making
connection to libvirt, so move it to the beginning of main().
For now, only 'domain-shutdown' event is emited.
This commit is contained in:
Marek Marczykowski-Górecki 2017-04-27 00:40:55 +02:00
parent 3e067a3ef5
commit 0dfcaa63c9
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
3 changed files with 44 additions and 3 deletions

View File

@ -106,6 +106,7 @@ class VirConnectWrapper(object):
is_dead = not self._conn.isAlive()
if is_dead:
self._conn = libvirt.open(self._conn.getURI())
# TODO: re-register event handlers
return is_dead
def _wrap_domain(self, ret):
@ -213,6 +214,33 @@ class VMMConnection(object):
self.init_vmm_connection()
return self._xs
def register_event_handlers(self, app):
'''Register libvirt event handlers, which will translate libvirt
events into qubes.events. This function should be called only in
'qubesd' process and only when mainloop has been already set.
'''
self._libvirt_conn.domainEventRegisterAny(
None, # any domain
libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
self._domain_event_callback,
app
)
@staticmethod
def _domain_event_callback(_conn, domain, event, _detail, opaque):
'''Generic libvirt event handler (virConnectDomainEventCallback),
translate libvirt event into qubes.events.
'''
app = opaque
try:
vm = app.domains[domain.name()]
except KeyError:
# ignore events for unknown domains
return
if event == libvirt.VIR_DOMAIN_EVENT_STOPPED:
vm.fire_event('domain-shutdown')
def __del__(self):
if self._libvirt_conn:
self._libvirt_conn.close()

View File

@ -176,11 +176,17 @@ def sighandler(loop, signame, server, server_internal):
parser = qubes.tools.QubesArgumentParser(description='Qubes OS daemon')
def main(args=None):
args = parser.parse_args(args)
loop = asyncio.get_event_loop()
def main(args=None):
loop = asyncio.get_event_loop()
libvirtaio.virEventRegisterAsyncIOImpl(loop=loop)
try:
args = parser.parse_args(args)
except:
loop.close()
raise
args.app.vmm.register_event_handlers(args.app)
try:
os.unlink(QUBESD_SOCK)

View File

@ -195,6 +195,13 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
*other arguments are as in :py:meth:`start`*
.. event:: domain-shutdown (subject, event)
Fired when domain has been shut down.
:param subject: Event emitter (the qube object)
:param event: Event name (``'domain-shutdown'``)
.. event:: domain-pre-shutdown (subject, event, force)
Fired at the beginning of :py:meth:`shutdown` method.