mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 13:02:59 +00:00
tests: Enhance topotests scripts to kill/start specific Daemons
1. Added APIs to topogen.py and topotest.py to kill/start specific Daemons, ex - bgpd, staticd Signed-off-by: Kuldeep Kashyap <kashyapk@vmware.com>
This commit is contained in:
parent
81ad029173
commit
c65a7e26dc
@ -707,6 +707,38 @@ class TopoRouter(TopoGear):
|
||||
self.logger.debug("stopping")
|
||||
return self.tgen.net[self.name].stopRouter(wait, assertOnError)
|
||||
|
||||
def startDaemons(self, daemons):
|
||||
"""
|
||||
Start Daemons: to start specific daemon(user defined daemon only)
|
||||
* Start daemons (e.g. FRR/Quagga)
|
||||
* Configure daemon logging files
|
||||
"""
|
||||
self.logger.debug('starting')
|
||||
nrouter = self.tgen.net[self.name]
|
||||
result = nrouter.startRouterDaemons(daemons)
|
||||
|
||||
# Enable all daemon command logging, logging files
|
||||
# and set them to the start dir.
|
||||
for daemon, enabled in nrouter.daemons.iteritems():
|
||||
for d in daemons:
|
||||
if enabled == 0:
|
||||
continue
|
||||
self.vtysh_cmd('configure terminal\nlog commands\nlog file {}.log'.\
|
||||
format(daemon), daemon=daemon)
|
||||
|
||||
if result != '':
|
||||
self.tgen.set_error(result)
|
||||
|
||||
return result
|
||||
|
||||
def killDaemons(self, daemons, wait=True, assertOnError=True):
|
||||
"""
|
||||
Kill specific daemon(user defined daemon only)
|
||||
forcefully using SIGKILL
|
||||
"""
|
||||
self.logger.debug('Killing daemons using SIGKILL..')
|
||||
return self.tgen.net[self.name].killRouterDaemons(daemons, wait, assertOnError)
|
||||
|
||||
def vtysh_cmd(self, command, isjson=False, daemon=None):
|
||||
"""
|
||||
Runs the provided command string in the vty shell and returns a string
|
||||
|
@ -1088,6 +1088,135 @@ class Router(Node):
|
||||
def getLog(self, log, daemon):
|
||||
return self.cmd("cat {}/{}/{}.{}".format(self.logdir, self.name, daemon, log))
|
||||
|
||||
def startRouterDaemons(self, daemons):
|
||||
# Starts actual daemons without init (ie restart)
|
||||
# cd to per node directory
|
||||
self.cmd('cd {}/{}'.format(self.logdir, self.name))
|
||||
self.cmd('umask 000')
|
||||
#Re-enable to allow for report per run
|
||||
self.reportCores = True
|
||||
rundaemons = self.cmd('ls -1 /var/run/%s/*.pid' % self.routertype)
|
||||
|
||||
for daemon in daemons:
|
||||
if daemon == 'zebra':
|
||||
# Start Zebra first
|
||||
if self.daemons['zebra'] == 1:
|
||||
zebra_path = os.path.join(self.daemondir, 'zebra')
|
||||
zebra_option = self.daemons_options['zebra']
|
||||
self.cmd('{0} {1} > zebra.out 2> zebra.err &'.format(
|
||||
zebra_path, zebra_option, self.logdir, self.name
|
||||
))
|
||||
self.waitOutput()
|
||||
logger.debug('{}: {} zebra started'.format(self, self.routertype))
|
||||
sleep(1, '{}: waiting for zebra to start'.format(self.name))
|
||||
|
||||
# Fix Link-Local Addresses
|
||||
# Somehow (on Mininet only), Zebra removes the IPv6 Link-Local
|
||||
# addresses on start. Fix this
|
||||
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')
|
||||
|
||||
if daemon == 'staticd':
|
||||
# Start staticd next if required
|
||||
if self.daemons['staticd'] == 1:
|
||||
staticd_path = os.path.join(self.daemondir, 'staticd')
|
||||
staticd_option = self.daemons_options['staticd']
|
||||
self.cmd('{0} {1} > staticd.out 2> staticd.err &'.format(
|
||||
staticd_path, staticd_option, self.logdir, self.name
|
||||
))
|
||||
self.waitOutput()
|
||||
logger.debug('{}: {} staticd started'.format(self, self.routertype))
|
||||
sleep(1, '{}: waiting for staticd to start'.format(self.name))
|
||||
|
||||
# Now start all the daemons
|
||||
# Skip disabled daemons and zebra
|
||||
if self.daemons[daemon] == 0 or daemon == 'zebra' or daemon == 'staticd':
|
||||
continue
|
||||
daemon_path = os.path.join(self.daemondir, daemon)
|
||||
self.cmd('{0} > {1}.out 2> {1}.err &'.format(
|
||||
daemon_path, daemon
|
||||
))
|
||||
self.waitOutput()
|
||||
logger.debug('{}: {} {} started'.format(self, self.routertype, daemon))
|
||||
sleep(1, '{}: waiting for {} to start'.format(self.name, daemon))
|
||||
|
||||
rundaemons = self.cmd('ls -1 /var/run/%s/*.pid' % self.routertype)
|
||||
|
||||
if re.search(r"No such file or directory", rundaemons):
|
||||
return "Daemons are not running"
|
||||
|
||||
return ""
|
||||
|
||||
def killRouterDaemons(self, daemons, wait=True, assertOnError=True,
|
||||
minErrorVersion='5.1'):
|
||||
# Kill Running Quagga or FRR specific
|
||||
# Daemons(user specified daemon only) using SIGKILL
|
||||
rundaemons = self.cmd('ls -1 /var/run/%s/*.pid' % self.routertype)
|
||||
errors = ""
|
||||
daemonsNotRunning = []
|
||||
if re.search(r"No such file or directory", rundaemons):
|
||||
return errors
|
||||
for daemon in daemons:
|
||||
if rundaemons is not None and daemon in rundaemons:
|
||||
numRunning = 0
|
||||
for d in StringIO.StringIO(rundaemons):
|
||||
if re.search(r"%s" % daemon, d):
|
||||
daemonpid = self.cmd('cat %s' % d.rstrip()).rstrip()
|
||||
if (daemonpid.isdigit() and pid_exists(int(daemonpid))):
|
||||
logger.info('{}: killing {}'.format(
|
||||
self.name,
|
||||
os.path.basename(d.rstrip().rsplit(".", 1)[0])
|
||||
))
|
||||
self.cmd('kill -9 %s' % daemonpid)
|
||||
self.waitOutput()
|
||||
if pid_exists(int(daemonpid)):
|
||||
numRunning += 1
|
||||
if wait and numRunning > 0:
|
||||
sleep(2, '{}: waiting for {} daemon to be stopped'.\
|
||||
format(self.name, daemon))
|
||||
# 2nd round of kill if daemons didn't exit
|
||||
for d in StringIO.StringIO(rundaemons):
|
||||
if re.search(r"%s" % daemon, d):
|
||||
daemonpid = \
|
||||
self.cmd('cat %s' % d.rstrip()).rstrip()
|
||||
if (daemonpid.isdigit() and pid_exists(
|
||||
int(daemonpid))):
|
||||
logger.info('{}: killing {}'.format(
|
||||
self.name,
|
||||
os.path.basename(d.rstrip().\
|
||||
rsplit(".", 1)[0])
|
||||
))
|
||||
self.cmd('kill -9 %s' % daemonpid)
|
||||
self.waitOutput()
|
||||
self.cmd('rm -- {}'.format(d.rstrip()))
|
||||
if wait:
|
||||
errors = self.checkRouterCores(reportOnce=True)
|
||||
if self.checkRouterVersion('<', minErrorVersion):
|
||||
#ignore errors in old versions
|
||||
errors = ""
|
||||
if assertOnError and len(errors) > 0:
|
||||
assert "Errors found - details follow:" == 0, errors
|
||||
|
||||
errors = ""
|
||||
# Check Memory leaks
|
||||
if pytest.config.getoption('--valgrind'):
|
||||
mem_leak, mem_data = self.check_mem_leaks_valgrind(
|
||||
daemon
|
||||
)
|
||||
if mem_leak:
|
||||
for d_name, data in mem_data.items():
|
||||
if data:
|
||||
logger.error(
|
||||
"Memory leaks in router [%s] for "
|
||||
"daemon [%s]", self.name, daemon)
|
||||
errors = "Router [%s] has memory leak, Check" \
|
||||
" logs for details." % self.name
|
||||
else:
|
||||
daemonsNotRunning.append(daemon)
|
||||
if len(daemonsNotRunning) > 0:
|
||||
errors = errors+"Daemons are not running", daemonsNotRunning
|
||||
|
||||
return errors
|
||||
|
||||
def checkRouterCores(self, reportLeaks=True, reportOnce=False):
|
||||
if reportOnce and not self.reportCores:
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user