[PATCH rhel7-branch 4/5] network: generate kickstart commands for team devices (#1003591)

Radek Vykydal rvykydal at redhat.com
Wed Nov 6 10:02:18 UTC 2013


Resolves: rhbz#1003591
---
 pyanaconda/network.py | 58 +++++++++++++++++++++++++++++++++++++-
 pyanaconda/nm.py      | 77 ++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 24 deletions(-)

diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index 8796676..b9a201e 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -553,6 +553,8 @@ def ksdata_from_ifcfg(devname):
         nm.device = ""
     elif nm.nm_device_type_is_bond(devname):
         nd.device = devname
+    elif nm.nm_device_type_is_team(devname):
+        nd.device = devname
     elif nm.nm_device_type_is_vlan(devname):
         nd.device = devname.split(".")[0]
 
@@ -567,6 +569,9 @@ def ifcfg_to_ksdata(ifcfg, devname):
     # no network command for bond slaves
     if ifcfg.get("MASTER"):
         return None
+    # no network command for team slaves
+    if ifcfg.get("TEAM_MASTER"):
+        return None
 
     # ipv4 and ipv6
     if ifcfg.get("ONBOOT") and ifcfg.get("ONBOOT" ) == "no":
@@ -660,7 +665,19 @@ def ifcfg_to_ksdata(ifcfg, devname):
         kwargs["device"] = ifcfg.get("PHYSDEV")
         kwargs["vlanid"] = ifcfg.get("VLAN_ID")
 
-    return handler.NetworkData(**kwargs)
+    nd = handler.NetworkData(**kwargs)
+
+    # teaming
+    if ifcfg.get("TYPE") == "Team" or ifcfg.get("DEVICETYPE") == "Team":
+        slaves = get_team_slaves([devname, ifcfg.get("UUID")])
+        for dev, cfg in slaves:
+            nd.teamslaves.append((dev, cfg))
+
+        teamconfig = nm.nm_device_setting_value(devname, "team", "config")
+        if teamconfig:
+            nd.teamconfig = teamconfig
+
+    return nd
 
 def hostname_ksdata(hostname):
     from pyanaconda.kickstart import AnacondaKSHandler
@@ -680,6 +697,8 @@ def find_ifcfg_file_of_device(devname, root_path=""):
             ifcfg_path = find_ifcfg_file([("ESSID", ssid)])
     elif nm.nm_device_type_is_bond(devname):
         ifcfg_path = find_ifcfg_file([("DEVICE", devname)])
+    elif nm.nm_device_type_is_team(devname):
+        ifcfg_path = find_ifcfg_file([("DEVICE", devname)])
     elif nm.nm_device_type_is_vlan(devname):
         ifcfg_path = find_ifcfg_file([("DEVICE", devname)])
     elif nm.nm_device_type_is_ethernet(devname):
@@ -695,6 +714,10 @@ def find_ifcfg_file_of_device(devname, root_path=""):
                                           ("MASTER", nonempty)],
                                          root_path)
             if not ifcfg_path:
+                ifcfg_path = find_ifcfg_file([("HWADDR", hwaddr_check),
+                                              ("TEAM_MASTER", nonempty)],
+                                             root_path)
+            if not ifcfg_path:
                 ifcfg_path = find_ifcfg_file([("HWADDR", hwaddr_check)], root_path)
         if not ifcfg_path:
             ifcfg_path = find_ifcfg_file([("DEVICE", devname)], root_path)
@@ -745,6 +768,39 @@ def get_bond_slaves_from_ifcfgs(master_specs):
                         break
     return slaves
 
+# why not from ifcfg? because we want config json value without escapes
+def get_team_slaves(master_specs):
+    """List of slaves of master specified by master_specs (name, opts).
+
+       master_specs is a list containing device name of master (dracut)
+       and/or master's connection uuid
+    """
+    slaves = []
+
+    for master in master_specs:
+        slave_settings = nm.nm_get_settings(master, "connection", "master")
+        for settings in slave_settings:
+            try:
+                cfg = settings["team-port"]["config"]
+            except KeyError as e:
+                cfg = ""
+            devname = settings["connection"].get("interface-name")
+            #nm-c-e doesn't save device name
+            # TODO: wifi, infiniband
+            if not devname:
+                type = settings["connection"]["type"]
+                if type == "802-3-ethernet":
+                    hwaddr = settings["802-3-ethernet"]["mac-address"]
+                    hwaddr = ":".join("%02X" % b for b in hwaddr)
+                    devname = nm.nm_hwaddr_to_device_name(hwaddr)
+            if devname:
+                slaves.append((devname, cfg))
+            else:
+                uuid = settings["connection"].get("uuid")
+                log.debug("network: can't get team slave device name of %s" % uuid)
+
+    return slaves
+
 def ifaceForHostIP(host):
     route = iutil.execWithCapture("ip", [ "route", "get", "to", host ])
     if not route:
diff --git a/pyanaconda/nm.py b/pyanaconda/nm.py
index 2ff208d..1eb0c76 100644
--- a/pyanaconda/nm.py
+++ b/pyanaconda/nm.py
@@ -443,6 +443,18 @@ def nm_device_slaves(name):
 
     return slave_ifaces
 
+def nm_hwaddr_to_device_name(hwaddr):
+    """Return device name of interface with given hardware address.
+
+        :param hwaddr: hardware address
+        :type hwaddr: str
+        :return: device name of interface having hwaddr
+        :rtype: str
+    """
+    for device in nm_devices():
+        if nm_device_hwaddress(device).upper() == hwaddr.upper():
+            return device
+    return None
 
 def nm_ntp_servers_from_dhcp():
     """Return a list of NTP servers that were specified the reply of the
@@ -471,9 +483,7 @@ def nm_ntp_servers_from_dhcp():
     return ntp_servers
 
 def _device_settings(name):
-    """Return object path of device setting
-
-       Returns None if settings were not found.
+    """Return list of object paths of device settings
 
        Exceptions:
        UnknownDeviceError - device was not found
@@ -489,34 +499,30 @@ def _device_settings(name):
             try:
                 hwaddr_str = nm_device_hwaddress(name)
             except PropertyNotFoundError:
-                settings = None
+                settings = []
             else:
                 settings = _settings_for_hwaddr(hwaddr_str)
 
     return settings
 
 def _settings_for_ap(ssid):
-    """Return object path of wireless access point settings.
-
-       Returns None if settings were not found.
+    """Return list of object paths of wireless access point settings.
 `   """
     return _find_settings(ssid, '802-11-wireless', 'ssid',
             format_value=lambda ba: "".join(chr(b) for b in ba))
 
 def _settings_for_hwaddr(hwaddr):
-    """Return object path of settings of device specified by hw address.
-
-       Returns None if settings were not found.
+    """Return list of object paths of settings of device specified by hw address.
     """
     return _find_settings(hwaddr, '802-3-ethernet', 'mac-address',
             format_value=lambda ba: ":".join("%02X" % b for b in ba))
 
 def _find_settings(value, key1, key2, format_value=lambda x:x):
-    """Return object path of settings having given value of key1, key2 setting
+    """Return list of object paths of settings having given value of key1, key2 setting
 
-       Returns None if settings were not found.
-    """
-    retval = None
+       Returns list of object paths found.
+       """
+    retval = []
 
     proxy = _get_proxy(object_path="/org/freedesktop/NetworkManager/Settings", interface_name="org.freedesktop.NetworkManager.Settings")
 
@@ -541,8 +547,27 @@ def _find_settings(value, key1, key2, format_value=lambda x:x):
         except KeyError:
             continue
         if format_value(v) == value:
-            retval = con
-            break
+            retval.append(con)
+
+    return retval
+
+def nm_get_settings(value, key1, key2, format_value=lambda x:x):
+    """Return settings having given value of key1, key2 setting
+
+       Returns list of settings(dicts) , None if settings were not found.
+    """
+    retval = []
+    settings_paths = _find_settings(value, key1, key2, format_value)
+    for settings_path in settings_paths:
+        proxy = _get_proxy(object_path=settings_path, interface_name="org.freedesktop.NetworkManager.Settings.Connection")
+        args = None
+        settings = proxy.call_sync("GetSettings",
+                                   args,
+                                   Gio.DBusCallFlags.NONE,
+                                   DEFAULT_DBUS_TIMEOUT,
+                                   None)
+        settings = settings.unpack()[0]
+        retval.append(settings)
 
     return retval
 
@@ -585,9 +610,11 @@ def nm_device_setting_value(name, key1, key2):
        UnknownDeviceError - device was not found
        SettingsNotFoundError - settings were not found (eg for "wlan0")
     """
-    settings_path = _device_settings(name)
-    if not settings_path:
+    settings_paths = _device_settings(name)
+    if not settings_paths:
         raise SettingsNotFoundError(name)
+    else:
+        settings_path = settings_paths[0]
     proxy = _get_proxy(object_path=settings_path, interface_name="org.freedesktop.NetworkManager.Settings.Connection")
     args = None
     settings = proxy.call_sync("GetSettings",
@@ -618,9 +645,11 @@ def nm_ap_setting_value(ssid, key1, key2):
        :raise SettingsNotFoundError: if settings were not found
                                            (eg for "wlan0")
     """
-    settings_path = _settings_for_ap(ssid)
-    if not settings_path:
+    settings_paths = _settings_for_ap(ssid)
+    if not settings_paths:
         raise SettingsNotFoundError(ssid)
+    else:
+        settings_path = settings_paths[0]
     proxy = _get_proxy(object_path=settings_path, interface_name="org.freedesktop.NetworkManager.Settings.Connection")
     args = None
     settings = proxy.call_sync("GetSettings",
@@ -693,7 +722,7 @@ def nm_activate_device_connection(dev_name, con_uuid):
 
         device_path = device.unpack()[0]
 
-    con_path = _find_settings(con_uuid, 'connection', 'uuid')
+    con_path = _find_settings(con_uuid, 'connection', 'uuid')[0]
 
     args = GLib.Variant('(ooo)', (con_path, device_path, "/"))
     nm_proxy = _get_proxy()
@@ -754,9 +783,11 @@ def nm_update_settings_of_device(name, new_values):
        UnknownDeviceError - device was not found
        SettingsNotFoundError - settings were not found (eg for "wlan0")
     """
-    settings_path = _device_settings(name)
-    if not settings_path:
+    settings_paths = _device_settings(name)
+    if not settings_paths:
         raise SettingsNotFoundError(name)
+    else:
+        settings_path = settings_paths[0]
     return _update_settings(settings_path, new_values)
 
 def _update_settings(settings_path, new_values):
-- 
1.7.11.7



More information about the anaconda-patches mailing list