Browse Source

core3: qubesmanager notifying extension

core/notify.py was excavated and tray notifying remnants were moved to
qubes.log. They are unused as yet.

Also extension events are fixed.
Wojtek Porczyk 8 years ago
parent
commit
fcdb579bab
7 changed files with 128 additions and 90 deletions
  1. 0 2
      core/Makefile
  2. 0 78
      core/notify.py
  3. 21 8
      qmemman/qmemman.py
  4. 4 2
      qubes/ext/__init__.py
  5. 63 0
      qubes/ext/qubesmanager.py
  6. 39 0
      qubes/log.py
  7. 1 0
      rpm_spec/core-dom0.spec

+ 0 - 2
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),)

+ 0 - 78
core/notify.py

@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# The Qubes OS Project, http://www.qubes-os.org
-#
-# Copyright (C) 2014 Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
-#
-# 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
-

+ 21 - 8
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 logging
+import os
 import string
 import time
-import qmemman_algo
-import os
-from notify import notify_error_qubes_manager, clear_error_qubes_manager
 
-import logging
+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
 

+ 4 - 2
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):

+ 63 - 0
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 <joanna@invisiblethingslab.com>
+# Copyright (C) 2014       Marek Marczykowski-Górecki
+#                               <marmarek@invisiblethingslab.com>
+# Copyright (C) 2015       Wojtek Porczyk <woju@invisiblethingslab.com>
+#
+# 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

+ 39 - 0
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
 

+ 1 - 0
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*