Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorgan Collett <morgan.collett@gmail.com>2008-11-19 14:56:25 (GMT)
committer Morgan Collett <morgan.collett@gmail.com>2008-11-25 13:01:11 (GMT)
commit4c1dd3b8f3cc430877b72062ae20928da7dcbee7 (patch)
tree08ccea2aa52eeaf0d5f2417c78170a621c77dd89
parent29c07d9a113dafb4cba3665250f3cb3341393aa7 (diff)
#6248: Port NetworkManager watcher code to NM 0.7's D-Bus API
-rw-r--r--src/psutils.py146
1 files changed, 82 insertions, 64 deletions
diff --git a/src/psutils.py b/src/psutils.py
index 630d39c..feabefe 100644
--- a/src/psutils.py
+++ b/src/psutils.py
@@ -1,5 +1,6 @@
# Copyright (C) 2007, Red Hat, Inc.
# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copyright 2008 One Laptop Per Child
#
# 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
@@ -26,6 +27,8 @@ except ImportError:
import dbus
from dbus.exceptions import DBusException
import gobject
+import socket
+import struct
_logger = logging.getLogger('s-p-s.psutils')
@@ -117,15 +120,20 @@ def escape_identifier(identifier):
return ''.join(ret)
-NM_SERVICE = 'org.freedesktop.NetworkManager'
-NM_IFACE = 'org.freedesktop.NetworkManager'
-NM_IFACE_DEVICES = 'org.freedesktop.NetworkManager.Devices'
-NM_PATH = '/org/freedesktop/NetworkManager'
+_NM_SERVICE = 'org.freedesktop.NetworkManager'
+_NM_IFACE = 'org.freedesktop.NetworkManager'
+_NM_IFACE_DEVICE = 'org.freedesktop.NetworkManager.Device'
+_NM_PATH = '/org/freedesktop/NetworkManager'
+_NM_DEVICE_STATE_ACTIVATED = 8
+_NM_STATE_CONNECTED = 3
+_NM_STATE_DISCONNECTED = 4
+_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
+_DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'
_ip4am = None
class IP4AddressMonitor(gobject.GObject):
- """This class, and direct buddy IPv4 address access, will go away quite soon"""
+ """Monitor NetworkManager for IP4 address changes."""
__gsignals__ = {
'address-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
@@ -150,11 +158,11 @@ class IP4AddressMonitor(gobject.GObject):
self._nm_has_been_present = False
self._matches = []
self._addr = None
- self._nm_obj = None
-
- sys_bus = dbus.SystemBus()
- self._watch = sys_bus.watch_name_owner(NM_SERVICE, self._nm_owner_cb)
- if not sys_bus.name_has_owner(NM_SERVICE):
+ self._nm_iface = None
+ self._sys_bus = dbus.SystemBus()
+ self._watch = self._sys_bus.watch_name_owner(_NM_SERVICE,
+ self._nm_owner_cb)
+ if not self._sys_bus.name_has_owner(_NM_SERVICE):
addr, iface = self._get_address_fallback()
self._update_address(addr, iface)
@@ -173,82 +181,92 @@ class IP4AddressMonitor(gobject.GObject):
self.emit('address-changed', new_addr, iface)
def _connect_to_nm(self):
- """Connect to NM device state signals to tell when the IPv4 address changes"""
+ """Connect to NM device state signals to watch IPv4 address changes"""
try:
- sys_bus = dbus.SystemBus()
- proxy = sys_bus.get_object(NM_SERVICE, NM_PATH)
- self._nm_obj = dbus.Interface(proxy, NM_IFACE)
+ nm_obj = self._sys_bus.get_object(_NM_SERVICE, _NM_PATH)
+ self._nm_iface = dbus.Interface(nm_obj, _NM_IFACE)
except DBusException, err:
_logger.debug("Error finding NetworkManager: %s" % err)
self._nm_present = False
+ addr, iface = self._get_address_fallback()
+ self._update_address(addr, iface)
+ return
+
+ # Detect NM 0.6 which is now unsupported, so we can use the fallback
+ try:
+ dummy = self._nm_iface.GetDevices()
+ except DBusException:
+ _logger.debug(
+ "Error NM 0.6 is now unsupported - we use the fallback.")
+ addr, iface = self._get_address_fallback()
+ self._update_address(addr, iface)
return
- sys_bus = dbus.SystemBus()
- match = sys_bus.add_signal_receiver(self._nm_device_active_cb,
- signal_name="DeviceNowActive",
- dbus_interface=NM_IFACE)
+ match = self._sys_bus.add_signal_receiver(
+ self._nm_device_added_cb, signal_name="DeviceAdded",
+ dbus_interface=_NM_IFACE, bus_name=_NM_SERVICE)
self._matches.append(match)
- match = sys_bus.add_signal_receiver(self._nm_device_no_longer_active_cb,
- signal_name="DeviceNoLongerActive",
- dbus_interface=NM_IFACE,
- bus_name=NM_SERVICE)
+ match = self._sys_bus.add_signal_receiver(
+ self._nm_device_removed_cb,
+ signal_name="DeviceRemoved",
+ dbus_interface=_NM_IFACE, bus_name=_NM_SERVICE)
self._matches.append(match)
- match = sys_bus.add_signal_receiver(self._nm_state_change_cb,
- signal_name="StateChange",
- dbus_interface=NM_IFACE,
- bus_name=NM_SERVICE)
+ match = self._sys_bus.add_signal_receiver(
+ self._nm_state_change_cb, signal_name="StateChanged",
+ dbus_interface=_NM_IFACE, bus_name=_NM_SERVICE)
self._matches.append(match)
- state = self._nm_obj.state()
- if state == 3: # NM_STATE_CONNECTED
+ nm_props = dbus.Interface(nm_obj, _DBUS_PROPERTIES)
+ state = nm_props.Get(_NM_IFACE, 'State')
+ if state == _NM_STATE_CONNECTED:
self._query_devices()
- def _device_properties_cb(self, *props):
- active = props[4]
- if not active:
- return
- act_stage = props[5]
- # HACK: OLPC NM has an extra stage, so activated == 8 on OLPC
- # but 7 everywhere else
- if act_stage != 8 and act_stage != 7:
- # not activated
- return
- self._update_address(props[6], props[1])
-
- def _device_properties_error_cb(self, err):
- _logger.debug("Error querying device properties: %s" % err)
-
- def _query_device_properties(self, device):
- sys_bus = dbus.SystemBus()
- proxy = sys_bus.get_object(NM_SERVICE, device)
- dev = dbus.Interface(proxy, NM_IFACE_DEVICES)
- dev.getProperties(reply_handler=self._device_properties_cb,
- error_handler=self._device_properties_error_cb)
-
- def _get_devices_cb(self, ops):
+ def _query_device_properties(self, device_path):
+ """Query a device's properties to get IP address and interface."""
+ device = self._sys_bus.get_object(_NM_SERVICE, device_path)
+ props = dbus.Interface(device, _DBUS_PROPERTIES)
+ state = props.Get(_NM_IFACE_DEVICE, 'State')
+ if state == _NM_DEVICE_STATE_ACTIVATED:
+ ip = props.Get(_NM_IFACE_DEVICE, 'Ip4Address')
+ ipaddr = socket.inet_ntoa(struct.pack('I', ip))
+ iface = props.Get(_NM_IFACE_DEVICE, 'Interface')
+ self._update_address(ipaddr, iface)
+
+ def _get_devices_cb(self, device_paths):
"""Query each device's properties"""
- for op in ops:
- self._query_device_properties(op)
+ for device_path in device_paths:
+ self._query_device_properties(device_path)
def _get_devices_error_cb(self, err):
_logger.debug("Error getting NetworkManager devices: %s" % err)
def _query_devices(self):
"""Query NM for a list of network devices"""
- self._nm_obj.getDevices(reply_handler=self._get_devices_cb,
- error_handler=self._get_devices_error_cb)
-
- def _nm_device_active_cb(self, device, ssid=None):
- self._query_device_properties(device)
-
- def _nm_device_no_longer_active_cb(self, device):
+ _nm_props = dbus.Interface(self._nm_iface, _DBUS_PROPERTIES)
+ active_connection_paths = _nm_props.Get(_NM_IFACE, 'ActiveConnections')
+ for conn_path in active_connection_paths:
+ conn = self._sys_bus.get_object(_NM_IFACE, conn_path)
+ conn_props = dbus.Interface(conn, _DBUS_PROPERTIES)
+ conn_props.Get(_NM_ACTIVE_CONN_IFACE, 'Devices',
+ reply_handler=self._get_devices_cb,
+ error_handler=self._get_devices_error_cb)
+
+ def _nm_device_added_cb(self, device_path):
+ """Handle NetworkManager DeviceAdded signal."""
+ self._query_device_properties(device_path)
+
+ def _nm_device_removed_cb(self, device_path):
+ """Handle NetworkManager DeviceRemoved signal."""
self._update_address(None, None)
def _nm_state_change_cb(self, new_state):
- if new_state == 4: # NM_STATE_DISCONNECTED
+ """Handle NetworkManager StateChanged signal."""
+ if new_state == _NM_STATE_DISCONNECTED:
self._update_address(None, None)
+ elif new_state == _NM_STATE_CONNECTED:
+ self._query_devices()
def _nm_owner_cb(self, unique_name):
"""Clear state when NM goes away"""
@@ -256,6 +274,7 @@ class IP4AddressMonitor(gobject.GObject):
# NM went away, or isn't there at all
self._nm_present = False
for match in self._matches:
+ self._sys_bus.remove_signal_receiver(match)
match.remove()
self._matches = []
if self._nm_has_been_present:
@@ -270,13 +289,12 @@ class IP4AddressMonitor(gobject.GObject):
self._connect_to_nm()
def _get_iface_address(self, iface):
- import socket
import fcntl
- import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
fd = s.fileno()
SIOCGIFADDR = 0x8915
- addr = fcntl.ioctl(fd, SIOCGIFADDR, struct.pack('256s', iface[:15]))[20:24]
+ addr = fcntl.ioctl(fd, SIOCGIFADDR,
+ struct.pack('256s', iface[:15]))[20:24]
s.close()
return socket.inet_ntoa(addr), iface