[node-patches] Change in ovirt-node[master]: network: Add better progress informations

fabiand at fedoraproject.org fabiand at fedoraproject.org
Tue Dec 11 20:09:43 UTC 2012


Fabian Deutsch has uploaded a new change for review.

Change subject: network: Add better progress informations
......................................................................

network: Add better progress informations

Change-Id: Ic82202726dbed9c7369cb28ffb5eb092a2f8127b
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/src/ovirt/node/config/defaults.py
M scripts/tui/src/ovirt/node/config/network.py
M scripts/tui/src/ovirt/node/setup/network_page.py
M scripts/tui/src/ovirt/node/utils/__init__.py
M scripts/tui/src/ovirt/node/utils/network.py
5 files changed, 208 insertions(+), 92 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/73/9973/1

diff --git a/scripts/tui/src/ovirt/node/config/defaults.py b/scripts/tui/src/ovirt/node/config/defaults.py
index 37e2c8b..b6084eb 100644
--- a/scripts/tui/src/ovirt/node/config/defaults.py
+++ b/scripts/tui/src/ovirt/node/config/defaults.py
@@ -303,24 +303,30 @@
         FIXME this should be rewritten o allow more fine grained progress
         informations
         """
-        iface = self.retrieve()["iface"]
 
         class ConfigureNIC(utils.Transaction.Element):
             title = "Configuring NIC"
 
             def prepare(self):
-                self.logger.debug("Psuedo prewparing ovirtnode.Network")
+                self.logger.debug("Psuedo preparing ovirtnode.Network")
 
             def commit(self):
                 from ovirtnode.network import Network as oNetwork
                 net = oNetwork()
-                if iface:
-                    net.configure_interface()
+                net.configure_interface()
                 net.save_network_configuration()
+                #utils.AugeasWrapper.force_reload()
+
+        class ReloadNetworkConfiguration(utils.Transaction.Element):
+            title = "Reloading network configuration"
+
+            def commit(self):
                 utils.AugeasWrapper.force_reload()
 
-        tx = utils.Transaction("Saving network configuration")
+
+        tx = utils.Transaction("Applying new network configuration")
         tx.append(ConfigureNIC())
+        tx.append(ReloadNetworkConfiguration())
         return tx
 
 
@@ -988,8 +994,8 @@
     @NodeConfigFileSection.map_and_update_defaults_decorator
     def update(self, pwauth, num_bytes, disable_aesni):
         valid.Boolean()(pwauth)
-        valid.Number()(num_bytes)
-        valid.Boolean()(disable_aesni)
+        (valid.Number() | valid.Empty(or_none=True))(num_bytes)
+        (valid.Boolean() | valid.Empty(or_none=True))(disable_aesni)
         return {
                 "OVIRT_SSH_PWAUTH": "yes" if pwauth else None,
                 "OVIRT_DISABLE_AES_NI": "true" if disable_aesni else None
@@ -1012,22 +1018,25 @@
         ssh = utils.security.Ssh()
 
         class ConfigurePasswordAuthentication(utils.Transaction.Element):
+            title = "Configuring SSH password authentication"
             def commit(self):
                 ssh.password_authentication(pwauth)
 
         class ConfigureStrongRNG(utils.Transaction.Element):
+            title = "Configuring strong RNG"
             def commit(self):
                 ssh.strong_rng(num_bytes)
 
         class ConfigureAESNI(utils.Transaction.Element):
+            title = "Configuring AES NI"
             def commit(self):
                 ssh.disable_aesni(disable_aesni)
 
         tx = utils.Transaction("Configuring SSH")
-        if pwauth:
+        if pwauth in [True, False]:
             tx.append(ConfigurePasswordAuthentication())
         if num_bytes:
             tx.append(ConfigureStrongRNG())
-        if disable_aesni:
+        if disable_aesni in [True, False]:
             tx.append(ConfigureAESNI())
         return tx
diff --git a/scripts/tui/src/ovirt/node/config/network.py b/scripts/tui/src/ovirt/node/config/network.py
index 415b419..d280abc 100644
--- a/scripts/tui/src/ovirt/node/config/network.py
+++ b/scripts/tui/src/ovirt/node/config/network.py
@@ -40,6 +40,7 @@
         A dict of (nic-name, nic-infos-dict)
     """
     LOGGER.debug("Getting configuration for '%s'" % iface)
+    Augeas.force_reload()
 
     info = {}
 
diff --git a/scripts/tui/src/ovirt/node/setup/network_page.py b/scripts/tui/src/ovirt/node/setup/network_page.py
index 2460a45..4cd9d91 100644
--- a/scripts/tui/src/ovirt/node/setup/network_page.py
+++ b/scripts/tui/src/ovirt/node/setup/network_page.py
@@ -145,11 +145,24 @@
         self.logger.debug("Building NIC details dialog")
         # Populate model with nic specific informations
         iface = self._model["nics"]
+
         self.logger.debug("Getting informations for NIC details page")
         live = ovirt.node.utils.network.node_nics()[iface]
         cfg = defaults.Network().retrieve()
 
-        self.logger.debug(cfg)
+        self.logger.debug("live: %s" % live)
+        self.logger.debug("cfg: %s" % cfg)
+
+        ipaddr, netmask, gateway, vlanid = (cfg["ipaddr"], cfg["netmask"],
+                                            cfg["gateway"], cfg["vlanid"])
+
+        if cfg["bootproto"] == "dhcp":
+            nic = utils.network.NIC(live["bridge"])
+            routes = utils.network.Routes()
+            ipaddr, netmask, gateway, vlanid = (nic.ipv4_address().items() +
+                                               (routes.default(),) +
+                                               (nic.vlanid(),))
+
         self._model.update({
             "dialog.nic.iface": live["name"],
             "dialog.nic.driver": live["driver"],
@@ -160,11 +173,13 @@
             "dialog.nic.hwaddress": live["hwaddr"],
 
             "dialog.nic.ipv4.bootproto": cfg["bootproto"],
-            "dialog.nic.ipv4.address": cfg["ipaddr"] or "",
-            "dialog.nic.ipv4.netmask": cfg["netmask"] or "",
-            "dialog.nic.ipv4.gateway": cfg["gateway"] or "",
-            "dialog.nic.vlanid": cfg["vlanid"] or "",
+            "dialog.nic.ipv4.address": ipaddr,
+            "dialog.nic.ipv4.netmask": netmask,
+            "dialog.nic.ipv4.gateway": gateway,
+            "dialog.nic.vlanid": vlanid,
         })
+
+        self.logger.debug("model: %s" % self._model)
 
         padd = lambda l: l.ljust(14)
         dialog = self._build_dialog("dialog.nic", "NIC Details: %s" % iface, [
@@ -317,13 +332,17 @@
         time.sleep(3)
         d.close()
 
+        # Behaves like a page reload
+        return self.ui_content()
+
     def _configure_nic(self, bootproto, ipaddr, netmask, gateway, vlanid):
         vlanid = vlanid or None
         model = defaults.Network()
         iface = self._model["dialog.nic.iface"]
         if bootproto == "none":
             self.logger.debug("Configuring no networking")
-            model.update(None, None, None, None, None, None)
+            name = iface + "-DISABLED"
+            model.update(name, None, None, None, None, None)
         elif bootproto == "dhcp":
             self.logger.debug("Configuring dhcp")
             model.update(iface, "dhcp", None, None, None, vlanid)
diff --git a/scripts/tui/src/ovirt/node/utils/__init__.py b/scripts/tui/src/ovirt/node/utils/__init__.py
index c42342b..897298c 100644
--- a/scripts/tui/src/ovirt/node/utils/__init__.py
+++ b/scripts/tui/src/ovirt/node/utils/__init__.py
@@ -41,6 +41,12 @@
 #        self._aug = _augeas.Augeas() # Is broken
         self._aug.set("/augeas/save/copy_if_rename_fails", "")
 
+    @staticmethod
+    def force_reload():
+        """Needs to be called when files were changed on-disk without using Aug
+        """
+        AugeasWrapper._aug.load()
+
     def get(self, p, strip_quotes=False):
         v = self._aug.get(p)
         if v and strip_quotes:
@@ -63,6 +69,9 @@
     def match(self, p):
         return self._aug.match(p)
 
+    def load(self):
+        return self._aug.load()
+
     def set_many(self, new_dict, basepath=""):
         """Set's many augpaths at once
 
diff --git a/scripts/tui/src/ovirt/node/utils/network.py b/scripts/tui/src/ovirt/node/utils/network.py
index 72bc868..b765ef0 100644
--- a/scripts/tui/src/ovirt/node/utils/network.py
+++ b/scripts/tui/src/ovirt/node/utils/network.py
@@ -18,23 +18,23 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.  A copy of the GNU General Public License is
 # also available at http://www.gnu.org/copyleft/gpl.html.
+from ovirt.node import base
+from socket import inet_ntoa
+from struct import pack
+import glob
+import gudev
+import logging
+import os.path
+import ovirt.node.config.network
+import ovirt.node.utils.fs
+import ovirt.node.utils.process as process
+import re
 
 """
 Some convenience functions related to networking
 """
 
-
-import os.path
-import logging
-import re
-import glob
-
-import ovirt.node.utils.process as process
-import ovirt.node.utils.fs
-import ovirt.node.config.network
-
 LOGGER = logging.getLogger(__name__)
-
 
 #
 # Try to use NM if available
@@ -49,7 +49,6 @@
 except Exception as e:
     LOGGER.warning("NetworkManager support disabled: " +
                    "NM Client not found (%s)" % e)
-import gudev
 
 
 class UnknownNicError(Exception):
@@ -78,6 +77,8 @@
 
 def iface_information(iface, with_slow=True):
     """Retuns all system NICs (via udev)
+
+    FIXME move into NIC
 
     Args:
         nics: List of NIC names
@@ -143,11 +144,12 @@
 def _slow_iface_information(iface):
     info = {}
 
+    nic = NIC(iface)
     # Current IP addresses
-    info["addresses"] = nic_ip_addresses(iface)
+    info["addresses"] = nic.ip_addresses()
 
     # Current link state
-    info["link_detected"] = nic_link_detected(iface)
+    info["link_detected"] = nic.has_link()
 
     return info
 
@@ -263,6 +265,8 @@
         if info["is_vlan"]:
             dst = info["vlan_parent"]
         for k in ["bootproto", "ipaddr", "netmask", "gateway"]:
+            LOGGER.debug("Merging cfg %s from bridge %s into device %s" % (k,
+                                                               bridge, slave))
             node_infos[dst][k] = bridge_cfg[k] if k in bridge_cfg else None
 
     LOGGER.debug("Node NICs: %s" % node_infos)
@@ -289,83 +293,133 @@
     return bridges[0] if len(bridges) else None
 
 
-def nic_link_detected(iface):
-    """Determin if L1 is up on a given interface
+class NIC(base.Base):
+    def __init__(self, iface):
+        self.iface = iface
+        super(NIC, self).__init__()
 
-    >>> nic_link_detected("lo")
-    True
+    def has_link(self):
+        """Determin if L1 is up on a given interface
 
-    >>> iface = all_ifaces()[0]
-    >>> cmd = "ip link set dev {dev} up ; ip link show {dev}".format(dev=iface)
-    >>> has_carrier = "LOWER_UP" in process.pipe(cmd, without_retval=True)
-    >>> has_carrier == nic_link_detected(iface)
-    True
+        >>> NIC("lo").has_link()
+        True
 
-    Args:
-        iface: The interface to be checked
-    Returns:
-        True if L1 (the-link-is-up) is detected (depends on driver support)
-    """
+        >>> iface = all_ifaces()[0]
+        >>> cmd = "ip link set dev {dev} up ;"
+        >>> cmd += "ip link show {dev}".format(dev=iface)
+        >>> has_carrier = "LOWER_UP" in process.pipe(cmd, without_retval=True)
+        >>> has_carrier == NIC(iface).has_link()
+        True
 
-    if iface not in all_ifaces():
-        raise UnknownNicError("Unknown network interface: '%s'" % iface)
+        Args:
+            iface: The interface to be checked
+        Returns:
+            True if L1 (the-link-is-up) is detected (depends on driver support)
+        """
 
-    if is_nm_managed(iface):
+        if self.iface not in all_ifaces():
+            raise UnknownNicError("Unknown network interface: '%s'" %
+                                  self.iface)
+
+        if is_nm_managed(self.iface):
+            try:
+                device = _nm_client.get_device_by_iface(self.iface)
+                if device:
+                    return device.get_carrier()
+            except:
+                LOGGER.debug("Failed to retrieve carrier with NM")
+
+        # Fallback
+        has_carrier = False
         try:
-            device = _nm_client.get_device_by_iface(iface)
-            if device:
-                return device.get_carrier()
+            with open("/sys/class/net/%s/carrier" % self.iface) as c:
+                content = c.read()
+                has_carrier = "1" in content
         except:
-            LOGGER.debug("Failed to retrieve carrier with NM")
+            LOGGER.debug("Carrier down for %s" % self.iface)
+        return has_carrier
 
-    # Fallback
-    has_carrier = False
-    try:
-        with open("/sys/class/net/%s/carrier" % iface) as c:
-            content = c.read()
-            has_carrier = "1" in content
-    except:
-        LOGGER.debug("Carrier down for %s" % iface)
-    return has_carrier
+    def ipv4_address(self):
+        return self.ip_addresses(["inet"])["inet"]
 
+    def ipv6_address(self):
+        return self.ip_addresses(["inet6"])["inet6"]
 
-def nic_ip_addresses(iface, families=["inet", "inet6"]):
-    """Get IP addresses for an iface
+    def ip_addresses(self, families=["inet", "inet6"]):
+        """Get IP addresses for an iface
 
-    FIXME NM client.get_device_by_iface(iface).get_ip?_config()
-    """
-    if iface not in all_ifaces():
-        raise UnknownNicError("Unknown network interface: '%s'" % iface)
+        FIXME NM client.get_device_by_iface(iface).get_ip?_config()
+        """
+        if self.iface not in all_ifaces():
+            raise UnknownNicError("Unknown network interface: '%s'" %
+                                  self.iface)
 
-    addresses = {f: None for f in families}
+        addresses = {f: (None, None) for f in families}
 
-    if False:
-        # FIXME to hackish to convert addr - is_nm_managed(iface):
-        device = _nm_client.get_device_by_iface(iface)
-        LOGGER.debug("Got '%s' for '%s'" % (device, iface))
-        if device:
-            for family, cfgfunc, sf in [
-                ("inet", device.get_ip4_config, socket.AF_INET),
-                ("inet6", device.get_ip6_config, socket.AF_INET6)]:
-                cfg = cfgfunc()
-                if not cfg:
-                    LOGGER.debug("No %s configuration for %s" % (family,
-                                                                 iface))
-                    break
-                addrs = cfg.get_addresses()
-                addr = addrs[0].get_address() if len(addrs) > 0 else None
-                addresses[family] = _nm_address_to_str(sf, addr) if addr \
-                                                                 else None
+        if False:
+            # FIXME to hackish to convert addr - is_nm_managed(iface):
+            device = _nm_client.get_device_by_iface(self.iface)
+            LOGGER.debug("Got '%s' for '%s'" % (device, self.iface))
+            if device:
+                for family, cfgfunc, sf in [
+                    ("inet", device.get_ip4_config, socket.AF_INET),
+                    ("inet6", device.get_ip6_config, socket.AF_INET6)]:
+                    cfg = cfgfunc()
+                    if not cfg:
+                        LOGGER.debug("No %s configuration for %s" % (family,
+                                                                 self.iface))
+                        break
+                    addrs = cfg.get_addresses()
+                    addr = addrs[0].get_address() if len(addrs) > 0 else None
+                    addresses[family] = _nm_address_to_str(sf, addr) if addr \
+                                                                     else None
+            return addresses
+
+        # Fallback
+        cmd = "ip -o addr show {iface}".format(iface=self.iface)
+        for line in process.pipe(cmd, without_retval=True).split("\n"):
+            token = re.split("\s+", line)
+            if re.search("\sinet[6]?\s", line):
+                addr, mask = token[3].split("/")
+                family = token[2]
+                if family == "inet":
+                    mask = calcDottedNetmask(mask)
+                addresses[family] = IPAddress(addr, mask)
+
         return addresses
 
-    # Fallback
-    cmd = "ip -o addr show {dev}".format(dev=iface)
-    for line in process.pipe(cmd, without_retval=True).split("\n"):
-        token = re.split("\s+", line)
-        if re.search("\sinet[6]?\s", line):
-            addresses[token[2]] = token[3]
+    def vlanid(self):
+        vlanids = []
+        vcfg = "/proc/net/vlan/config"
+        pat = re.compile("([0-9]+)\s*\|\s*%s$" % self.iface)
+        if os.path.exists(vcfg):
+            try:
+                with open(vcfg) as f:
+                    for line in f:
+                        r = pat.search(line)
+                        if r:
+                            vlanids.append(r.groups[0])
+            except IOError as e:
+                self.logger.warning("Could not read vlan config: %s" %
+                                    e.message)
+        if len(vlanids) > 1:
+            self.logger.info("Found more than one (expected) vlan: %s" %
+                             vlanids)
+        return vlanids[0] if vlanids else None
 
-    return addresses
+
+class Routes(base.Base):
+    def default(self):
+        """Return the default gw of the system
+        """
+        # Fallback
+        gw = None
+        cmd = "ip route list"
+        for line in process.pipe(cmd, without_retval=True).split("\n"):
+            token = re.split("\s+", line)
+            if line.startswith("default via"):
+                gw = token[2]
+        return gw
 
 
 def _nm_address_to_str(family, ipaddr):
@@ -382,10 +436,11 @@
     iface = iface or node_bridge()
     addresses = []
     if iface:
-        addresses = nic_ip_addresses(iface)
+        nic = NIC(iface)
+        addresses = nic.ip_addresses()
         has_address = any([a != None for a in addresses.values()])
 
-        if nic_link_detected(iface):
+        if nic.has_link():
             status = "Connected (Link only, no IP)"
         if has_address:
             status = "Connected"
@@ -393,3 +448,26 @@
     summary = (status, iface, addresses)
     LOGGER.debug(summary)
     return summary
+
+
+def calcDottedNetmask(mask):
+    """
+    http://code.activestate.com/recipes/576483/
+    >>> calcDottedNetmask(24)
+    '255.255.255.0'
+    """
+    mask = int(str(mask))
+    bits = 0xffffffff ^ (1 << 32 - mask) - 1
+    return inet_ntoa(pack('>I', bits))
+
+
+class IPAddress(base.Base):
+    def __init__(self, address, netmask):
+        self.address = address
+        self.netmask = netmask
+
+    def __str__(self):
+        return str(self.address)
+
+    def items(self):
+        return (self.address, self.netmask)


--
To view, visit http://gerrit.ovirt.org/9973
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic82202726dbed9c7369cb28ffb5eb092a2f8127b
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Fabian Deutsch <fabiand at fedoraproject.org>



More information about the node-patches mailing list