Change in vdsm[master]: ipwrapper: wrap `ip monitor link`

danken at redhat.com danken at redhat.com
Wed Oct 23 06:45:43 UTC 2013


Dan Kenigsberg has uploaded a new change for review.

Change subject: ipwrapper: wrap `ip monitor link`
......................................................................

ipwrapper: wrap `ip monitor link`

Change-Id: I556459220b09fea035774ad82a0ffa4555efaf7b
Signed-off-by: Dan Kenigsberg <danken at redhat.com>
---
M lib/vdsm/ipwrapper.py
M tests/functional/networkTests.py
M tests/ipwrapperTests.py
3 files changed, 66 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/18/20418/1

diff --git a/lib/vdsm/ipwrapper.py b/lib/vdsm/ipwrapper.py
index 0f04dce..f7405a0 100644
--- a/lib/vdsm/ipwrapper.py
+++ b/lib/vdsm/ipwrapper.py
@@ -17,6 +17,8 @@
 # Refer to the README and COPYING files for full details of the license
 #
 
+from collections import namedtuple
+
 from netaddr.core import AddrFormatError
 from netaddr import IPAddress
 from netaddr import IPNetwork
@@ -321,3 +323,41 @@
 def linkDel(dev):
     command = [_IP_BINARY.cmd, 'link', 'del', 'dev', dev]
     _execCmd(command)
+
+MonitorEvent = namedtuple('MonitorEvent', ['device', 'flags', 'state'])
+
+class Monitor():
+    """Minimal wrapper over `ip monitor link`"""
+
+    def __init__(self):
+        self.proc = None
+
+    def start(self):
+        self.proc = execCmd([_IP_BINARY.cmd, 'monitor', 'link'], sync=False)
+
+    def stop(self):
+        self.proc.kill()
+
+    @classmethod
+    def _parse(cls, text):
+        changes = []
+        for line in text.splitlines():
+            if line.startswith(' '):
+                continue
+
+            tokens = line.split()
+            if not tokens[1].endswith(':'):
+                continue
+
+            device = tokens[1][:-2]
+            flags = frozenset(tokens[2][1:-1].split(','))
+            values = dict(tokens[i:i + 2] for i in range(3, len(tokens), 2))
+
+            changes.append(MonitorEvent(device, flags, values.get('state')))
+
+        return changes
+
+    def events(self):
+        out, _ = self.proc.communicate()
+
+        return self._parse(out)
diff --git a/tests/functional/networkTests.py b/tests/functional/networkTests.py
index 4dcc23f..bd8f59b 100644
--- a/tests/functional/networkTests.py
+++ b/tests/functional/networkTests.py
@@ -33,7 +33,7 @@
                             ruleExists, Route, Rule, addrFlush)
 
 from vdsm.netinfo import prefix2netmask
-from vdsm.utils import execCmd
+from vdsm import ipwrapper
 
 
 NETWORK_NAME = 'test-network'
@@ -85,17 +85,14 @@
 @contextmanager
 def nonChangingOperstate(device):
     """Raises an exception if it detects that the device link state changes."""
+    monitor = ipwrapper.Monitor()
+    monitor.start()
     try:
-        monitoringProc = execCmd(['ip', 'monitor', 'link'], sync=False)
         yield
     finally:
-        monitoringProc.kill()
-        out, _ = monitoringProc.communicate()
-        changes = []
-        for line in out.splitlines():
-            tokens = line.split()
-            if '%s:' % device == tokens[1]:
-                changes.append(tokens[-1])
+        monitor.stop()
+        changes = [(dev, state) for (dev, state) in monitor.events()
+                   if dev == device]
         if changes:
             raise OperStateChangedError('%s operstate changed: %r' %
                                         (device, changes))
diff --git a/tests/ipwrapperTests.py b/tests/ipwrapperTests.py
index de9558f..338f926 100644
--- a/tests/ipwrapperTests.py
+++ b/tests/ipwrapperTests.py
@@ -18,6 +18,8 @@
 # Refer to the README and COPYING files for full details of the license
 #
 
+from vdsm.ipwrapper import Monitor
+from vdsm.ipwrapper import MonitorEvent
 from vdsm.ipwrapper import Route
 from vdsm.ipwrapper import Rule
 
@@ -69,3 +71,21 @@
                      '32:    from 10.0.0.0/8 to 264.0.0.0/8 lookup table_100']
         for text in bad_rules:
             self.assertRaises(ValueError, Rule.fromText, text)
+
+    def testMonitorEvents(self):
+        out = ("273: bond0: <BROADCAST,MULTICAST,MASTER> "
+               "mtu 1500 qdisc noqueue state DOWN \n"
+               "    link/ether 33:44:55:66:77:88 brd ff:ff:ff:ff:ff:ff \n"
+               "4: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> \n"
+               "    link/ether \n")
+        expected = [
+            MonitorEvent(
+                'bond',
+                frozenset(['BROADCAST', 'MULTICAST', 'MASTER']),
+                'DOWN'),
+            MonitorEvent(
+                'wlp3s',
+                frozenset(['BROADCAST', 'MULTICAST', 'UP', 'LOWER_UP']),
+                None)]
+
+        self.assertEqual(Monitor._parse(out), expected)


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I556459220b09fea035774ad82a0ffa4555efaf7b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Dan Kenigsberg <danken at redhat.com>


More information about the vdsm-patches mailing list