[PATCH] Fix check for device state when reading its IPXConfig (#1001776)

Radek Vykydal rvykydal at redhat.com
Mon Sep 9 07:41:39 UTC 2013


Device has to be in ACTIVATED state for IPXConfig to be valid.

1) use a recently added nm module function to get IP configuration, replacing
python-dbus with GDBus here. Python-dbus would give us stale value.

2) Don't use get_cached_property of GDBus as it would give us stale value too.
Instead use DBus.Properties interface call to get current values.
---
 pyanaconda/nm.py                    | 77 ++++++++++++++++++++-----------------
 pyanaconda/ui/gui/spokes/network.py | 64 +++++++++++-------------------
 2 files changed, 63 insertions(+), 78 deletions(-)

diff --git a/pyanaconda/nm.py b/pyanaconda/nm.py
index 1109d6e..4f0923d 100644
--- a/pyanaconda/nm.py
+++ b/pyanaconda/nm.py
@@ -73,10 +73,27 @@ def _get_proxy(bus_type=Gio.BusType.SYSTEM,
                                            cancellable)
     return proxy
 
+def _get_property(object_path, prop, interface_name_suffix=""):
+    interface_name = "org.freedesktop.NetworkManager" + interface_name_suffix
+    proxy = _get_proxy(object_path=object_path, interface_name="org.freedesktop.DBus.Properties")
+    args = GLib.Variant('(ss)', (interface_name, prop))
+    try:
+        prop = proxy.call_sync("Get",
+                                args,
+                                Gio.DBusCallFlags.NONE,
+                                DEFAULT_DBUS_TIMEOUT,
+                                None)
+    except GLib.GError as e:
+        if "org.freedesktop.DBus.Error.AccessDenied" in e.message:
+            return None
+        else:
+            raise
+
+    return prop.unpack()[0]
+
 def nm_state():
     """Return state of NetworkManager"""
-    proxy = _get_proxy()
-    return proxy.get_cached_property("State").unpack()
+    return _get_property("/org/freedesktop/NetworkManager", "State")
 
 # FIXME - use just GLOBAL? There is some connectivity checking
 # for GLOBAL in NM (nm_connectivity_get_connected), not sure if
@@ -107,11 +124,11 @@ def nm_devices():
 
     devices = devices.unpack()[0]
     for device in devices:
-        proxy = _get_proxy(object_path=device, interface_name="org.freedesktop.NetworkManager.Device")
-        device_type = proxy.get_cached_property("DeviceType").unpack()
+        device_type = _get_property(device, "DeviceType", ".Device")
         if device_type not in supported_device_types:
             continue
-        interfaces.append(proxy.get_cached_property("Interface").unpack())
+        iface = _get_property(device, "Interface", ".Device")
+        interfaces.append(iface)
 
     return interfaces
 
@@ -120,19 +137,15 @@ def nm_activated_devices():
 
     interfaces = []
 
-    proxy = _get_proxy()
-    active_connections = proxy.get_cached_property("ActiveConnections").unpack()
+    active_connections = _get_property("/org/freedesktop/NetworkManager", "ActiveConnections")
     for ac in active_connections:
-        proxy = _get_proxy(object_path=ac, interface_name="org.freedesktop.NetworkManager.Connection.Active")
-        state = proxy.get_cached_property("State")
-        if not state or state.unpack() != NetworkManager.ActiveConnectionState.ACTIVATED:
-            continue
-        devices = proxy.get_cached_property("Devices")
-        if not devices:
+        state = _get_property(ac, "State", ".Connection.Active")
+        if state != NetworkManager.ActiveConnectionState.ACTIVATED:
             continue
-        for device in devices.unpack():
-            proxy = _get_proxy(object_path=device, interface_name="org.freedesktop.NetworkManager.Device")
-            interfaces.append(proxy.get_cached_property("Interface").unpack())
+        devices = _get_property(ac, "Devices", ".Connection.Active")
+        for device in devices:
+            iface = _get_property(device, "Interface", ".Device")
+            interfaces.append(iface)
 
     return interfaces
 
@@ -181,18 +194,14 @@ def nm_device_property(name, prop):
         raise
 
     device = device.unpack()[0]
-    proxy = _get_proxy(object_path=device, interface_name="org.freedesktop.NetworkManager.Device")
 
-    if prop in proxy.get_cached_property_names():
-        retval = proxy.get_cached_property(prop).unpack()
-    else:
+    retval = _get_property(device, prop, ".Device")
+    if not retval:
         # Look in device type based interface
         interface = _device_type_specific_interface(device)
         if interface:
-            proxy = _get_proxy(object_path=device, interface_name=interface)
-            if prop in proxy.get_cached_property_names():
-                retval = proxy.get_cached_property(prop).unpack()
-            else:
+            retval = _get_property(device, prop, interface[30:])
+            if not retval:
                 raise PropertyNotFoundError(prop)
         else:
             raise PropertyNotFoundError(prop)
@@ -284,10 +293,10 @@ def nm_device_ip_config(name, version=4):
         return []
 
     if version == 4:
-        dbus_iface = "org.freedesktop.NetworkManager.IP4Config"
+        dbus_iface = ".IP4Config"
         prop= "Ip4Config"
     elif version == 6:
-        dbus_iface = "org.freedesktop.NetworkManager.IP6Config"
+        dbus_iface = ".IP6Config"
         prop= "Ip6Config"
     else:
         return []
@@ -296,9 +305,7 @@ def nm_device_ip_config(name, version=4):
     if config == "/":
         return []
 
-    proxy = _get_proxy(object_path=config, interface_name=dbus_iface)
-
-    addresses = proxy.get_cached_property("Addresses").unpack()
+    addresses = _get_property(config, "Addresses", dbus_iface)
     addr_list = []
     for addr, prefix, gateway in addresses:
         # TODO - look for a library function (could have used IPy but byte order!)
@@ -310,7 +317,7 @@ def nm_device_ip_config(name, version=4):
             gateway_str = nm_dbus_ay_to_ipv6(gateway)
         addr_list.append([addr_str, prefix, gateway_str])
 
-    nameservers = proxy.get_cached_property("Nameservers").unpack()
+    nameservers = _get_property(config, "Nameservers", dbus_iface)
     ns_list = []
     for ns in nameservers:
         # TODO - look for a library function
@@ -322,7 +329,6 @@ def nm_device_ip_config(name, version=4):
 
     return [addr_list, ns_list]
 
-
 def nm_ntp_servers_from_dhcp():
     """Return a list of NTP servers that were specified the reply of the
        DHCP server or empty list if no NTP servers were returned.
@@ -335,16 +341,15 @@ def nm_ntp_servers_from_dhcp():
     for device in active_devices:
         # harvest NTP server addresses from DHCPv4
         dhcp4_path = nm_device_property(device, "Dhcp4Config")
-        dhcp4_proxy = _get_proxy(object_path=dhcp4_path,
-                interface_name="org.freedesktop.NetworkManager.DHCP4Config")
-        options = dhcp4_proxy.get_cached_property("Options")
-        if options and 'ntp_servers' in options.unpack():
+        options = _get_property(dhcp4_path, "Options", ".DHCP4Config")
+        if options and 'ntp_servers' in options:
             # NTP server addresses returned by DHCP are whitespace delimited
-            ntp_servers_string = options.unpack()["ntp_servers"] 
+            ntp_servers_string = options["ntp_servers"]
             for ip in ntp_servers_string.split(" "):
                 ntp_servers.append(ip)
 
         # NetworkManager does not request NTP/SNTP options for DHCP6
+    print ntp_servers
     return ntp_servers
 
 def _device_settings(name):
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index f7c1275..132c7f2 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -43,7 +43,7 @@ from pyanaconda.ui.gui.utils import gtk_call_once, enlightbox
 from pyanaconda.ui.common import FirstbootSpokeMixIn
 
 from pyanaconda import network
-from pyanaconda.nm import nm_activated_devices, nm_device_setting_value, nm_dbus_ay_to_ipv6
+from pyanaconda.nm import nm_device_setting_value, nm_device_ip_config
 
 from gi.repository import GLib, GObject, Pango, Gio, NetworkManager, NMClient
 import dbus
@@ -704,12 +704,9 @@ class NetworkControlBox(object):
         self._refresh_parent_vlanid(device)
         self._refresh_speed_hwaddr(device, state)
         self._refresh_ap(device, state)
-        self._refresh_device_cfg(device, state)
+        self._refresh_device_cfg(device)
 
-    def _refresh_device_cfg(self, device, state):
-
-        if state is None:
-            state = device.get_state()
+    def _refresh_device_cfg(self, device):
 
         dev_type = device.get_device_type()
         if dev_type == NetworkManager.DeviceType.ETHERNET:
@@ -721,45 +718,28 @@ class NetworkControlBox(object):
         elif dev_type == NetworkManager.DeviceType.VLAN:
             dt = "wired"
 
-        if state == NetworkManager.DeviceState.ACTIVATED:
-            ipv4cfg = device.get_ip4_config()
-            ipv6cfg = device.get_ip6_config()
-        else:
-            ipv4cfg = None
-            ipv6cfg = None
-
-        if ipv4cfg:
-            addr = socket.inet_ntoa(struct.pack('=L',
-                                                ipv4cfg.get_addresses()[0].get_address()))
-            self._set_device_info_value(dt, "ipv4", addr)
-            dnss = " ".join(socket.inet_ntoa(struct.pack('=L', addr))
-                             for addr in ipv4cfg.get_nameservers())
-            self._set_device_info_value(dt, "dns", dnss)
-            gateway = socket.inet_ntoa(struct.pack('=L',
-                                                   ipv4cfg.get_addresses()[0].get_gateway()))
-            self._set_device_info_value(dt, "route", gateway)
-            if dt == "wired":
-                prefix = ipv4cfg.get_addresses()[0].get_prefix()
-                nm_utils.nm_utils_ip4_prefix_to_netmask.argtypes = [ctypes.c_uint32]
-                nm_utils.nm_utils_ip4_prefix_to_netmask.restype = ctypes.c_uint32
-                netmask = nm_utils.nm_utils_ip4_prefix_to_netmask(prefix)
-                netmask = socket.inet_ntoa(struct.pack('=L', netmask))
-                self._set_device_info_value(dt, "subnet", netmask)
+        ipv4cfg = nm_device_ip_config(device.get_iface(), version=4)
+        ipv6cfg = nm_device_ip_config(device.get_iface(), version=6)
+
+        if ipv4cfg and ipv4cfg[0]:
+            addr_str, prefix, gateway_str = ipv4cfg[0][0]
+            netmask_str = network.prefix2netmask(prefix)
+            dnss_str = " ".join(ipv4cfg[1])
         else:
-            self._set_device_info_value(dt, "ipv4", None)
-            self._set_device_info_value(dt, "dns", None)
-            self._set_device_info_value(dt, "route", None)
-            if dt == "wired":
-                self._set_device_info_value(dt, "subnet", None)
+            addr_str = dnss_str = gateway_str = netmask_str = None
+        self._set_device_info_value(dt, "ipv4", addr_str)
+        self._set_device_info_value(dt, "dns", dnss_str)
+        self._set_device_info_value(dt, "route", gateway_str)
+        if dt == "wired":
+            self._set_device_info_value(dt, "subnet", netmask_str)
 
-        # TODO NM_GI_BUGS - segfaults on get_addres(), get_prefix()
         addr6_str = ""
-        if ipv6cfg:
-            config = dbus.SystemBus().get_object(NM_SERVICE, ipv6cfg.get_path())
-            for addr, _prefix, _gw in getNMObjProperty(config, ".IP6Config", "Addresses"):
-                ipv6_addr = nm_dbus_ay_to_ipv6(addr)
-                if not ipv6_addr.startswith("fe80:"):
-                    addr6_str += "%s\n" % ipv6_addr
+        if ipv6cfg and ipv6cfg[0]:
+            for ipv6addr in ipv6cfg[0]:
+                addr_str, prefix, gateway_str = ipv6addr
+                # Do not display link-local addresses
+                if not addr_str.startswith("fe80:"):
+                    addr6_str += "%s/%d\n" % (addr_str, prefix)
 
         self._set_device_info_value(dt, "ipv6", addr6_str.strip() or None)
 
-- 
1.7.11.7



More information about the anaconda-patches mailing list