From 12c888cd03e4d5fe33995d1ef30f65d668b572cc Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Sun, 17 May 2020 02:27:27 +0100 Subject: [PATCH] formating changes --- .pre-commit-config.yaml | 2 +- dev/bin/recorder-connect | 2 +- dev/bin/replay-connect | 2 +- etc/exabgp/example-tcp-control.run | 348 ++++++++++++++++------------- lib/exabgp/application/pipe.py | 2 - qa/bin/functional | 5 +- qa/self/api/receive.py | 1 - qa/tests/parsing_test.py | 2 +- setup.py | 1 + tox.ini | 2 +- 10 files changed, 197 insertions(+), 170 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fbf2b710f..56e0be456 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,4 +4,4 @@ repos: hooks: - id: black language_version: python3.8 - args: [--line-length=130, --skip-string-normalization,--exclude=lib/exabgp/vendoring] + args: [--line-length=120, --skip-string-normalization,--exclude=lib/exabgp/vendoring] diff --git a/dev/bin/recorder-connect b/dev/bin/recorder-connect index 8e2bc6057..79d4eb073 100755 --- a/dev/bin/recorder-connect +++ b/dev/bin/recorder-connect @@ -40,7 +40,7 @@ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect the socket to the port on the server given by the caller server_address = (sys.argv[1], int(sys.argv[2])) -print >> sys.stderr, 'connecting to %s port %s' % server_address +sys.stderr.write('connecting to %s port %s\n' % server_address) sock.connect(server_address) with open(sys.argv[3]) as record: diff --git a/dev/bin/replay-connect b/dev/bin/replay-connect index 69d723ba2..334f7943a 100755 --- a/dev/bin/replay-connect +++ b/dev/bin/replay-connect @@ -10,7 +10,7 @@ if len(sys.argv) != 4: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = (sys.argv[1], int(sys.argv[2])) - print >> sys.stderr, 'connecting to %s port %s' % server_address + sys.stderr('connecting to %s port %s\n' % server_address) sock.connect(server_address) except socket.error: print "failed to connect to server" diff --git a/etc/exabgp/example-tcp-control.run b/etc/exabgp/example-tcp-control.run index 941ef8b3f..769e0b7cd 100755 --- a/etc/exabgp/example-tcp-control.run +++ b/etc/exabgp/example-tcp-control.run @@ -12,154 +12,178 @@ import select from SocketServer import TCPServer from SocketServer import StreamRequestHandler + class TimeoutException(Exception): - pass - -def read_command (rfile, wfile, prompt): - def timeout_handler (signum, frame): - raise TimeoutException() - - signal.signal(signal.SIGALRM, timeout_handler) - signal.alarm(1) - - try: - if prompt: - wfile.write('\n> ') - c = rfile.readline() - except TimeoutException: - c = '' - finally: - signal.alarm(0) - - return c.strip() - -class Control (StreamRequestHandler): - allow_reuse_address = True - - def handle (self): - command = 'go' - prompt = True - while command not in ['quit','exit']: - # reading the command on TCP - # relaying it to exabgp via the socket - command = read_command(self.rfile,self.wfile,prompt) - prompt = False - - if command in ['quit','exit']: - continue - - if command in ['help','?']: - self.wfile.write('exabgp tcp-control help\n') - self.wfile.write('\n') - self.wfile.write('This program is just a way to manually enter commands using telnet\n') - self.wfile.write('routes and flows syntax are parsed like normal configuration\n') - self.wfile.write('\n') - self.wfile.write('quit (close the telnet connection)\n') - self.wfile.write('exit (close the telnet connection)\n') - self.wfile.write('\n') - self.wfile.write('version (returns the version of exabgp)\n') - self.wfile.write('reload (reload the configuration - cause exabgp to forget all routes learned via external processes)\n') - self.wfile.write('restart (reload the configuration and bounce all BGP session)\n') - self.wfile.write('shutdown (politely terminate all session and exit)\n') - self.wfile.write('\n') - self.wfile.write('WARNING : The result of the following commands will depend on the route, it could even cause the BGP session to drop)\n') - self.wfile.write('WARNING : It could even cause the BGP session to drop, for example if you send flow routes to a router which does not support it\n') - self.wfile.write('\n') - self.wfile.write('With "announce route" and "withdraw route" the route will be sent to ALL the peers unless the "neighbor x.x.x.x [announce|withdraw] route" commands are used. Details at https://github.com/Exa-Networks/exabgp/wiki/Controlling-ExaBGP-:-limiting-diffusion-of-routes\n') - self.wfile.write('\n') - self.wfile.write('[neighbor x.x.x.x] annouce route\n') - self.wfile.write(' The multi-line syntax is currently not supported\n') - self.wfile.write(' example: announce route 1.2.3.4 next-hop 5.6.7.8\n') - self.wfile.write('[neighbor x.x.x.x] withdraw route\n') - self.wfile.write(' example: withdraw route (example: withdraw route 1.2.3.4 next-hop 5.6.7.8)\n') - self.wfile.write('announce flow\n') - self.wfile.write(' exabgp does not have a single line flow syntax so you must use the multiline version indicating newlines with \\n\n') - self.wfile.write(' example: announce flow route {\\n match {\\n source 10.0.0.1/32;\\n destination 1.2.3.4/32;\\n }\\n then {\\n discard;\\n }\\n }\\n\n') - self.wfile.write('withdraw flow\n') - self.wfile.write(' exabgp does not have a single line flow syntax so you must use the multiline version indicating newlines with \\n\n') - self.wfile.write(' example: withdraw flow route {\\n match {\\n source 10.0.0.1/32;\\n destination 1.2.3.4/32;\\n }\\n then {\\n discard;\\n }\\n }\\n\n') - self.wfile.write('\n') - self.wfile.write('SHOW COMMANDS SHOULD NOT BE USED IN PRODUCTION AS THEY HALT THE BGP ROUTE PROCESSING\n') - self.wfile.write('AND CAN RESULT IN BGP PEERING SESSION DROPPING - You have been warned\n') - self.wfile.write('\n') - self.wfile.write('show neighbors\n') - self.wfile.write(' display the neighbor configured\\n\n') - self.wfile.write('show routes\n') - self.wfile.write(' display routes which have been announced\\n\n') - self.wfile.write('\n') - self.wfile.flush() - prompt = True - - elif command.startswith('announce '): - sys.stdout.write('%s\n' % command) - sys.stdout.flush() - self.wfile.write('requested %s annoucement\n' % command.split(' ')[1]) - self.wfile.flush() - prompt = True - - elif command.startswith('withdraw '): - sys.stdout.write('%s\n' % command) - sys.stdout.flush() - self.wfile.write('request %s withdrawal\n' % command.split(' ')[1]) - self.wfile.flush() - prompt = True - - elif command.startswith('neighbor '): - sys.stdout.write('%s\n' % command) - sys.stdout.flush() - self.wfile.write('neighbor %s requested\n' % command.split(' ')[1]) - self.wfile.flush() - prompt = True - - elif command.startswith('show '): - sys.stdout.write('%s\n' % command) - sys.stdout.flush() - self.wfile.write('%s requested\n' % command.split(' ')[1]) - self.wfile.flush() - prompt = True - - elif command in ['shutdown','reload','restart','version','#']: - sys.stdout.write('%s\n' % command) - sys.stdout.flush() - prompt = True - - elif command not in ['go','']: - self.wfile.write('unknown command [%s], try: help\n' % command) - self.wfile.flush() - prompt = True - - try: - r,_,_ = select.select([sys.stdin], [], [], 1.0) - except select.error: - raise KeyboardInterrupt('SIGNAL received in select') - - if r: - self.wfile.write('\n') - - while r: - # Can not use readline with select. - # From https://stackoverflow.com/questions/5486717/python-select-doesnt-signal-all-input-from-pipe - # Note that internally file.readlines([size]) loops and invokes the read() syscall more than once, attempting to fill an internal buffer of size. The first call to read() will immediately return, since select() indicated the fd was readable. However the 2nd call will block until data is available, which defeats the purpose of using select. In any case it is tricky to use file.readlines([size]) in an asynchronous app. - response = os.read(sys.stdin.fileno(),4096) - # this should not happen as select informed us of data to read but it seems it does - if not response: - break - self.wfile.write(response) - prompt = True - time.sleep(0.1) - try: - r,_,_ = select.select([sys.stdin], [], [], 1.0) - except select.error: - raise KeyboardInterrupt('SIGNAL received in select') - continue - -def timed (message): - now = time.strftime('%a, %d %b %Y %H:%M:%S',time.localtime()) - return "%s | %-8s | %-6d | %-13s | %s" % (now,'FORKED',os.getpid(),'tcp-server',message) - -def sig (signum, frame): - # outch rude but prevent silly trace on exit if waiting for a read on stdin :p - os.kill(os.getpid(),signal.SIGKILL) + pass + + +def read_command(rfile, wfile, prompt): + def timeout_handler(signum, frame): + raise TimeoutException() + + signal.signal(signal.SIGALRM, timeout_handler) + signal.alarm(1) + + try: + if prompt: + wfile.write('\n> ') + c = rfile.readline() + except TimeoutException: + c = '' + finally: + signal.alarm(0) + + return c.strip() + + +class Control(StreamRequestHandler): + allow_reuse_address = True + + def handle(self): + command = 'go' + prompt = True + while command not in ['quit', 'exit']: + # reading the command on TCP + # relaying it to exabgp via the socket + command = read_command(self.rfile, self.wfile, prompt) + prompt = False + + if command in ['quit', 'exit']: + continue + + if command in ['help', '?']: + self.wfile.write('exabgp tcp-control help\n') + self.wfile.write('\n') + self.wfile.write('This program is just a way to manually enter commands using telnet\n') + self.wfile.write('routes and flows syntax are parsed like normal configuration\n') + self.wfile.write('\n') + self.wfile.write('quit (close the telnet connection)\n') + self.wfile.write('exit (close the telnet connection)\n') + self.wfile.write('\n') + self.wfile.write('version (returns the version of exabgp)\n') + self.wfile.write( + 'reload (reload the configuration - cause exabgp to forget all routes learned via external processes)\n' + ) + self.wfile.write('restart (reload the configuration and bounce all BGP session)\n') + self.wfile.write('shutdown (politely terminate all session and exit)\n') + self.wfile.write('\n') + self.wfile.write( + 'WARNING : The result of the following commands will depend on the route, it could even cause the BGP session to drop)\n' + ) + self.wfile.write( + 'WARNING : It could even cause the BGP session to drop, for example if you send flow routes to a router which does not support it\n' + ) + self.wfile.write('\n') + self.wfile.write( + 'With "announce route" and "withdraw route" the route will be sent to ALL the peers unless the "neighbor x.x.x.x [announce|withdraw] route" commands are used. Details at https://github.com/Exa-Networks/exabgp/wiki/Controlling-ExaBGP-:-limiting-diffusion-of-routes\n' + ) + self.wfile.write('\n') + self.wfile.write('[neighbor x.x.x.x] annouce route\n') + self.wfile.write(' The multi-line syntax is currently not supported\n') + self.wfile.write(' example: announce route 1.2.3.4 next-hop 5.6.7.8\n') + self.wfile.write('[neighbor x.x.x.x] withdraw route\n') + self.wfile.write(' example: withdraw route (example: withdraw route 1.2.3.4 next-hop 5.6.7.8)\n') + self.wfile.write('announce flow\n') + self.wfile.write( + ' exabgp does not have a single line flow syntax so you must use the multiline version indicating newlines with \\n\n' + ) + self.wfile.write( + ' example: announce flow route {\\n match {\\n source 10.0.0.1/32;\\n destination 1.2.3.4/32;\\n }\\n then {\\n discard;\\n }\\n }\\n\n' + ) + self.wfile.write('withdraw flow\n') + self.wfile.write( + ' exabgp does not have a single line flow syntax so you must use the multiline version indicating newlines with \\n\n' + ) + self.wfile.write( + ' example: withdraw flow route {\\n match {\\n source 10.0.0.1/32;\\n destination 1.2.3.4/32;\\n }\\n then {\\n discard;\\n }\\n }\\n\n' + ) + self.wfile.write('\n') + self.wfile.write( + 'SHOW COMMANDS SHOULD NOT BE USED IN PRODUCTION AS THEY HALT THE BGP ROUTE PROCESSING\n' + ) + self.wfile.write('AND CAN RESULT IN BGP PEERING SESSION DROPPING - You have been warned\n') + self.wfile.write('\n') + self.wfile.write('show neighbors\n') + self.wfile.write(' display the neighbor configured\\n\n') + self.wfile.write('show routes\n') + self.wfile.write(' display routes which have been announced\\n\n') + self.wfile.write('\n') + self.wfile.flush() + prompt = True + + elif command.startswith('announce '): + sys.stdout.write('%s\n' % command) + sys.stdout.flush() + self.wfile.write('requested %s annoucement\n' % command.split(' ')[1]) + self.wfile.flush() + prompt = True + + elif command.startswith('withdraw '): + sys.stdout.write('%s\n' % command) + sys.stdout.flush() + self.wfile.write('request %s withdrawal\n' % command.split(' ')[1]) + self.wfile.flush() + prompt = True + + elif command.startswith('neighbor '): + sys.stdout.write('%s\n' % command) + sys.stdout.flush() + self.wfile.write('neighbor %s requested\n' % command.split(' ')[1]) + self.wfile.flush() + prompt = True + + elif command.startswith('show '): + sys.stdout.write('%s\n' % command) + sys.stdout.flush() + self.wfile.write('%s requested\n' % command.split(' ')[1]) + self.wfile.flush() + prompt = True + + elif command in ['shutdown', 'reload', 'restart', 'version', '#']: + sys.stdout.write('%s\n' % command) + sys.stdout.flush() + prompt = True + + elif command not in ['go', '']: + self.wfile.write('unknown command [%s], try: help\n' % command) + self.wfile.flush() + prompt = True + + try: + r, _, _ = select.select([sys.stdin], [], [], 1.0) + except select.error: + raise KeyboardInterrupt('SIGNAL received in select') + + if r: + self.wfile.write('\n') + + while r: + # Can not use readline with select. + # From https://stackoverflow.com/questions/5486717/python-select-doesnt-signal-all-input-from-pipe + # Note that internally file.readlines([size]) loops and invokes the read() syscall more than once, attempting to fill an internal buffer of size. The first call to read() will immediately return, since select() indicated the fd was readable. However the 2nd call will block until data is available, which defeats the purpose of using select. In any case it is tricky to use file.readlines([size]) in an asynchronous app. + response = os.read(sys.stdin.fileno(), 4096) + # this should not happen as select informed us of data to read but it seems it does + if not response: + break + self.wfile.write(response) + prompt = True + time.sleep(0.1) + try: + r, _, _ = select.select([sys.stdin], [], [], 1.0) + except select.error: + raise KeyboardInterrupt('SIGNAL received in select') + continue + + +def timed(message): + now = time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime()) + return "%s | %-8s | %-6d | %-13s | %s" % (now, 'FORKED', os.getpid(), 'tcp-server', message) + + +def sig(signum, frame): + # outch rude but prevent silly trace on exit if waiting for a read on stdin :p + os.kill(os.getpid(), signal.SIGKILL) + signal.signal(signal.SIGINT, sig) signal.signal(signal.SIGTERM, sig) @@ -167,20 +191,22 @@ signal.signal(signal.SIGTERM, sig) count = 0 connected = False -class Server (TCPServer): - def server_activate (self): - print >> sys.stderr, timed('tcp-server listening on %s:%d' % (host,port)) - sys.stderr.flush() - TCPServer.server_activate(self) + +class Server(TCPServer): + def server_activate(self): + sys.stderr.write(timed('tcp-server listening on %s:%d' % (host, port))) + sys.stderr.flush() + TCPServer.server_activate(self) + while not connected: - try: - server = Server((host, port), Control) - connected = True - except socket.error: - count += 1 - if count % 1 == 0: - print >> sys.stderr, timed('tcp-server still trying to bind to %s:%d' % (host,port)) - # we can not connect to the socket, retrying (happens if respawns too quickly) - time.sleep(1) + try: + server = Server((host, port), Control) + connected = True + except socket.error: + count += 1 + if count % 1 == 0: + sys.stderr.write(timed('tcp-server still trying to bind to %s:%d' % (host, port))) + # we can not connect to the socket, retrying (happens if respawns too quickly) + time.sleep(1) server.serve_forever() diff --git a/lib/exabgp/application/pipe.py b/lib/exabgp/application/pipe.py index e0a279f6b..673901a2c 100644 --- a/lib/exabgp/application/pipe.py +++ b/lib/exabgp/application/pipe.py @@ -151,9 +151,7 @@ def loop(self): def monitor(function): def wrapper(*args): - # print >> sys.stderr, "%s(%s)" % (function.func_name,','.join([str(_).replace('\n','\\n') for _ in args])) r = function(*args) - # print >> sys.stderr, "%s -> %s" % (function.func_name,str(r)) return r return wrapper diff --git a/qa/bin/functional b/qa/bin/functional index 2cc72cfc7..81e35c952 100755 --- a/qa/bin/functional +++ b/qa/bin/functional @@ -42,6 +42,7 @@ export exabgp_debug_rotate=true export exabgp_debug_defensive=true """ + class Color(object): NONE = '\033[0m' + '\033[0m' + ' ' # NONE STARTING = '\033[0m' + '\033[96m' + '~' # LIGHT BLUE @@ -434,7 +435,9 @@ if __name__ == '__main__': def run(parsed): Port.base = parsed.port if parsed.test: - to_run = [parsed.test, ] + to_run = [ + parsed.test, + ] else: to_run = [index for index, _ in Identifier.identifiers()] chunk = len(to_run) if not parsed.steps else parsed.steps diff --git a/qa/self/api/receive.py b/qa/self/api/receive.py index 1190ed2d0..e4b4262d0 100755 --- a/qa/self/api/receive.py +++ b/qa/self/api/receive.py @@ -33,7 +33,6 @@ while True: line = sys.stdin.readline().strip() - # print >> sys.stderr, '[%s]' % line.replace('\n','\\n'), start, end options = match[count % 4] diff --git a/qa/tests/parsing_test.py b/qa/tests/parsing_test.py index dc1361baa..7d14a438c 100755 --- a/qa/tests/parsing_test.py +++ b/qa/tests/parsing_test.py @@ -42,7 +42,7 @@ def test_all_configuration(self): print(filename) print('=' * 80) sys.stdout.flush() - configuration = Configuration([filename, ]) + configuration = Configuration([filename,]) configuration.reload() del configuration diff --git a/setup.py b/setup.py index e45ee96e6..416eba0d3 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ sys.path.append(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), 'lib')) + def filesOf(directory): return [ os.path.join(directory, fname) diff --git a/tox.ini b/tox.ini index ad748815a..bdefcc590 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [flake8] ignore = W191 -max-line-length = 130 +max-line-length = 120 max-complexity = 10 exclude = .git,