forked from PEERINGTestbed/client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
peering.py
84 lines (68 loc) · 2.86 KB
/
peering.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import json
import os
import subprocess
import sys
import jinja2
import jsonschema
class AnnouncementController(object):
def __init__(self, bird_cfg_dir, bird_sock, schema_fn):
with open(schema_fn) as fd:
self.schema = json.load(fd)
self.bird_cfg_dir = str(bird_cfg_dir)
self.bird_sock = str(bird_sock)
self.config_template = self.__load_config_template()
self.__create_routes()
def __load_config_template(self):
path = os.path.join(self.bird_cfg_dir, 'templates')
env = jinja2.Environment(loader=jinja2.FileSystemLoader(path))
return env.get_template('export_mux_pfx.jinja2')
def __config_file(self, prefix, mux):
fn = 'export_%s_%s.conf' % (mux, prefix.replace('/', '-'))
return os.path.join(self.bird_cfg_dir, 'prefix-filters', fn)
def __create_routes(self):
path = os.path.join(self.bird_cfg_dir, 'route-announcements')
os.makedirs(path, exist_ok=True)
for pfx in self.schema['definitions']['allocatedPrefix']['enum']:
fpath = os.path.join(path, pfx.replace('/', '-'))
fd = open(fpath, 'w')
fd.write('route %s unreachable;\n' % pfx)
fd.close()
def validate(self, announcement):
jsonschema.validate(announcement, self.schema)
def deploy(self, announcement):
self.validate(announcement)
self.update_config(announcement)
self.reload_config()
def update_config(self, announcement):
self.validate(announcement)
for prefix, announce in announcement.items():
for mux in announce.get('withdraw', list()):
self.withdraw(prefix, mux)
for spec in announce.get('announce', list()):
self.announce(prefix, spec)
def withdraw(self, prefix, mux):
try:
os.unlink(self.__config_file(prefix, mux))
except FileNotFoundError:
pass
def announce(self, prefix, spec):
for mux in spec['muxes']:
with open(self.__config_file(prefix, mux), 'w') as fd:
fd.write(self.config_template.render(prefix=prefix, spec=spec))
def reload_config(self):
cmd = 'birdc -s %s' % self.bird_sock
proc = subprocess.Popen(cmd.split(),
stdin=subprocess.PIPE,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
_stdout, _stderr = proc.communicate(b'configure\n')
def main():
with open(sys.argv[1], 'r') as announcement_json_fd:
announcement = json.load(announcement_json_fd)
bird_cfg_dir = 'configs/bird'
bird_sock = 'var/bird.ctl'
schema_fn = 'configs/announcement_schema.json'
ctrl = AnnouncementController(bird_cfg_dir, bird_sock, schema_fn)
ctrl.deploy(announcement)
if __name__ == '__main__':
sys.exit(main())