From: Rafael Zalamena Date: Tue, 27 Jun 2017 21:11:02 +0000 (-0300) Subject: topogen: support configuration file X-Git-Tag: frr-7.1-dev~151^2~292 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=edd2bdf6de95b1e1ace1a8de3cf586c13cec2129;p=mirror%2Ffrr.git topogen: support configuration file Use a configuration file for casual settings like: * Verbosity level (helps when debugging mininet issues) * Custom daemon directory (in order to support running different daemon binaries without touching tests) * Daemon type switch: allow running quagga without touching any test files Also fix the add_router() documentation to include all options. --- diff --git a/tests/topotests/GUIDELINES.md b/tests/topotests/GUIDELINES.md index 1566705bc1..8c26c837b9 100644 --- a/tests/topotests/GUIDELINES.md +++ b/tests/topotests/GUIDELINES.md @@ -552,3 +552,15 @@ r1 *** Starting CLI: mininet> ``` + +To enable more debug messages in other Topogen subsystems (like Mininet), more +logging messages can be displayed by modifying the test configuration file +`pytest.ini`: + +```ini +[topogen] +# Change the default verbosity line from 'info'... +#verbosity = info +# ...to 'debug' +verbosity = debug +``` diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 97f006c59c..ed0339d8f0 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -41,6 +41,7 @@ Basic usage instructions: import os import sys import json +import ConfigParser from mininet.net import Mininet from mininet.log import setLogLevel @@ -48,6 +49,8 @@ from mininet.cli import CLI from lib import topotest +CWD = os.path.dirname(os.path.realpath(__file__)) + # pylint: disable=C0103 # Global Topogen variable. This is being used to keep the Topogen available on # all test functions without declaring a test local variable. @@ -75,7 +78,10 @@ def set_topogen(tgen): class Topogen(object): "A topology test builder helper." + CONFIG_SECTION = 'topogen' + def __init__(self, cls): + self.config = None self.topo = None self.net = None self.gears = {} @@ -97,6 +103,9 @@ class Topogen(object): # Set the global variable so the test cases can access it anywhere set_topogen(self) + # Load the default topology configurations + self._load_config() + # Initialize the API self._mininet_reset() cls() @@ -104,11 +113,28 @@ class Topogen(object): for gear in self.gears.values(): gear.net = self.net + def _load_config(self): + """ + 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', + } + self.config = ConfigParser.ConfigParser(defaults) + pytestini_path = os.path.join(CWD, '../pytest.ini') + self.config.read(pytestini_path) + def add_router(self, name=None, cls=topotest.Router, **params): """ Adds a new router to the topology. This function has the following options: - name: (optional) select the router name + * `name`: (optional) select the router name + * `daemondir`: (optional) custom daemon binary directory + * `routertype`: (optional) `quagga` or `frr` Returns a TopoRouter. """ if name is None: @@ -116,6 +142,11 @@ class Topogen(object): if name in self.gears: raise KeyError('router already exists') + params['frrdir'] = self.config.get(self.CONFIG_SECTION, 'frrdir') + params['quaggadir'] = self.config.get(self.CONFIG_SECTION, 'quaggadir') + if not params.has_key('routertype'): + params['routertype'] = self.config.get(self.CONFIG_SECTION, 'routertype') + self.gears[name] = TopoRouter(self, cls, name, **params) self.routern += 1 return self.gears[name] @@ -167,7 +198,7 @@ class Topogen(object): return dict((rname, gear) for rname, gear in self.gears.iteritems() if isinstance(gear, TopoRouter)) - def start_topology(self, log_level='info'): + def start_topology(self, log_level=None): """ Starts the topology class. Possible `log_level`s are: 'debug': all information possible @@ -177,6 +208,10 @@ class Topogen(object): 'error': only error and critical messages 'critical': only critical messages """ + # If log_level is not specified use the configuration. + if log_level is None: + log_level = self.config.get('topogen', 'verbosity') + # Run mininet setLogLevel(log_level) self.net.start() diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 9f540fc86f..da7dc06191 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -259,6 +259,26 @@ class Router(Node): 'ospf6d': 0, 'isisd': 0, 'bgpd': 0, 'pimd': 0, 'ldpd': 0} + def _config_frr(self, **params): + "Configure FRR binaries" + self.daemondir = params.get('frrdir') + if self.daemondir is None: + self.daemondir = '/usr/lib/frr' + + zebra_path = os.path.join(self.daemondir, 'zebra') + if not os.path.isfile(zebra_path): + raise Exception("FRR zebra binary doesn't exist at {}".format(zebra_path)) + + def _config_quagga(self, **params): + "Configure Quagga binaries" + self.daemondir = params.get('quaggadir') + if self.daemondir is None: + self.daemondir = '/usr/lib/quagga' + + zebra_path = os.path.join(self.daemondir, 'zebra') + if not os.path.isfile(zebra_path): + raise Exception("Quagga zebra binary doesn't exist at {}".format(zebra_path)) + # pylint: disable=W0221 # Some params are only meaningful for the parent class. def config(self, **params): @@ -267,12 +287,11 @@ class Router(Node): # User did not specify the daemons directory, try to autodetect it. self.daemondir = params.get('daemondir') if self.daemondir is None: - self.daemondir = '/usr/lib/frr' - if not os.path.isfile(os.path.join(self.daemondir, 'zebra')): - self.daemondir = '/usr/lib/quagga' - self.routertype = 'quagga' - if not os.path.isfile(os.path.join(self.daemondir, 'zebra')): - raise Exception('No FRR or Quagga binaries found') + self.routertype = params.get('routertype', 'frr') + if self.routertype == 'quagga': + self._config_quagga(**params) + else: + self._config_frr(**params) else: # Test the provided path zpath = os.path.join(self.daemondir, 'zebra') diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini index a744b34aae..1866bae1cf 100644 --- a/tests/topotests/pytest.ini +++ b/tests/topotests/pytest.ini @@ -1,3 +1,19 @@ # Skip pytests example directory [pytest] norecursedirs = .git example-test + +[topogen] +# Default configuration values +# +# 'verbosity' controls how much data the underline systems will use to +# provide output (e.g. mininet output, test debug output etc...). The +# value is 'info', but can be changed to 'debug' to provide more details. +#verbosity = info + +# Default daemons binaries path. +#frrdir = /usr/lib/frr +#quaggadir = /usr/lib/quagga + +# Default router type to use. Possible values are: +# 'frr' and 'quagga'. +#routertype = frr