diff --git a/napalm/eos/pyeapi_syntax_wrapper.py b/napalm/eos/pyeapi_syntax_wrapper.py index 246b185c9..c240df3d4 100644 --- a/napalm/eos/pyeapi_syntax_wrapper.py +++ b/napalm/eos/pyeapi_syntax_wrapper.py @@ -25,7 +25,7 @@ def update_cli_version(self, version): """ self.cli_version = version - def run_commands(self, commands, **kwargs): + def run_commands(self, commands, *args, **kwargs): """ Run commands wrapper :param commands: list of commands @@ -39,4 +39,4 @@ def run_commands(self, commands, **kwargs): else: commands = [cli_convert(cmd, self.cli_version) for cmd in commands] - return super(Node, self).run_commands(commands, **kwargs) + return super(Node, self).run_commands(commands, *args, **kwargs) diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index ef690c0e0..bf691e365 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -88,6 +88,7 @@ RE_BGP_REMOTE_AS = re.compile(r"remote AS (" + ASN_REGEX + r")") RE_BGP_AS_PATH = re.compile(r"^[ ]{2}([\d\(]([\d\) ]+)|Local)") +RE_RP_ROUTE = re.compile(r"Routing entry for (" + IP_ADDR_REGEX + r"\/\d+)") RE_RP_FROM = re.compile(r"Known via \"([a-z]+)[ \"]") RE_RP_VIA = re.compile(r"via (\S+)") RE_RP_METRIC = re.compile(r"[ ]+Route metric is (\d+)") @@ -2773,7 +2774,7 @@ def _get_bgp_route_attr(self, destination, vrf, next_hop, ip_version=4): search_re_dict = { "aspath": { - "re": r"[^|\\n][ ]{2}([\d\(\)]([\d\(\) ])*)", + "re": r"[^|\\n][ ]{2}([\d\(\)]([\d\(\) ])*|Local)", "group": 1, "default": "", }, @@ -2947,8 +2948,11 @@ def get_route_to(self, destination="", protocol="", longer=False): vrfs.append("default") # global VRF ipnet_dest = IPNetwork(destination) prefix = str(ipnet_dest.network) - netmask = str(ipnet_dest.netmask) - routes = {destination: []} + netmask = "" + routes = {} + if "/" in destination: + netmask = str(ipnet_dest.netmask) + routes = {destination: []} commands = [] for _vrf in vrfs: if _vrf == "default": @@ -2969,6 +2973,14 @@ def get_route_to(self, destination="", protocol="", longer=False): for (outitem, _vrf) in zip(output, vrfs): # for all VRFs route_proto_regex = RE_RP_FROM.search(outitem) if route_proto_regex: + route_match = destination + if netmask == "": + # Get the matching route for a non-exact lookup + route_match_regex = RE_RP_ROUTE.search(outitem) + if route_match_regex: + route_match = route_match_regex.group(1) + if route_match not in routes: + routes[route_match] = [] # routing protocol name (bgp, ospf, ...) route_proto = route_proto_regex.group(1) rdb = outitem.split("Routing Descriptor Blocks:") @@ -3035,9 +3047,9 @@ def get_route_to(self, destination="", protocol="", longer=False): destination, _vrf, nh, ip_version ) nh_line_found = ( - False # for next RT entry processing ... - ) - routes[destination].append(route_entry) + False + ) # for next RT entry processing ... + routes[route_match].append(route_entry) return routes def get_snmp_information(self): @@ -3405,7 +3417,14 @@ def get_network_instances(self, name=""): if "No interfaces" in first_part: interfaces = {} else: - interfaces = {itf: {} for itf in if_regex.group(1).split()} + interfaces = { + canonical_interface_name(itf, {"Vl": "Vlan"}): {} + for itf in if_regex.group(1).split() + } + + # remove interfaces in the VRF from the default VRF + for item in interfaces: + del instances["default"]["interfaces"]["interface"][item] instances[vrf_name] = { "name": vrf_name, diff --git a/requirements-dev.txt b/requirements-dev.txt index 99dc168ad..1457bb8f8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,4 +8,4 @@ pytest-json==0.4.0 pytest-pythonpath==0.7.3 pylama==7.7.1 mock==4.0.2 -tox==3.18.0 \ No newline at end of file +tox==3.19.0 \ No newline at end of file diff --git a/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/expected_result.json b/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/expected_result.json new file mode 100644 index 000000000..6e995be8d --- /dev/null +++ b/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/expected_result.json @@ -0,0 +1,33 @@ +{ + "default": { + "name": "default", + "type": "DEFAULT_INSTANCE", + "state": { + "route_distinguisher": "" + }, + "interfaces": { + "interface": { + "Ethernet0/0": {}, + "Ethernet0/1": {}, + "Ethernet0/2": {}, + "Ethernet0/3": {}, + "Ethernet1/0": {}, + "Ethernet1/1": {}, + "Ethernet1/2": {}, + "Ethernet1/3": {}, + "Ethernet2/0": {}, + "Ethernet2/1": {}, + "Ethernet2/2": {}, + "Ethernet2/3": {}, + "Ethernet3/0": {}, + "Ethernet3/1": {}, + "Ethernet3/2": {}, + "Ethernet3/3": {}, + "Vlan1": {}, + "Vlan2": {}, + "Vlan3": {}, + "Vlan4": {} + } + } + } +} diff --git a/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/show_ip_interface_brief.txt b/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/show_ip_interface_brief.txt new file mode 100644 index 000000000..fcee66929 --- /dev/null +++ b/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/show_ip_interface_brief.txt @@ -0,0 +1,21 @@ +Interface IP-Address OK? Method Status Protocol +Ethernet0/0 172.29.29.220 YES manual up up +Ethernet0/1 unassigned YES unset up up +Ethernet0/2 unassigned YES unset up up +Ethernet0/3 unassigned YES unset up up +Ethernet1/0 unassigned YES unset up up +Ethernet1/1 unassigned YES unset up up +Ethernet1/2 unassigned YES unset up up +Ethernet1/3 unassigned YES unset up up +Ethernet2/0 unassigned YES unset up up +Ethernet2/1 unassigned YES unset up up +Ethernet2/2 unassigned YES unset up up +Ethernet2/3 unassigned YES unset up up +Ethernet3/0 unassigned YES unset up up +Ethernet3/1 unassigned YES unset up up +Ethernet3/2 unassigned YES unset up up +Ethernet3/3 unassigned YES unset up up +Vlan1 unassigned YES unset administratively down down +Vlan2 2.2.2.2 YES manual up up +Vlan3 3.3.3.3 YES manual up up +Vlan4 4.4.4.4 YES manual up up diff --git a/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/show_vrf_detail.txt b/test/ios/mocked_data/test_get_network_instances/no_vrf_svis/show_vrf_detail.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/ios/mocked_data/test_get_network_instances/normal/expected_result.json b/test/ios/mocked_data/test_get_network_instances/normal/expected_result.json index ce1c42502..3a0e182dd 100644 --- a/test/ios/mocked_data/test_get_network_instances/normal/expected_result.json +++ b/test/ios/mocked_data/test_get_network_instances/normal/expected_result.json @@ -1,78 +1,66 @@ { - "default":{ - "interfaces":{ - "interface":{ - "GigabitEthernet0/0/0":{ - - }, - "Gi0/0/0.152":{ - - }, - "GigabitEthernet0/0/2":{ - - }, - "Gi0/0/0.1774":{ - - }, - "GigabitEthernet0/0/4":{ - - }, - "Gi0/0/0.1772":{ - - }, - "GigabitEthernet0/0/3":{ - - }, - "Gi0/0/0.154":{ - - }, - "GigabitEthernet0/0/1":{ - - }, - "GigabitEthernet0":{ - - }, - "Gi0/0/0.1776":{ - - }, - "Gi0/0/0.600":{ - - }, - "Loopback2":{ - - } - } - }, - "state":{ - "route_distinguisher":"" + "default": { + "name": "default", + "type": "DEFAULT_INSTANCE", + "state": { + "route_distinguisher": "" }, - "type":"DEFAULT_INSTANCE", - "name":"default" - }, - "Mgmt-intf":{ - "interfaces":{ - "interface":{ - "Gi0":{ - - } + "interfaces": { + "interface": { + "Ethernet0/0": {}, + "Ethernet0/1": {}, + "Ethernet0/2": {}, + "Ethernet0/3": {}, + "Ethernet1/0": {}, + "Ethernet1/1": {}, + "Ethernet1/2": {}, + "Ethernet1/3": {}, + "Ethernet2/0": {}, + "Ethernet2/1": {}, + "Ethernet2/2": {}, + "Ethernet2/3": {}, + "Ethernet3/0": {}, + "Ethernet3/1": {}, + "Ethernet3/2": {}, + "Ethernet3/3": {}, + "Vlan1": {} } - }, - "state":{ - "route_distinguisher":"" - }, - "type":"L3VRF", - "name":"Mgmt-intf" + } }, - "opsnet":{ - "interfaces":{ - "interface":{ - + "CustA": { + "name": "CustA", + "type": "L3VRF", + "state": { + "route_distinguisher": "1:1" + }, + "interfaces": { + "interface": { + "Vlan2": {} } + } + }, + "CustB": { + "name": "CustB", + "type": "L3VRF", + "state": { + "route_distinguisher": "2:2" }, - "state":{ - "route_distinguisher":"10283:1021312690" + "interfaces": { + "interface": { + "Vlan3": {} + } + } + }, + "CustC": { + "name": "CustC", + "type": "L3VRF", + "state": { + "route_distinguisher": "3:3" }, - "type":"L3VRF", - "name":"opsnet" + "interfaces": { + "interface": { + "Vlan4": {} + } + } } -} \ No newline at end of file +} diff --git a/test/ios/mocked_data/test_get_network_instances/normal/show_ip_interface_brief.txt b/test/ios/mocked_data/test_get_network_instances/normal/show_ip_interface_brief.txt index 8ef3917eb..fcee66929 100644 --- a/test/ios/mocked_data/test_get_network_instances/normal/show_ip_interface_brief.txt +++ b/test/ios/mocked_data/test_get_network_instances/normal/show_ip_interface_brief.txt @@ -1,17 +1,21 @@ -Load for five secs: 0%/0%; one minute: 1%; five minutes: 1% -Time source is NTP, 09:30:03.851 DST Wed Nov 8 2017 - Interface IP-Address OK? Method Status Protocol -GigabitEthernet0/0/0 unassigned YES NVRAM up up -Gi0/0/0.152 192.168.241.21 YES NVRAM up up -Gi0/0/0.154 192.168.241.30 YES NVRAM up up -Gi0/0/0.600 192.168.241.141 YES NVRAM up up -Gi0/0/0.1772 120.177.177.1 YES NVRAM up up -Gi0/0/0.1774 101.177.177.1 YES NVRAM up up -Gi0/0/0.1776 100.177.177.1 YES NVRAM up up -GigabitEthernet0/0/1 unassigned YES NVRAM administratively down down -GigabitEthernet0/0/2 unassigned YES NVRAM administratively down down -GigabitEthernet0/0/3 unassigned YES NVRAM administratively down down -GigabitEthernet0/0/4 unassigned YES NVRAM administratively down down -GigabitEthernet0 192.168.243.80 YES NVRAM up up -Loopback2 192.168.242.152 YES NVRAM up up \ No newline at end of file +Ethernet0/0 172.29.29.220 YES manual up up +Ethernet0/1 unassigned YES unset up up +Ethernet0/2 unassigned YES unset up up +Ethernet0/3 unassigned YES unset up up +Ethernet1/0 unassigned YES unset up up +Ethernet1/1 unassigned YES unset up up +Ethernet1/2 unassigned YES unset up up +Ethernet1/3 unassigned YES unset up up +Ethernet2/0 unassigned YES unset up up +Ethernet2/1 unassigned YES unset up up +Ethernet2/2 unassigned YES unset up up +Ethernet2/3 unassigned YES unset up up +Ethernet3/0 unassigned YES unset up up +Ethernet3/1 unassigned YES unset up up +Ethernet3/2 unassigned YES unset up up +Ethernet3/3 unassigned YES unset up up +Vlan1 unassigned YES unset administratively down down +Vlan2 2.2.2.2 YES manual up up +Vlan3 3.3.3.3 YES manual up up +Vlan4 4.4.4.4 YES manual up up diff --git a/test/ios/mocked_data/test_get_network_instances/normal/show_vrf_detail.txt b/test/ios/mocked_data/test_get_network_instances/normal/show_vrf_detail.txt index f29e9a0f9..e7875737b 100644 --- a/test/ios/mocked_data/test_get_network_instances/normal/show_vrf_detail.txt +++ b/test/ios/mocked_data/test_get_network_instances/normal/show_vrf_detail.txt @@ -1,11 +1,8 @@ -Load for five secs: 0%/0%; one minute: 0%; five minutes: 1% -Time source is NTP, 09:28:50.737 DST Wed Nov 8 2017 - -VRF Mgmt-intf (VRF Id = 1); default RD ; default VPNID +VRF CustA (VRF Id = 1); default RD 1:1; default VPNID New CLI format, supports multiple address-families - Flags: 0x1808 + Flags: 0x180C Interfaces: - Gi0 + Vl2 Address family ipv4 unicast (Table ID = 0x1): Flags: 0x0 No Export VPN route-target communities @@ -15,7 +12,14 @@ Address family ipv4 unicast (Table ID = 0x1): No export route-map VRF label distribution protocol: not configured VRF label allocation mode: per-prefix -Address family ipv6 unicast (Table ID = 0x1E000001): +Address family ipv6 unicast not active + +VRF CustB (VRF Id = 2); default RD 2:2; default VPNID + New CLI format, supports multiple address-families + Flags: 0x180C + Interfaces: + Vl3 +Address family ipv4 unicast (Table ID = 0x2): Flags: 0x0 No Export VPN route-target communities No Import VPN route-target communities @@ -24,22 +28,21 @@ Address family ipv6 unicast (Table ID = 0x1E000001): No export route-map VRF label distribution protocol: not configured VRF label allocation mode: per-prefix -Address family ipv4 multicast not active +Address family ipv6 unicast not active -VRF opsnet (VRF Id = 2); default RD 10283:1021312690; default VPNID +VRF CustC (VRF Id = 3); default RD 3:3; default VPNID New CLI format, supports multiple address-families Flags: 0x180C - No interfaces -Address family ipv4 unicast (Table ID = 0x2): + Interfaces: + Vl4 +Address family ipv4 unicast (Table ID = 0x3): Flags: 0x0 - Export VPN route-target communities - RT:10283:50000 - Import VPN route-target communities - RT:10283:50000 + No Export VPN route-target communities + No Import VPN route-target communities No import route-map No global export route-map No export route-map VRF label distribution protocol: not configured VRF label allocation mode: per-prefix Address family ipv6 unicast not active -Address family ipv4 multicast not active \ No newline at end of file + diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/expected_result.json b/test/ios/mocked_data/test_get_route_to/non_exact/expected_result.json new file mode 100644 index 000000000..ea0b9b259 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/expected_result.json @@ -0,0 +1,44 @@ +{ + "1.0.4.0/24": [ + { + "protocol": "bgp", + "outgoing_interface": "", + "age": 98, + "current_active": true, + "routing_table": "CustB", + "last_active": true, + "protocol_attributes": { + "as_path": "Local", + "remote_address": "169.254.255.1", + "communities": [], + "local_preference": 100, + "local_as": 1, + "remote_as": 1 + }, + "next_hop": "169.254.255.1", + "selected_next_hop": true, + "inactive_reason": "", + "preference": 0 + }, + { + "protocol": "bgp", + "outgoing_interface": "", + "age": 62, + "current_active": true, + "routing_table": "default", + "last_active": true, + "protocol_attributes": { + "as_path": "3 3 3 3", + "remote_address": "200.200.200.1", + "communities": [], + "local_preference": 100, + "local_as": 1, + "remote_as": 3 + }, + "next_hop": "200.200.200.1", + "selected_next_hop": true, + "inactive_reason": "", + "preference": 0 + } + ] +} diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_1_0_4_0_24.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_1_0_4_0_24.txt new file mode 100644 index 000000000..6a4fe2cc7 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_1_0_4_0_24.txt @@ -0,0 +1,9 @@ +BGP routing table entry for 1.0.4.0/24, version 2 +Paths: (1 available, best #1, table default) + Advertised to update-groups: + 2 + Refresh Epoch 1 + 3 3 3 3 + 200.200.200.1 from 200.200.200.1 (1.1.1.1) + Origin IGP, metric 0, localpref 100, valid, external, best + rx pathid: 0, tx pathid: 0x0 diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_neighbors___include_is_200_200_200_1.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_neighbors___include_is_200_200_200_1.txt new file mode 100644 index 000000000..6ee579e97 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_neighbors___include_is_200_200_200_1.txt @@ -0,0 +1 @@ +BGP neighbor is 200.200.200.1, remote AS 3, local AS 2 no-prepend replace-as, external link diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_vpnv4_vrf_CustB_1_0_4_0_24.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_vpnv4_vrf_CustB_1_0_4_0_24.txt new file mode 100644 index 000000000..31895d6a4 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_vpnv4_vrf_CustB_1_0_4_0_24.txt @@ -0,0 +1,8 @@ +BGP routing table entry for 3:3:1.0.4.0/24, version 3 +Paths: (1 available, best #1, table CustB) + Not advertised to any peer + Refresh Epoch 1 + Local + 169.254.255.1 (via vrf CustB) from 169.254.255.1 (1.1.1.1) + Origin IGP, metric 0, localpref 100, valid, internal, best + rx pathid: 0, tx pathid: 0x0 diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_vpnv4_vrf_CustB_neighbors___include_is_169_254_255_1.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_vpnv4_vrf_CustB_neighbors___include_is_169_254_255_1.txt new file mode 100644 index 000000000..7c70cf487 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_bgp_vpnv4_vrf_CustB_neighbors___include_is_169_254_255_1.txt @@ -0,0 +1 @@ +BGP neighbor is 169.254.255.1, vrf CustB, remote AS 1, internal link diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_protocols___include_bgp.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_protocols___include_bgp.txt new file mode 100644 index 000000000..87aa166dc --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_protocols___include_bgp.txt @@ -0,0 +1 @@ +Routing Protocol is "bgp 1" diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_1_0_4_0_255_255_255_0.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_1_0_4_0_255_255_255_0.txt new file mode 100644 index 000000000..5f43ba8d9 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_1_0_4_0_255_255_255_0.txt @@ -0,0 +1,10 @@ +Routing entry for 1.0.4.0/24 + Known via "bgp 1", distance 20, metric 0 + Tag 3, type external + Last update from 200.200.200.1 00:01:02 ago + Routing Descriptor Blocks: + * 200.200.200.1, from 200.200.200.1, 00:01:02 ago + Route metric is 0, traffic share count is 1 + AS Hops 4 + Route tag 3 + MPLS label: none diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_vrf_CustA_1_0_4_0_255_255_255_0.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_vrf_CustA_1_0_4_0_255_255_255_0.txt new file mode 100644 index 000000000..3c5449984 --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_vrf_CustA_1_0_4_0_255_255_255_0.txt @@ -0,0 +1 @@ +% Network not in table diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_vrf_CustB_1_0_4_0_255_255_255_0.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_vrf_CustB_1_0_4_0_255_255_255_0.txt new file mode 100644 index 000000000..c3c8dba2e --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_ip_route_vrf_CustB_1_0_4_0_255_255_255_0.txt @@ -0,0 +1,10 @@ + +Routing Table: CustB +Routing entry for 1.0.4.0/24 + Known via "bgp 1", distance 200, metric 0, type internal + Last update from 169.254.255.1 00:01:38 ago + Routing Descriptor Blocks: + * 169.254.255.1, from 169.254.255.1, 00:01:38 ago + Route metric is 0, traffic share count is 1 + AS Hops 0 + MPLS label: none diff --git a/test/ios/mocked_data/test_get_route_to/non_exact/show_vrf.txt b/test/ios/mocked_data/test_get_route_to/non_exact/show_vrf.txt new file mode 100644 index 000000000..dd96083fa --- /dev/null +++ b/test/ios/mocked_data/test_get_route_to/non_exact/show_vrf.txt @@ -0,0 +1,3 @@ + Name Default RD Protocols Interfaces + CustA 2:2 ipv4 Et0/1 + CustB 3:3 ipv4 Et0/2