mgmt: rework mgmt.Events to use per-instance handlers

QubesOS/qubes-issues#2622
This commit is contained in:
Marek Marczykowski-Górecki 2017-05-12 14:08:54 +02:00
parent da7496794a
commit 3bc8facc0b
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -179,6 +179,34 @@ class AbstractQubesMgmt(object):
self.fire_event_for_permission(**kwargs))
class QubesMgmtEventsDispatcher(object):
def __init__(self, filters, send_event):
self.filters = filters
self.send_event = send_event
def vm_handler(self, subject, event, **kwargs):
if event.startswith('mgmt-permission:'):
return
if not list(apply_filters([(subject, event, kwargs)],
self.filters)):
return
self.send_event(subject, event, **kwargs)
def app_handler(self, subject, event, **kwargs):
if not list(apply_filters([(subject, event, kwargs)],
self.filters)):
return
self.send_event(subject, event, **kwargs)
def on_domain_add(self, subject, event, vm):
# pylint: disable=unused-argument
vm.add_handler('*', self.vm_handler)
def on_domain_delete(self, subject, event, vm):
# pylint: disable=unused-argument
vm.remove_handler('*', self.vm_handler)
class QubesMgmt(AbstractQubesMgmt):
'''Implementation of Qubes Management API calls
@ -590,19 +618,15 @@ class QubesMgmt(AbstractQubesMgmt):
# cache event filters, to not call an event each time an event arrives
event_filters = self.fire_event_for_permission()
def handler(subject, event, **kwargs):
if self.dest.name != 'dom0' and subject != self.dest:
return
if event.startswith('mgmt-permission:'):
return
if not list(apply_filters([(subject, event, kwargs)],
event_filters)):
return
self.send_event(subject, event, **kwargs)
dispatcher = QubesMgmtEventsDispatcher(event_filters, self.send_event)
if self.dest.name == 'dom0':
type(self.app).add_handler('*', handler)
qubes.vm.BaseVM.add_handler('*', handler)
self.app.add_handler('*', dispatcher.app_handler)
self.app.add_handler('domain-add', dispatcher.on_domain_add)
self.app.add_handler('domain-delete', dispatcher.on_domain_delete)
for vm in self.app.domains:
vm.add_handler('*', dispatcher.vm_handler)
else:
self.dest.add_handler('*', dispatcher.vm_handler)
# send artificial event as a confirmation that connection is established
self.send_event(self.app, 'connection-established')
@ -614,8 +638,14 @@ class QubesMgmt(AbstractQubesMgmt):
pass
if self.dest.name == 'dom0':
type(self.app).remove_handler('*', handler)
qubes.vm.BaseVM.remove_handler('*', handler)
self.app.remove_handler('*', dispatcher.app_handler)
self.app.remove_handler('domain-add', dispatcher.on_domain_add)
self.app.remove_handler('domain-delete',
dispatcher.on_domain_delete)
for vm in self.app.domains:
vm.remove_handler('*', dispatcher.vm_handler)
else:
self.dest.remove_handler('*', dispatcher.vm_handler)
@api('mgmt.vm.feature.List', no_payload=True)
@asyncio.coroutine