Change in vdsm[master]: net_models: make network hierarchies iterable

asegurap at redhat.com asegurap at redhat.com
Mon Sep 8 09:21:26 UTC 2014


Antoni Segura Puimedon has uploaded a new change for review.

Change subject: net_models: make network hierarchies iterable
......................................................................

net_models: make network hierarchies iterable

network hierarchies are tree-like data structures that contain all
the devices in a network. It is useful to be able to iterate through
the 'tree' in order to retrieve hierarchy properties such as vlan
tag and backing device (nic or bond) of the network topology.

This patch adds that with proper unit tests.

Change-Id: I333866c1b8d569520c641e462dfe64cb43ea1ae7
Signed-off-by: Antoni S. Puimedon <asegurap at redhat.com>
---
M tests/netmodelsTests.py
M vdsm/network/models.py
2 files changed, 122 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/06/32606/1

diff --git a/tests/netmodelsTests.py b/tests/netmodelsTests.py
index 859b6a4..d005d3d 100644
--- a/tests/netmodelsTests.py
+++ b/tests/netmodelsTests.py
@@ -25,6 +25,7 @@
 
 from network import errors
 from network.models import Bond, Bridge, IPv4, IPv6, Nic, Vlan
+from network.models import hierarchy_backing_device, hierarchy_vlan_tag
 from network.models import _nicSort
 
 from testlib import VdsmTestCase as TestCaseBase
@@ -169,3 +170,67 @@
 
         inverted = Bond._reorderOptions('miimon=250 mode=4')
         self.assertEqual(inverted, 'mode=4 miimon=250')
+
+    @MonkeyPatch(netinfo, 'getMtu', lambda *x: 1500)
+    @MonkeyPatch(Bond, 'validateOptions', lambda *x: 0)
+    def testIterNetworkHierarchy(self):
+        _netinfo = {'networks': {}, 'vlans': {},
+                    'nics': ['testnic1', 'testnic2'],
+                    'bondings': {}, 'bridges': {}}
+        fakeInfo = netinfo.NetInfo(_netinfo)
+        # Vlanned and bonded VM network
+        nic1 = Nic('testnic1', configurator=None, _netinfo=fakeInfo)
+        nic2 = Nic('testnic2', configurator=None, _netinfo=fakeInfo)
+        bond1 = Bond('bond42', configurator=None, slaves=(nic1, nic2))
+        vlan1 = Vlan(bond1, 4, configurator=None)
+        bridge1 = Bridge('testbridge', configurator=None, port=vlan1)
+
+        self.assertEqual([dev for dev in bridge1],
+                         [bridge1, vlan1, bond1, nic1, nic2])
+        self.assertEqual(bond1, hierarchy_backing_device(bridge1))
+        self.assertEqual(4, hierarchy_vlan_tag(bridge1))
+
+        # Nic-less VM net
+        bridge2 = Bridge('testbridge', configurator=None, port=None)
+        self.assertEqual([dev for dev in bridge2], [bridge2])
+        self.assertEqual(None, hierarchy_backing_device(bridge2))
+        self.assertEqual(None, hierarchy_vlan_tag(bridge2))
+
+        # vlan-less VM net
+        bridge3 = Bridge('testbridge', configurator=None, port=bond1)
+        self.assertEqual([dev for dev in bridge3],
+                         [bridge3, bond1, nic1, nic2])
+        self.assertEqual(bond1, hierarchy_backing_device(bridge3))
+        self.assertEqual(None, hierarchy_vlan_tag(bridge3))
+
+        # Bond-less VM net
+        bridge4 = Bridge('testbridge', configurator=None, port=nic1)
+        self.assertEqual([dev for dev in bridge4],
+                         [bridge4, nic1])
+        self.assertEqual(nic1, hierarchy_backing_device(bridge4))
+        self.assertEqual(None, hierarchy_vlan_tag(bridge4))
+
+        # vlanned and bonded non-VM net
+        self.assertEqual([dev for dev in vlan1],
+                         [vlan1, bond1, nic1, nic2])
+        self.assertEqual(bond1, hierarchy_backing_device(vlan1))
+        self.assertEqual(4, hierarchy_vlan_tag(vlan1))
+
+        # vlanned, bond-less non-VM net
+        vlan2 = Vlan(nic1, 5, configurator=None)
+        self.assertEqual([dev for dev in vlan2],
+                         [vlan2, nic1])
+        self.assertEqual(nic1, hierarchy_backing_device(vlan2))
+        self.assertEqual(5, hierarchy_vlan_tag(vlan2))
+
+        # non-vlanned and bonded non-VM net
+        self.assertEqual([dev for dev in bond1],
+                         [bond1, nic1, nic2])
+        self.assertEqual(bond1, hierarchy_backing_device(bond1))
+        self.assertEqual(None, hierarchy_vlan_tag(bond1))
+
+        # non-vlanned and bond-less non-VM net
+        self.assertEqual([dev for dev in nic2],
+                         [nic2])
+        self.assertEqual(nic2, hierarchy_backing_device(nic2))
+        self.assertEqual(None, hierarchy_vlan_tag(nic2))
diff --git a/vdsm/network/models.py b/vdsm/network/models.py
index 402a4b5..638a6a1 100644
--- a/vdsm/network/models.py
+++ b/vdsm/network/models.py
@@ -38,6 +38,9 @@
         self.configurator = configurator
         self.master = None
 
+    def __iter__(self):
+        raise NotImplementedError
+
     def __str__(self):
         return self.name
 
@@ -80,6 +83,10 @@
             device = device.master
         return False
 
+    @property
+    def backing_device(self):
+        return False
+
 
 class Nic(NetDevice):
     def __init__(self, name, configurator, ipconfig=None, mtu=None,
@@ -108,6 +115,14 @@
     def remove(self):
         self.configurator.removeNic(self)
 
+    @property
+    def backing_device(self):
+        return True
+
+    def __iter__(self):
+        yield self
+        raise StopIteration
+
     def __repr__(self):
         return 'Nic(%s)' % self.name
 
@@ -125,6 +140,11 @@
         self.tag = tag
         super(Vlan, self).__init__('%s.%s' % (device.name, tag), configurator,
                                    ipconfig, mtu)
+
+    def __iter__(self):
+        yield self
+        for dev in self.device:
+            yield dev
 
     def __repr__(self):
         return 'Vlan(%s: %r)' % (self.name, self.device)
@@ -162,6 +182,13 @@
         self.stp = stp
         super(Bridge, self).__init__(name, configurator, ipconfig, mtu)
 
+    def __iter__(self):
+        yield self
+        if self.port is None:
+            raise StopIteration
+        for dev in self.port:
+            yield dev
+
     def __repr__(self):
         return 'Bridge(%s: %r)' % (self.name, self.port)
 
@@ -195,6 +222,13 @@
             self.options = self._reorderOptions(options)
         self.destroyOnMasterRemoval = destroyOnMasterRemoval
         super(Bond, self).__init__(name, configurator, ipconfig, mtu)
+
+    def __iter__(self):
+        yield self
+        for slave in self.slaves:
+            for dev in slave:
+                yield dev
+        raise StopIteration
 
     def __repr__(self):
         return 'Bond(%s: %r)' % (self.name, self.slaves)
@@ -323,6 +357,10 @@
             opts.insert(0, ('mode', mode))
 
         return ' '.join((opt + '=' + val for (opt, val) in opts))
+
+    @property
+    def backing_device(self):
+        return True
 
 
 class IPv4(object):
@@ -498,3 +536,22 @@
         nicsList.append((prefix, intidx, stridx + postfix))
 
     return [x + z for x, y, z in sorted(nicsList)]
+
+
+def hierarchy_vlan_tag(device):
+    """Returns the vlan tag of the network hierarchy if any"""
+    vlan_tag = None
+    for dev in device:
+        vlan_tag = getattr(dev, 'tag', None)
+        if vlan_tag is not None:
+            break
+    return vlan_tag
+
+
+def hierarchy_backing_device(device):
+    """Returns the backing device of a network hierarchy, i.e., a bond if
+    the network is bonded, a nic otherwise (an no nic-less net)"""
+    for dev in device:
+        if dev.backing_device:
+            return dev
+    return None


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I333866c1b8d569520c641e462dfe64cb43ea1ae7
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap at redhat.com>


More information about the vdsm-patches mailing list