From 2ab855307865489db418e2a00719f1cd154eac76 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Wed, 21 Jun 2017 12:54:40 -0300 Subject: [PATCH] topotest: parameterize daemon's path This diff is a code cleanup that will allow us more flexibility when defining and using the daemon binaries path, it also fixes a few pylint warnings. --- tests/topotests/lib/topogen.py | 11 ++--- tests/topotests/lib/topotest.py | 74 +++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 1cd0980a3..72da0d444 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -103,7 +103,7 @@ class Topogen(object): for gear in self.gears.values(): gear.net = self.net - def add_router(self, name=None, cls=topotest.Router): + def add_router(self, name=None, cls=topotest.Router, **params): """ Adds a new router to the topology. This function has the following options: @@ -115,7 +115,7 @@ class Topogen(object): if name in self.gears: raise KeyError('router already exists') - self.gears[name] = TopoRouter(self, cls, name) + self.gears[name] = TopoRouter(self, cls, name, **params) self.routern += 1 return self.gears[name] @@ -282,14 +282,15 @@ class TopoRouter(TopoGear): RD_LDP: 'ldpd', } - def __init__(self, tgen, cls, name): + def __init__(self, tgen, cls, name, **params): super(TopoRouter, self).__init__() self.tgen = tgen self.net = None self.name = name self.cls = cls - self.tgen.topo.addNode(self.name, cls=self.cls, - privateDirs=self.PRIVATE_DIRS) + if not params.has_key('privateDirs'): + params['privateDirs'] = self.PRIVATE_DIRS + self.tgen.topo.addNode(self.name, cls=self.cls, **params) def load_config(self, daemon, source=None): """ diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 0385a07a9..d0b377b33 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -189,16 +189,37 @@ class LinuxRouter(Node): class Router(Node): "A Node with IPv4/IPv6 forwarding enabled and Quagga as Routing Engine" + def __init__(self, name, **params): + super(Router, self).__init__(name, **params) + self.daemondir = None + self.routertype = 'frr' + self.daemons = {'zebra': 0, 'ripd': 0, 'ripngd': 0, 'ospfd': 0, + 'ospf6d': 0, 'isisd': 0, 'bgpd': 0, 'pimd': 0, + 'ldpd': 0} + + # pylint: disable=W0221 + # Some params are only meaningful for the parent class. def config(self, **params): super(Router, self).config(**params) - # Check if Quagga or FRR is installed - if os.path.isfile('/usr/lib/frr/zebra'): - self.routertype = 'frr' - elif os.path.isfile('/usr/lib/quagga/zebra'): - self.routertype = 'quagga' + # 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') else: - raise Exception('No FRR or Quagga found in ususal location') + # Test the provided path + zpath = os.path.join(self.daemondir, 'zebra') + if not os.path.isfile(zpath): + raise Exception('No zebra binary found in {}'.format(zpath)) + # Allow user to specify routertype when the path was specified. + if params.get('routertype') is not None: + self.routertype = self.params.get('routertype') + # Enable forwarding on the router assert_sysctl(self, 'net.ipv4.ip_forward', 1) assert_sysctl(self, 'net.ipv6.conf.all.forwarding', 1) @@ -209,10 +230,8 @@ class Router(Node): assert_sysctl(self, 'kernel.core_pattern', corefile) self.cmd('ulimit -c unlimited') # Set ownership of config files - self.cmd('chown %s:%svty /etc/%s' % (self.routertype, self.routertype, self.routertype)) - self.daemons = {'zebra': 0, 'ripd': 0, 'ripngd': 0, 'ospfd': 0, - 'ospf6d': 0, 'isisd': 0, 'bgpd': 0, 'pimd': 0, - 'ldpd': 0} + self.cmd('chown {0}:{0}vty /etc/{0}'.format(self.routertype)) + def terminate(self): # Delete Running Quagga or FRR Daemons self.stopRouter() @@ -266,7 +285,8 @@ class Router(Node): # If ldp is used, check for LDP to be compiled and Linux Kernel to be 4.5 or higher # No error - but return message and skip all the tests if self.daemons['ldpd'] == 1: - if not os.path.isfile('/usr/lib/%s/ldpd' % self.routertype): + ldpd_path = os.path.join(self.daemondir, 'ldpd') + if not os.path.isfile(ldpd_path): print("LDP Test, but no ldpd compiled or installed") return "LDP Test, but no ldpd compiled or installed" kernel_version = re.search(r'([0-9]+)\.([0-9]+).*', platform.release()) @@ -276,8 +296,7 @@ class Router(Node): (float(kernel_version.group(1)) == 4 and float(kernel_version.group(2)) < 5)): print("LDP Test need Linux Kernel 4.5 minimum") return "LDP Test need Linux Kernel 4.5 minimum" - # Add mpls modules to kernel if we use LDP - if self.daemons['ldpd'] == 1: + self.cmd('/sbin/modprobe mpls-router') self.cmd('/sbin/modprobe mpls-iptunnel') self.cmd('echo 100000 > /proc/sys/net/mpls/platform_labels') @@ -288,8 +307,10 @@ class Router(Node): # Starts actuall daemons without init (ie restart) # Start Zebra first if self.daemons['zebra'] == 1: -# self.cmd('/usr/lib/%s/zebra -d' % self.routertype) - self.cmd('/usr/lib/%s/zebra > /tmp/%s-zebra.out 2> /tmp/%s-zebra.err &' % (self.routertype, self.name, self.name)) + zebra_path = os.path.join(self.daemondir, 'zebra') + self.cmd('{0} > /tmp/{1}-zebra.out 2> /tmp/{1}-zebra.err &'.format( + zebra_path, self.name + )) self.waitOutput() print('%s: %s zebra started' % (self, self.routertype)) sleep(1) @@ -298,11 +319,16 @@ class Router(Node): self.cmd('for i in `ls /sys/class/net/` ; do mac=`cat /sys/class/net/$i/address`; IFS=\':\'; set $mac; unset IFS; ip address add dev $i scope link fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6/64; done') # Now start all the other daemons for daemon in self.daemons: - if (self.daemons[daemon] == 1) and (daemon != 'zebra'): -# self.cmd('/usr/lib/%s/%s -d' % (self.routertype, daemon)) - self.cmd('/usr/lib/%s/%s > /tmp/%s-%s.out 2> /tmp/%s-%s.err &' % (self.routertype, daemon, self.name, daemon, self.name, daemon)) - self.waitOutput() - print('%s: %s %s started' % (self, self.routertype, daemon)) + # Skip disabled daemons and zebra + if self.daemons[daemon] == 0 or daemon == 'zebra': + continue + + daemon_path = os.path.join(self.daemondir, daemon) + self.cmd('{0} > /tmp/{1}-{2}.out 2> /tmp/{1}-{2}.err &'.format( + daemon_path, self.name, daemon + )) + self.waitOutput() + print('%s: %s %s started' % (self, self.routertype, daemon)) def getStdErr(self, daemon): return self.getLog('err', daemon) def getStdOut(self, daemon): @@ -325,7 +351,10 @@ class Router(Node): # Look for core file corefiles = glob.glob("/tmp/%s_%s_core*.dmp" % (self.name, daemon)) if (len(corefiles) > 0): - backtrace = subprocess.check_output(["gdb /usr/lib/%s/%s %s --batch -ex bt 2> /dev/null" % (self.routertype, daemon, corefiles[0])], shell=True) + daemon_path = os.path.join(self.daemondir, daemon) + backtrace = subprocess.check_output([ + "gdb {} {} --batch -ex bt 2> /dev/null".format(daemon_path, corefiles[0]) + ], shell=True) sys.stderr.write("\n%s: %s crashed. Core file found - Backtrace follows:\n" % (self.name, daemon)) sys.stderr.write("%s\n" % backtrace) else: @@ -368,7 +397,8 @@ class Router(Node): def daemon_available(self, daemon): "Check if specified daemon is installed (and for ldp if kernel supports MPLS)" - if not os.path.isfile('/usr/lib/%s/%s' % (self.routertype, daemon)): + daemon_path = os.path.join(self.daemondir, daemon) + if not os.path.isfile(daemon_path): return False if (daemon == 'ldpd'): kernel_version = re.search(r'([0-9]+)\.([0-9]+).*', platform.release()) -- 2.39.5