github.com/osrg/gobgp/v3@v3.30.0/test/lib/bird.py (about) 1 # Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 # implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 17 18 import time 19 20 from lib.base import ( 21 BGPContainer, 22 CmdBuffer, 23 try_several_times, 24 wait_for_completion, 25 yellow, 26 indent, 27 local, 28 ) 29 30 31 class BirdContainer(BGPContainer): 32 33 WAIT_FOR_BOOT = 1 34 SHARED_VOLUME = '/etc/bird' 35 36 def __init__(self, name, asn, router_id, ctn_image_name='osrg/bird'): 37 super(BirdContainer, self).__init__(name, asn, router_id, 38 ctn_image_name) 39 self.shared_volumes.append((self.config_dir, self.SHARED_VOLUME)) 40 41 def _start_bird(self): 42 c = CmdBuffer() 43 c << '#!/bin/sh' 44 c << 'bird' 45 cmd = 'echo "{0:s}" > {1}/start.sh'.format(c, self.config_dir) 46 local(cmd) 47 cmd = 'chmod 755 {0}/start.sh'.format(self.config_dir) 48 local(cmd) 49 self.local('{0}/start.sh'.format(self.SHARED_VOLUME)) 50 51 def _wait_for_boot(self): 52 def _f(): 53 ret = self.local('birdc show status > /dev/null 2>&1; echo $?', capture=True) 54 return ret == '0' 55 56 return wait_for_completion(_f) 57 58 def run(self): 59 super(BirdContainer, self).run() 60 self.reload_config() 61 return self.WAIT_FOR_BOOT 62 63 def create_config(self): 64 c = CmdBuffer() 65 c << 'router id {0};'.format(self.router_id) 66 for peer, info in self.peers.items(): 67 c << 'protocol bgp {' 68 c << ' local as {0};'.format(self.asn) 69 n_addr = info['neigh_addr'].split('/')[0] 70 c << ' neighbor {0} as {1};'.format(n_addr, peer.asn) 71 c << ' multihop;' 72 c << '}' 73 74 with open('{0}/bird.conf'.format(self.config_dir), 'w') as f: 75 print(yellow('[{0}\'s new bird.conf]'.format(self.name))) 76 print(yellow(indent(str(c)))) 77 f.writelines(str(c)) 78 79 def reload_config(self): 80 if len(self.peers) == 0: 81 return 82 83 def _reload(): 84 def _is_running(): 85 ps = self.local('ps', capture=True) 86 running = False 87 for line in ps.split('\n')[1:]: 88 if 'bird' in line: 89 running = True 90 return running 91 92 if _is_running(): 93 self.local('birdc configure') 94 else: 95 self._start_bird() 96 97 self._wait_for_boot() 98 if not _is_running(): 99 raise RuntimeError() 100 101 try_several_times(_reload) 102 103 104 class RawBirdContainer(BirdContainer): 105 def __init__(self, name, config, ctn_image_name='osrg/bird'): 106 asn = None 107 router_id = None 108 for line in config.split('\n'): 109 line = line.strip() 110 if line.startswith('local as'): 111 asn = int(line[len('local as'):].strip('; ')) 112 if line.startswith('router id'): 113 router_id = line[len('router id'):].strip('; ') 114 if not asn: 115 raise Exception('asn not in bird config') 116 if not router_id: 117 raise Exception('router-id not in bird config') 118 self.config = config 119 super(RawBirdContainer, self).__init__(name, asn, router_id, 120 ctn_image_name) 121 122 def create_config(self): 123 with open('{0}/bird.conf'.format(self.config_dir), 'w') as f: 124 print(yellow('[{0}\'s new bird.conf]'.format(self.name))) 125 print(yellow(indent(self.config))) 126 f.writelines(self.config)