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:
parent
3e067a3ef5
commit
0dfcaa63c9
28
qubes/app.py
28
qubes/app.py
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user