python-dbus: Monitoring a remote system bus
Kipper, Matthew
Matthew.Kipper at gd-ms.ca
Tue Sep 4 22:51:29 UTC 2018
I'm trying to write an application that runs on a machine and monitors an instance of systemd running on a remote target. Essentially, I'm trying to add some custom handling around this command:
dbus-monitor --address "unixexec:path=ssh,argv1=user%40host,argv2=systemd-stdio-bridge"
I've been trying to implement this in python with dbus-python. I've hit a roadblock, and after some initial debugging, it seems like my issue isn't caused by my exact use-case (monitoring a remote bus), but rather by something a little broader. Here's a simple example that shows my issue:
from dbus import Bus, SystemBus, Interface
from dbus.mainloop.glib import DBusGMainLoop
from glib import MainLoop
def monitor_systemd(bus):
obj = bus.get_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
manager = Interface(obj, dbus_interface="org.freedesktop.systemd1.Manager")
manager.Subscribe()
manager.connect_to_signal("JobNew", lambda a,b,c: print("systemd job added"))
DBusGMainLoop(set_as_default=True)
monitor_systemd(SystemBus())
MainLoop().run()
This code works as expected, printing a message whenever a systemd job is added. However, things break when I try to replace SystemBus() with a custom bus (e.g. remote system bus). Here's a simple example, using a wrapper for the local system bus instead of the remote system bus. My remote bus implementation is quite different (e.g. inherits from BusConnection, not Bus), but this example is simpler and generates the same behavior.
[...snip...]
class MySystemBus(Bus):
def __new__(cls, private=False, mainloop=None):
return Bus.__new__(cls, Bus.TYPE_SYSTEM, mainloop=mainloop, private=private)
DBusGMainLoop(set_as_default=True)
monitor_systemd(MySystemBus())
MainLoop().run()
I copied this __new__ method from the dbus-python SystemBus class (https://github.com/posborne/dbus-python/blob/master/dbus/_dbus.py#L179), so as far as I can tell, MySystemBus() should return the same thing as SystemBus(). However, I know get the following error:
Traceback (most recent call last):
File "dbus_test.py", line 24, in <module>
main()
File "dbus_test.py", line 19, in main
monitor_systemd(MySystemBus())
File "dbus_test.py", line 14, in monitor_systemd
manager.connect_to_signal("JobNew", lambda a,b,c: print("systemd job added"))
File "/usr/lib/python3.6/site-packages/dbus/proxies.py", line 544, in connect_to_signal
dbus_interface, **keywords)
File "/usr/lib/python3.6/site-packages/dbus/proxies.py", line 369, in connect_to_signal
**keywords)
File "/usr/lib/python3.6/site-packages/dbus/bus.py", line 148, in add_signal_receiver
path, **keywords)
File "/usr/lib/python3.6/site-packages/dbus/connection.py", line 416, in add_signal_receiver
self._signals_lock.acquire()
AttributeError: 'SystemBus' object has no attribute '_signals_lock'
It looks like when I invoke MySystemBus(), Connection.__init__ (https://github.com/posborne/dbus-python/blob/master/dbus/connection.py#L257) never runs, and all the initialization work to support signals is skipped. This is the same error I get when my full implementation inherits from BusConnection to support remote connections.
My python-foo is quite weak, so I'm not sure if I'm misunderstanding something basic about inheritance. Any help would be appreciated.
Thanks!
Matthew Kipper
“This message and/or attachments may include information subject to GD Corporate Policies 07-103 and 07-105 and is intended to be accessed only by authorized recipients. Use, storage and transmission are governed by General Dynamics and its policies. Contractual restrictions apply to third parties. Recipients should refer to the policies or contract to determine proper handling. Unauthorized review, use, disclosure or distribution is prohibited. If you are not an intended recipient, please contact the sender and destroy all copies of the original message.”
More information about the dbus
mailing list