github.com/osrg/gobgp@v2.0.0+incompatible/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 from __future__ import absolute_import 17 18 import time 19 20 from fabric import colors 21 from fabric.api import local 22 from fabric.utils import indent 23 24 from lib.base import ( 25 BGPContainer, 26 CmdBuffer, 27 try_several_times, 28 wait_for_completion, 29 ) 30 31 32 class BirdContainer(BGPContainer): 33 34 WAIT_FOR_BOOT = 1 35 SHARED_VOLUME = '/etc/bird' 36 37 def __init__(self, name, asn, router_id, ctn_image_name='osrg/bird'): 38 super(BirdContainer, self).__init__(name, asn, router_id, 39 ctn_image_name) 40 self.shared_volumes.append((self.config_dir, self.SHARED_VOLUME)) 41 42 def _start_bird(self): 43 c = CmdBuffer() 44 c << '#!/bin/sh' 45 c << 'bird' 46 cmd = 'echo "{0:s}" > {1}/start.sh'.format(c, self.config_dir) 47 local(cmd) 48 cmd = 'chmod 755 {0}/start.sh'.format(self.config_dir) 49 local(cmd) 50 self.local('{0}/start.sh'.format(self.SHARED_VOLUME)) 51 52 def _wait_for_boot(self): 53 def _f(): 54 ret = self.local('birdc show status > /dev/null 2>&1; echo $?', capture=True) 55 return ret == '0' 56 57 return wait_for_completion(_f) 58 59 def run(self): 60 super(BirdContainer, self).run() 61 self.reload_config() 62 return self.WAIT_FOR_BOOT 63 64 def create_config(self): 65 c = CmdBuffer() 66 c << 'router id {0};'.format(self.router_id) 67 for peer, info in self.peers.iteritems(): 68 c << 'protocol bgp {' 69 c << ' local as {0};'.format(self.asn) 70 n_addr = info['neigh_addr'].split('/')[0] 71 c << ' neighbor {0} as {1};'.format(n_addr, peer.asn) 72 c << ' multihop;' 73 c << '}' 74 75 with open('{0}/bird.conf'.format(self.config_dir), 'w') as f: 76 print colors.yellow('[{0}\'s new bird.conf]'.format(self.name)) 77 print colors.yellow(indent(str(c))) 78 f.writelines(str(c)) 79 80 def reload_config(self): 81 if len(self.peers) == 0: 82 return 83 84 def _reload(): 85 def _is_running(): 86 ps = self.local('ps', capture=True) 87 running = False 88 for line in ps.split('\n')[1:]: 89 if 'bird' in line: 90 running = True 91 return running 92 93 if _is_running(): 94 self.local('birdc configure') 95 else: 96 self._start_bird() 97 98 self._wait_for_boot() 99 if not _is_running(): 100 raise RuntimeError() 101 102 try_several_times(_reload) 103 104 105 class RawBirdContainer(BirdContainer): 106 def __init__(self, name, config, ctn_image_name='osrg/bird'): 107 asn = None 108 router_id = None 109 for line in config.split('\n'): 110 line = line.strip() 111 if line.startswith('local as'): 112 asn = int(line[len('local as'):].strip('; ')) 113 if line.startswith('router id'): 114 router_id = line[len('router id'):].strip('; ') 115 if not asn: 116 raise Exception('asn not in bird config') 117 if not router_id: 118 raise Exception('router-id not in bird config') 119 self.config = config 120 super(RawBirdContainer, self).__init__(name, asn, router_id, 121 ctn_image_name) 122 123 def create_config(self): 124 with open('{0}/bird.conf'.format(self.config_dir), 'w') as f: 125 print colors.yellow('[{0}\'s new bird.conf]'.format(self.name)) 126 print colors.yellow(indent(self.config)) 127 f.writelines(self.config)