[PATCH rhel6-branch] (v2) Support bonding in %pre section (#971961)

Radek Vykydal rvykydal at redhat.com
Tue Oct 8 13:08:58 UTC 2013


Changes in this version:
- waiting for bond device: poll for device existence every 1s instead of sleep(2)
- disconnecting of slaves: use dbus method instead of writing NM_CONTROLLED=no
  to ifcfg file
- wait for bond device activation (instead of waiting for nm to be connected
  which returns immediately if another device is active)

Based on patch by Masahiro Matsuya

Resolves: rhbz#971961
---
 kickstart.py | 43 +++++++++++++++++++++++++++++++++++++++----
 network.py   | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/kickstart.py b/kickstart.py
index 1e9b529..1c113a8 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -684,13 +684,36 @@ class NetworkData(commands.network.RHEL6_NetworkData):
             anaconda.id.network.setHostname(self.hostname)
             anaconda.id.network.overrideDHCPhostname = True
 
+        activate_new_device = False
         if not dev:
-            if self.hostname:
+            if self.bondslaves:
+                if not self.activate:
+                    log.info("bond %s not configured in stage 2, only activation supported, please use --activate option" % device)
+                    return
+                activate_new_device = True
+                dev = anaconda.id.network.enableBondingDevice(device)
+                dev.set(("BONDING_OPTS", self.bondopts))
+                slaves = self.bondslaves.split(',')
+                for slave in slaves:
+                    slavedev = devices.get(slave, None)
+                    if slavedev:
+                        # disconnect the slave
+                        anaconda.id.network.disconnectDevice(slavedev.iface)
+
+                        mac = slavedev.get('HWADDR')
+                        uuid = slavedev.get('UUID')
+                        slavedev.clear()
+                        slavedev.set(("DEVICE", slave))
+                        if mac:
+                            slavedev.set(("HWADDR", mac))
+                        if uuid:
+                            slavedev.set(("UUID", uuid))
+                        slavedev.set(("SLAVE", "yes"))
+                        slavedev.set(("MASTER", device))
+                        slavedev.set(("ONBOOT", "yes"))
+            elif self.hostname:
                 # Only set hostname
                 return
-            elif self.bondslaves:
-                log.info("bond %s not configured, only supported for devices activated during installation" % device)
-                return
             else:
                 raise KickstartValueError, formatErrorMsg(self.lineno, msg="The provided network interface %s does not exist" % device)
 
@@ -743,6 +766,18 @@ class NetworkData(commands.network.RHEL6_NetworkData):
         if self.nodefroute:
             dev.set (("DEFROUTE", "no"))
 
+        if activate_new_device:
+            log.info("Bringing up network device %s in stage2 kickstart ..." %
+                     dev.iface)
+            dev.set (("onboot", "yes"))
+            anaconda.id.network.write()
+            if not anaconda.id.network.waitForDevice(dev.iface):
+                log.info("Can't find bond device %s")
+                return
+            failed_ifaces = anaconda.id.network.waitForDevicesActivation([dev.iface])
+            log.info("Activation %s" % ('succeeded' if not failed_ifaces else 'failed',))
+            return
+
         needs_net = (anaconda.methodstr and
                      (anaconda.methodstr.startswith("http:") or
                       anaconda.methodstr.startswith("ftp:") or
diff --git a/network.py b/network.py
index 523ef6b..29f17c4 100644
--- a/network.py
+++ b/network.py
@@ -642,6 +642,18 @@ class Network:
                     log.warning("autoconnectFCoEDevices: %s file not found" %
                                 device.path)
 
+    def enableBondingDevice(self, devName, instPath=''):
+        dev = NetworkDevice(instPath + netscriptsDir, devName)
+        self.netdevices[devName] = dev
+        dev.set(("DEVICE", devName))
+        dev.set(("TYPE", "Bond"))
+        dev.set(("NM_CONTROLLED", "yes"))
+        if not os.access(dev.path, os.R_OK):
+            f = open(dev.path, "w")
+            f.close()
+        dev.writeIfcfgFile()
+        return dev
+
     def hasActiveIPoIBDevice(self):
         active_devs = getActiveNetDevs()
         for devName, device in self.netdevices.items():
@@ -734,6 +746,15 @@ class Network:
                 f.write("options ipv6 disable=1\n")
                 f.close()
 
+    def waitForDevice(self, device, timeout=CONNECTION_TIMEOUT):
+        props = isys.getDeviceProperties(device)
+        i = 0
+        while not props and i < timeout:
+            props = isys.getDeviceProperties(device)
+            i += 1
+            time.sleep(1)
+        return bool(props)
+
     def waitForDevicesActivation(self, devices):
         waited_devs_props = {}
 
@@ -795,6 +816,23 @@ class Network:
         self.write()
         return self.waitForConnection()
 
+    def disconnectDevice(self, devname):
+        bus = dbus.SystemBus()
+        nm = bus.get_object(isys.NM_SERVICE, isys.NM_MANAGER_PATH)
+        device_paths = nm.get_dbus_method("GetDevices")()
+        for device_path in device_paths:
+            device = bus.get_object(isys.NM_SERVICE, device_path)
+            device_props_iface = dbus.Interface(device, isys.DBUS_PROPS_IFACE)
+            iface = str(device_props_iface.Get(isys.NM_DEVICE_IFACE, "Interface"))
+            if iface == devname:
+                try:
+                    device.get_dbus_method("Disconnect")()
+                except dbus.DBusException as e:
+                    log.debug("disconnectDevice %s: %s" % (devname, e))
+                    return False
+                return True
+        return False
+
     # get a kernel cmdline string for dracut needed for access to host host
     def dracutSetupArgs(self, networkStorageDevice):
         netargs=set()
-- 
1.7.11.7



More information about the anaconda-patches mailing list