diff --git a/napalm/eos.py b/napalm/eos.py index 6cf460afb..4a694f156 100644 --- a/napalm/eos.py +++ b/napalm/eos.py @@ -232,92 +232,126 @@ def get_interfaces_counters(self): return interface_counters + @staticmethod + def _parse_neigbor_info(line): + m = re.match('BGP neighbor is (?P.*?), remote AS (?P.*?), .*', line) + return m.group('neighbor'), m.group('as') + + @staticmethod + def _parse_rid_info(line): + m = re.match('.*BGP version 4, remote router ID (?P.*?), VRF (?P.*?)$', line) + return m.group('rid'), m.group('vrf') + + @staticmethod + def _parse_desc(line): + m = re.match('\s+Description: (?P.*?)', line) + if m: + return m.group('description') + else: + return None + + @staticmethod + def _parse_local_info(line): + m = re.match('Local AS is (?P.*?),.*', line) + return m.group('as') + + @staticmethod + def _parse_prefix_info(line): + m = re.match('(\s*?)(?PIPv[46]) Unicast:\s*(?P\d+)\s*(?P\d+)', line) + return m.group('sent'), m.group('received') + def get_bgp_neighbors(self): + NEIGHBOR_FILTER = 'bgp neighbors vrf all | include remote AS | remote router ID |^\s*IPv[46] Unicast:.*[0-9]+|^Local AS|Desc' + output_summary_cmds = self.device.run_commands( + ['show ipv6 bgp summary vrf all', 'show ip bgp summary vrf all'], + encoding='json') + output_neighbor_cmds = self.device.run_commands( + ['show ip ' + NEIGHBOR_FILTER, 'show ipv6 ' + NEIGHBOR_FILTER], + encoding='text') + + bgp_counters = defaultdict(lambda: dict(peers=dict())) + for summary in output_summary_cmds: + """ + Json output looks as follows + "vrfs": { + "default": { + "routerId": 1, + "asn": 1, + "peers": { + "1.1.1.1": { + "msgSent": 1, + "inMsgQueue": 0, + "prefixReceived": 3926, + "upDownTime": 1449501378.418644, + "version": 4, + "msgReceived": 59616, + "prefixAccepted": 3926, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": 1 + } + } + } + } + """ + for vrf, vrf_data in summary['vrfs'].iteritems(): + bgp_counters[vrf]['router_id'] = vrf_data['routerId'] + for peer, peer_data in vrf_data['peers'].iteritems(): + peer_info = { + 'is_up': peer_data['peerState'] == 'Established', + 'is_enabled': peer_data['peerState'] == 'Established' or peer_data['peerState'] == 'Active', + 'uptime': int(peer_data['upDownTime']) + } + bgp_counters[vrf]['peers'][peer] = peer_info + lines = [] + [lines.extend(x['output'].splitlines()) for x in output_neighbor_cmds] + for line in lines: + """ + Raw output from the command looks like the following: + + BGP neighbor is 1.1.1.1, remote AS 1, external link + Description: Very info such descriptive + BGP version 4, remote router ID 1.1.1.1, VRF my_vrf + IPv4 Unicast: 683 78 + IPv6 Unicast: 0 0 + Local AS is 2, local router ID 2.2.2.2 + """ + if line is '': + continue + neighbor, r_as = self._parse_neigbor_info(lines.pop(0)) + # this line can be either description or rid info + next_line = lines.pop(0) + desc = self._parse_desc(next_line) + if desc is None: + rid, vrf = self._parse_rid_info(next_line) + desc = '' + else: + rid, vrf = self._parse_rid_info(lines.pop(0)) + + v4_sent, v4_recv = self._parse_prefix_info(lines.pop(0)) + v6_sent, v6_recv = self._parse_prefix_info(lines.pop(0)) + local_as = self._parse_local_info(lines.pop(0)) + data = { + 'remote_as': int(r_as), + 'remote_id': unicode(rid), + 'local_as': int(local_as), + 'description': unicode(desc), + 'address_family': { + 'ipv4': { + 'sent_prefixes': int(v4_sent), + 'received_prefixes': int(v4_recv), + 'accepted_prefixes': -1 + }, + 'ipv6': { + 'sent_prefixes': int(v6_sent), + 'received_prefixes': int(v6_recv), + 'accepted_prefixes': -1 + } + } + } + bgp_counters[vrf]['peers'][neighbor].update(data) - commands_json = list() - commands_txt = list() - commands_json.append('show ip bgp summary vrf all') - commands_json.append('show ipv6 bgp summary vrf all') - commands_txt.append('show ip bgp neighbors vrf all | include remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:') - commands_txt.append('show ipv6 bgp neighbors vrf all | include remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:') - - output_summary = self.device.run_commands(commands_json, encoding='json') - output_neighbors = self.device.run_commands(commands_txt, encoding='text') - - ########################################## - # no JSON available for show ip bgp neigh - # Using 'show ipv[4-6] bgp neighbors vrf all | i remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:' - # NOTE: if there is no description, EOS does not print the line. - - - # Regex the output from show ip bgp neigh - def get_bgp_neighbor(needed_peer, vrf, output_to_parse): - import re - - bgp_neighbors = dict() - bgp_peer = dict() - neighbor_regexp = re.compile('BGP neighbor is (.*?),') - description_regexp = re.compile('Description: (.*?)$') - remote_id_regexp = re.compile('remote router ID (.*?),') - vrf_regexp = re.compile('VRF (.*?)$') - IPv4_sent_regexp = re.compile('IPv4 Unicast: ( *)(\d*) ') - IPv6_sent_regexp = re.compile('IPv6 Unicast: ( *)(\d*) ') - - for line in output_to_parse.splitlines(): - if re.search(neighbor_regexp, line): - peer = re.search(neighbor_regexp, line).group(1) - bgp_neighbors[peer] = dict() - bgp_neighbors[peer]['description'] = '' - continue - elif re.search(description_regexp, line): - bgp_neighbors[peer]['description'] = re.search(description_regexp, line).group(1) - continue - elif re.search(remote_id_regexp, line): - bgp_neighbors[peer]['remote_id'] = re.search(remote_id_regexp, line).group(1) - bgp_neighbors[peer]['vrf'] = re.search(vrf_regexp, line).group(1) - continue - elif re.search(IPv4_sent_regexp, line): - bgp_neighbors[peer]['ipv4'] = re.search(IPv4_sent_regexp, line).group(2) - continue - elif re.search(IPv6_sent_regexp, line): - bgp_neighbors[peer]['ipv6'] = re.search(IPv6_sent_regexp, line).group(2) - continue - try: - peer = next(peer for peer in bgp_neighbors if peer == needed_peer) - except StopIteration: - raise Exception("Peer %s not found in show bgp neighbors" % needed_peer) - if bgp_neighbors[peer]['vrf'] == vrf: - bgp_peer['remote_id'] = bgp_neighbors[peer]['remote_id'] - bgp_peer['description'] = bgp_neighbors[peer]['description'] - bgp_peer['ipv4'] = bgp_neighbors[peer]['ipv4'] - bgp_peer['ipv6'] = bgp_neighbors[peer]['ipv6'] - return bgp_peer - - bgp_counters = defaultdict(dict) - for output_id in [0, 1]: - for vrf in output_summary[output_id]['vrfs']: - bgp_counters[vrf]['router_id'] = unicode(output_summary[output_id]['vrfs'][vrf]['routerId']) - bgp_counters[vrf]['peers'] = dict() - for peer in output_summary[output_id]['vrfs'][vrf]['peers']: - bgp_counters[vrf]['peers'][peer] = dict() - bgp_counters[vrf]['peers'][peer]['local_as'] = int(output_summary[output_id]['vrfs'][vrf]['asn']) - bgp_counters[vrf]['peers'][peer]['remote_as'] = int(output_summary[output_id]['vrfs'][vrf]['peers'][peer]['asn']) - peerState = output_summary[output_id]['vrfs'][vrf]['peers'][peer]['peerState'] - bgp_counters[vrf]['peers'][peer]['is_up'] = peerState == 'Established' - if 'peerStateIdleReason' in output_summary[output_id]['vrfs'][vrf]['peers'][peer]: - bgp_counters[vrf]['peers'][peer]['is_enabled'] = False - else: - bgp_counters[vrf]['peers'][peer]['is_enabled'] = peerState == 'Established' or peerState == 'Active' - bgp_counters[vrf]['peers'][peer]['uptime'] = int(output_summary[output_id]['vrfs'][vrf]['peers'][peer]['upDownTime']) - bgp_peer = get_bgp_neighbor(peer, vrf, output_neighbors[output_id]['output']) - bgp_counters[vrf]['peers'][peer]['remote_id'] = unicode(bgp_peer['remote_id']) - bgp_counters[vrf]['peers'][peer]['description'] = unicode(bgp_peer['description']) - bgp_counters[vrf]['peers'][peer]['address_family'] = dict() - for family in ['ipv4', 'ipv6']: - bgp_counters[vrf]['peers'][peer]['address_family'][family] = dict() - bgp_counters[vrf]['peers'][peer]['address_family'][family]['received_prefixes'] = int(output_summary[output_id]['vrfs'][vrf]['peers'][peer]['prefixReceived']) - bgp_counters[vrf]['peers'][peer]['address_family'][family]['accepted_prefixes'] = int(output_summary[output_id]['vrfs'][vrf]['peers'][peer]['prefixAccepted']) - bgp_counters[vrf]['peers'][peer]['address_family'][family]['sent_prefixes'] = int(bgp_peer[family]) if 'default' in bgp_counters.keys(): bgp_counters['global'] = bgp_counters.pop('default') return bgp_counters diff --git a/test/unit/TestEOSDriver.py b/test/unit/TestEOSDriver.py index cf0edceed..2931fd492 100644 --- a/test/unit/TestEOSDriver.py +++ b/test/unit/TestEOSDriver.py @@ -17,6 +17,7 @@ from napalm import eos from base import TestConfigNetworkDriver, TestGettersNetworkDriver import json +import re class TestConfigEOSDriver(unittest.TestCase, TestConfigNetworkDriver): @@ -72,6 +73,7 @@ def run_commands(self, command_list, encoding='json'): if encoding == 'json': result.append(self.read_json_file('eos/mock_data/{}.json'.format(command.replace(' ', '_')))) else: - result.append({'output': self.read_txt_file('eos/mock_data/{}.txt'.format(command.replace(' ', '_')))}) + cmd = re.sub(r'[\[\]\*\^\+\s\|]', '_', command) + result.append({'output': self.read_txt_file('eos/mock_data/{}.txt'.format(cmd))}) return result diff --git "a/test/unit/eos/mock_data/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID___\\s_IPv_46__Unicast:.__0-9____Local_AS_Desc.txt" "b/test/unit/eos/mock_data/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID___\\s_IPv_46__Unicast:.__0-9____Local_AS_Desc.txt" new file mode 100644 index 000000000..813db0418 --- /dev/null +++ "b/test/unit/eos/mock_data/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID___\\s_IPv_46__Unicast:.__0-9____Local_AS_Desc.txt" @@ -0,0 +1,10 @@ +BGP neighbor is 192.168.56.2, remote AS 65002, external link + BGP version 4, remote router ID 192.168.56.2, VRF default + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65001, local router ID 192.168.56.3 +BGP neighbor is 192.168.56.4, remote AS 65001, external link + BGP version 4, remote router ID 192.168.56.3, VRF default + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/unit/eos/mock_data/show_ip_bgp_neighbors_vrf_all_|_include_remote_AS|remote_router_ID|Description|^_*IPv[4-6]_Unicast:.txt b/test/unit/eos/mock_data/show_ip_bgp_neighbors_vrf_all_|_include_remote_AS|remote_router_ID|Description|^_*IPv[4-6]_Unicast:.txt deleted file mode 100644 index d9505ee74..000000000 --- a/test/unit/eos/mock_data/show_ip_bgp_neighbors_vrf_all_|_include_remote_AS|remote_router_ID|Description|^_*IPv[4-6]_Unicast:.txt +++ /dev/null @@ -1,32 +0,0 @@ -BGP neighbor is 10.240.161.159, remote AS 4200102114, external link - BGP version 4, remote router ID 10.240.212.97, VRF public - IPv4 Unicast: 406 0 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.160.201, remote AS 4200102105, external link - BGP version 4, remote router ID 10.240.212.88, VRF public - IPv4 Unicast: 406 0 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.160.203, remote AS 4200102106, external link - BGP version 4, remote router ID 10.240.212.89, VRF public - IPv4 Unicast: 406 0 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.160.205, remote AS 4200102107, external link - BGP version 4, remote router ID 10.240.212.90, VRF public - IPv4 Unicast: 406 0 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.112.185, remote AS 4200103176, external link - BGP version 4, remote router ID 10.240.208.128, VRF service - IPv4 Unicast: 695 1 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.112.187, remote AS 4200103157, external link - BGP version 4, remote router ID 10.240.208.108, VRF service - IPv4 Unicast: 695 1 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.112.181, remote AS 4200103177, external link - BGP version 4, remote router ID 10.240.208.129, VRF service - IPv4 Unicast: 695 1 - IPv6 Unicast: 0 0 -BGP neighbor is 10.240.112.183, remote AS 4200103172, external link - BGP version 4, remote router ID 10.240.208.124, VRF service - IPv4 Unicast: 695 1 - IPv6 Unicast: 0 0 \ No newline at end of file diff --git a/test/unit/eos/mock_data/show_ip_bgp_summary_vrf_all.json b/test/unit/eos/mock_data/show_ip_bgp_summary_vrf_all.json index af3baa9d6..acf1484f8 100644 --- a/test/unit/eos/mock_data/show_ip_bgp_summary_vrf_all.json +++ b/test/unit/eos/mock_data/show_ip_bgp_summary_vrf_all.json @@ -1,115 +1,37 @@ { "vrfs": { - "public": { - "routerId": "10.240.212.2", + "default": { + "routerId": "192.168.56.3", "peers": { - "10.240.161.159": { - "outMsgQueue": 0, - "peerStateIdleReason": "Admin", - "version": 4, - "msgSent": 251663, + "192.168.56.2": { + "msgSent": 6, "inMsgQueue": 0, - "msgReceived": 259976, - "prefixAccepted": 0, "prefixReceived": 0, - "peerState": "Established", - "upDownTime": 1441805829.766247, - "asn": 4200102114 - }, - "10.240.160.201": { - "outMsgQueue": 0, + "upDownTime": 1452680643.198489, "version": 4, - "msgSent": 352976, - "inMsgQueue": 0, - "msgReceived": 365937, + "msgReceived": 5, "prefixAccepted": 0, - "prefixReceived": 0, "peerState": "Established", - "upDownTime": 1438864651.752042, - "asn": 4200102105 - }, - "10.240.160.203": { "outMsgQueue": 0, - "version": 4, - "msgSent": 329552, - "inMsgQueue": 0, - "msgReceived": 340528, - "prefixAccepted": 0, - "prefixReceived": 0, - "peerState": "Established", - "upDownTime": 1439558603.752355, - "asn": 4200102106 + "underMaintenance": false, + "asn": 65002 }, - "10.240.160.205": { - "outMsgQueue": 0, - "version": 4, - "msgSent": 329553, + "192.168.56.4": { + "msgSent": 267, "inMsgQueue": 0, - "msgReceived": 340539, - "prefixAccepted": 0, "prefixReceived": 0, - "peerState": "Established", - "upDownTime": 1439558615.752671, - "asn": 4200102107 - } - }, - "vrf": "public", - "asn": 4200102900 - }, - "service": { - "routerId": "10.240.208.2", - "peers": { - "10.240.112.185": { - "outMsgQueue": 0, - "version": 4, - "msgSent": 470510, - "inMsgQueue": 0, - "msgReceived": 501980, - "prefixAccepted": 1, - "prefixReceived": 1, - "peerState": "Established", - "upDownTime": 1435246775.799272, - "asn": 4200103176 - }, - "10.240.112.187": { - "outMsgQueue": 0, + "upDownTime": 1452696202.499104, "version": 4, - "msgSent": 470870, - "inMsgQueue": 0, - "msgReceived": 502000, - "prefixAccepted": 1, - "prefixReceived": 1, - "peerState": "Established", - "upDownTime": 1436657587.799585, - "asn": 4200103157 - }, - "10.240.112.181": { - "outMsgQueue": 0, - "version": 4, - "msgSent": 323979, - "inMsgQueue": 0, - "msgReceived": 345641, - "prefixAccepted": 1, - "prefixReceived": 1, - "peerState": "Established", - "upDownTime": 1439497916.798645, - "asn": 4200103177 - }, - "10.240.112.183": { + "msgReceived": 263, + "prefixAccepted": 0, + "peerState": "Active", "outMsgQueue": 0, - "version": 4, - "msgSent": 470470, - "inMsgQueue": 0, - "msgReceived": 502028, - "prefixAccepted": 1, - "prefixReceived": 1, - "peerState": "Established", - "upDownTime": 1435246725.798959, - "asn": 4200103172 + "underMaintenance": false, + "asn": 65001 } }, - "vrf": "service", - "asn": 4200103900 + "vrf": "default", + "asn": 65001 } } -} \ No newline at end of file +} diff --git "a/test/unit/eos/mock_data/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID___\\s_IPv_46__Unicast:.__0-9____Local_AS_Desc.txt" "b/test/unit/eos/mock_data/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID___\\s_IPv_46__Unicast:.__0-9____Local_AS_Desc.txt" new file mode 100644 index 000000000..234bb2f4d --- /dev/null +++ "b/test/unit/eos/mock_data/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID___\\s_IPv_46__Unicast:.__0-9____Local_AS_Desc.txt" @@ -0,0 +1,10 @@ +BGP neighbor is 2001:7f8::f10:0:2, remote AS 65002, external link + BGP version 4, remote router ID 192.168.56.2, VRF default + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65001, local router ID 192.168.56.3 +BGP neighbor is 2001:7f8::f10:0:3, remote AS 65001, external link + BGP version 4, remote router ID 192.168.56.3, VRF default + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/unit/eos/mock_data/show_ipv6_bgp_neighbors_vrf_all_|_include_remote_AS|remote_router_ID|Description|^_*IPv[4-6]_Unicast:.txt b/test/unit/eos/mock_data/show_ipv6_bgp_neighbors_vrf_all_|_include_remote_AS|remote_router_ID|Description|^_*IPv[4-6]_Unicast:.txt deleted file mode 100644 index 93bddd9c4..000000000 --- a/test/unit/eos/mock_data/show_ipv6_bgp_neighbors_vrf_all_|_include_remote_AS|remote_router_ID|Description|^_*IPv[4-6]_Unicast:.txt +++ /dev/null @@ -1,20 +0,0 @@ -BGP neighbor is 2001:7f8::f10:0:1, remote AS 3856, external link - Description: Packet Clearing House - BGP version 4, remote router ID 74.80.98.4, VRF default - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 1 -BGP neighbor is 2001:7f8::20ea:0:2, remote AS 8426, external link - Description: Claranet - BGP version 4, remote router ID 212.6.200.5, VRF default - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 21 -BGP neighbor is 2001:7f8::21b8:0:1, remote AS 8632, external link - Description: Luxembourg-Online - BGP version 4, remote router ID 195.218.2.244, VRF default - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 1 -BGP neighbor is 2001:7f8::71d4:0:1, remote AS 29140, external link - Description: Hostserver - BGP version 4, remote router ID 217.31.95.251, VRF default - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 3 \ No newline at end of file diff --git a/test/unit/eos/mock_data/show_ipv6_bgp_summary_vrf_all.json b/test/unit/eos/mock_data/show_ipv6_bgp_summary_vrf_all.json index f6b7f4abe..8fb632db0 100644 --- a/test/unit/eos/mock_data/show_ipv6_bgp_summary_vrf_all.json +++ b/test/unit/eos/mock_data/show_ipv6_bgp_summary_vrf_all.json @@ -1,63 +1,37 @@ { "vrfs": { "default": { - "routerId": "10.208.224.149", + "routerId": "192.168.56.3", "peers": { - "2001:7f8::f10:0:1": { - "msgSent": 138207, + "2001:7f8::f10:0:2": { + "msgSent": 5, "inMsgQueue": 0, - "prefixReceived": 1, - "upDownTime": 1448374400.650718, + "prefixReceived": 0, + "upDownTime": 1452681618.167685, "version": 4, - "msgReceived": 138206, + "msgReceived": 5, "prefixAccepted": 0, "peerState": "Established", "outMsgQueue": 0, "underMaintenance": false, - "asn": 3856 + "asn": 65002 }, - "2001:7f8::20ea:0:2": { - "msgSent": 138232, + "2001:7f8::f10:0:3": { + "msgSent": 267, "inMsgQueue": 0, - "prefixReceived": 21, - "upDownTime": 1448374477.663486, + "prefixReceived": 0, + "upDownTime": 1452696202.499104, "version": 4, - "msgReceived": 156257, + "msgReceived": 263, "prefixAccepted": 0, - "peerState": "Established", - "outMsgQueue": 0, - "underMaintenance": false, - "asn": 8426 - }, - "2001:7f8::21b8:0:1": { - "msgSent": 131100, - "inMsgQueue": 0, - "prefixReceived": 1, - "upDownTime": 1448374399.665499, - "version": 4, - "msgReceived": 132797, - "prefixAccepted": 0, - "peerState": "Established", - "outMsgQueue": 0, - "underMaintenance": false, - "asn": 8632 - }, - "2001:7f8::71d4:0:1": { - "msgSent": 276459, - "inMsgQueue": 0, - "prefixReceived": 3, - "upDownTime": 1448374403.678457, - "version": 4, - "msgReceived": 276495, - "prefixAccepted": 0, - "peerState": "Established", + "peerState": "Active", "outMsgQueue": 0, "underMaintenance": false, - "asn": 29140 + "asn": 65001 } }, "vrf": "default", - "asn": 8403 + "asn": 65001 } } } \ No newline at end of file