mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-25 22:30:52 +00:00
tests: fix bmp test parallelization
Multiple BMP tests can run in parallel but, when one instance ends,
it kills the BMP server process of all BMP tests.
Save the PID of a BMP server and only kill it at the end.
Link: https://github.com/FRRouting/frr/issues/17465
Fixes: 875511c466
("topotests: add basic bmp collector")
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
parent
bbf8ee1769
commit
b12e04fdf1
@ -7,6 +7,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
# XXX: something more reliable should be used "Twisted" a great choice.
|
# XXX: something more reliable should be used "Twisted" a great choice.
|
||||||
|
import os
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
@ -20,11 +21,11 @@ BGP_MAX_SIZE = 4096
|
|||||||
# Global variable to track shutdown signal
|
# Global variable to track shutdown signal
|
||||||
shutdown = False
|
shutdown = False
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
|
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
|
||||||
parser.add_argument("-p", "--port", type=int, default=1789)
|
parser.add_argument("-p", "--port", type=int, default=1789)
|
||||||
parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log")
|
parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log")
|
||||||
|
parser.add_argument("-r", "--pidfile", type=str, default="/var/run/bmp.pid")
|
||||||
|
|
||||||
|
|
||||||
def handle_signal(signum, frame):
|
def handle_signal(signum, frame):
|
||||||
@ -40,6 +41,74 @@ def timestamp_print(message, file=sys.stderr):
|
|||||||
print(f"[{current_time}] {message}", file=file)
|
print(f"[{current_time}] {message}", file=file)
|
||||||
|
|
||||||
|
|
||||||
|
def check_pid(pid):
|
||||||
|
if pid < 0: # user input error
|
||||||
|
return False
|
||||||
|
if pid == 0: # all processes
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
os.kill(pid, 0)
|
||||||
|
return True
|
||||||
|
except OSError as err:
|
||||||
|
if err.errno == errno.EPERM: # a process we were denied access to
|
||||||
|
return True
|
||||||
|
if err.errno == errno.ESRCH: # No such process
|
||||||
|
return False
|
||||||
|
# should never happen
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def savepid():
|
||||||
|
ownid = os.getpid()
|
||||||
|
|
||||||
|
flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
|
||||||
|
mode = ((os.R_OK | os.W_OK) << 6) | (os.R_OK << 3) | os.R_OK
|
||||||
|
|
||||||
|
try:
|
||||||
|
fd = os.open(pid_file, flags, mode)
|
||||||
|
except OSError:
|
||||||
|
try:
|
||||||
|
pid = open(pid_file, "r").readline().strip()
|
||||||
|
if check_pid(int(pid)):
|
||||||
|
timestamp_print(
|
||||||
|
"PID file already exists and program still running %s\n" % pid_file
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# If pid is not running, reopen file without O_EXCL
|
||||||
|
fd = os.open(pid_file, flags ^ os.O_EXCL, mode)
|
||||||
|
except (OSError, IOError, ValueError):
|
||||||
|
timestamp_print(
|
||||||
|
"issue accessing PID file %s (most likely permission or ownership)\n"
|
||||||
|
% pid_file
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = os.fdopen(fd, "w")
|
||||||
|
line = "%d\n" % ownid
|
||||||
|
f.write(line)
|
||||||
|
f.close()
|
||||||
|
saved_pid = True
|
||||||
|
except IOError:
|
||||||
|
timestamp_print("Can not create PID file %s\n" % pid_file)
|
||||||
|
return False
|
||||||
|
timestamp_print("Created PID file %s with value %d\n" % (pid_file, ownid))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def removepid():
|
||||||
|
try:
|
||||||
|
os.remove(pid_file)
|
||||||
|
except OSError as exc:
|
||||||
|
if exc.errno == errno.ENOENT:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
timestamp_print("Can not remove PID file %s\n" % pid_file)
|
||||||
|
return
|
||||||
|
timestamp_print("Removed PID file %s\n" % pid_file)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global shutdown
|
global shutdown
|
||||||
|
|
||||||
@ -51,8 +120,13 @@ def main():
|
|||||||
ADDRESS, PORT = args.address, args.port
|
ADDRESS, PORT = args.address, args.port
|
||||||
LOG_FILE = args.logfile
|
LOG_FILE = args.logfile
|
||||||
|
|
||||||
|
global pid_file
|
||||||
|
pid_file = args.pidfile
|
||||||
|
|
||||||
timestamp_print(f"Starting bmpserver on {args.address}:{args.port}")
|
timestamp_print(f"Starting bmpserver on {args.address}:{args.port}")
|
||||||
|
|
||||||
|
savepid()
|
||||||
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
try:
|
try:
|
||||||
@ -97,6 +171,7 @@ def main():
|
|||||||
timestamp_print(f"{e}")
|
timestamp_print(f"{e}")
|
||||||
finally:
|
finally:
|
||||||
timestamp_print(f"Server shutting down on {ADDRESS}:{PORT}")
|
timestamp_print(f"Server shutting down on {ADDRESS}:{PORT}")
|
||||||
|
removepid()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -104,4 +179,5 @@ if __name__ == "__main__":
|
|||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.info("BMP server was interrupted and is shutting down.")
|
logging.info("BMP server was interrupted and is shutting down.")
|
||||||
|
removepid()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -1293,18 +1293,19 @@ class TopoBMPCollector(TopoHost):
|
|||||||
log_err = os.path.join(log_dir, "bmpserver.log")
|
log_err = os.path.join(log_dir, "bmpserver.log")
|
||||||
|
|
||||||
log_arg = "-l {}".format(log_file) if log_file else ""
|
log_arg = "-l {}".format(log_file) if log_file else ""
|
||||||
|
self.pid_file = os.path.join(log_dir, "bmpserver.pid")
|
||||||
|
|
||||||
with open(log_err, "w") as err:
|
with open(log_err, "w") as err:
|
||||||
self.run(
|
self.run(
|
||||||
"{}/bmp_collector/bmpserver.py -a {} -p {} {}&".format(
|
"{}/bmp_collector/bmpserver.py -a {} -p {} -r {} {}&".format(
|
||||||
CWD, self.ip, self.port, log_arg
|
CWD, self.ip, self.port, self.pid_file, log_arg
|
||||||
),
|
),
|
||||||
stdout=None,
|
stdout=None,
|
||||||
stderr=err,
|
stderr=err,
|
||||||
)
|
)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.run("pkill -f bmpserver.py")
|
self.run(f"kill $(cat {self.pid_file}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user