[PATCH 4/5] Bonding support: GUI - generate kickstart network command for bonds (#906263)

Radek Vykydal rvykydal at redhat.com
Thu Mar 7 13:47:09 UTC 2013


---
 pyanaconda/network.py               | 77 +++++++++++++++++++++++++++++++++----
 pyanaconda/ui/gui/spokes/network.py | 10 ++++-
 2 files changed, 77 insertions(+), 10 deletions(-)

diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index 06136e1..626e2c0 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -195,17 +195,22 @@ def logIfcfgFile(path, message=""):
         content = "file not found"
     ifcfglog.debug("%s%s:\n%s" % (message, path, content))
 
-def logIfcfgFiles(message=""):
-    ifcfglog.debug("content of files (%s):" % message)
-    for name in os.listdir(netscriptsDir):
+def _ifcfg_files(directory):
+    rv = []
+    for name in os.listdir(directory):
         if name.startswith("ifcfg-"):
-            if name == 'ifcfg-lo':
+            if name == "ifcfg-lo":
                 continue
-            path = os.path.join(netscriptsDir, name)
-            f = open(path, 'r')
+            rv.append(name)
+    return rv
+
+def logIfcfgFiles(message=""):
+    ifcfglog.debug("content of files (%s):" % message)
+    for name in _ifcfg_files(netscriptsDir):
+        path = os.path.join(netscriptsDir, name)
+        with open(path, "r") as f:
             content = f.read()
-            f.close()
-            ifcfglog.debug("%s:\n%s" % (path, content))
+        ifcfglog.debug("%s:\n%s" % (path, content))
 
 class NetworkDevice(IfcfgFile):
 
@@ -410,6 +415,10 @@ def kickstartNetworkData(ifcfg=None, hostname=None):
     if not ifcfg and hostname:
         return handler.NetworkData(hostname=hostname, bootProto="")
 
+    # no network command for bond slaves
+    if ifcfg.get("MASTER"):
+        return None
+
     # ipv4 and ipv6
     if not ifcfg.get("ESSID"):
         kwargs["device"] = ifcfg.iface
@@ -490,8 +499,60 @@ def kickstartNetworkData(ifcfg=None, hostname=None):
             hostname != DEFAULT_HOSTNAME):
             kwargs["hostname"] = hostname
 
+    # bonding
+    # FIXME: dracut has only BOND_OPTS
+    if ifcfg.get("BONDING_MASTER") == "yes" or ifcfg.get("TYPE") == "Bond":
+        slaves = get_bond_slaves_from_ifcfgs([ifcfg.iface, ifcfg.get("UUID")])
+        if slaves:
+            kwargs["bondslaves"] = ",".join(slaves)
+        bondopts = ifcfg.get("BONDING_OPTS")
+        if bondopts:
+            sep = ","
+            if sep in bondopts:
+                sep = ";"
+            kwargs["bondopts"] = sep.join(bondopts.split())
+
     return handler.NetworkData(**kwargs)
 
+def get_bond_master_ifcfg_name(devname):
+    """Name of ifcfg file of bond device devname"""
+
+    for filename in _ifcfg_files(netscriptsDir):
+        ifcfg = NetworkDevice(netscriptsDir, filename[6:])
+        ifcfg.loadIfcfgFile()
+        # FIXME: dracut has only BOND_OPTS
+        if ifcfg.get("BONDING_MASTER") == "yes" or ifcfg.get("TYPE") == "Bond":
+            if ifcfg.get("DEVICE") == devname:
+                return filename
+
+def get_bond_slaves_from_ifcfgs(master_specs):
+    """List of slave device names of master specified by master_specs.
+
+       master_specs is a list containing device name of master (dracut)
+       and/or master's connection uuid
+    """
+    slaves = []
+
+    for filename in _ifcfg_files(netscriptsDir):
+        ifcfg = NetworkDevice(netscriptsDir, filename[6:])
+        ifcfg.loadIfcfgFile()
+        master = ifcfg.get("MASTER")
+        if master in master_specs:
+            device = ifcfg.get("DEVICE")
+            if device:
+                slaves.append(device)
+            else:
+                hwaddr = ifcfg.get("HWADDR")
+                for devname in nm.nm_devices():
+                    try:
+                        h = nm.nm_device_property(devname, "PermHwAddress")
+                    except nm.PropertyNotFoundError:
+                        pass
+                    if h.upper() == hwaddr.upper():
+                        slaves.append(devname)
+                        break
+    return slaves
+
 def ifaceForHostIP(host):
     route = iutil.execWithCapture("ip", [ "route", "get", "to", host ])
     if not route:
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index f1133cf..6f646ec 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -42,7 +42,7 @@ from pyanaconda.ui.gui.categories.software import SoftwareCategory
 from pyanaconda.ui.gui.hubs.summary import SummaryHub
 from pyanaconda.ui.gui.utils import gtk_call_once
 
-from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, logIfcfgFiles, update_hostname_data, sanityCheckHostname, getHostname, DEFAULT_HOSTNAME
+from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, logIfcfgFiles, update_hostname_data, sanityCheckHostname, getHostname, DEFAULT_HOSTNAME, get_bond_master_ifcfg_name
 from pyanaconda.nm import nm_activated_devices
 
 from gi.repository import GLib, GObject, Pango, Gio, NetworkManager, NMClient
@@ -1046,6 +1046,8 @@ class NetworkSpoke(NormalSpoke):
         hostname = self.network_control_box.hostname
         update_hostname_data(self.data, hostname)
 
+        log.debug("network: apply ksdata %s" % self.data.network)
+
     @property
     def completed(self):
         # TODO: check also if source requires updates when implemented
@@ -1170,6 +1172,8 @@ class NetworkStandaloneSpoke(StandaloneSpoke):
         hostname = self.network_control_box.hostname
         update_hostname_data(self.data, hostname)
 
+        log.debug("network: apply ksdata %s" % self.data.network)
+
         self._now_available = self.completed
 
         log.debug("network standalone spoke (apply) payload: %s completed: %s" % (self.payload.baseRepo, self._now_available))
@@ -1226,6 +1230,8 @@ def getKSNetworkData(device):
         ap = device.get_active_access_point()
         if ap:
             ifcfg_suffix = ap.get_ssid()
+    elif device.get_device_type() == NetworkManager.DeviceType.BOND:
+        ifcfg_suffix = get_bond_master_ifcfg_name(device.get_iface())[6:]
 
     if ifcfg_suffix:
         ifcfg_suffix = ifcfg_suffix.replace(' ', '_')
@@ -1236,7 +1242,7 @@ def getKSNetworkData(device):
             log.debug("getKSNetworkData %s: %s" % (ifcfg_suffix, e))
             return None
         retval = kickstartNetworkData(ifcfg=device_cfg)
-        if device.get_iface() in nm_activated_devices():
+        if retval and device.get_iface() in nm_activated_devices():
             retval.activate = True
 
     return retval
-- 
1.7.11.7



More information about the anaconda-patches mailing list