]> git.puffer.fish Git - mirror/frr.git/commitdiff
topotest: implement environment diagnostics
authorRafael Zalamena <rzalamena@gmail.com>
Tue, 18 Jul 2017 19:44:27 +0000 (16:44 -0300)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 28 Nov 2018 01:22:12 +0000 (20:22 -0500)
Run environment diagnostics on topotest start, report all detected
problems and abort if an error condition is met.

tests/topotests/conftest.py
tests/topotests/lib/topogen.py

index cea7ad448abcc6b8a5bb7b2ba4278a76becce895..05ac329488f62a5dfbc2b69ddb1cf0065ba4e4c7 100755 (executable)
@@ -2,7 +2,7 @@
 Topotest conftest.py file.
 """
 
-from lib.topogen import get_topogen
+from lib.topogen import get_topogen, diagnose_env
 from lib.topotest import json_cmp_result
 import pytest
 
@@ -40,3 +40,8 @@ def pytest_assertrepr_compare(op, left, right):
             return None
 
     return json_result.errors
+
+def pytest_configure(config):
+    "Assert that the environment is correctly configured."
+    if not diagnose_env():
+        pytest.exit('enviroment has errors, please read the logs')
index f947ec34eedc65729625eb2e1c6670215c2fea14..840b9fe2208bad13f2e3a32a5f0be8abe7b374c1 100644 (file)
@@ -44,6 +44,10 @@ import json
 import ConfigParser
 import glob
 import grp
+import platform
+import pwd
+import re
+import subprocess
 
 from mininet.net import Mininet
 from mininet.log import setLogLevel
@@ -78,6 +82,15 @@ def set_topogen(tgen):
 # Main class: topology builder
 #
 
+# Topogen configuration defaults
+tgen_defaults = {
+    'verbosity': 'info',
+    'frrdir': '/usr/lib/frr',
+    'quaggadir': '/usr/lib/quagga',
+    'routertype': 'frr',
+    'memleak_path': None,
+}
+
 class Topogen(object):
     "A topology test builder helper."
 
@@ -130,14 +143,7 @@ class Topogen(object):
         Loads the configuration file `pytest.ini` located at the root dir of
         topotests.
         """
-        defaults = {
-            'verbosity': 'info',
-            'frrdir': '/usr/lib/frr',
-            'quaggadir': '/usr/lib/quagga',
-            'routertype': 'frr',
-            'memleak_path': None,
-        }
-        self.config = ConfigParser.ConfigParser(defaults)
+        self.config = ConfigParser.ConfigParser(tgen_defaults)
         pytestini_path = os.path.join(CWD, '../pytest.ini')
         self.config.read(pytestini_path)
 
@@ -836,3 +842,129 @@ class TopoExaBGP(TopoHost):
     def stop(self):
         "Stop ExaBGP peer and kill the daemon"
         self.run('kill `cat /var/run/exabgp/exabgp.pid`')
+
+
+#
+# Diagnostic function
+#
+
+# Disable linter branch warning. It is expected to have these here.
+# pylint: disable=R0912
+def diagnose_env():
+    """
+    Run diagnostics in the running environment. Returns `True` when everything
+    is ok, otherwise `False`.
+    """
+    ret = True
+    logger.info('Running environment diagnostics')
+
+    # Load configuration
+    config = ConfigParser.ConfigParser(tgen_defaults)
+    pytestini_path = os.path.join(CWD, '../pytest.ini')
+    config.read(pytestini_path)
+
+    # Assert that we are running as root
+    if os.getuid() != 0:
+        logger.error('you must run topotest as root')
+        ret = False
+
+    # Assert that we have mininet
+    if os.system('which mn >/dev/null 2>/dev/null') != 0:
+        logger.error('could not find mininet binary (mininet is not installed)')
+        ret = False
+
+    # Assert that we have iproute installed
+    if os.system('which ip >/dev/null 2>/dev/null') != 0:
+        logger.error('could not find ip binary (iproute is not installed)')
+        ret = False
+
+    # Assert that we have gdb installed
+    if os.system('which gdb >/dev/null 2>/dev/null') != 0:
+        logger.error('could not find gdb binary (gdb is not installed)')
+        ret = False
+
+    # Assert that FRR utilities exist
+    frrdir = config.get('topogen', 'frrdir')
+    if not os.path.isdir(frrdir):
+        logger.error('could not find {} directory'.format(frrdir))
+        ret = False
+    else:
+        try:
+            pwd.getpwnam('frr')[2]
+        except KeyError:
+            logger.warning('could not find "frr" user')
+
+        try:
+            grp.getgrnam('frr')[2]
+        except KeyError:
+            logger.warning('could not find "frr" group')
+
+        try:
+            if 'frr' not in grp.getgrnam('frrvty').gr_mem:
+                logger.error('"frr" user and group exist, but user is not under "frrvty"')
+        except KeyError:
+            logger.warning('could not find "frrvty" group')
+
+        for fname in ['zebra', 'ospfd', 'ospf6d', 'bgpd', 'ripd', 'ripngd',
+                      'isisd', 'pimd', 'ldpd']:
+            path = os.path.join(frrdir, fname)
+            if not os.path.isfile(path):
+                # LDPd is an exception
+                if fname == 'ldpd':
+                    logger.info('could not find {} in {}'.format(fname, frrdir) +
+                                '(LDPd tests will not run)')
+                    continue
+
+                logger.warning('could not find {} in {}'.format(fname, frrdir))
+                ret = False
+
+    # Assert that Quagga utilities exist
+    quaggadir = config.get('topogen', 'quaggadir')
+    if not os.path.isdir(quaggadir):
+        logger.info('could not find {} directory (quagga tests will not run)'.format(quaggadir))
+    else:
+        try:
+            pwd.getpwnam('quagga')[2]
+        except KeyError:
+            logger.info('could not find "quagga" user')
+
+        try:
+            grp.getgrnam('quagga')[2]
+        except KeyError:
+            logger.info('could not find "quagga" group')
+
+        try:
+            if 'quagga' not in grp.getgrnam('quaggavty').gr_mem:
+                logger.error('"quagga" user and group exist, but user is not under "quaggavty"')
+        except KeyError:
+            logger.warning('could not find "frrvty" group')
+
+        for fname in ['zebra', 'ospfd', 'ospf6d', 'bgpd', 'ripd', 'ripngd',
+                      'isisd', 'pimd']:
+            path = os.path.join(quaggadir, fname)
+            if not os.path.isfile(path):
+                logger.warning('could not find {} in {}'.format(fname, quaggadir))
+                ret = False
+
+    if not os.path.isdir('/tmp'):
+        logger.warning('could not find /tmp for logs')
+
+    # Test MPLS availability
+    krel = platform.release()
+    if topotest.version_cmp(krel, '4.5') < 0:
+        logger.info('LDPd tests will not run (have kernel "{}", but it requires 4.5)'.format(krel))
+
+    # TODO remove me when we start supporting exabgp >= 4
+    try:
+        output = subprocess.check_output(['exabgp', '-v'])
+        line = output.split('\n')[0]
+        version = line.split(' ')[2]
+        if topotest.version_cmp(version, '4') >= 0:
+            logger.warning('BGP topologies are still using exabgp version 3, expect failures')
+
+    # We want to catch all exceptions
+    # pylint: disable=W0702
+    except:
+        logger.warning('failed to find exabgp or returned error')
+
+    return ret