diff --git a/core/Makefile b/core/Makefile index 9204929f..7b28a09c 100644 --- a/core/Makefile +++ b/core/Makefile @@ -19,8 +19,6 @@ endif cp qubesutils.py[co] $(DESTDIR)$(PYTHON_QUBESPATH) cp guihelpers.py $(DESTDIR)$(PYTHON_QUBESPATH) cp guihelpers.py[co] $(DESTDIR)$(PYTHON_QUBESPATH) - cp notify.py $(DESTDIR)$(PYTHON_QUBESPATH) - cp notify.py[co] $(DESTDIR)$(PYTHON_QUBESPATH) cp backup.py $(DESTDIR)$(PYTHON_QUBESPATH) cp backup.py[co] $(DESTDIR)$(PYTHON_QUBESPATH) ifneq ($(BACKEND_VMM),) diff --git a/core/notify.py b/core/notify.py deleted file mode 100644 index 5ca75f3f..00000000 --- a/core/notify.py +++ /dev/null @@ -1,78 +0,0 @@ -# -*- coding: utf-8 -*- -# -# The Qubes OS Project, http://www.qubes-os.org -# -# Copyright (C) 2014 Marek Marczykowski-Górecki -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# - -import sys - -system_bus = None -session_bus = None - -notify_object = None - -def tray_notify_init(): - import dbus - global notify_object - try: - notify_object = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications") - except dbus.DBusException as ex: - print >>sys.stderr, "WARNING: failed connect to tray notification service: %s" % str(ex) - -def tray_notify(msg, label, timeout = 3000): - if notify_object: - if label: - if not isinstance(label, str): - label = label.icon - notify_object.Notify("Qubes", 0, label, "Qubes", msg, [], [], timeout, - dbus_interface="org.freedesktop.Notifications") - -def tray_notify_error(msg, timeout = 3000): - if notify_object: - notify_object.Notify("Qubes", 0, "dialog-error", "Qubes", msg, [], [], - timeout, dbus_interface="org.freedesktop.Notifications") - -def notify_error_qubes_manager(name, message): - import dbus - global system_bus - if system_bus is None: - system_bus = dbus.SystemBus() - - try: - qubes_manager = system_bus.get_object('org.qubesos.QubesManager', - '/org/qubesos/QubesManager') - qubes_manager.notify_error(name, message, dbus_interface='org.qubesos.QubesManager') - except dbus.DBusException: - # ignore the case when no qubes-manager is running - pass - -def clear_error_qubes_manager(name, message): - import dbus - global system_bus - if system_bus is None: - system_bus = dbus.SystemBus() - - try: - qubes_manager = system_bus.get_object('org.qubesos.QubesManager', - '/org/qubesos/QubesManager') - qubes_manager.clear_error_exact(name, message, dbus_interface='org.qubesos.QubesManager') - except dbus.DBusException: - # ignore the case when no qubes-manager is running - pass - diff --git a/qmemman/qmemman.py b/qmemman/qmemman.py index 4a4b0d0e..f7d7efa4 100755 --- a/qmemman/qmemman.py +++ b/qmemman/qmemman.py @@ -21,15 +21,18 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # -import xen.lowlevel.xc -import xen.lowlevel.xs -import string -import time -import qmemman_algo -import os -from notify import notify_error_qubes_manager, clear_error_qubes_manager import logging +import os +import string +import time + +import xen.lowlevel.xc +import xen.lowlevel.xs + +import qubes +import qubes.qmemman_algo + no_progress_msg="VM refused to give back requested memory" slow_memset_react_msg="VM didn't give back all requested memory" @@ -274,7 +277,12 @@ class SystemState(object): self.domdict[dom2].no_progress = True dom_name = self.xs.read('', '/local/domain/%s/name' % str(dom2)) if dom_name is not None: - notify_error_qubes_manager(str(dom_name), no_progress_msg) + try: + qubes.Qubes()[str(dom_name)].fire_event( + 'status:error', 'error', + no_progress_msg) + except LookupError: + pass else: self.log.warning('dom {!r} still hold more' ' memory than have assigned ({} > {})' @@ -284,7 +292,12 @@ class SystemState(object): self.domdict[dom2].slow_memset_react = True dom_name = self.xs.read('', '/local/domain/%s/name' % str(dom2)) if dom_name is not None: - notify_error_qubes_manager(str(dom_name), slow_memset_react_msg) + try: + qubes.Qubes()[str(dom_name)].fire_event( + 'status:error', 'error', + slow_memset_react_msg) + except LookupError: + pass self.mem_set(dom, self.get_free_xen_memory() + self.domdict[dom].memory_actual - self.XEN_FREE_MEM_LEFT) return diff --git a/qubes/ext/__init__.py b/qubes/ext/__init__.py index 8dde7a8c..7240cdfb 100644 --- a/qubes/ext/__init__.py +++ b/qubes/ext/__init__.py @@ -63,10 +63,12 @@ class Extension(object): continue if attr.ha_vm is not None: - attr.ha_vm.add_hook(attr.ha_event, attr) + for event in attr.ha_events: + attr.ha_vm.add_handler(event, attr) else: # global hook - self.app.add_hook(attr.ha_event, attr) + for event in attr.ha_events: + self.app.add_handler(event, attr) def handler(*events, **kwargs): diff --git a/qubes/ext/qubesmanager.py b/qubes/ext/qubesmanager.py new file mode 100644 index 00000000..a65fd2c3 --- /dev/null +++ b/qubes/ext/qubesmanager.py @@ -0,0 +1,63 @@ +#!/usr/bin/python2 -O +# vim: fileencoding=utf-8 + +# +# The Qubes OS Project, https://www.qubes-os.org/ +# +# Copyright (C) 2014-2015 Joanna Rutkowska +# Copyright (C) 2014 Marek Marczykowski-Górecki +# +# Copyright (C) 2015 Wojtek Porczyk +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +'''Qubes Manager hooks. + +.. warning:: API defined here is not declared stable. +''' + +import qubes.ext +import dbus + + +class QubesManagerExtension(qubes.ext.Extension): + def __init__(self, *args, **kwargs): + super(QubesManagerExtension, self).__init__(*args, **kwargs) + self._system_bus = dbus.SystemBus() + + @qubes.ext.handler('status:error') + def on_status_error(self, vm, status, message): + try: + qubes_manager = system_bus.get_object( + 'org.qubesos.QubesManager', + '/org/qubesos/QubesManager') + qubes_manager.notify_error(vm.name, message, + dbus_interface='org.qubesos.QubesManager') + except dbus.DBusException: + # ignore the case when no qubes-manager is running + pass + + @qubes.ext.handler('status:no-error') + def on_status_error(self, vm, status, message): + try: + qubes_manager = system_bus.get_object( + 'org.qubesos.QubesManager', + '/org/qubesos/QubesManager') + qubes_manager.clear_error_exact(vm.name, message, + dbus_interface='org.qubesos.QubesManager') + except dbus.DBusException: + # ignore the case when no qubes-manager is running + pass diff --git a/qubes/log.py b/qubes/log.py index 6494afb5..67a98b3f 100644 --- a/qubes/log.py +++ b/qubes/log.py @@ -31,6 +31,8 @@ import logging import os import sys +import dbus + FORMAT_CONSOLE = '%(message)s' FORMAT_LOG = '%(asctime)s %(message)s' FORMAT_DEBUG = '%(asctime)s ' \ @@ -42,6 +44,43 @@ formatter_console = logging.Formatter(FORMAT_CONSOLE) formatter_log = logging.Formatter(FORMAT_LOG) formatter_debug = logging.Formatter(FORMAT_DEBUG) +class DBusHandler(logging.Handler): + '''Handler which displays records as DBus notifications''' + + #: mapping of loglevels to icons + app_icons = { + logging.ERROR: 'dialog-error', + logging.WARNING: 'dialog-warning', + logging.NOTSET: 'dialog-information', + } + + def __init__(self, *args, **kwargs): + super(DBusHandler, self).__init__(*args, **kwargs) + + self._notify_object = dbus.SessionBus().get_object( + 'org.freedesktop.Notifications', '/org/freedesktop/Notifications') + + + def handle(self, record): + app_icon = self.app_icons[ + max(level for level in self.app_icons if level <= record.levelno)] + + try: + # https://developer.gnome.org/notification-spec/#command-notify + self._notify_object.Notify( + 'Qubes', # STRING app_name + 0, # UINT32 replaces_id + app_icon, # STRING app_icon + record.msg, # STRING summary + '', # STRING body + (), # ARRAY actions + {}, # DICT hints + 0, # INT32 timeout + dbus_interface='org.freedesktop.Notifications') + except dbus.DBusException: + pass + + def enable(): '''Enable global logging diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index c8e52ae5..5ae927ce 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -229,6 +229,7 @@ fi %dir %{python_sitelib}/qubes/ext %{python_sitelib}/qubes/ext/__init__.py* +%{python_sitelib}/qubes/ext/qubesmanager.py* %dir %{python_sitelib}/qubes/tests %{python_sitelib}/qubes/tests/__init__.py*