1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
"""
Expose some API over D-Bus.
"""
import logging
import threading
from plinth.utils import import_from_gi
from . import setup
gio = import_from_gi('Gio', '2.0')
logger = logging.getLogger(__name__)
_server = None
class PackageHandler():
"""D-Bus service to listen for messages when apt cache is updated."""
introspection_xml = '''
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/freedombox/Service/PackageHandler">
<interface name="org.freedombox.Service.PackageHandler">
<method name="CacheUpdated"/>
</interface>
</node>
'''
def register(self, connection):
"""Register the object in D-Bus connection."""
introspection_data = gio.DBusNodeInfo.new_for_xml(
self.introspection_xml)
interface_info = gio.DBusNodeInfo.lookup_interface(
introspection_data, 'org.freedombox.Service.PackageHandler')
connection.register_object('/org/freedombox/Service/PackageHandler',
interface_info, self.on_method_call, None,
None)
def on_method_call(self, _connection, _sender, _object_path,
_interface_name, method_name, _parameters, invocation):
"""Handle method being called.
No need to check all the incoming parameters as D-Bus will validate all
the incoming parameters using introspection data.
"""
if method_name == 'CacheUpdated':
self.on_cache_updated()
invocation.return_value()
@staticmethod
def on_cache_updated():
"""Called when system package cache is updated."""
logger.info('Apt package cache updated.')
threading.Thread(target=setup.on_package_cache_updated).start()
class DBusServer():
"""Abstraction over a connection to D-Bus."""
def __init__(self):
"""Initialize the server object."""
self.package_handler = None
def connect(self):
"""Connect to bus with well-known name."""
gio.bus_own_name(gio.BusType.SYSTEM, 'org.freedombox.Service',
gio.BusNameOwnerFlags.NONE, self.on_bus_acquired,
self.on_name_acquired, self.on_name_lost)
def on_bus_acquired(self, connection, name):
"""Callback when connection to D-Bus has been acquired."""
logger.info('D-Bus connection acquired: %s', name)
self.package_handler = PackageHandler()
self.package_handler.register(connection)
from plinth.modules.letsencrypt.dbus import LetsEncrypt
lets_encrypt = LetsEncrypt()
lets_encrypt.register(connection)
@staticmethod
def on_name_acquired(_connection, name):
"""Callback when service name on D-Bus has been acquired."""
logger.info('D-Bus name acquired: %s', name)
@staticmethod
def on_name_lost(_connection, name):
"""Callback when service name or DBus connection is closed."""
logger.info('D-Bus connection lost: %s', name)
def init():
"""Connect to D-Bus service. Must be run from glib thread."""
global _server
_server = DBusServer()
_server.connect()
|