# Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os import time import json import requests import quagga_access as qaccess import toml from peer_info import Peer from peer_info import Destination from peer_info import Path from ciscoconfparse import CiscoConfParse # get address of each neighbor from gobpg configration def get_neighbor_address(config): address = [] neighbors_config = config['NeighborList'] for neighbor_config in neighbors_config: neighbor_ip = neighbor_config['NeighborAddress'] address.append(neighbor_ip) return address # get route information on quagga def get_routing_table(neighbor_address, target_prefix, retry=3, interval=5): print "check route %s on quagga : %s" % (target_prefix, neighbor_address) retry_count = 0 while True: tn = qaccess.login(neighbor_address) q_rib = qaccess.show_rib(tn) qaccess.logout(tn) for q_path in q_rib: if target_prefix == q_path['Network']: return q_path retry_count += 1 if retry_count > retry: break else: print "target_prefix %s is none" % target_prefix print "wait (" + str(interval) + " seconds)" time.sleep(interval) print "route : %s is none" % target_prefix return None def get_adj_rib_in(url, neighbor_address, target_prefix, retry=3, interval=5): return get_adj_rib(url, neighbor_address, target_prefix, retry, interval, type="in") def get_adj_rib_out(url, neighbor_address, target_prefix, retry=3, interval=5): return get_adj_rib(url, neighbor_address, target_prefix, retry, interval, type="out") def get_adj_rib(base_url, neighbor_address, target_prefix, retry, interval, type="in"): url = base_url + neighbor_address + "/adj-rib-" +type +"/ipv4" retry_count = 0 while True: r = requests.get(url) in_rib = json.loads(r.text) print in_rib paths = [p for p in in_rib if p['Network'] == target_prefix] if len(paths) > 0: assert len(paths) == 1 return paths[0] else: retry_count += 1 if retry_count > retry: break else: print "adj_rib_%s is none" % type print "wait (" + str(interval) + " seconds)" time.sleep(interval) print "adj_rib_%s is none" % type return None def get_neighbor_state(base_url, neighbor_address): print "check neighbor state for %s" % (neighbor_address) state = None url = base_url + neighbor_address try: r = requests.get(url) neighbor = json.loads(r.text) state = neighbor['info']['bgp_state'] remote_ip = neighbor['conf']['remote_ip'] assert remote_ip == neighbor_address return state except Exception as e: print e return state def get_paths_in_localrib(base_url, neighbor_address, target_prefix, retry=3, interval=5): url = base_url + neighbor_address + "/local-rib" + "/ipv4" retry_count = 0 while True: r = requests.get(url) local_rib = json.loads(r.text) g_dests = local_rib['Destinations'] g_dest = [dest for dest in g_dests if dest['Prefix'] == target_prefix] if len(g_dest) > 0: assert len(g_dest) == 1 d = g_dest[0] return d['Paths'] else: retry_count += 1 if retry_count > retry: break else: print "destination is none : %s" % neighbor_address print "please wait more (" + str(interval) + " second)" time.sleep(interval) print "destination is none" return None def load_gobgp_config(gobgp_config_file): config = None try: config = toml.loads(open(gobgp_config_file).read()) except IOError, (errno, strerror): print "I/O error(%s): %s" % (errno, strerror) return config # load configration from quagga(bgpd.conf) def load_quagga_config(base_dir): configs = [] dirs = [] try: content = os.listdir(base_dir) for item in content: if "q" != item[0]: continue if os.path.isdir(os.path.join(base_dir, item)): dirs.append(item) except OSError, (errno, strerror): print "I/O error(%s): %s" % (errno, strerror) for dir in dirs: config_path = base_dir + dir + "/bgpd.conf" config = CiscoConfParse(config_path) peer_ip = config.find_objects(r"^!\smy\saddress")[0].text.split(" ")[3] peer_ip_version = config.find_objects(r"^!\smy\sip_version")[0].text.split(" ")[3] peer_id = config.find_objects(r"^bgp\srouter-id")[0].text.split(" ")[2] peer_as = config.find_objects(r"^router\sbgp")[0].text.split(" ")[2] quagga_config = Peer(peer_ip, peer_id, peer_as, peer_ip_version) networks = config.find_objects(r"^network") if len(networks) == 0: continue for network in networks: elems = network.text.split(" ") prefix = elems[1].split("/")[0] network = elems[1] nexthop = peer_ip path = Path(network, nexthop) dest = Destination(prefix) dest.paths.append(path) quagga_config.destinations[prefix] = dest # print "prefix: " + prefix # print "network: " + network # print "nexthop: " + nexthop neighbors = config.find_objects(r"^neighbor\s.*\sremote-as") if len(neighbors) == 0: continue for neighbor in neighbors: elems = neighbor.text.split(" ") neighbor = Peer(elems[1], None, elems[3], None) quagga_config.neighbors.append(neighbor) configs.append(quagga_config) return configs