Skip to content
This repository has been archived by the owner on Jan 27, 2023. It is now read-only.

Commit

Permalink
Automatically reconnect to NetworkManager
Browse files Browse the repository at this point in the history
When NetworkManager restarts, they will have different unique object
names on the system bus. Trying to the old objects will fail, so when
that happens we can simply reconnect.

To activate automatic reconnection, call
NetworkManager.NetworkManager.auto_reconnect after setting up your
mainloop.
  • Loading branch information
seveas committed Aug 8, 2016
1 parent 535a846 commit 6da0797
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
34 changes: 32 additions & 2 deletions NetworkManager.py
Expand Up @@ -10,6 +10,7 @@
import socket
import struct
import sys
import weakref

PY3 = sys.version_info >= (3,0)
if PY3:
Expand All @@ -26,17 +27,21 @@ def debug(msg, data):
except:
debug = lambda *args: None

auto_reconnect = True
registry = []

class NMDbusInterface(object):
bus = dbus.SystemBus()
dbus_service = 'org.freedesktop.NetworkManager'
object_path = None

def __init__(self, object_path=None):
global registry
if isinstance(object_path, NMDbusInterface):
object_path = object_path.object_path
self.object_path = self.object_path or object_path
self.proxy = self.bus.get_object(self.dbus_service, self.object_path)
self.interface = dbus.Interface(self.proxy, self.interface_name)
self.signals = []
self.connect()

properties = []
try:
Expand All @@ -50,6 +55,25 @@ def __init__(self, object_path=None):
if not hasattr(self.__class__, p):
setattr(self.__class__, p, self._make_property(p))

registry.append(weakref.proxy(self))

def connect(self):
self.proxy = self.bus.get_object(self.dbus_service, self.object_path)
self.interface = dbus.Interface(self.proxy, self.interface_name)
signals = self.signals[:]
self.signals = []
for signal, handler, args, kwargs in signals:
self.connect_to_signal(signal, handler, *args, **kwargs)

def reconnect(self, name, old, new):
if str(new) == "" or str(name) != 'org.freedesktop.NetworkManager':
return
for obj in registry:
try:
obj.connect()
except ReferenceError:
pass

def _make_property(self, name):
def get_func(self):
data = self.proxy.Get(self.interface_name, name, dbus_interface='org.freedesktop.DBus.Properties')
Expand Down Expand Up @@ -121,6 +145,7 @@ def proxy_call(*args, **kwargs):
return proxy_call

def connect_to_signal(self, signal, handler, *args, **kwargs):
self.signals.append((signal, handler, args, kwargs))
def helper(*args, **kwargs):
args = [self.unwrap(x) for x in args]
handler(*args, **kwargs)
Expand All @@ -138,6 +163,11 @@ class NetworkManager(NMDbusInterface):
interface_name = 'org.freedesktop.NetworkManager'
object_path = '/org/freedesktop/NetworkManager'

def auto_reconnect(self):
global auto_reconnect
auto_reconnect = True
self.bus.add_signal_receiver(self.reconnect, 'NameOwnerChanged', 'org.freedesktop.DBus')

def preprocess(self, name, args, kwargs):
if name in ('AddConnection', 'Update', 'UpdateUnsaved', 'AddAndActivateConnection'):
settings = copy.deepcopy(args[0])
Expand Down
5 changes: 5 additions & 0 deletions docs/index.rst
Expand Up @@ -82,6 +82,11 @@ This class represents the :data:`org.freedesktop.NetworkManager` interface.
Note that :data:`NetworkManager.NetworkManager` actually is the singleton
instance of this class.

.. method:: auto_reconnect

Call this method to automatically update D-Bus paths and reconnect signals when
NetworkManager restarts.

.. class:: Settings

This class represents the :data:`org.freedesktop.NetworkManager.Settings`
Expand Down
1 change: 1 addition & 0 deletions examples/listener.py
Expand Up @@ -5,6 +5,7 @@
import dbus.mainloop.glib; dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
from gi.repository import GObject
import NetworkManager
NetworkManager.NetworkManager.auto_reconnect()

d_args = ('sender', 'destination', 'interface', 'member', 'path')
d_args = dict([(x + '_keyword', 'd_' + x) for x in d_args])
Expand Down

0 comments on commit 6da0797

Please sign in to comment.