[node-patches] Change in ovirt-node[master]: network: Fix network layout discovery

fabiand at fedoraproject.org fabiand at fedoraproject.org
Fri Jul 5 11:13:47 UTC 2013


Fabian Deutsch has uploaded a new change for review.

Change subject: network: Fix network layout discovery
......................................................................

network: Fix network layout discovery

Previously Node conuldn't discover all allowed network layouts. This is
nowed fixed. Additionally many unittests were added to prevent
regressions.

Change-Id: Ie9e2e226b0eb060168708756825026c36e7a3330
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=980233
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M src/ovirt/node/config/defaults.py
M src/ovirt/node/utils/fs.py
M src/ovirt/node/utils/network.py
M tests/nose/network_config.py
4 files changed, 378 insertions(+), 152 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/05/16505/1

diff --git a/src/ovirt/node/config/defaults.py b/src/ovirt/node/config/defaults.py
index 26fe1f7..1e410f8 100644
--- a/src/ovirt/node/config/defaults.py
+++ b/src/ovirt/node/config/defaults.py
@@ -323,20 +323,62 @@
 
                 has_network = m["iface"] is not None
                 if has_network:
-                    topology = NetworkLayout().retrieve()["layout"]
-                    if topology == "bridged":
-                        self.__write_bridged_config()
-                    else:
-                        self.__write_direct_config()
-                else:
-                    topology = NetworkLayout().configure_direct()
+                    self.__write_config()
 
                 aug.set("/files/etc/sysconfig/network/NETWORKING",
                         "yes" if has_network else "no")
                 fs.Config().persist("/etc/sysconfig/network")
                 fs.Config().persist("/etc/hosts")
 
-            def __assign_common(self, cfg):
+            def __write_config(self):
+                m = Network().retrieve()
+
+                topology = NetworkLayout().retrieve()["layout"]
+                with_bridge = (topology == "bridged")
+
+                mbond = NicBonding().retrieve()
+
+                bridge_ifname = "br%s" % m["iface"]
+                vlan_ifname = "%s.%s" % (m["iface"], m["vlanid"])
+
+                nic_cfg = NicConfig(m["iface"])
+                nic_cfg.device = m["iface"]
+                nic_cfg.onboot = "yes"
+
+                # Only assign a hwaddr if it's not a bond
+                if mbond["name"] != m["iface"]:
+                    nic_cfg.hwaddr = NIC(m["iface"]).hwaddr
+
+                if m["vlanid"]:
+                    # Add a tagged interface
+                    vlan_cfg = NicConfig(vlan_ifname)
+                    vlan_cfg.device = vlan_ifname
+                    vlan_cfg.vlan = "yes"
+                    vlan_cfg.onboot = "yes"
+                    if with_bridge:
+                        vlan_cfg.bridge = bridge_ifname
+                    else:
+                        self.__assign_ip_config(vlan_cfg)
+                    vlan_cfg.save()
+                else:
+                    if with_bridge:
+                        nic_cfg.bridge = bridge_ifname
+                    else:
+                        # No vlan and no bridge: So assign IP to NIC
+                        self.__assign_ip_config(nic_cfg)
+
+                if with_bridge:
+                    # Add a bridge
+                    bridge_cfg = NicConfig(bridge_ifname)
+                    self.__assign_ip_config(bridge_cfg)
+                    bridge_cfg.device = bridge_ifname
+                    bridge_cfg.delay = "0"
+                    bridge_cfg.type = "Bridge"
+                    bridge_cfg.save()
+
+                nic_cfg.save()
+
+            def __assign_ip_config(self, cfg):
                 m = Network().retrieve()
                 m_dns = Nameservers().retrieve()
                 m_ipv6 = IPv6().retrieve()
@@ -364,47 +406,6 @@
                     cfg.ipv6addr = "%s/%s" % (m_ipv6["ipaddr"],
                                               m_ipv6["netmask"])
                     cfg.ipv6_defaultgw = m_ipv6["gateway"]
-
-            def __write_bridged_config(self):
-                m = Network().retrieve()
-
-                # Bridge
-                bridge_ifname = "br%s" % m["iface"]
-                bridge_cfg = NicConfig(bridge_ifname)
-                self.__assign_common(bridge_cfg)
-                bridge_cfg.device = bridge_ifname
-                bridge_cfg.delay = "0"
-                bridge_cfg.type = "Bridge"
-
-                # Now the slave
-                slave_ifname_vlan = "%s.%s" % (m["iface"],
-                                               m["vlanid"])
-                slave_ifname = slave_ifname_vlan if m["vlanid"] else m["iface"]
-                slave_cfg = NicConfig(slave_ifname)
-                slave_cfg.device = m["iface"]
-                slave_cfg.device = slave_ifname
-                slave_cfg.bridge = bridge_ifname
-                slave_cfg.hwaddr = NIC(m["iface"]).hwaddr
-                slave_cfg.vlan = "yes" if m["vlanid"] else None
-                slave_cfg.onboot = "yes"
-
-                # save()includes persisting
-                bridge_cfg.save()
-                slave_cfg.save()
-
-            def __write_direct_config(self):
-                m = Network().retrieve()
-
-                nic_ifname_vlan = "%s.%s" % (m["iface"],
-                                             m["vlanid"])
-                nic_ifname = nic_ifname_vlan if m["vlanid"] \
-                    else m["iface"]
-                nic_cfg = NicConfig(nic_ifname)
-                nic_cfg.device = nic_ifname
-                self.__assign_common(nic_cfg)
-                nic_cfg.hwaddr = NIC(m["iface"]).hwaddr
-
-                nic_cfg.save()
 
         class PersistMacNicMapping(utils.Transaction.Element):
             title = "Persist MAC-NIC Mappings"
@@ -512,6 +513,7 @@
 
                 for slave in bond["slaves"]:
                     slave_cfg = NicConfig(slave)
+                    slave_cfg.hwaddr = NIC(slave).hwaddr
                     slave_cfg.device = slave
                     slave_cfg.slave = "yes"
                     slave_cfg.master = bond["name"]
diff --git a/src/ovirt/node/utils/fs.py b/src/ovirt/node/utils/fs.py
index abb678b..da6d2d7 100644
--- a/src/ovirt/node/utils/fs.py
+++ b/src/ovirt/node/utils/fs.py
@@ -86,6 +86,7 @@
     filename = None
 
     def __init__(self, filename):
+        base.Base.__init__(self)
         self.filename = filename
 
     def read(self):
@@ -180,6 +181,8 @@
             return FakeFs.filemap[self.filename]
 
         def write(self, contents, mode=None):
+            self.logger.debug("Saving: %s" % self.filename)
+            self.logger.debug("Writing:\n%s" % contents)
             self._cond_create()
             FakeFs.filemap[self.filename] = contents
 
diff --git a/src/ovirt/node/utils/network.py b/src/ovirt/node/utils/network.py
index 30f3d09..4c8b922 100644
--- a/src/ovirt/node/utils/network.py
+++ b/src/ovirt/node/utils/network.py
@@ -18,7 +18,7 @@
 # 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, utils
+from ovirt.node import base, utils, config
 from ovirt.node.config.network import NicConfig
 from ovirt.node.utils.fs import File
 import glob
@@ -378,8 +378,8 @@
         self.slave_nic.identify(self)
 
     def __str__(self):
-        pairs = {"bridge": self.bridge_nic.ifname,
-                 "slave": self.slave_nic.ifname}
+        pairs = {"bridge": self.bridge_nic,
+                 "slave": self.slave_nic}
         return self.build_str(["ifname"], additional_pairs=pairs)
 
 
@@ -389,15 +389,16 @@
     vlan_nic = None
     parent_nic = None
 
-    def __init__(self, vnic):
+    def __init__(self, parent_nic, vlanid):
         """A unified API for tagged NICs
         Args:
             vnic: A NIC instance pointing to the tagged part of a device
         """
-        parent_ifname, _ = TaggedNIC._parent_and_vlanid_from_name(vnic.ifname)
-        super(TaggedNIC, self).__init__(parent_ifname)
-        self.vlan_nic = vnic
-        self.parent_nic = NIC(parent_ifname)
+        slave_ifname = "%s.%s" % (parent_nic.ifname, vlanid)
+        super(TaggedNIC, self).__init__(parent_nic.ifname)
+        self.vlan_nic = NIC(slave_ifname)
+        self.parent_nic = self
+        self.config = self.vlan_nic.config
 
     @staticmethod
     def _parent_and_vlanid_from_name(ifname):
@@ -453,67 +454,38 @@
 class BondedNIC(NIC):
     """A class to provide easy access to bonded NICs
     """
-    master_nic = None
-    slave_nic = None
+    slave_nics = None
 
-    def __init__(self, snic):
+    def __init__(self, master_nic, slave_nics=[]):
         """Handle snic like beeing a slave of a bond device
         """
-        master_ifname = snic.config.master
-        super(BondedNIC, self).__init__(master_ifname)
-        self.slave_nic = snic
-        self.master_nic = NIC(master_ifname)
-
-    def exists(self):
-        return self.master_nic.exists()
-
-    def is_configured(self):
-        return self.master_nic.is_configured()
-
-    def has_link(self):
-        return self.master_nic.has_link()
-
-    def ipv4_address(self):
-        return self.master_nic.ipv4_address()
-
-    def ipv6_address(self):
-        return self.master_nic.ipv6_address()
-
-    def ip_addresses(self, families=["inet", "inet6"]):
-        return self.master_nic.ip_addresses(families=families)
-
-    def is_vlan(self):
-        return self.master_nic.is_vlan()
-
-    def has_vlans(self):
-        return self.master_nic.has_vlans()
-
-    def vlanids(self):
-        return self.master_nic.vlanids()
+        super(BondedNIC, self).__init__(master_nic.ifname)
+        self.slave_nics = [NIC(n) for n in slave_nics]
 
     def identify(self):
-        self.slave_nic.identify()
+        (slave.identify() for slave in self.slave_nics)
 
     def __str__(self):
-        pairs = {"slave": self.slave_nic.ifname,
-                 "master": self.master_nic.ifname}
-        return self.build_str(["ifname"], additional_pairs=pairs)
+        return self.build_str(["ifname", "slave_nics"])
 
 
 class NodeNetwork(base.Base):
     def all_ifnames(self):
         return all_ifaces()
 
-    def relevant_ifnames(self, filter_bridges=True, filter_vlans=True):
+    def relevant_ifnames(self, filter_bridges=True, filter_vlans=True,
+                         filter_bonds=True):
         all_ifaces = self.all_ifnames()
-        relevant_ifaces = self._filter_on_ifname(all_ifaces, filter_vlans)
+        relevant_ifaces = self._filter_on_ifname(all_ifaces, filter_vlans,
+                                                 filter_bonds, filter_bridges)
         irrelevant_names = set(all_ifaces) - set(relevant_ifaces)
         LOGGER.debug("Irrelevant interfaces: %s" % irrelevant_names)
         LOGGER.debug("Relevant interfaces: %s" % relevant_ifaces)
 
         return relevant_ifaces
 
-    def _filter_on_ifname(self, ifnames, filter_vlans=True):
+    def _filter_on_ifname(self, ifnames, filter_vlans=True,
+                          filter_bonds=True, filter_bridges=True):
         """Retuns relevant system NICs (via udev)
 
         Filters out
@@ -526,10 +498,19 @@
         - phy (wireless device)
 
         >>> names = ["bond007", "sit1", "vnet11", "tun0", "wlan1", "virbr0"]
-        >>> names += ["ens1", "eth0", "phy0", "p1p7"]
+        >>> names += ["ens1", "eth0", "phy0", "p1p7", "breth0", "ens1.42"]
         >>> model = NodeNetwork()
         >>> model._filter_on_ifname(names)
         ['ens1', 'eth0', 'p1p7']
+
+        >>> model._filter_on_ifname(names, filter_bonds=False)
+        ['bond007', 'ens1', 'eth0', 'p1p7']
+
+        >>> model._filter_on_ifname(names, filter_bridges=False)
+        ['ens1', 'eth0', 'p1p7', 'breth0']
+
+        >>> model._filter_on_ifname(names, filter_vlans=False)
+        ['ens1', 'eth0', 'p1p7', 'ens1.42']
 
         Args:
             filter_bridges: If bridges shall be filtered out too
@@ -538,29 +519,49 @@
             List of strings, the NIC names
         """
         return [n for n in ifnames if not (n == "lo" or
-                                           n.startswith("bond") or
+                                           (filter_bonds and
+                                            n.startswith("bond")) or
+                                           (filter_bridges and
+                                            n.startswith("br")) or
+                                           (filter_vlans and
+                                            ("." in n)) or
                                            n.startswith("sit") or
                                            n.startswith("vnet") or
                                            n.startswith("tun") or
                                            n.startswith("wlan") or
                                            n.startswith("virbr") or
-                                           n.startswith("phy") or
-                                           (filter_vlans and ("." in n)))]
+                                           n.startswith("phy"))]
 
     def build_nic_model(self, ifname):
+        mnet = config.defaults.Network().retrieve()
+        mlayout = config.defaults.NetworkLayout().retrieve()
+        mbond = config.defaults.NicBonding().retrieve()
+
+        bootif, vlanid = mnet["iface"], mnet["vlanid"]
+        bond_name, bond_slaves = mbond["name"], mbond["slaves"]
+        layout = mlayout["layout"]
+
         nic = NIC(ifname)
+        self.logger.debug("Building model for: %s" % nic)
 
-        if nic.config.bridge and nic.config.vlan:
-            nic = BridgedNIC(TaggedNIC(nic))
-
-        elif nic.config.bridge:
-            nic = BridgedNIC(nic)
-
-        elif nic.config.vlan:
-            nic = TaggedNIC(nic)
-
-        elif nic.config.master:
+        if ifname == bond_name:
+            self.logger.debug(" Is bond master")
             nic = BondedNIC(nic)
+
+        if ifname == bootif:
+            self.logger.debug(" Is bootif")
+            if vlanid:
+                self.logger.debug(" Has tag")
+                nic = TaggedNIC(nic, vlanid)
+
+            if layout == "bridged":
+                self.logger.debug(" Is bridged")
+                nic = BridgedNIC(nic)
+
+        if ifname in bond_slaves:
+            nic = None
+
+        self.logger.debug("Concluded Model: %s" % nic)
 
         return nic
 
@@ -569,7 +570,9 @@
         >>> model = NodeNetwork()
         """
         nics = [NIC(ifname) for ifname
-                in self.relevant_ifnames(filter_vlans=False)]
+                in self.relevant_ifnames(filter_vlans=True,
+                                         filter_bonds=False,
+                                         filter_bridges=True)]
 
         bridges = [nic for nic in nics if nic.typ == "bridge"]
         vlans = [nic for nic in nics if nic.typ == "vlan"]
@@ -583,10 +586,11 @@
 
         for nic in nics + vlans:
             candidate = self.build_nic_model(nic.ifname)
-            if nic.ifname not in candidates or \
-               type(candidates[nic.ifname]) is NIC:
+            if candidate:
                 candidates[candidate.ifname] = candidate
 
+        self.logger.debug("Candidates: %s" % candidates)
+
         return candidates
 
     def configured_nic(self):
diff --git a/tests/nose/network_config.py b/tests/nose/network_config.py
index e9d949d..70311b0 100644
--- a/tests/nose/network_config.py
+++ b/tests/nose/network_config.py
@@ -22,7 +22,8 @@
 from ovirt.node.config import defaults
 from ovirt.node.utils import fs
 from ovirt.node.utils.fs import ShellVarFile, FakeFs
-from ovirt.node.utils.network import UdevNICInfo, SysfsNICInfo
+from ovirt.node.utils.network import UdevNICInfo, SysfsNICInfo, NodeNetwork, \
+    BondedNIC, BridgedNIC, NIC, TaggedNIC
 import logging
 import pprint
 
@@ -62,6 +63,29 @@
 
 
 @patch_common
+class TestCleanNetwork():
+    """Test that a clean network environment is detected correctly
+    """
+    def setUp(self):
+        FakeFs.erase()
+        FakeFs.File("/etc/default/ovirt").touch()
+
+    def tearDown(self):
+        FakeFs.erase()
+
+    def test_clean(self, *args, **kwargs):
+        ifnames = ["ens1", "ens2", "brens3", "bond007", "ens4.42"]
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ifnames
+        nics = nn.nics()
+
+        print nics
+
+        assert sorted(nics.keys()) == ["bond007", "ens1", "ens2"]
+        assert all(type(n) is NIC for n in nics.values())
+
+
+ at patch_common
 class TestBridgedNIC():
     """Test the bridged/legacy configuration
     """
@@ -82,13 +106,28 @@
         run_tx_by_name(m.transaction(), "WriteConfiguration")
 
         assert ifcfg_has_items("eth0",
-                               [('BRIDGE', 'breth0'), ('DEVICE', 'eth0'),
+                               [('BRIDGE', 'breth0'),
+                                ('DEVICE', 'eth0'),
                                 ('HWADDR', 'th:em:ac:ad:dr'),
                                 ('ONBOOT', 'yes')])
         assert ifcfg_has_items("breth0",
-                               [('BOOTPROTO', 'dhcp'), ('DELAY', '0'),
-                                ('DEVICE', 'breth0'), ('ONBOOT', 'yes'),
-                                ('PEERNTP', 'yes'), ('TYPE', 'Bridge')])
+                               [('BOOTPROTO', 'dhcp'),
+                                ('DELAY', '0'),
+                                ('DEVICE', 'breth0'),
+                                ('ONBOOT', 'yes'),
+                                ('PEERNTP', 'yes'),
+                                ('TYPE', 'Bridge')])
+
+    def test_dhcp_discovery(self, *args, **kwargs):
+        self.test_dhcp()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["eth0",
+                                  "breth0"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["eth0"]
+        assert type(nics["eth0"]) is BridgedNIC
 
     def test_static(self, *args, **kwargs):
         m = defaults.Network()
@@ -101,7 +140,8 @@
         run_tx_by_name(m.transaction(), "WriteConfiguration")
 
         assert ifcfg_has_items("ens1",
-                               [('BRIDGE', 'brens1'), ('DEVICE', 'ens1'),
+                               [('BRIDGE', 'brens1'),
+                                ('DEVICE', 'ens1'),
                                 ('HWADDR', 'th:em:ac:ad:dr'),
                                 ('ONBOOT', 'yes')])
         assert ifcfg_has_items("brens1",
@@ -113,6 +153,17 @@
                                 ('ONBOOT', 'yes'),
                                 ('PEERNTP', 'yes'),
                                 ('TYPE', 'Bridge')])
+
+    def test_static_discovery(self, *args, **kwargs):
+        self.test_static()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["ens1",
+                                  "brens1"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["ens1"]
+        assert type(nics["ens1"]) is BridgedNIC
 
 
 @patch_common
@@ -127,8 +178,6 @@
         FakeFs.erase()
 
     def test_dhcp(self, *args, **kwargs):
-        """Test bridgeless with DHCP configuration file creation
-        """
         mt = defaults.NetworkLayout()
         m = defaults.Network()
 
@@ -146,9 +195,50 @@
 
         assert "breth0" not in FakeFs.filemap
 
+    def test_dhcp_discovery(self, *args, **kwargs):
+        self.test_dhcp()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["eth0"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["eth0"]
+        assert type(nics["eth0"]) is NIC
+
+    def test_tagged_dhcp(self, *args, **kwargs):
+        mt = defaults.NetworkLayout()
+        m = defaults.Network()
+
+        mt.configure_direct()
+        m.configure_dhcp("eth0", "42")
+
+        run_tx_by_name(m.transaction(), "WriteConfiguration")
+
+        assert ifcfg_has_items("eth0",
+                               [('DEVICE', 'eth0'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('ONBOOT', 'yes')])
+
+        assert ifcfg_has_items("eth0.42",
+                               [('BOOTPROTO', 'dhcp'),
+                                ('DEVICE', 'eth0.42'),
+                                ('ONBOOT', 'yes'),
+                                ('PEERNTP', 'yes'),
+                                ('VLAN', 'yes')])
+
+        assert "breth0" not in FakeFs.filemap
+
+    def test_tagged_dhcp_discovery(self, *args, **kwargs):
+        self.test_tagged_dhcp()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["eth0", "eth0.42"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["eth0"]
+        assert type(nics["eth0"]) is TaggedNIC
+
     def test_static(self, *args, **kwargs):
-        """Test bridgeless with static IP configuration file creation
-        """
         mt = defaults.NetworkLayout()
         m = defaults.Network()
 
@@ -168,6 +258,16 @@
                                 ('PEERNTP', 'yes')])
 
         assert "brens1" not in FakeFs.filemap
+
+    def test_static_discovery(self, *args, **kwargs):
+        self.test_static()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["ens1"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["ens1"]
+        assert type(nics["ens1"]) is NIC
 
 
 @patch_common
@@ -192,26 +292,45 @@
 
         run_tx_by_name(m.transaction(), "WriteConfiguration")
 
+        assert ifcfg_has_items("ens1",
+                               [('DEVICE', 'ens1'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("ens2",
+                               [('DEVICE', 'ens2'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("ens3",
+                               [('DEVICE', 'ens3'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
         assert ifcfg_has_items("bond0",
                                [('BONDING_OPTS', 'mode=4'),
                                 ('BOOTPROTO', 'dhcp'),
                                 ('DEVICE', 'bond0'),
-                                ('HWADDR', 'th:em:ac:ad:dr'),
-                                ('ONBOOT', 'yes'), ('PEERNTP', 'yes')])
-
-        assert ifcfg_has_items("ens1",
-                               [('DEVICE', 'ens1'), ('MASTER', 'bond0'),
-                                ('ONBOOT', 'yes'), ('SLAVE', 'yes')])
-
-        assert ifcfg_has_items("ens2",
-                               [('DEVICE', 'ens2'), ('MASTER', 'bond0'),
-                                ('ONBOOT', 'yes'), ('SLAVE', 'yes')])
-
-        assert ifcfg_has_items("ens3",
-                               [('DEVICE', 'ens3'), ('MASTER', 'bond0'),
-                                ('ONBOOT', 'yes'), ('SLAVE', 'yes')])
+                                ('ONBOOT', 'yes'),
+                                ('PEERNTP', 'yes')])
 
         assert len(FakeFs.filemap) == (1 + 1 + 3)
+
+    def test_direct_dhcp_discovery(self, *args, **kwargs):
+        self.test_direct_dhcp()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["bond0", "ens1", "ens2", "ens3"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["bond0"]
+        assert type(nics["bond0"]) is BondedNIC
 
     def test_bridged_dhcp(self, *args, **kwargs):
         mb = defaults.NicBonding()
@@ -224,24 +343,32 @@
 
         run_tx_by_name(m.transaction(), "WriteConfiguration")
 
+        assert ifcfg_has_items("ens1",
+                               [('DEVICE', 'ens1'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("ens2",
+                               [('DEVICE', 'ens2'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("ens3",
+                               [('DEVICE', 'ens3'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
         assert ifcfg_has_items("bond0",
                                [('BONDING_OPTS', 'mode=4'),
                                 ('BRIDGE', 'brbond0'),
                                 ('DEVICE', 'bond0'),
-                                ('HWADDR', 'th:em:ac:ad:dr'),
                                 ('ONBOOT', 'yes')])
-
-        assert ifcfg_has_items("ens1",
-                               [('DEVICE', 'ens1'), ('MASTER', 'bond0'),
-                                ('ONBOOT', 'yes'), ('SLAVE', 'yes')])
-
-        assert ifcfg_has_items("ens2",
-                               [('DEVICE', 'ens2'), ('MASTER', 'bond0'),
-                                ('ONBOOT', 'yes'), ('SLAVE', 'yes')])
-
-        assert ifcfg_has_items("ens3",
-                               [('DEVICE', 'ens3'), ('MASTER', 'bond0'),
-                                ('ONBOOT', 'yes'), ('SLAVE', 'yes')])
 
         assert ifcfg_has_items("brbond0",
                                [('BOOTPROTO', 'dhcp'),
@@ -252,6 +379,83 @@
                                 ('TYPE', 'Bridge')])
 
         assert len(FakeFs.filemap) == (1 + 1 + 3 + 1)
+
+    def test_bridged_dhcp_discovery(self, *args, **kwargs):
+        self.test_bridged_dhcp()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["ens1", "ens2", "ens3",
+                                  "bond0"]
+        nics = nn.nics()
+
+        assert nics.keys() == ["bond0"]
+        assert type(nics["bond0"]) is BridgedNIC
+
+    def test_tagged_bridged_dhcp(self, *args, **kwargs):
+        mb = defaults.NicBonding()
+        mt = defaults.NetworkLayout()
+        m = defaults.Network()
+
+        mb.configure_8023ad("bond0", ["ens1", "ens2", "ens3"])
+        m.configure_dhcp("bond0", "42")
+        mt.configure_bridged()
+
+        run_tx_by_name(m.transaction(), "WriteConfiguration")
+
+        assert ifcfg_has_items("ens1",
+                               [('DEVICE', 'ens1'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("ens2",
+                               [('DEVICE', 'ens2'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("ens3",
+                               [('DEVICE', 'ens3'),
+                                ('HWADDR', 'th:em:ac:ad:dr'),
+                                ('MASTER', 'bond0'),
+                                ('ONBOOT', 'yes'),
+                                ('SLAVE', 'yes')])
+
+        assert ifcfg_has_items("bond0",
+                               [('BONDING_OPTS', 'mode=4'),
+                                ('DEVICE', 'bond0'),
+                                ('ONBOOT', 'yes')])
+
+        assert ifcfg_has_items("bond0.42",
+                               [('BRIDGE', 'brbond0'),
+                                ('DEVICE', 'bond0.42'),
+                                ('ONBOOT', 'yes'),
+                                ('VLAN', 'yes')])
+
+        assert ifcfg_has_items("brbond0",
+                               [('BOOTPROTO', 'dhcp'),
+                                ('DELAY', '0'),
+                                ('DEVICE', 'brbond0'),
+                                ('ONBOOT', 'yes'),
+                                ('PEERNTP', 'yes'),
+                                ('TYPE', 'Bridge')])
+
+        assert len(FakeFs.filemap) == (1 + 1 + 1 + 3 + 1)
+
+    def test_tagged_bridged_dhcp_discovery(self, *args, **kwargs):
+        self.test_tagged_bridged_dhcp()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["ens1", "ens2", "ens3",
+                                  "bond0"]
+        nics = nn.nics()
+
+        bridge_nic = nics["bond0"]
+        assert nics.keys() == ["bond0"]
+        assert type(bridge_nic) is BridgedNIC
+        assert bridge_nic.slave_nic.vlan_nic.ifname == "bond0.42"
 
     def test_bond_slave_as_primary(self, *args, **kwargs):
         mb = defaults.NicBonding()
@@ -297,12 +501,25 @@
 
         assert ifcfgfilename("bond0") not in FakeFs.filemap
         assert ifcfg_has_items("ens1", [('DEVICE', 'ens1'),
+                                        ('HWADDR', 'th:em:ac:ad:dr'),
                                         ('ONBOOT', 'yes')])
         assert ifcfg_has_items("ens2", [('DEVICE', 'ens2'),
+                                        ('HWADDR', 'th:em:ac:ad:dr'),
                                         ('ONBOOT', 'yes')])
         assert ifcfg_has_items("ens3", [('DEVICE', 'ens3'),
+                                        ('HWADDR', 'th:em:ac:ad:dr'),
                                         ('ONBOOT', 'yes')])
 
+    def test_no_bond_and_clean_discovery(self, *args, **kwargs):
+        self.test_no_bond_and_clean()
+
+        nn = NodeNetwork()
+        nn.all_ifnames = lambda: ["ens1", "ens2", "ens3"]
+        nics = nn.nics()
+
+        assert sorted(nics.keys()) == ["ens1", "ens2", "ens3"]
+        assert all(type(n) is NIC for n in nics.values())
+
 
 def run_tx_by_name(txs, name):
     """Run a Transaction.Element by it's classname


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie9e2e226b0eb060168708756825026c36e7a3330
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