|
1
|
|
|
# encoding: utf-8 |
|
2
|
|
|
|
|
3
|
|
|
"""exabgp configuration validation""" |
|
4
|
|
|
|
|
5
|
|
|
|
|
6
|
|
|
import sys |
|
7
|
|
|
import syslog |
|
8
|
|
|
import argparse |
|
9
|
|
|
|
|
10
|
|
|
from exabgp.environment import getenv |
|
11
|
|
|
from exabgp.environment import getconf |
|
12
|
|
|
|
|
13
|
|
|
from exabgp.debug import trace_interceptor |
|
14
|
|
|
from exabgp.logger import log |
|
15
|
|
|
|
|
16
|
|
|
from exabgp.reactor.loop import Reactor |
|
17
|
|
|
from exabgp.configuration.check import check_generation |
|
18
|
|
|
|
|
19
|
|
|
|
|
20
|
|
|
def args(sub): |
|
21
|
|
|
# fmt:off |
|
22
|
|
|
sub.add_argument('-n', '--neighbor', help='check the parsing of the neighbors', action='store_true') |
|
23
|
|
|
sub.add_argument('-r', '--route', help='check the parsing of the routes', action='store_true') |
|
24
|
|
|
sub.add_argument('-v', '--verbose', help='be verbose in the display', action='store_true') |
|
25
|
|
|
sub.add_argument('-p', '--pdb', help='fire the debugger on critical logging, SIGTERM, and exceptions (shortcut for exabgp.pdb.enable=true)', action='store_true') |
|
26
|
|
|
sub.add_argument('configuration', help='configuration file(s)', nargs='+', type=str) |
|
27
|
|
|
# fmt:on |
|
28
|
|
|
|
|
29
|
|
|
|
|
30
|
|
|
def cmdline(cmdarg): |
|
31
|
|
|
env = getenv() |
|
32
|
|
|
|
|
33
|
|
|
# Must be done before setting the logger as it modify its behaviour |
|
34
|
|
|
if cmdarg.verbose: |
|
35
|
|
|
env.log.all = True |
|
36
|
|
|
env.log.level = syslog.LOG_DEBUG |
|
37
|
|
|
|
|
38
|
|
|
log.init() |
|
39
|
|
|
|
|
40
|
|
|
if cmdarg.pdb: |
|
41
|
|
|
env.debug.pdb = True |
|
42
|
|
|
|
|
43
|
|
|
if cmdarg.verbose: |
|
44
|
|
|
env.log.parser = True |
|
45
|
|
|
|
|
46
|
|
|
for configuration in cmdarg.configuration: |
|
47
|
|
|
log.notice(f'loading {configuration}', 'configuration') |
|
48
|
|
|
location = getconf(configuration) |
|
49
|
|
|
if not location: |
|
50
|
|
|
log.critical(f'{configuration} is not an exabgp config file', 'configuration') |
|
51
|
|
|
sys.exit(1) |
|
52
|
|
|
|
|
53
|
|
|
config = Reactor([location]).configuration |
|
54
|
|
|
|
|
55
|
|
|
if not config.reload(): |
|
56
|
|
|
log.critical(f'{configuration} is not a valid config file', 'configuration') |
|
57
|
|
|
sys.exit(1) |
|
58
|
|
|
log.info(f'\u2713 loading', 'configuration') |
|
59
|
|
|
|
|
60
|
|
|
if cmdarg.neighbor: |
|
61
|
|
|
log.notice(f'checking neighbors', 'configuration') |
|
62
|
|
|
for name, neighbor in config.neighbors.items(): |
|
63
|
|
|
reparsed = neighbor.string() |
|
64
|
|
|
for line in reparsed.split('\n'): |
|
65
|
|
|
log.debug(line, configuration) |
|
66
|
|
|
log.info(f'\u2713 neighbor {name.split()[1]}', 'configuration') |
|
67
|
|
|
|
|
68
|
|
|
if cmdarg.route: |
|
69
|
|
|
log.notice(f'checking routes', 'configuration') |
|
70
|
|
|
if not check_generation(config.neighbors): |
|
71
|
|
|
log.critical(f'{configuration} has an invalid route', 'configuration') |
|
72
|
|
|
sys.exit(1) |
|
73
|
|
|
log.info(f'\u2713 routes', 'configuration') |
|
74
|
|
|
|
|
75
|
|
|
|
|
76
|
|
|
def main(): |
|
77
|
|
|
parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__) |
|
78
|
|
|
args(parser) |
|
79
|
|
|
trace_interceptor() |
|
80
|
|
|
cmdline(parser, parser.parse_args()) |
|
81
|
|
|
|
|
82
|
|
|
|
|
83
|
|
|
if __name__ == '__main__': |
|
84
|
|
|
main() |
|
85
|
|
|
|