From b4dc3912e8945736bea33923dad1d88bc52752b3 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 26 Jan 2017 14:53:11 +0000 Subject: [PATCH 1/9] Replace list() with [] and dict() with {} I don't like them anymore :( --- napalm_eos/eos.py | 88 +++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/napalm_eos/eos.py b/napalm_eos/eos.py index 011c58b..9594422 100644 --- a/napalm_eos/eos.py +++ b/napalm_eos/eos.py @@ -128,7 +128,7 @@ def _load_config(self, filename=None, config=None, replace=True): else: self.config_session = 'napalm_{}'.format(datetime.now().microsecond) - commands = list() + commands = [] commands.append('configure session {}'.format(self.config_session)) if replace: @@ -183,7 +183,7 @@ def compare_config(self): def commit_config(self): """Implementation of NAPALM method commit_config.""" - commands = list() + commands = [] commands.append('copy startup-config flash:rollback-0') commands.append('configure session {}'.format(self.config_session)) commands.append('commit') @@ -195,7 +195,7 @@ def commit_config(self): def discard_config(self): """Implementation of NAPALM method discard_config.""" if self.config_session is not None: - commands = list() + commands = [] commands.append('configure session {}'.format(self.config_session)) commands.append('abort') self.device.run_commands(commands) @@ -203,7 +203,7 @@ def discard_config(self): def rollback(self): """Implementation of NAPALM method rollback.""" - commands = list() + commands = [] commands.append('configure replace flash:rollback-0') commands.append('write memory') self.device.run_commands(commands) @@ -238,14 +238,14 @@ def get_facts(self): } def get_interfaces(self): - commands = list() + commands = [] commands.append('show interfaces') output = self.device.run_commands(commands)[0] - interfaces = dict() + interfaces = {} for interface, values in output['interfaces'].items(): - interfaces[interface] = dict() + interfaces[interface] = {} if values['lineProtocolStatus'] == 'up': interfaces[interface]['is_up'] = True @@ -268,15 +268,15 @@ def get_interfaces(self): return interfaces def get_lldp_neighbors(self): - commands = list() + commands = [] commands.append('show lldp neighbors') output = self.device.run_commands(commands)[0]['lldpNeighbors'] - lldp = dict() + lldp = {} for n in output: if n['port'] not in lldp.keys(): - lldp[n['port']] = list() + lldp[n['port']] = [] lldp[n['port']].append( { @@ -329,7 +329,7 @@ def get_re_group(res, key, default=None): ['show ip ' + NEIGHBOR_FILTER, 'show ipv6 ' + NEIGHBOR_FILTER], encoding='text') - bgp_counters = defaultdict(lambda: dict(peers=dict())) + bgp_counters = defaultdict(lambda: dict(peers={})) for summary in output_summary_cmds: """ Json output looks as follows @@ -497,13 +497,13 @@ def extract_temperature_data(data): def get_lldp_neighbors_detail(self, interface=''): - lldp_neighbors_out = dict() + lldp_neighbors_out = {} - filters = list() + filters = [] if interface: filters.append(interface) - commands = list() + commands = [] commands.append( 'show lldp neighbors {filters} detail'.format( filters=' '.join(filters) @@ -522,7 +522,7 @@ def get_lldp_neighbors_detail(self, interface=''): # it is provided a list of neighbors per interface for neighbor in interface_neighbors: if interface not in lldp_neighbors_out.keys(): - lldp_neighbors_out[interface] = list() + lldp_neighbors_out[interface] = [] capabilities = neighbor.get('systemCapabilities') capabilities_list = list(capabilities.keys()) capabilities_list.sort() @@ -545,7 +545,7 @@ def get_lldp_neighbors_detail(self, interface=''): return lldp_neighbors_out def cli(self, commands): - cli_output = dict() + cli_output = {} if type(commands) is not list: raise TypeError('Please enter a valid list of commands!') @@ -635,7 +635,7 @@ def get_bgp_config(self, group='', neighbor=''): def parse_options(options, default_value=False): if not options: - return dict() + return {} config_property = options[0] field_name = _PROPERTY_FIELD_MAP_.get(config_property) @@ -644,7 +644,7 @@ def parse_options(options, default_value=False): if not field_type: # no type specified at all => return empty dictionary - return dict() + return {} if not default_value: if len(options) > 1: @@ -673,16 +673,16 @@ def parse_options(options, default_value=False): field_name = 'export_policy' return {field_name: field_value} - return dict() + return {} - bgp_config = dict() + bgp_config = {} - commands = list() + commands = [] commands.append('show running-config | section router bgp') bgp_conf = self.device.run_commands(commands, encoding='text')[0].get('output', '\n\n') bgp_conf_lines = bgp_conf.splitlines()[2:] - bgp_neighbors = dict() + bgp_neighbors = {} if not group: neighbor = '' @@ -737,9 +737,9 @@ def parse_options(options, default_value=False): # match the neighbors with the group they belong to # directly will apend the neighbor in the neighbor list of the group at the end if last_peer_group not in bgp_neighbors.keys(): - bgp_neighbors[last_peer_group] = dict() + bgp_neighbors[last_peer_group] = {} if peer_address not in bgp_neighbors[last_peer_group]: - bgp_neighbors[last_peer_group][peer_address] = dict() + bgp_neighbors[last_peer_group][peer_address] = {} bgp_neighbors[last_peer_group][peer_address].update({ key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) for prop, key in _PEER_FIELD_MAP_.items() @@ -759,7 +759,7 @@ def parse_options(options, default_value=False): if group and group_name != group: continue if group_name not in bgp_config.keys(): - bgp_config[group_name] = dict() + bgp_config[group_name] = {} bgp_config[group_name].update({ key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) for prop, key in _GROUP_FIELD_MAP_.items() @@ -785,7 +785,7 @@ def parse_options(options, default_value=False): def get_arp_table(self): - arp_table = list() + arp_table = [] commands = ['show arp'] @@ -822,7 +822,7 @@ def get_ntp_servers(self): for ntp_peer in ntp_config if ntp_peer.get('ntppeer', '')} def get_ntp_stats(self): - ntp_stats = list() + ntp_stats = [] REGEX = ( '^\s?(\+|\*|x|-)?([a-zA-Z0-9\.+-:]+)' @@ -832,7 +832,7 @@ def get_ntp_stats(self): '\s+([0-9\.]+)\s?$' ) - commands = list() + commands = [] commands.append('show ntp associations') # output = self.device.run_commands(commands) @@ -869,7 +869,7 @@ def get_ntp_stats(self): def get_interfaces_ip(self): - interfaces_ip = dict() + interfaces_ip = {} interfaces_ipv4_out = self.device.run_commands(['show ip interface'])[0]['interfaces'] try: @@ -881,14 +881,14 @@ def get_interfaces_ip(self): raise for interface_name, interface_details in interfaces_ipv4_out.items(): - ipv4_list = list() + ipv4_list = [] if interface_name not in interfaces_ip.keys(): - interfaces_ip[interface_name] = dict() + interfaces_ip[interface_name] = {} if u'ipv4' not in interfaces_ip.get(interface_name): - interfaces_ip[interface_name][u'ipv4'] = dict() + interfaces_ip[interface_name][u'ipv4'] = {} if u'ipv6' not in interfaces_ip.get(interface_name): - interfaces_ip[interface_name][u'ipv6'] = dict() + interfaces_ip[interface_name][u'ipv6'] = {} iface_details = interface_details.get('interfaceAddress', {}) if iface_details.get('primaryIp', {}).get('address') != '0.0.0.0': @@ -916,14 +916,14 @@ def get_interfaces_ip(self): } for interface_name, interface_details in interfaces_ipv6_out.items(): - ipv6_list = list() + ipv6_list = [] if interface_name not in interfaces_ip.keys(): - interfaces_ip[interface_name] = dict() + interfaces_ip[interface_name] = {} if u'ipv4' not in interfaces_ip.get(interface_name): - interfaces_ip[interface_name][u'ipv4'] = dict() + interfaces_ip[interface_name][u'ipv4'] = {} if u'ipv6' not in interfaces_ip.get(interface_name): - interfaces_ip[interface_name][u'ipv6'] = dict() + interfaces_ip[interface_name][u'ipv6'] = {} ipv6_list.append( { @@ -954,7 +954,7 @@ def get_interfaces_ip(self): def get_mac_address_table(self): - mac_table = list() + mac_table = [] commands = ['show mac address-table'] @@ -987,7 +987,7 @@ def get_mac_address_table(self): return mac_table def get_route_to(self, destination='', protocol=''): - routes = dict() + routes = {} if protocol.lower() == 'direct': protocol = 'connected' @@ -1014,7 +1014,7 @@ def get_route_to(self, destination='', protocol=''): for prefix, route_details in routes_out.items(): if prefix not in routes.keys(): - routes[prefix] = list() + routes[prefix] = [] route_protocol = route_details.get('routeType').upper() preference = route_details.get('preference', 0) @@ -1139,7 +1139,7 @@ def _sshkey_type(sshkey): return u'ssh_dsa', py23_compat.text_type(sshkey) return u'ssh_rsa', u'' - users = dict() + users = {} commands = ['show user-account'] user_items = self.device.run_commands(commands)[0].get('users', {}) @@ -1521,15 +1521,15 @@ def get_network_instances(self, name=''): raw_output = self.device.run_commands(commands, encoding='text')[0].get('output', '') output = napalm_base.helpers.textfsm_extractor(self, 'vrf', raw_output) - vrfs = dict() - all_vrf_interfaces = dict() + vrfs = {} + all_vrf_interfaces = {} for vrf in output: if (vrf.get('route_distinguisher', '') == "" or vrf.get('route_distinguisher', '') == 'None'): vrf['route_distinguisher'] = u'' else: vrf['route_distinguisher'] = py23_compat.text_type(vrf['route_distinguisher']) - interfaces = dict() + interfaces = {} for interface_raw in vrf.get('interfaces', []): interface = interface_raw.split(',') for line in interface: From 25d78c83d7f6b9bb7b331803109ae1d717b065bf Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 26 Jan 2017 15:45:32 +0000 Subject: [PATCH 2/9] Various improvements for get_route_to Also fix #109 --- napalm_eos/eos.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/napalm_eos/eos.py b/napalm_eos/eos.py index 9594422..4222df4 100644 --- a/napalm_eos/eos.py +++ b/napalm_eos/eos.py @@ -1015,12 +1015,12 @@ def get_route_to(self, destination='', protocol=''): for prefix, route_details in routes_out.items(): if prefix not in routes.keys(): routes[prefix] = [] - route_protocol = route_details.get('routeType').upper() + route_protocol = route_details.get('routeType') preference = route_details.get('preference', 0) route = { - 'current_active': False, - 'last_active': False, + 'current_active': True, + 'last_active': True, 'age': 0, 'next_hop': u'', 'protocol': route_protocol, @@ -1028,10 +1028,14 @@ def get_route_to(self, destination='', protocol=''): 'preference': preference, 'inactive_reason': u'', 'routing_table': u'default', - 'selected_next_hop': False, + 'selected_next_hop': True, 'protocol_attributes': {} } - if protocol == 'bgp': + if protocol == 'bgp' or route_protocol.lower() in ('ebgp', 'ibgp'): + nexthop_interface_map = {} + for next_hop in route_details.get('vias'): + nexthop_ip = napalm_base.helpers.ip(next_hop.get('nexthopAddr')) + nexthop_interface_map[nexthop_ip] = next_hop.get('interface') metric = route_details.get('metric') command = 'show ip{ipv} bgp {destination} detail'.format( ipv=ipv, @@ -1054,10 +1058,13 @@ def get_route_to(self, destination='', protocol=''): last_active = active_route # should find smth better communities = bgp_route_details.get('routeDetail', {}).get('communityList', []) preference2 = bgp_route_details.get('weight') + inactive_reason = bgp_route_details.get('reasonNotBestpath') bgp_route.update({ 'current_active': active_route, + 'inactive_reason': inactive_reason, 'last_active': last_active, 'next_hop': next_hop, + 'outgoing_interface': nexthop_interface_map.get(next_hop), 'selected_next_hop': active_route, 'protocol_attributes': { 'metric': metric, @@ -1072,6 +1079,11 @@ def get_route_to(self, destination='', protocol=''): }) routes[prefix].append(bgp_route) else: + if route_details.get('routeAction') in ('drop',): + route['next_hop'] = 'NULL' + if route_details.get('routingDisabled') is True: + route['last_active'] = False + route['current_active'] = False for next_hop in route_details.get('vias'): route_next_hop = route.copy() if next_hop.get('nexthopAddr') is None: @@ -1089,7 +1101,8 @@ def get_route_to(self, destination='', protocol=''): } ) routes[prefix].append(route_next_hop) - + if route_details.get('vias') == []: # empty list + routes[prefix].append(route) return routes def get_snmp_information(self): From f174053cd54b1f461366335ccc48d1d265fbf1fd Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Fri, 27 Jan 2017 13:41:33 +0000 Subject: [PATCH 3/9] Version 0.5.3 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b7223b4..1e38e59 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="napalm-eos", - version="0.5.2", + version="0.5.3", packages=find_packages(), author="David Barroso, Mircea Ulinic", author_email="dbarrosop@dravetech.com, mircea@cloudflare.com", From 7d9b62e2b18e392b22120e58a211da849dce78ee Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 2 Feb 2017 11:28:54 +0000 Subject: [PATCH 4/9] empty inactive_reason rather than None --- napalm_eos/eos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_eos/eos.py b/napalm_eos/eos.py index 4222df4..a36c0cc 100644 --- a/napalm_eos/eos.py +++ b/napalm_eos/eos.py @@ -1058,7 +1058,7 @@ def get_route_to(self, destination='', protocol=''): last_active = active_route # should find smth better communities = bgp_route_details.get('routeDetail', {}).get('communityList', []) preference2 = bgp_route_details.get('weight') - inactive_reason = bgp_route_details.get('reasonNotBestpath') + inactive_reason = bgp_route_details.get('reasonNotBestpath', '') bgp_route.update({ 'current_active': active_route, 'inactive_reason': inactive_reason, From 06afb40197c765add579c473c13fea178c56c00c Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 2 Feb 2017 11:29:13 +0000 Subject: [PATCH 5/9] Consistent expected output as well --- .../mocked_data/test_get_route_to/normal/expected_result.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/mocked_data/test_get_route_to/normal/expected_result.json b/test/unit/mocked_data/test_get_route_to/normal/expected_result.json index 3b112ad..c67e70a 100644 --- a/test/unit/mocked_data/test_get_route_to/normal/expected_result.json +++ b/test/unit/mocked_data/test_get_route_to/normal/expected_result.json @@ -1 +1 @@ -{"1.0.4.0/24": [{"protocol": "EBGP", "inactive_reason": "", "last_active": true, "age": 0, "routing_table": "default", "next_hop": "192.168.0.1", "outgoing_interface": "", "preference": 200, "current_active": true, "selected_next_hop": true, "protocol_attributes": {"local_preference": 50, "remote_as": 43515, "communities": ["1299:1234", "1299:5678", "1299:91011", "1299:12134"], "preference2": 0, "metric": 0, "local_as": 13335, "as_path": "1299 15169 43515", "remote_address": "192.168.0.1"}}]} +{"1.0.4.0/24": [{"next_hop": "192.168.0.1", "preference": 200, "protocol": "eBGP", "selected_next_hop": true, "current_active": true, "routing_table": "default", "protocol_attributes": {"remote_as": 43515, "as_path": "1299 15169 43515", "local_preference": 50, "remote_address": "192.168.0.1", "preference2": 0, "metric": 0, "communities": ["1299:1234", "1299:5678", "1299:91011", "1299:12134"], "local_as": 13335}, "outgoing_interface": "Port-Channel2", "last_active": true, "inactive_reason": "", "age": 0}]} From dfd665b273022317705b4aac2c91daf5a566000f Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 26 Jan 2017 17:24:07 +0000 Subject: [PATCH 6/9] Group neighbors without peer-group under the '_' key Painful stuff here. @itdependsnetworks owes me a beer for that :D --- napalm_eos/eos.py | 88 ++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/napalm_eos/eos.py b/napalm_eos/eos.py index a36c0cc..c9f8548 100644 --- a/napalm_eos/eos.py +++ b/napalm_eos/eos.py @@ -632,6 +632,32 @@ def get_bgp_config(self, group='', neighbor=''): list: [] } + def default_group_dict(local_as): + group_dict = {} + group_dict.update({ + key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) + for prop, key in _GROUP_FIELD_MAP_.items() + }) + group_dict.update({ + 'prefix_limit': {}, + 'neighbors': {}, + 'local_as': local_as + }) # few more default values + return group_dict + + def default_neighbor_dict(local_as): + neighbor_dict = {} + neighbor_dict.update({ + key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) + for prop, key in _PEER_FIELD_MAP_.items() + }) # populating with default values + neighbor_dict.update({ + 'prefix_limit': {}, + 'local_as': local_as, + 'authentication_key': u'' + }) # few more default values + return neighbor_dict + def parse_options(options, default_value=False): if not options: @@ -648,7 +674,9 @@ def parse_options(options, default_value=False): if not default_value: if len(options) > 1: - field_value = field_type(options[1]) + field_value = napalm_base.helpers.convert(field_type, + options[1], + _DATATYPE_DEFAULT_.get(field_type)) else: if field_type is bool: field_value = True @@ -680,15 +708,15 @@ def parse_options(options, default_value=False): commands = [] commands.append('show running-config | section router bgp') bgp_conf = self.device.run_commands(commands, encoding='text')[0].get('output', '\n\n') - bgp_conf_lines = bgp_conf.splitlines()[2:] + bgp_conf_lines = bgp_conf.splitlines() bgp_neighbors = {} if not group: - neighbor = '' + neighbor = '' # noqa - last_peer_group = '' local_as = 0 + bgp_neighbors = {} for bgp_conf_line in bgp_conf_lines: default_value = False bgp_conf_line = bgp_conf_line.strip() @@ -711,18 +739,10 @@ def parse_options(options, default_value=False): IPAddress(group_or_neighbor) # if passes the test => it is an IP Address, thus a Neighbor! peer_address = group_or_neighbor - + if peer_address not in bgp_neighbors: + bgp_neighbors[peer_address] = default_neighbor_dict(local_as) if options[0] == 'peer-group': - last_peer_group = options[1] - - # if looking for a specific group - if group and last_peer_group != group: - continue - - # or even more. a specific neighbor within a group - if neighbor and peer_address != neighbor: - continue - # skip all other except the target + bgp_neighbors[peer_address]['__group'] = options[1] # in the config, neighbor details are lister after # the group is specified for the neighbor: @@ -736,20 +756,8 @@ def parse_options(options, default_value=False): # that way we avoid one more loop to # match the neighbors with the group they belong to # directly will apend the neighbor in the neighbor list of the group at the end - if last_peer_group not in bgp_neighbors.keys(): - bgp_neighbors[last_peer_group] = {} - if peer_address not in bgp_neighbors[last_peer_group]: - bgp_neighbors[last_peer_group][peer_address] = {} - bgp_neighbors[last_peer_group][peer_address].update({ - key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) - for prop, key in _PEER_FIELD_MAP_.items() - }) # populating with default values - bgp_neighbors[last_peer_group][peer_address].update({ - 'prefix_limit': {}, - 'local_as': local_as, - 'authentication_key': u'' - }) # few more default values - bgp_neighbors[last_peer_group][peer_address].update( + + bgp_neighbors[peer_address].update( parse_options(options, default_value) ) except AddrFormatError: @@ -759,16 +767,7 @@ def parse_options(options, default_value=False): if group and group_name != group: continue if group_name not in bgp_config.keys(): - bgp_config[group_name] = {} - bgp_config[group_name].update({ - key: _DATATYPE_DEFAULT_.get(_PROPERTY_TYPE_MAP_.get(prop)) - for prop, key in _GROUP_FIELD_MAP_.items() - }) - bgp_config[group_name].update({ - 'prefix_limit': {}, - 'neighbors': {}, - 'local_as': local_as - }) # few more default values + bgp_config[group_name] = default_group_dict(local_as) bgp_config[group_name].update( parse_options(options, default_value) ) @@ -776,10 +775,13 @@ def parse_options(options, default_value=False): # for other kind of exception pass to next line continue - for group, peers in bgp_neighbors.items(): - if group not in bgp_config.keys(): - continue - bgp_config[group]['neighbors'] = peers + for peer, peer_details in bgp_neighbors.items(): + peer_group = peer_details.pop('__group', None) + if not peer_group: + peer_group = '_' + if peer_group not in bgp_config: + bgp_config[peer_group] = default_group_dict(local_as) + bgp_config[peer_group]['neighbors'][peer] = peer_details return bgp_config From f9417750939092e07a17bb6b941b8cc64769b878 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 26 Jan 2017 18:32:37 +0000 Subject: [PATCH 7/9] Fix previously wrong mock --- .../mocked_data/test_get_bgp_config/normal/expected_result.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/unit/mocked_data/test_get_bgp_config/normal/expected_result.json index eb4367c..de52578 100644 --- a/test/unit/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/unit/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -1 +1 @@ -{"IPv6-PEERS-GROUP-NAME": {"neighbors": {"2001:db8::0:2": {"export_policy": "", "prefix_limit": {}, "import_policy": "", "local_as": 0, "route_reflector_client": false, "nhs": false, "local_address": "", "remote_as": 54113, "authentication_key": "", "description": ""}, "2001:db8::0:1": {"export_policy": "", "prefix_limit": {}, "import_policy": "", "local_as": 0, "route_reflector_client": false, "nhs": false, "local_address": "", "remote_as": 8403, "authentication_key": "", "description": ""}}, "export_policy": "reject-all", "multipath": false, "prefix_limit": {}, "import_policy": "reject-all", "local_as": 0, "multihop_ttl": 0, "apply_groups": [], "remote_as": 0, "remove_private_as": true, "local_address": "", "type": "", "description": ""}, "IPv4-PEERS-GROUP-NAME": {"neighbors": {"192.168.0.1": {"export_policy": "", "prefix_limit": {}, "import_policy": "", "local_as": 0, "route_reflector_client": false, "nhs": false, "local_address": "", "remote_as": 32934, "authentication_key": "", "description": ""}, "172.17.17.1": {"export_policy": "", "prefix_limit": {}, "import_policy": "", "local_as": 0, "route_reflector_client": false, "nhs": false, "local_address": "", "remote_as": 13414, "authentication_key": "", "description": ""}}, "export_policy": "4-public-peer-anycast-out", "multipath": false, "prefix_limit": {}, "import_policy": "reject-all", "local_as": 0, "multihop_ttl": 0, "apply_groups": [], "remote_as": 0, "remove_private_as": true, "local_address": "", "type": "", "description": ""}} +{"IPv4-PEERS-GROUP-NAME": {"local_address": "", "description": "", "type": "", "local_as": 13335, "apply_groups": [], "multihop_ttl": 0, "remove_private_as": true, "remote_as": 0, "import_policy": "reject-all", "export_policy": "4-public-peer-anycast-out", "neighbors": {"172.17.17.1": {"local_address": "", "authentication_key": "", "description": "", "nhs": false, "local_as": 13335, "route_reflector_client": false, "remote_as": 13414, "import_policy": "", "export_policy": "", "prefix_limit": {}}, "192.168.0.1": {"local_address": "", "authentication_key": "", "description": "", "nhs": false, "local_as": 13335, "route_reflector_client": false, "remote_as": 32934, "import_policy": "", "export_policy": "", "prefix_limit": {}}}, "prefix_limit": {}, "multipath": false}, "IPv6-PEERS-GROUP-NAME": {"local_address": "", "description": "", "type": "", "local_as": 13335, "apply_groups": [], "multihop_ttl": 0, "remove_private_as": true, "remote_as": 0, "import_policy": "reject-all", "export_policy": "reject-all", "neighbors": {"2001:db8::0:2": {"local_address": "", "authentication_key": "", "description": "", "nhs": false, "local_as": 13335, "route_reflector_client": false, "remote_as": 54113, "import_policy": "", "export_policy": "", "prefix_limit": {}}, "2001:db8::0:1": {"local_address": "", "authentication_key": "", "description": "", "nhs": false, "local_as": 13335, "route_reflector_client": false, "remote_as": 8403, "import_policy": "", "export_policy": "", "prefix_limit": {}}}, "prefix_limit": {}, "multipath": false}} From 60964ce2cba371427d006c846d3e0e27ba85c024 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 2 Feb 2017 11:36:31 +0000 Subject: [PATCH 8/9] Remove too generic Exception --- napalm_eos/eos.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/napalm_eos/eos.py b/napalm_eos/eos.py index c9f8548..1cf9a36 100644 --- a/napalm_eos/eos.py +++ b/napalm_eos/eos.py @@ -771,9 +771,6 @@ def parse_options(options, default_value=False): bgp_config[group_name].update( parse_options(options, default_value) ) - except Exception: - # for other kind of exception pass to next line - continue for peer, peer_details in bgp_neighbors.items(): peer_group = peer_details.pop('__group', None) From 3e5c5c169ffe107a044d42167668d3b33d776ae9 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 2 Feb 2017 11:43:49 +0000 Subject: [PATCH 9/9] Testcase for #119 --- .../expected_result.json | 66 +++++++++++++++++++ ...w_running_config___section_router_bgp.text | 18 +++++ 2 files changed, 84 insertions(+) create mode 100644 test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/expected_result.json create mode 100644 test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/show_running_config___section_router_bgp.text diff --git a/test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/expected_result.json b/test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/expected_result.json new file mode 100644 index 0000000..295fde3 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/expected_result.json @@ -0,0 +1,66 @@ +{ + "_": { + "multipath": false, + "multihop_ttl": 0, + "apply_groups": [], + "export_policy": "", + "import_policy": "", + "remove_private_as": false, + "local_as": 13335, + "local_address": "", + "type": "", + "remote_as": 0, + "prefix_limit": {}, + "description": "", + "neighbors": { + "192.168.0.1": { + "route_reflector_client": false, + "nhs": false, + "authentication_key": "", + "export_policy": "export-policy", + "import_policy": "import-policy", + "local_as": 13335, + "local_address": "", + "remote_as": 32934, + "prefix_limit": {}, + "description": "" + }, + "2001:db8::0:1": { + "route_reflector_client": false, + "nhs": false, + "authentication_key": "", + "export_policy": "export-policy", + "import_policy": "import-policy", + "local_as": 13335, + "local_address": "", + "remote_as": 8403, + "prefix_limit": {}, + "description": "" + }, + "172.17.17.1": { + "route_reflector_client": false, + "nhs": false, + "authentication_key": "", + "export_policy": "export-policy", + "import_policy": "import-policy", + "local_as": 13335, + "local_address": "", + "remote_as": 13414, + "prefix_limit": {}, + "description": "" + }, + "2001:db8::0:2": { + "route_reflector_client": false, + "nhs": false, + "authentication_key": "", + "export_policy": "export-policy", + "import_policy": "import-policy", + "local_as": 13335, + "local_address": "", + "remote_as": 54113, + "prefix_limit": {}, + "description": "" + } + } + } +} diff --git a/test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/show_running_config___section_router_bgp.text b/test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/show_running_config___section_router_bgp.text new file mode 100644 index 0000000..9d8540f --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_config/iss199_bgp_neighbors_without_peer_group/show_running_config___section_router_bgp.text @@ -0,0 +1,18 @@ +router bgp 13335 + maximum-paths 32 + neighbor 192.168.0.1 remote-as 32934 + neighbor 192.168.0.1 maximum-routes 100 + neighbor 192.168.0.1 route-map import-policy in + neighbor 192.168.0.1 route-map export-policy out + neighbor 172.17.17.1 remote-as 13414 + neighbor 172.17.17.1 maximum-routes 500 + neighbor 172.17.17.1 route-map import-policy in + neighbor 172.17.17.1 route-map export-policy out + neighbor 2001:db8::0:1 remote-as 8403 + neighbor 2001:db8::0:1 maximum-routes 500 + neighbor 2001:db8::0:1 route-map import-policy in + neighbor 2001:db8::0:1 route-map export-policy out + neighbor 2001:db8::0:2 remote-as 54113 + neighbor 2001:db8::0:2 route-map import-policy in + neighbor 2001:db8::0:2 route-map export-policy out +!