[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH rhel6-branch] Control all devs by NM by default + filtering (iSCSI, FCoE) (#606745)



* All devices are set to NM_CONTROLLED in Network.__init__.
  This solves the issue that for media installs without network
  devices were not controlled by NM and thus not configurable
  with nm-applet after install (the bug).

* For devices used for FCoE and iSCSI NM_CONTROLLED is modified
  later (after storage initialization and FCoE/iSCSI setting)
  in two places:

  - in dialog run before nm-c-e (see attached screenshot):
    - FCoE devices are not controlled and are grayed-out
      so that they are not accessible in nm-c-e.
    - iSCSI are controlled and grayed-out (toggle to not
      controlled would cause connection rupture) - these devices
      are accessible in nm-c-e

  - before writing ifcfg files to installed system
    - FCoE devices are set to not controlled
    - iSCSI devices *backing root* are set to not controlled
      (according to Dan Williams this may not be longer necessary,
      I'll look at it and try, see.
      https://bugzilla.redhat.com/show_bug.cgi?id=597206#c17
      for details)

  This change required splitting of isStorageDevice into three
  finer functions (usedByFCoE, usedBy..., ...). Also note that
  iSCSI case was fixed to count only devices actually used in route
  to the target - code from dracutSetupString moved into function
  ifaceForHostIP is used, as Hans suggested.
---
 gui.py            |   16 ++++-------
 iw/network_gui.py |   75 ++++++++++++++++++++++++++++++++++-------------------
 network.py        |   69 ++++++++++++++++++++++++++++++++++--------------
 3 files changed, 103 insertions(+), 57 deletions(-)

diff --git a/gui.py b/gui.py
index 88942d3..c148d27 100755
--- a/gui.py
+++ b/gui.py
@@ -955,7 +955,6 @@ class InstallInterface(InstallInterfaceBase):
         pass
 
 
-    # TODORV: handle one device case - don't ask
     # just_setup is used for [Configure Network] button
     def enableNetwork(self, just_setup=False):
 
@@ -967,15 +966,12 @@ class InstallInterface(InstallInterfaceBase):
 
         networkEnabled = False
         while not networkEnabled:
-            if just_setup and len(self.anaconda.id.network.netdevices) <= 1:
-                nm_controlled_devices = self.anaconda.id.network.netdevices.keys()
-                install_device = None
-            else:
-                choice = selectNetDevicesDialog(self.anaconda.id.network,
-                                                select_install_device=(not just_setup))
-                if not choice:
-                    break
-                nm_controlled_devices, install_device = choice
+
+            choice = selectNetDevicesDialog(self.anaconda,
+                                            select_install_device=(not just_setup))
+            if not choice:
+                break
+            nm_controlled_devices, install_device = choice
 
             # update ifcfg files for nm-c-e
             self.anaconda.id.network.setNMControlledDevices(nm_controlled_devices)
diff --git a/iw/network_gui.py b/iw/network_gui.py
index 18c16f7..00aa782 100644
--- a/iw/network_gui.py
+++ b/iw/network_gui.py
@@ -123,8 +123,9 @@ def runNMCE(anaconda=None, blocking=True):
         else:
             gobject.child_watch_add(proc.pid, NMCEExited, data=anaconda, priority=gobject.PRIORITY_DEFAULT)
 
-def selectNetDevicesDialog(network, select_install_device=True):
+def selectNetDevicesDialog(anaconda, select_install_device=True):
 
+    network = anaconda.id.network
     netdevs = network.netdevices
     devs = netdevs.keys()
     devs.sort()
@@ -155,10 +156,14 @@ def selectNetDevicesDialog(network, select_install_device=True):
         ksdevice = network.getKSDevice()
         if ksdevice:
             ksdevice = ksdevice.get('DEVICE')
-        selected_interface_idx = 0
+        preselected = None
 
-        for idx, dev in enumerate(devs):
+        for dev in devs:
+            if netdevs[dev].usedByFCoE(anaconda):
+                continue
             i = store.append(None)
+            if not preselected:
+                preselected = i
 
             desc = netdevs[dev].description
             if desc:
@@ -172,21 +177,24 @@ def selectNetDevicesDialog(network, select_install_device=True):
                 desc = "%s - %s" %(desc, hwaddr,)
 
             if ksdevice and ksdevice == dev:
-                selected_interface_idx = idx
+                preselected = i
 
             store[i] = (desc, dev)
 
-        # TODORV: simplify to use just indexes
-        combo.set_active(selected_interface_idx)
-
-        def installDevChanged(combo, dev_check_buttons):
-            active = combo.get_active()
-            for idx, (dev, cb) in enumerate(dev_check_buttons):
-                if idx == active:
-                    cb.set_active(True)
-                    cb.set_sensitive(False)
+        combo.set_active_iter(preselected)
+
+        def installDevChanged(combo, check_buttons):
+            install_dev = combo.get_model().get_value(combo.get_active_iter(), 1)
+            for dev, cb, forced_value in check_buttons:
+                if forced_value is None:
+                    if dev == install_dev:
+                        cb.set_active(True)
+                        cb.set_sensitive(False)
+                    else:
+                        cb.set_sensitive(True)
                 else:
-                    cb.set_sensitive(True)
+                    cb.set_active(forced_value)
+                    cb.set_sensitive(False)
 
         dialog.vbox.pack_start(combo)
 
@@ -198,23 +206,36 @@ def selectNetDevicesDialog(network, select_install_device=True):
     table.set_row_spacings(5)
     table.set_col_spacings(5)
 
-    dev_check_buttons = []
+    check_buttons = []
     for i, dev in enumerate(devs):
-        cb = gtk.CheckButton(dev)
-        # TODORV: We want all devices controlled by nm by default,
-        # but we might want to add storage net devices filtering here
-        #if not (netdevs[dev].get("NM_CONTROLLED") == "no"):
-        cb.set_active(True)
+
+        forced_value = None
+        value = netdevs[dev].get("NM_CONTROLLED") != "no"
+        label = dev
+
+        if netdevs[dev].usedByFCoE(anaconda):
+            forced_value = False
+            value = forced_value
+            label += ' (used by FCoE)'
+
+        if netdevs[dev].usedByISCSI(anaconda):
+            forced_value = True
+            value = forced_value
+            label += ' (used by iSCSI)'
+
+        cb = gtk.CheckButton(label)
+        cb.set_active(value)
+        if forced_value is not None:
+            cb.set_sensitive(False)
+
         table.attach(cb, 0, 1, i, i+1, gtk.FILL, gtk.FILL)
-        dev_check_buttons.append([dev, cb])
+        check_buttons.append([dev, cb, forced_value])
 
     dialog.vbox.pack_start(table)
 
     if select_install_device:
-        selected_dev_cb = dev_check_buttons[selected_interface_idx][1]
-        selected_dev_cb.set_active(True)
-        selected_dev_cb.set_sensitive(False)
-        combo.connect("changed", installDevChanged, dev_check_buttons)
+        installDevChanged(combo, check_buttons)
+        combo.connect("changed", installDevChanged, check_buttons)
 
     dialog.show_all()
 
@@ -228,8 +249,8 @@ def selectNetDevicesDialog(network, select_install_device=True):
             active = combo.get_active_iter()
             install_device = combo.get_model().get_value(active, 1)
 
-        nm_controlled_devices = [dev for (dev, cb) in dev_check_buttons if
-                                 cb.get_active()]
+        nm_controlled_devices = [dev for (dev, cb, forced_value) in check_buttons
+                                 if cb.get_active()]
 
         retval = (nm_controlled_devices, install_device)
 
diff --git a/network.py b/network.py
index 02f1ff2..f6b09e7 100644
--- a/network.py
+++ b/network.py
@@ -307,17 +307,34 @@ class NetworkDevice(IfcfgFile):
         lf.close()
         f.close()
 
-    def isStorageDevice(self, anaconda):
+    def usedByFCoE(self, anaconda):
+        return self.iface == "eth1"
         import storage
-        rootdev = anaconda.id.storage.rootDevice
-        # FIXME: use d.host_address to only add "NM_CONTROLLED=no"
-        # for interfaces actually used enroute to the device
         for d in anaconda.id.storage.devices:
-            if isinstance(d, storage.devices.NetworkStorageDevice) and\
-               (rootdev.dependsOn(d) or d.nic == self.iface):
+            if (isinstance(d, storage.devices.NetworkStorageDevice) and
+                d.nic == self.iface):
                 return True
         return False
 
+    def usedByRootOnISCSI(self, anaconda):
+        import storage
+        rootdev = anaconda.id.storage.rootDevice
+        for d in anaconda.id.storage.devices:
+            if (isinstance(d, storage.devices.NetworkStorageDevice) and
+                d.host_address and
+                rootdev.dependsOn(d)):
+                if self.iface == ifaceForHostIP(d.host_address):
+                    return True
+        return False
+
+    def usedByISCSI(self, anaconda):
+        import storage
+        for d in anaconda.id.storage.devices:
+            if (isinstance(d, storage.devices.NetworkStorageDevice) and
+                d.host_address):
+                if self.iface == ifaceForHostIP(d.host_address):
+                    return True
+        return False
 
 class Network:
 
@@ -328,6 +345,12 @@ class Network:
 
         self.update()
 
+        # Set all devices to be controlled by NM by default.
+        # We can filter out storage devices only after
+        # we have device tree populated. So we do it before
+        # running nm-c-e and before writing ifcfg files to system.
+        self.setNMControlledDevices(self.netdevices.keys())
+
     def update(self):
 
         self.netdevices = {}
@@ -553,7 +576,8 @@ class Network:
 
     def disableNMForStorageDevices(self, anaconda, instPath=''):
         for devName, device in self.netdevices.items():
-            if device.isStorageDevice(anaconda):
+            if (device.usedByFCoE(anaconda) or
+                device.usedByRootOnISCSI(anaconda)):
                 dev = NetworkDevice(instPath + netscriptsDir, devName)
                 if os.access(dev.path, os.R_OK):
                     dev.loadIfcfgFile()
@@ -762,21 +786,10 @@ class Network:
             nic = networkStorageDevice.nic
         else:
             # Storage bound through ip, find out which interface leads to host
-            host = networkStorageDevice.host_address
-            route = iutil.execWithCapture("ip", [ "route", "get", "to", host ])
-            if not route:
-                log.error("Could net get interface for route to %s" % host)
-                return ""
-
-            routeInfo = route.split()
-            if routeInfo[0] != host or len(routeInfo) < 5 or \
-               "dev" not in routeInfo or routeInfo.index("dev") > 3:
-                log.error('Unexpected "ip route get to %s" reply: %s' %
-                          (host, routeInfo))
+            nic = ifaceForHostIP(networkStorageDevice.host_address)
+            if not nic:
                 return ""
 
-            nic = routeInfo[routeInfo.index("dev") + 1]
-
         if nic not in self.netdevices.keys():
             log.error('Unknown network interface: %s' % nic)
             return ""
@@ -821,3 +834,19 @@ class Network:
                 netargs += ",%s" % (','.join(options))
 
         return netargs
+
+def ifaceForHostIP(host):
+    route = iutil.execWithCapture("ip", [ "route", "get", "to", host ])
+    if not route:
+        log.error("Could not get interface for route to %s" % host)
+        return ""
+
+    routeInfo = route.split()
+    if routeInfo[0] != host or len(routeInfo) < 5 or \
+       "dev" not in routeInfo or routeInfo.index("dev") > 3:
+        log.error('Unexpected "ip route get to %s" reply: %s' %
+                  (host, routeInfo))
+        return ""
+
+    return routeInfo[routeInfo.index("dev") + 1]
+
-- 
1.6.0.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]