From fe2ac1bcd999b6fe2c6af305d63072e2fce7376c Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Mon, 11 Jul 2022 14:47:12 +0100 Subject: [PATCH 01/71] Use token to publish packages to PyPI Switching to use the PyPI token instead of username / password. --- .github/workflows/pythonpublish.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 1fba0b41b..12d829c1e 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -20,11 +20,12 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + pip install setuptools wheel + - name: Build run: | python setup.py sdist bdist_wheel - twine upload dist/* + - name: Publish + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} From 062b42b11074578fc82339003db1776fa0f93854 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 11:22:52 -0700 Subject: [PATCH 02/71] Trying to fix doc build --- .github/workflows/commit.yaml | 2 +- requirements-dev.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index f7d265f1f..6cc2260d0 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -65,8 +65,8 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install -e . - pip install -r requirements.txt pip install -r requirements-dev.txt + pip install -r requirements.txt python -m pip install -r docs/requirements.txt - name: Doctests diff --git a/requirements-dev.txt b/requirements-dev.txt index b1197ced2..cbd9ca470 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,6 +2,7 @@ black==22.6.0 coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.1 +jinja2==2.11.3 pytest==7.1.2 pytest-cov==3.0.0 pytest-json==0.4.0 @@ -14,4 +15,4 @@ types-six==1.16.17 types-setuptools==57.4.18 types-PyYAML==6.0.9 ttp==0.9.0 -ttp_templates==0.3.0 \ No newline at end of file +ttp_templates==0.3.0 From 8b6ba3d6f5466db5d5a43e16d27d163ab784d50c Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 11:27:14 -0700 Subject: [PATCH 03/71] Add types-jinja2 --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index cbd9ca470..a073f00b7 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,6 +3,7 @@ coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.1 jinja2==2.11.3 +types-Jinja2==2.11.9 pytest==7.1.2 pytest-cov==3.0.0 pytest-json==0.4.0 From eec39eae11bc0fdc383e3f71e4b6948edc6a5ef6 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 11:37:28 -0700 Subject: [PATCH 04/71] Fixing doc build issue --- .github/workflows/commit.yaml | 2 +- docs/requirements.txt | 2 ++ requirements-dev.txt | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index 6cc2260d0..508c38172 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -65,9 +65,9 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install -e . + python -m pip install -r docs/requirements.txt pip install -r requirements-dev.txt pip install -r requirements.txt - python -m pip install -r docs/requirements.txt - name: Doctests run: | diff --git a/docs/requirements.txt b/docs/requirements.txt index f822bffdb..d97b84765 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,3 +2,5 @@ sphinx sphinx-rtd-theme sphinxcontrib-napoleon invoke +jinja2==2.11.3 +MarkupSafe==2.0.1 diff --git a/requirements-dev.txt b/requirements-dev.txt index a073f00b7..fe70dc1a4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,8 +2,6 @@ black==22.6.0 coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.1 -jinja2==2.11.3 -types-Jinja2==2.11.9 pytest==7.1.2 pytest-cov==3.0.0 pytest-json==0.4.0 From a904fb64c243d30a5d2151a9aa9653b9f6cb1db9 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 12:11:00 -0700 Subject: [PATCH 05/71] Trying to fix broken docs tests --- docs/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/test.sh b/docs/test.sh index 78a572fac..5db4f638c 100755 --- a/docs/test.sh +++ b/docs/test.sh @@ -1,5 +1,6 @@ #!/bin/bash CWD=`pwd` +echo $CWD TEST_RESULTS_PATH="$CWD/support/tests" if [ ! -f "report.json" ]; then From c5df3e4f2250b055025cc32ca1e584458a6fa82b Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 12:24:05 -0700 Subject: [PATCH 06/71] py.test breakage --- docs/requirements.txt | 1 + docs/test.sh | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index d97b84765..37f1ae224 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,3 +4,4 @@ sphinxcontrib-napoleon invoke jinja2==2.11.3 MarkupSafe==2.0.1 +pytest==6.2.5 diff --git a/docs/test.sh b/docs/test.sh index 5db4f638c..99ad9c5e2 100755 --- a/docs/test.sh +++ b/docs/test.sh @@ -1,15 +1,11 @@ #!/bin/bash CWD=`pwd` -echo $CWD TEST_RESULTS_PATH="$CWD/support/tests" if [ ! -f "report.json" ]; then set -e - pip install -r ../requirements.txt -r ../requirements-dev.txt - - set +e py.test -c /dev/null --cov=./ -vs --json=report.json ../test*/*/test_getters.py - set -e + set -e cp report.json $TEST_RESULTS_PATH/report.json fi From b5f492dc513fb67c0ea6e161befb9e02bf6ac448 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 12:30:14 -0700 Subject: [PATCH 07/71] Try again to fix py.test --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index fe70dc1a4..9c50d9995 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ black==22.6.0 coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.1 -pytest==7.1.2 +pytest==6.2.5 pytest-cov==3.0.0 pytest-json==0.4.0 pylama==8.2.1 From 792e70d28843362136696a195b6c9e4b1dea92e4 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 12 Jul 2022 12:50:06 -0700 Subject: [PATCH 08/71] Force ansible to be earlier version so Jinja2 2.x is used --- docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index 37f1ae224..a5380314c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -5,3 +5,4 @@ invoke jinja2==2.11.3 MarkupSafe==2.0.1 pytest==6.2.5 +ansible==4.10.0 From 4abe545101f47fa20ec1a6da0b81c2b394b819b6 Mon Sep 17 00:00:00 2001 From: Vivek Vashist Date: Wed, 13 Jul 2022 20:00:55 +0930 Subject: [PATCH 09/71] Fix minor typo --- napalm/base/utils/string_parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm/base/utils/string_parsers.py b/napalm/base/utils/string_parsers.py index c7dd8f376..830ec1d65 100644 --- a/napalm/base/utils/string_parsers.py +++ b/napalm/base/utils/string_parsers.py @@ -50,7 +50,7 @@ def colon_separated_string_to_dict( dictionary[line_data[0].strip()] = None else: raise Exception( - "Something went wrong parsing the colo separated string {}".format(line) + "Something went wrong parsing the colon separated string {}".format(line) ) return dictionary From 553fa1c258cd3d68d11f669e39ae9051bc15a8f6 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 17 Jul 2022 13:45:03 +1000 Subject: [PATCH 10/71] docs: Fix a few typos There are small typos in: - docs/support/ios.rst - napalm/eos/eos.py - napalm/ios/ios.py - napalm/junos/junos.py - napalm/pyIOSXR/iosxr.py - test/base/test_helpers.py - test/pyiosxr/test_iosxr.py Fixes: - Should read `uncommitted` rather than `uncommited`. - Should read `retrieve` rather than `retrive`. - Should read `retrieve` rather than `retreive`. - Should read `millions` rather than `milions`. - Should read `locally` rather than `localy`. - Should read `interface` rather than `interfacece`. - Should read `incorrect` rather than `incorrecet`. - Should read `elements` rather than `lements`. - Should read `argument` rather than `arguement`. - Should read `against` rather than `agains`. Signed-off-by: Tim Gates --- docs/support/ios.rst | 2 +- napalm/eos/eos.py | 2 +- napalm/ios/ios.py | 2 +- napalm/junos/junos.py | 8 ++++---- napalm/pyIOSXR/iosxr.py | 2 +- test/base/test_helpers.py | 2 +- test/pyiosxr/test_iosxr.py | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/support/ios.rst b/docs/support/ios.rst index b46a92a54..1bbc5116e 100644 --- a/docs/support/ios.rst +++ b/docs/support/ios.rst @@ -116,7 +116,7 @@ File Operation Prompts ______________________ By default IOS will prompt for confirmation on file operations. These prompts need to be disabled before the NAPALM-ios driver performs any such operation on the device. -This can be controlled using the `auto_file_prompt` optional arguement: +This can be controlled using the `auto_file_prompt` optional argument: * `auto_file_prompt=True` (default): NAPALM will automatically add `file prompt quiet` to the device configuration before performing file operations, and un-configure it again afterwards. If the device already had the command in its configuration then it will be silently removed as a result, and diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index b38ae4e7d..6524ce556 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -656,7 +656,7 @@ def get_interfaces_counters(self): def get_bgp_neighbors(self): def get_re_group(res, key, default=None): - """Small helper to retrive data from re match groups""" + """Small helper to retrieve data from re match groups""" try: return res.group(key) except KeyError: diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index 59284a362..19cbbc2f3 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -3005,7 +3005,7 @@ def _get_bgp_route_attr(self, destination, vrf, next_hop, ip_version=4): # next-hop is not known in this vrf, route leaked from # other vrf or from vpnv4 table? # get remote AS nr. from as-path if it is ebgp neighbor - # localy sourced prefix is not in routing table as a bgp route (i hope...) + # locally sourced prefix is not in routing table as a bgp route (i hope...) if search_re_dict["bgpie"]["result"] == "external": bgpras = ( search_re_dict["aspath"]["result"] diff --git a/napalm/junos/junos.py b/napalm/junos/junos.py index d274dac91..8d56b0fbc 100644 --- a/napalm/junos/junos.py +++ b/napalm/junos/junos.py @@ -176,10 +176,10 @@ def _unlock(self): def _rpc(self, get, child=None, **kwargs): """ - This allows you to construct an arbitrary RPC call to retreive common stuff. For example: + This allows you to construct an arbitrary RPC call to retrieve common stuff. For example: Configuration: get: "" Interface information: get: "" - A particular interfacece information: + A particular interface information: get: "" child: "ge-0/0/0" """ @@ -1169,7 +1169,7 @@ def update_dict(d, u): # for deep dictionary update def build_prefix_limit(**args): """ - Transform the lements of a dictionary into nested dictionaries. + Transform the elements of a dictionary into nested dictionaries. Example: { @@ -1824,7 +1824,7 @@ def get_route_to(self, destination="", protocol="", longer=False): try: routes_table.get(**rt_kargs) except RpcTimeoutError: - # on devices with milions of routes + # on devices with millions of routes # in case the destination is too generic (e.g.: 10/8) # will take very very long to determine all routes and # moreover will return a huge list diff --git a/napalm/pyIOSXR/iosxr.py b/napalm/pyIOSXR/iosxr.py index 694a73227..a1ddc2215 100644 --- a/napalm/pyIOSXR/iosxr.py +++ b/napalm/pyIOSXR/iosxr.py @@ -690,7 +690,7 @@ def commit_replace_config(self, label=None, comment=None, confirmed=None): def discard_config(self): """ - Clear uncommited changes in the current session. + Clear uncommitted changes in the current session. Clear previously loaded configuration on the device without committing it. """ diff --git a/test/base/test_helpers.py b/test/base/test_helpers.py index f6ca9717b..afe280eb9 100644 --- a/test/base/test_helpers.py +++ b/test/base/test_helpers.py @@ -81,7 +81,7 @@ def test_load_template(self): custom path * check if can load correct template from custom path * check if template passed as string can be loaded - * check that the search path setup by MRO is correct when loading an incorrecet template + * check that the search path setup by MRO is correct when loading an incorrect template """ self.assertTrue(HAS_JINJA) # firstly check if jinja2 is installed diff --git a/test/pyiosxr/test_iosxr.py b/test/pyiosxr/test_iosxr.py index 9c8128c45..b8485659d 100755 --- a/test/pyiosxr/test_iosxr.py +++ b/test/pyiosxr/test_iosxr.py @@ -257,7 +257,7 @@ def test__getattr_show_config(self): def test__getattr__no_show(self): - """Test special attribute __getattr__ agains a no-show command""" + """Test special attribute __getattr__ against a no-show command""" raised = False From 029a38bf119771631ad7243f657c60ea3afd9c1c Mon Sep 17 00:00:00 2001 From: bewing Date: Mon, 22 Aug 2022 14:15:32 -0500 Subject: [PATCH 11/71] fix: pin pyflakes version (#1739) Incompatibility between pylama and pyflakes > 2.4.0 https://github.com/klen/pylama/issues/224 --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index 9c50d9995..dc9df3dca 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,6 +5,7 @@ flake8-import-order==0.18.1 pytest==6.2.5 pytest-cov==3.0.0 pytest-json==0.4.0 +pyflakes==2.4.0 pylama==8.2.1 mock==4.0.3 tox==3.25.1 From d297056ff191d2fe447b5467504554415398d78f Mon Sep 17 00:00:00 2001 From: bewing Date: Mon, 22 Aug 2022 19:21:23 -0500 Subject: [PATCH 12/71] fix(eos): handle netmiko close (#1736) Resolves #1735 --- napalm/eos/eos.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index 6524ce556..a7a1a89fa 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -36,7 +36,7 @@ # third party libs import pyeapi from pyeapi.eapilib import ConnectionError, EapiConnection -from netmiko import ConfigInvalidException +from netmiko import BaseConnection, ConfigInvalidException # NAPALM base import napalm.base.helpers @@ -231,7 +231,9 @@ def open(self): def close(self): """Implementation of NAPALM method close.""" self.discard_config() - if hasattr(self.device.connection, "close") and callable( + if isinstance(self.device, BaseConnection): + self._netmiko_close() + elif hasattr(self.device.connection, "close") and callable( self.device.connection.close ): self.device.connection.close() From 8ec78e93b9e1f8c2d7fb2473d6e7befbd7b33eee Mon Sep 17 00:00:00 2001 From: Saurabh Saran Date: Thu, 8 Sep 2022 20:34:29 -0600 Subject: [PATCH 13/71] eos issue#1743 bug fix get_bgp_neighbors() --- 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 a7a1a89fa..79ca7cb44 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -664,7 +664,7 @@ def get_re_group(res, key, default=None): except KeyError: return default - NEIGHBOR_FILTER = "bgp neighbors vrf all | include remote AS | remote router ID |IPv[46] (Unicast|6PE):.*[0-9]+|^Local AS|Desc|BGP state" # noqa + NEIGHBOR_FILTER = "bgp neighbors vrf all | include IPv[46] (Unicast|6PE):.*[0-9]+ | grep -v ' IPv[46] Unicast:/.' | remote AS |^Local AS|Desc|BGP state |remote router ID" # noqa output_summary_cmds = self._run_commands( ["show ipv6 bgp summary vrf all", "show ip bgp summary vrf all"], encoding="json", From c0d3f45995e47cd5fdc83ede851fd1adf1307918 Mon Sep 17 00:00:00 2001 From: Saurabh Saran Date: Tue, 13 Sep 2022 16:29:17 -0600 Subject: [PATCH 14/71] added mocked data for pytest --- ...S___Local_AS_Desc_BGP_state__remote_r.text | 12 + ..._AS___Local_AS_Desc_BGP_state__remote.text | 12 + ...S___Local_AS_Desc_BGP_state__remote_r.text | 234 ++++++++++++++++++ ..._AS___Local_AS_Desc_BGP_state__remote.text | 0 ...S___Local_AS_Desc_BGP_state__remote_r.text | 12 + ..._AS___Local_AS_Desc_BGP_state__remote.text | 12 + ...S___Local_AS_Desc_BGP_state__remote_r.text | 12 + ..._AS___Local_AS_Desc_BGP_state__remote.text | 12 + ...S___Local_AS_Desc_BGP_state__remote_r.text | 12 + ..._AS___Local_AS_Desc_BGP_state__remote.text | 12 + 10 files changed, 330 insertions(+) create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text new file mode 100644 index 000000000..270822d7d --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text @@ -0,0 +1,12 @@ +BGP neighbor is 192.168.56.2, remote AS 65002, external link + BGP version 4, remote router ID 192.168.56.2, VRF default + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text new file mode 100644 index 000000000..6643bdc03 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text @@ -0,0 +1,12 @@ +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 + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text new file mode 100644 index 000000000..e8d38e423 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text @@ -0,0 +1,234 @@ +BGP neighbor is 10.10.10.52, remote AS 64804, external link + BGP version 4, remote router ID 10.10.10.50, VRF default + BGP state is Established, up for 55d22h + IPv4 Unicast: 4366 4 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.51, remote AS 64804, external link + BGP version 4, remote router ID 10.10.10.50, VRF default + BGP state is Established, up for 6d01h + IPv4 Unicast: 4369 4 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.47, remote AS 64805, external link + BGP version 4, remote router ID 10.10.10.48, VRF default + BGP state is Established, up for 5d23h + IPv4 Unicast: 4369 4 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.57, remote AS 64805, external link + BGP version 4, remote router ID 10.10.10.48, VRF default + BGP state is Established, up for 5d23h + IPv4 Unicast: 4368 4 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.43, remote AS 64638, external link + BGP version 4, remote router ID 10.10.10.43, VRF default + BGP state is Established, up for 49d06h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.41, remote AS 64638, external link + BGP version 4, remote router ID 10.10.10.41, VRF default + BGP state is Established, up for 22:42:48 + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.29, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.29, VRF default + BGP state is Established, up for 97d08h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.35, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.35, VRF default + BGP state is Established, up for 134d05h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.39, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.39, VRF default + BGP state is Established, up for 82d03h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.38, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.38, VRF default + BGP state is Established, up for 128d07h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.34, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.29, VRF default + BGP state is Established, up for 4d06h + IPv4 Unicast: 4241 1620 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.44, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.35, VRF default + BGP state is Established, up for 81d08h + IPv4 Unicast: 3701 1620 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.45, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.39, VRF default + BGP state is Established, up for 81d08h + IPv4 Unicast: 3998 1620 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.46, remote AS 65118, external link + BGP version 4, remote router ID 10.10.10.38, VRF default + BGP state is Established, up for 124d02h + IPv4 Unicast: 3919 1620 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.58, remote AS 64638, external link + BGP version 4, remote router ID 10.10.10.43, VRF default + BGP state is Idle, Could not find interface for peer + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.49, remote AS 64638, external link + BGP version 4, remote router ID 10.10.10.41, VRF default + BGP state is Established, up for 22:44:04 + IPv4 Unicast: 4369 14 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.54, remote AS 64638, external link + BGP version 4, remote router ID 10.10.10.43, VRF default + BGP state is Established, up for 6d02h + IPv4 Unicast: 4357 14 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.37, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.37, VRF default + BGP state is Established, up for 96d00h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.36, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.37, VRF default + BGP state is Established, up for 90d07h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.53, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.37, VRF default + BGP state is Established, up for 81d07h + IPv4 Unicast: 3119 2721 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.59, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.37, VRF default + BGP state is Established, up for 22d00h + IPv4 Unicast: 4369 2721 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.56, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.37, VRF default + BGP state is Established, up for 62d07h + IPv4 Unicast: 3048 2721 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.55, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.37, VRF default + BGP state is Established, up for 62d07h + IPv4 Unicast: 4219 2720 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 2.2.2.2 +BGP neighbor is 10.10.10.8, remote AS 64805, external link + BGP version 4, remote router ID 10.10.10.9, VRF BLUE + BGP state is Established, up for 5d23h + IPv4 Unicast: 12 2 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.18 +BGP neighbor is 10.10.10.10, remote AS 64805, external link + BGP version 4, remote router ID 10.10.10.9, VRF BLUE + BGP state is Established, up for 5d23h + IPv4 Unicast: 14 2 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.18 +BGP neighbor is 10.10.10.16, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.13, VRF BLUE + BGP state is Established, up for 22d00h + IPv4 Unicast: 14 7 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.18 +BGP neighbor is 10.10.10.12, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.13, VRF BLUE + BGP state is Established, up for 60d02h + IPv4 Unicast: 7 7 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.18 +BGP neighbor is 10.10.10.14, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.15, VRF BLUE + BGP state is Established, up for 60d02h + IPv4 Unicast: 10 7 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.18 +BGP neighbor is 10.10.10.30, remote AS 64804, external link + BGP version 4, remote router ID 10.10.10.27, VRF GREEN + BGP state is Established, up for 55d22h + IPv4 Unicast: 53 8 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.33, remote AS 64804, external link + BGP version 4, remote router ID 10.10.10.27, VRF GREEN + BGP state is Established, up for 6d01h + IPv4 Unicast: 59 8 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.21, remote AS 64805, external link + BGP version 4, remote router ID 10.10.10.20, VRF GREEN + BGP state is Established, up for 5d23h + IPv4 Unicast: 58 8 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.19, remote AS 64805, external link + BGP version 4, remote router ID 10.10.10.20, VRF GREEN + BGP state is Established, up for 5d23h + IPv4 Unicast: 58 8 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.31, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.26, VRF GREEN + BGP state is Established, up for 60d02h + IPv4 Unicast: 24 50 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.32, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.26, VRF GREEN + BGP state is Established, up for 22d00h + IPv4 Unicast: 59 50 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.25, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.26, VRF GREEN + BGP state is Established, up for 60d02h + IPv4 Unicast: 59 50 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.23, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.24, VRF GREEN + BGP state is Established, up for 60d02h + IPv4 Unicast: 44 44 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.28 +BGP neighbor is 10.10.10.5, remote AS 64804, external link + BGP version 4, remote router ID 10.10.10.2, VRF RED + BGP state is Established, up for 55d22h + IPv4 Unicast: 12 2 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.7 +BGP neighbor is 10.10.10.1, remote AS 64804, external link + BGP version 4, remote router ID 10.10.10.2, VRF RED + BGP state is Established, up for 6d01h + IPv4 Unicast: 14 2 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.7 +BGP neighbor is 10.10.10.3, remote AS 65066, external link + BGP version 4, remote router ID 10.10.10.4, VRF RED + BGP state is Established, up for 60d02h + IPv4 Unicast: 3 11 + IPv6 Unicast: 0 0 +Local AS is 65101, local router ID 10.10.10.7 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text new file mode 100644 index 000000000..e69de29bb diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text new file mode 100644 index 000000000..270822d7d --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text @@ -0,0 +1,12 @@ +BGP neighbor is 192.168.56.2, remote AS 65002, external link + BGP version 4, remote router ID 192.168.56.2, VRF default + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text new file mode 100644 index 000000000..6643bdc03 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text @@ -0,0 +1,12 @@ +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 + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text new file mode 100644 index 000000000..577f118a3 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text @@ -0,0 +1,12 @@ +BGP neighbor is 192.168.56.2, remote AS 65002, external link + BGP version 4, remote router ID 192.168.56.2, VRF default + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 6PE: 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 6PE: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text new file mode 100644 index 000000000..6643bdc03 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text @@ -0,0 +1,12 @@ +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 + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text b/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text new file mode 100644 index 000000000..270822d7d --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text @@ -0,0 +1,12 @@ +BGP neighbor is 192.168.56.2, remote AS 65002, external link + BGP version 4, remote router ID 192.168.56.2, VRF default + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text b/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text new file mode 100644 index 000000000..6643bdc03 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text @@ -0,0 +1,12 @@ +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 + BGP state is Established, up for 32d16h + 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 + BGP state is Established, up for 32d16h + IPv4 Unicast: 0 0 + IPv6 Unicast: 0 0 +Local AS is 65002, local router ID 192.168.56.2 From 6168f9399f8f07781ec6d978bb1afe8cf6f4b8dd Mon Sep 17 00:00:00 2001 From: Saurabh Saran Date: Mon, 26 Sep 2022 11:54:07 -0600 Subject: [PATCH 15/71] git rm'd old/unused show_ip_bgp_neighbors_vrf_all__include_remote... files from testcases --- ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 234 ------------------ ...PE_____0_9____Local_AS_Desc_BGP_state.text | 0 ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - ...PE_____0_9____Local_AS_Desc_BGP_state.text | 12 - 10 files changed, 330 deletions(-) delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text delete mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 270822d7d..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -BGP neighbor is 192.168.56.2, remote AS 65002, external link - BGP version 4, remote router ID 192.168.56.2, VRF default - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 6643bdc03..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue1168/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -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 - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index e8d38e423..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,234 +0,0 @@ -BGP neighbor is 10.10.10.52, remote AS 64804, external link - BGP version 4, remote router ID 10.10.10.50, VRF default - BGP state is Established, up for 55d22h - IPv4 Unicast: 4366 4 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.51, remote AS 64804, external link - BGP version 4, remote router ID 10.10.10.50, VRF default - BGP state is Established, up for 6d01h - IPv4 Unicast: 4369 4 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.47, remote AS 64805, external link - BGP version 4, remote router ID 10.10.10.48, VRF default - BGP state is Established, up for 5d23h - IPv4 Unicast: 4369 4 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.57, remote AS 64805, external link - BGP version 4, remote router ID 10.10.10.48, VRF default - BGP state is Established, up for 5d23h - IPv4 Unicast: 4368 4 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.43, remote AS 64638, external link - BGP version 4, remote router ID 10.10.10.43, VRF default - BGP state is Established, up for 49d06h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.41, remote AS 64638, external link - BGP version 4, remote router ID 10.10.10.41, VRF default - BGP state is Established, up for 22:42:48 - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.29, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.29, VRF default - BGP state is Established, up for 97d08h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.35, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.35, VRF default - BGP state is Established, up for 134d05h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.39, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.39, VRF default - BGP state is Established, up for 82d03h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.38, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.38, VRF default - BGP state is Established, up for 128d07h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.34, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.29, VRF default - BGP state is Established, up for 4d06h - IPv4 Unicast: 4241 1620 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.44, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.35, VRF default - BGP state is Established, up for 81d08h - IPv4 Unicast: 3701 1620 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.45, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.39, VRF default - BGP state is Established, up for 81d08h - IPv4 Unicast: 3998 1620 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.46, remote AS 65118, external link - BGP version 4, remote router ID 10.10.10.38, VRF default - BGP state is Established, up for 124d02h - IPv4 Unicast: 3919 1620 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.58, remote AS 64638, external link - BGP version 4, remote router ID 10.10.10.43, VRF default - BGP state is Idle, Could not find interface for peer - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.49, remote AS 64638, external link - BGP version 4, remote router ID 10.10.10.41, VRF default - BGP state is Established, up for 22:44:04 - IPv4 Unicast: 4369 14 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.54, remote AS 64638, external link - BGP version 4, remote router ID 10.10.10.43, VRF default - BGP state is Established, up for 6d02h - IPv4 Unicast: 4357 14 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.37, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.37, VRF default - BGP state is Established, up for 96d00h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.36, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.37, VRF default - BGP state is Established, up for 90d07h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.53, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.37, VRF default - BGP state is Established, up for 81d07h - IPv4 Unicast: 3119 2721 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.59, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.37, VRF default - BGP state is Established, up for 22d00h - IPv4 Unicast: 4369 2721 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.56, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.37, VRF default - BGP state is Established, up for 62d07h - IPv4 Unicast: 3048 2721 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.55, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.37, VRF default - BGP state is Established, up for 62d07h - IPv4 Unicast: 4219 2720 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 2.2.2.2 -BGP neighbor is 10.10.10.8, remote AS 64805, external link - BGP version 4, remote router ID 10.10.10.9, VRF BLUE - BGP state is Established, up for 5d23h - IPv4 Unicast: 12 2 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.18 -BGP neighbor is 10.10.10.10, remote AS 64805, external link - BGP version 4, remote router ID 10.10.10.9, VRF BLUE - BGP state is Established, up for 5d23h - IPv4 Unicast: 14 2 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.18 -BGP neighbor is 10.10.10.16, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.13, VRF BLUE - BGP state is Established, up for 22d00h - IPv4 Unicast: 14 7 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.18 -BGP neighbor is 10.10.10.12, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.13, VRF BLUE - BGP state is Established, up for 60d02h - IPv4 Unicast: 7 7 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.18 -BGP neighbor is 10.10.10.14, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.15, VRF BLUE - BGP state is Established, up for 60d02h - IPv4 Unicast: 10 7 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.18 -BGP neighbor is 10.10.10.30, remote AS 64804, external link - BGP version 4, remote router ID 10.10.10.27, VRF GREEN - BGP state is Established, up for 55d22h - IPv4 Unicast: 53 8 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.33, remote AS 64804, external link - BGP version 4, remote router ID 10.10.10.27, VRF GREEN - BGP state is Established, up for 6d01h - IPv4 Unicast: 59 8 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.21, remote AS 64805, external link - BGP version 4, remote router ID 10.10.10.20, VRF GREEN - BGP state is Established, up for 5d23h - IPv4 Unicast: 58 8 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.19, remote AS 64805, external link - BGP version 4, remote router ID 10.10.10.20, VRF GREEN - BGP state is Established, up for 5d23h - IPv4 Unicast: 58 8 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.31, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.26, VRF GREEN - BGP state is Established, up for 60d02h - IPv4 Unicast: 24 50 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.32, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.26, VRF GREEN - BGP state is Established, up for 22d00h - IPv4 Unicast: 59 50 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.25, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.26, VRF GREEN - BGP state is Established, up for 60d02h - IPv4 Unicast: 59 50 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.23, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.24, VRF GREEN - BGP state is Established, up for 60d02h - IPv4 Unicast: 44 44 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.28 -BGP neighbor is 10.10.10.5, remote AS 64804, external link - BGP version 4, remote router ID 10.10.10.2, VRF RED - BGP state is Established, up for 55d22h - IPv4 Unicast: 12 2 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.7 -BGP neighbor is 10.10.10.1, remote AS 64804, external link - BGP version 4, remote router ID 10.10.10.2, VRF RED - BGP state is Established, up for 6d01h - IPv4 Unicast: 14 2 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.7 -BGP neighbor is 10.10.10.3, remote AS 65066, external link - BGP version 4, remote router ID 10.10.10.4, VRF RED - BGP state is Established, up for 60d02h - IPv4 Unicast: 3 11 - IPv6 Unicast: 0 0 -Local AS is 65101, local router ID 10.10.10.7 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1356/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 270822d7d..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -BGP neighbor is 192.168.56.2, remote AS 65002, external link - BGP version 4, remote router ID 192.168.56.2, VRF default - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 6643bdc03..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue58_neighbor_down/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -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 - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 577f118a3..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -BGP neighbor is 192.168.56.2, remote AS 65002, external link - BGP version 4, remote router ID 192.168.56.2, VRF default - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 6PE: 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 6PE: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 6643bdc03..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/issue944/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -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 - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 270822d7d..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -BGP neighbor is 192.168.56.2, remote AS 65002, external link - BGP version 4, remote router ID 192.168.56.2, VRF default - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text b/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text deleted file mode 100644 index 6643bdc03..000000000 --- a/test/eos/mocked_data/test_get_bgp_neighbors/normal/show_ipv6_bgp_neighbors_vrf_all___include_remote_AS___remote_router_ID__IPv_46___Unicast_6PE_____0_9____Local_AS_Desc_BGP_state.text +++ /dev/null @@ -1,12 +0,0 @@ -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 - BGP state is Established, up for 32d16h - 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 - BGP state is Established, up for 32d16h - IPv4 Unicast: 0 0 - IPv6 Unicast: 0 0 -Local AS is 65002, local router ID 192.168.56.2 From 2cce6287663e4aa49d3eae9bbbddc5aeac38f526 Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Tue, 11 Oct 2022 17:03:40 -0500 Subject: [PATCH 16/71] add test case for BGP link local neighbors --- .../issue1759/expected_result.json | 112 ++++++++++++++++++ ...S___Local_AS_Desc_BGP_state__remote_r.text | 0 .../show_ip_bgp_summary_vrf_all.json | 76 ++++++++++++ ..._AS___Local_AS_Desc_BGP_state__remote.text | 30 +++++ .../show_ipv6_bgp_summary_vrf_all.json | 76 ++++++++++++ 5 files changed, 294 insertions(+) create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1759/expected_result.json create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_summary_vrf_all.json create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text create mode 100644 test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_summary_vrf_all.json diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/expected_result.json b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/expected_result.json new file mode 100644 index 000000000..ee7922393 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/expected_result.json @@ -0,0 +1,112 @@ +{ + "global": { + "peers": { + "fe80::a8c1:abff:fe0b:7b5f%Et5": { + "is_up": true, + "is_enabled": true, + "uptime": "...", + "description": "", + "remote_as": 4259840008, + "remote_id": "172.18.0.8", + "local_as": 4259906562, + "address_family": { + "ipv4": { + "sent_prefixes": 9, + "received_prefixes": 2, + "accepted_prefixes": -1 + }, + "ipv6": { + "sent_prefixes": 9, + "received_prefixes": 2, + "accepted_prefixes": -1 + } + } + }, + "fe80::a8c1:abff:fe27:69e9%Et2": { + "is_up": true, + "is_enabled": true, + "uptime": "...", + "description": "", + "remote_as": 4259973121, + "remote_id": "172.18.8.1", + "local_as": 4259906562, + "address_family": { + "ipv4": { + "sent_prefixes": 9, + "received_prefixes": 5, + "accepted_prefixes": -1 + }, + "ipv6": { + "sent_prefixes": 9, + "received_prefixes": 5, + "accepted_prefixes": -1 + } + } + }, + "fe80::a8c1:abff:fe35:51d9%Et1": { + "is_up": true, + "is_enabled": true, + "uptime": "...", + "description": "", + "remote_as": 4259973120, + "remote_id": "172.18.8.0", + "local_as": 4259906562, + "address_family": { + "ipv4": { + "sent_prefixes": 6, + "received_prefixes": 5, + "accepted_prefixes": -1 + }, + "ipv6": { + "sent_prefixes": 6, + "received_prefixes": 5, + "accepted_prefixes": -1 + } + } + }, + "fe80::a8c1:abff:fe5d:9706%Et4": { + "is_up": true, + "is_enabled": true, + "uptime": "...", + "description": "", + "remote_as": 4259840007, + "remote_id": "172.18.0.7", + "local_as": 4259906562, + "address_family": { + "ipv4": { + "sent_prefixes": 9, + "received_prefixes": 2, + "accepted_prefixes": -1 + }, + "ipv6": { + "sent_prefixes": 9, + "received_prefixes": 2, + "accepted_prefixes": -1 + } + } + }, + "fe80::a8c1:abff:fe95:fa49%Et3": { + "is_up": true, + "is_enabled": true, + "uptime": "...", + "description": "", + "remote_as": 4259840005, + "remote_id": "172.18.0.5", + "local_as": 4259906562, + "address_family": { + "ipv4": { + "sent_prefixes": 9, + "received_prefixes": 2, + "accepted_prefixes": -1 + }, + "ipv6": { + "sent_prefixes": 9, + "received_prefixes": 2, + "accepted_prefixes": -1 + } + } + } + }, + "router_id": "172.18.4.2" + } +} diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote_r.text new file mode 100644 index 000000000..e69de29bb diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_summary_vrf_all.json b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_summary_vrf_all.json new file mode 100644 index 000000000..0155ea42a --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ip_bgp_summary_vrf_all.json @@ -0,0 +1,76 @@ +{ + "vrfs": { + "default": { + "routerId": "172.18.4.2", + "peers": { + "fe80::a8c1:abff:fe0b:7b5f%Et5": { + "msgSent": 239229, + "inMsgQueue": 0, + "prefixReceived": 2, + "upDownTime": 1664912777.128896, + "version": 4, + "prefixAccepted": 2, + "msgReceived": 203694, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65000.8" + }, + "fe80::a8c1:abff:fe27:69e9%Et2": { + "msgSent": 11997, + "inMsgQueue": 0, + "prefixReceived": 5, + "upDownTime": 1664912780.356704, + "version": 4, + "prefixAccepted": 5, + "msgReceived": 11972, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65002.2049" + }, + "fe80::a8c1:abff:fe35:51d9%Et1": { + "msgSent": 11984, + "inMsgQueue": 0, + "prefixReceived": 5, + "upDownTime": 1664912783.670673, + "version": 4, + "prefixAccepted": 5, + "msgReceived": 11979, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65002.2048" + }, + "fe80::a8c1:abff:fe5d:9706%Et4": { + "msgSent": 239170, + "inMsgQueue": 0, + "prefixReceived": 2, + "upDownTime": 1664912777.50903, + "version": 4, + "prefixAccepted": 2, + "msgReceived": 203718, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65000.7" + }, + "fe80::a8c1:abff:fe95:fa49%Et3": { + "msgSent": 239116, + "inMsgQueue": 0, + "prefixReceived": 2, + "upDownTime": 1664912777.604791, + "version": 4, + "prefixAccepted": 2, + "msgReceived": 203718, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65000.5" + } + }, + "vrf": "default", + "asn": "65001.1026" + } + } +} diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text new file mode 100644 index 000000000..f1d5ed371 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_neighbors_vrf_all___include_IPv_46___Unicast_6PE_____0_9_____grep__v___IPv_46__Unicast_______remote_AS___Local_AS_Desc_BGP_state__remote.text @@ -0,0 +1,30 @@ +BGP neighbor is fe80::a8c1:abff:fe0b:7b5f%Et5, remote AS 65000.8, external link + BGP version 4, remote router ID 172.18.0.8, VRF default + BGP state is Established, up for 7d01h + IPv4 Unicast: 9 2 1 0 + IPv6 Unicast: 9 2 1 0 +Local AS is 65001.1026, local router ID 172.18.4.2 +BGP neighbor is fe80::a8c1:abff:fe27:69e9%Et2, remote AS 65002.2049, external link + BGP version 4, remote router ID 172.18.8.1, VRF default + BGP state is Established, up for 7d01h + IPv4 Unicast: 9 5 1 0 + IPv6 Unicast: 9 5 1 0 +Local AS is 65001.1026, local router ID 172.18.4.2 +BGP neighbor is fe80::a8c1:abff:fe35:51d9%Et1, remote AS 65002.2048, external link + BGP version 4, remote router ID 172.18.8.0, VRF default + BGP state is Established, up for 7d01h + IPv4 Unicast: 6 5 4 0 + IPv6 Unicast: 6 5 4 0 +Local AS is 65001.1026, local router ID 172.18.4.2 +BGP neighbor is fe80::a8c1:abff:fe5d:9706%Et4, remote AS 65000.7, external link + BGP version 4, remote router ID 172.18.0.7, VRF default + BGP state is Established, up for 7d01h + IPv4 Unicast: 9 2 1 0 + IPv6 Unicast: 9 2 1 0 +Local AS is 65001.1026, local router ID 172.18.4.2 +BGP neighbor is fe80::a8c1:abff:fe95:fa49%Et3, remote AS 65000.5, external link + BGP version 4, remote router ID 172.18.0.5, VRF default + BGP state is Established, up for 7d01h + IPv4 Unicast: 9 2 1 0 + IPv6 Unicast: 9 2 1 0 +Local AS is 65001.1026, local router ID 172.18.4.2 diff --git a/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_summary_vrf_all.json b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_summary_vrf_all.json new file mode 100644 index 000000000..aa96e6d48 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_neighbors/issue1759/show_ipv6_bgp_summary_vrf_all.json @@ -0,0 +1,76 @@ +{ + "vrfs": { + "default": { + "routerId": "172.18.4.2", + "peers": { + "fe80::a8c1:abff:fe0b:7b5f%Et5": { + "msgSent": 239193, + "inMsgQueue": 0, + "prefixReceived": 2, + "upDownTime": 1664912777.128896, + "version": 4, + "prefixAccepted": 2, + "msgReceived": 203664, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65000.8" + }, + "fe80::a8c1:abff:fe27:69e9%Et2": { + "msgSent": 11995, + "inMsgQueue": 0, + "prefixReceived": 5, + "upDownTime": 1664912780.356703, + "version": 4, + "prefixAccepted": 5, + "msgReceived": 11970, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65002.2049" + }, + "fe80::a8c1:abff:fe35:51d9%Et1": { + "msgSent": 11982, + "inMsgQueue": 0, + "prefixReceived": 5, + "upDownTime": 1664912783.670674, + "version": 4, + "prefixAccepted": 5, + "msgReceived": 11977, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65002.2048" + }, + "fe80::a8c1:abff:fe5d:9706%Et4": { + "msgSent": 239135, + "inMsgQueue": 0, + "prefixReceived": 2, + "upDownTime": 1664912777.50903, + "version": 4, + "prefixAccepted": 2, + "msgReceived": 203688, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65000.7" + }, + "fe80::a8c1:abff:fe95:fa49%Et3": { + "msgSent": 239080, + "inMsgQueue": 0, + "prefixReceived": 2, + "upDownTime": 1664912777.604791, + "version": 4, + "prefixAccepted": 2, + "msgReceived": 203688, + "peerState": "Established", + "outMsgQueue": 0, + "underMaintenance": false, + "asn": "65000.5" + } + }, + "vrf": "default", + "asn": "65001.1026" + } + } +} From 4869ca52097013ab07bb40e13fc1aec76ec944eb Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Thu, 6 Oct 2022 13:27:39 -0500 Subject: [PATCH 17/71] refactor: replace netaddr with ipaddress --- napalm/base/helpers.py | 15 ++++++++++++--- napalm/eos/eos.py | 15 ++++++--------- napalm/ios/ios.py | 11 +++++------ napalm/iosxr/iosxr.py | 12 +++++------- napalm/iosxr_netconf/iosxr_netconf.py | 11 +++++------ napalm/nxos/nxos.py | 11 +++++------ napalm/nxos_ssh/nxos_ssh.py | 11 ++++------- test/base/test_helpers.py | 6 ++---- 8 files changed, 44 insertions(+), 48 deletions(-) diff --git a/napalm/base/helpers.py b/napalm/base/helpers.py index 935dfd58d..e40b88a77 100644 --- a/napalm/base/helpers.py +++ b/napalm/base/helpers.py @@ -1,4 +1,5 @@ """Helper functions for the NAPALM base.""" +import ipaddress import itertools import logging @@ -14,7 +15,6 @@ import textfsm from lxml import etree from netaddr import EUI -from netaddr import IPAddress from netaddr import mac_unix from netutils.config.parser import IOSConfigParser @@ -537,10 +537,19 @@ def ip(addr: str, version: Optional[int] = None) -> str: >>> ip('2001:0dB8:85a3:0000:0000:8A2e:0370:7334') u'2001:db8:85a3::8a2e:370:7334' """ - addr_obj = IPAddress(addr) + scope = "" + if "%" in addr: + addr, scope = addr.split("%", 1) + addr_obj = ipaddress.ip_address(addr) if version and addr_obj.version != version: raise ValueError("{} is not an ipv{} address".format(addr, version)) - return str(addr_obj) + if addr_obj.version == 6 and addr_obj.ipv4_mapped is not None: + return_addr = "%s:%s" % ("::ffff", addr_obj.ipv4_mapped) + else: + return_addr = str(addr_obj) + if scope: + return_addr = "%s%%%s" % (return_addr, scope) + return return_addr def as_number(as_number_val: str) -> int: diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index 79ca7cb44..f10290cd6 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -23,15 +23,12 @@ import time import importlib import inspect +import ipaddress import json import socket from datetime import datetime from collections import defaultdict -from netaddr import IPAddress -from netaddr import IPNetwork - -from netaddr.core import AddrFormatError # third party libs import pyeapi @@ -1134,7 +1131,7 @@ def parse_options(options, default_value=False): # will try to parse the neighbor name # which sometimes is the IP Address of the neigbor # or the name of the BGP group - IPAddress(group_or_neighbor) + ipaddress.ip_address(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: @@ -1162,7 +1159,7 @@ def parse_options(options, default_value=False): bgp_neighbors[peer_address].update( parse_options(options, default_value) ) - except AddrFormatError: + except ValueError: # exception trying to parse group name # group_or_neighbor represents the name of the group group_name = group_or_neighbor @@ -1425,7 +1422,7 @@ def get_route_to(self, destination="", protocol="", longer=False): protocol = "connected" ipv = "" - if IPNetwork(destination).version == 6: + if ipaddress.ip_network(destination).version == 6: ipv = "v6" commands = [] @@ -1532,7 +1529,7 @@ def get_route_to(self, destination="", protocol="", longer=False): .get("peerEntry", {}) .get("peerAddr", "") ) - except AddrFormatError: + except ValueError: remote_address = napalm.base.helpers.ip( bgp_route_details.get("peerEntry", {}).get( "peerAddr", "" @@ -1911,7 +1908,7 @@ def _append(bgp_dict, peer_info): summary_commands.append("show ipv6 bgp summary vrf all") else: try: - peer_ver = IPAddress(neighbor_address).version + peer_ver = ipaddress.ip_address(neighbor_address).version except Exception as e: raise e diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index 19cbbc2f3..ecd6964ce 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -14,6 +14,7 @@ # the License. import copy import functools +import ipaddress import os import re import socket @@ -22,8 +23,6 @@ import uuid from collections import defaultdict -from netaddr import IPNetwork -from netaddr.core import AddrFormatError from netmiko import FileTransfer, InLineTransfer import napalm.base.constants as C @@ -3074,8 +3073,8 @@ def get_route_to(self, destination="", protocol="", longer=False): vrf = "" ip_version = None try: - ip_version = IPNetwork(destination).version - except AddrFormatError: + ip_version = ipaddress.ip_network(destination).version + except ValueError: return "Please specify a valid destination!" if ip_version == 4: # process IPv4 routing table if vrf == "": @@ -3083,8 +3082,8 @@ def get_route_to(self, destination="", protocol="", longer=False): else: vrfs = [vrf] # VRFs where IPv4 is enabled vrfs.append("default") # global VRF - ipnet_dest = IPNetwork(destination) - prefix = str(ipnet_dest.network) + ipnet_dest = ipaddress.ip_network(destination) + prefix = str(ipnet_dest.network_address) netmask = "" routes = {} if "/" in destination: diff --git a/napalm/iosxr/iosxr.py b/napalm/iosxr/iosxr.py index e8e4e5921..f491addfe 100644 --- a/napalm/iosxr/iosxr.py +++ b/napalm/iosxr/iosxr.py @@ -16,15 +16,13 @@ # import stdlib import re import copy +import ipaddress from collections import defaultdict import logging # import third party lib from lxml import etree as ETREE -from netaddr import IPAddress # needed for traceroute, to check IP version -from netaddr.core import AddrFormatError - from napalm.pyIOSXR import IOSXR from napalm.pyIOSXR.exceptions import ConnectError from napalm.pyIOSXR.exceptions import TimeoutError @@ -1733,8 +1731,8 @@ def get_route_to(self, destination="", protocol="", longer=False): ipv = 4 try: - ipv = IPAddress(network).version - except AddrFormatError: + ipv = ipaddress.ip_address(network).version + except ValueError: logger.error("Wrong destination IP Address format supplied to get_route_to") raise TypeError("Wrong destination IP Address!") @@ -2187,8 +2185,8 @@ def traceroute( ipv = 4 try: - ipv = IPAddress(destination).version - except AddrFormatError: + ipv = ipaddress.ip_address(destination).version + except ValueError: logger.error( "Incorrect format of IP Address in traceroute \ with value provided:%s" diff --git a/napalm/iosxr_netconf/iosxr_netconf.py b/napalm/iosxr_netconf/iosxr_netconf.py index 656078880..3f238a1b0 100644 --- a/napalm/iosxr_netconf/iosxr_netconf.py +++ b/napalm/iosxr_netconf/iosxr_netconf.py @@ -22,6 +22,7 @@ import re import copy import difflib +import ipaddress import logging # import third party lib @@ -31,8 +32,6 @@ from ncclient.operations.errors import TimeoutExpiredError from lxml import etree as ETREE from lxml.etree import XMLSyntaxError -from netaddr import IPAddress # needed for traceroute, to check IP version -from netaddr.core import AddrFormatError # import NAPALM base from napalm.iosxr_netconf import constants as C @@ -2481,8 +2480,8 @@ def get_route_to(self, destination="", protocol="", longer=False): ipv = 4 try: - ipv = IPAddress(network).version - except AddrFormatError: + ipv = ipaddress.ip_address(network).version + except ValueError: logger.error("Wrong destination IP Address format supplied to get_route_to") raise TypeError("Wrong destination IP Address!") @@ -2952,8 +2951,8 @@ def traceroute( ipv = 4 try: - ipv = IPAddress(destination).version - except AddrFormatError: + ipv = ipaddress.ip_address(destination).version + except ValueError: logger.error( "Incorrect format of IP Address in traceroute \ with value provided:%s" diff --git a/napalm/nxos/nxos.py b/napalm/nxos/nxos.py index d857832e4..abdf4dada 100644 --- a/napalm/nxos/nxos.py +++ b/napalm/nxos/nxos.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations under # the License. +import ipaddress import json import os import re @@ -42,8 +43,6 @@ DefaultDict, ) -from netaddr import IPAddress -from netaddr.core import AddrFormatError from netmiko import file_transfer from requests.exceptions import ConnectionError from netutils.config.compliance import diff_network_config @@ -356,8 +355,8 @@ def ping( version = "" try: - version = "6" if IPAddress(destination).version == 6 else "" - except AddrFormatError: + version = "6" if ipaddress.ip_address(destination).version == 6 else "" + except ValueError: # Allow use of DNS names pass @@ -470,8 +469,8 @@ def traceroute( version = "" try: - version = "6" if IPAddress(destination).version == 6 else "" - except AddrFormatError: + version = "6" if ipaddress.ip_address(destination).version == 6 else "" + except ValueError: # Allow use of DNS names pass diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py index 01147d0e6..3306b1058 100644 --- a/napalm/nxos_ssh/nxos_ssh.py +++ b/napalm/nxos_ssh/nxos_ssh.py @@ -15,13 +15,10 @@ # import stdlib from builtins import super +import ipaddress import re import socket -# import third party lib -from netaddr import IPAddress, IPNetwork -from netaddr.core import AddrFormatError - # import NAPALM Base from napalm.base import helpers from napalm.base.exceptions import CommandErrorException, ReplaceConfigException @@ -953,7 +950,7 @@ def _get_ntp_entity(self, peer_type): # Skip first two lines and last line of command output if line == "" or "-----" in line or "Peer IP Address" in line: continue - elif IPAddress(len(line.split()[0])).is_unicast: + elif not ipaddress.ip_address(len(line.split()[0])).is_multicast: peer_addr = line.split()[0] ntp_entities[peer_addr] = {} else: @@ -1340,8 +1337,8 @@ def get_route_to(self, destination="", protocol="", longer=False): ip_version = None try: - ip_version = IPNetwork(destination).version - except AddrFormatError: + ip_version = ipaddress.ip_network(destination).version + except ValueError: return "Please specify a valid destination!" if ip_version == 4: # process IPv4 routing table routes = {} diff --git a/test/base/test_helpers.py b/test/base/test_helpers.py index afe280eb9..24bdb0f5f 100644 --- a/test/base/test_helpers.py +++ b/test/base/test_helpers.py @@ -375,10 +375,8 @@ def test_ip(self): * check if IPv6 address returned as expected """ - self.assertTrue(HAS_NETADDR) - - # test that raises AddrFormatError when wrong format - self.assertRaises(AddrFormatError, napalm.base.helpers.ip, "fake") + # test that raises ValueError when wrong format + self.assertRaises(ValueError, napalm.base.helpers.ip, "fake") self.assertRaises( ValueError, napalm.base.helpers.ip, From d9f9f0ddce0e67f6adfe7574d55bf166a8e59e2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 10:21:57 -0700 Subject: [PATCH 18/71] Bump mypy from 0.961 to 0.982 (#1765) Bumps [mypy](https://github.com/python/mypy) from 0.961 to 0.982. - [Release notes](https://github.com/python/mypy/releases) - [Commits](https://github.com/python/mypy/compare/v0.961...v0.982) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index dc9df3dca..f4598915f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -9,7 +9,7 @@ pyflakes==2.4.0 pylama==8.2.1 mock==4.0.3 tox==3.25.1 -mypy==0.961 +mypy==0.982 types-requests==2.28.0 types-six==1.16.17 types-setuptools==57.4.18 From 7ecb9b9a330579fc9669b92b2bb56ff54131e83a Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 14 Oct 2022 11:12:53 -0700 Subject: [PATCH 19/71] Extending amount of time that IOS commit_config is allowed (#1744) --- napalm/ios/ios.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index ecd6964ce..6235f5880 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -480,10 +480,10 @@ def _commit_handler(self, cmd): # Handle special username removal pattern pattern2 = r".*all username.*confirm" patterns = rf"(?:{pattern1}|{pattern2})" - output = self.device.send_command(cmd, expect_string=patterns) + output = self.device.send_command(cmd, expect_string=patterns, read_timeout=90) loop_count = 50 new_output = output - for i in range(loop_count): + for _ in range(loop_count): if re.search(pattern2, new_output): # Send confirmation if username removal new_output = self.device.send_command_timing( From df06defbea34d7bb8893c174d87e96be2c38d189 Mon Sep 17 00:00:00 2001 From: "Jamie (Bear) Murphy" <1613241+ITJamie@users.noreply.github.com> Date: Fri, 14 Oct 2022 20:44:14 +0100 Subject: [PATCH 20/71] pull "full" config for diff merges. (#1732) --- napalm/nxos/nxos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm/nxos/nxos.py b/napalm/nxos/nxos.py index abdf4dada..7eac8077e 100644 --- a/napalm/nxos/nxos.py +++ b/napalm/nxos/nxos.py @@ -232,7 +232,7 @@ def _get_merge_diff(self) -> str: interface loopback0 ip address 10.1.4.5/32 """ - running_config = self.get_config(retrieve="running")["running"] + running_config = self.get_config(retrieve="running", full=True)["running"] return diff_network_config(self.merge_candidate, running_config, "cisco_nxos") def _get_diff(self) -> str: From 41d19fe9bb72418dedb643f9445a58abbb78d802 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 17 Oct 2022 11:55:48 -0700 Subject: [PATCH 21/71] NX-OS SSH make some Netmiko version 4.x improvements (#1774) * Improvements to NX-OS SSH driver behavior under Netmiko 4.X * Roll required Netmiko version * Fixing Python black issue --- napalm/nxos_ssh/nxos_ssh.py | 26 ++++++++++++-------------- requirements.txt | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py index 3306b1058..6c7489014 100644 --- a/napalm/nxos_ssh/nxos_ssh.py +++ b/napalm/nxos_ssh/nxos_ssh.py @@ -453,21 +453,15 @@ def _send_command(self, command, raw_text=False, cmd_verify=True): """ return self.device.send_command(command, cmd_verify=cmd_verify) - def _send_command_list(self, commands, expect_string=None): - """Wrapper for Netmiko's send_command method (for list of commands.""" - output = "" - for command in commands: - output += self.device.send_command( - command, - strip_prompt=False, - strip_command=False, - expect_string=expect_string, - ) - return output + def _send_command_list(self, commands, expect_string=None, **kwargs): + """Send a list of commands using Netmiko""" + return self.device.send_multiline( + commands, expect_string=expect_string, **kwargs + ) def _send_config(self, commands): if isinstance(commands, str): - commands = (command for command in commands.splitlines() if command) + commands = [command for command in commands.splitlines() if command] return self.device.send_config_set(commands) @staticmethod @@ -538,7 +532,9 @@ def _load_cfg_from_checkpoint(self): ] try: - rollback_result = self._send_command_list(commands, expect_string=r"[#>]") + rollback_result = self._send_command_list( + commands, expect_string=r"[#>]", read_timeout=90 + ) finally: self.changed = True msg = rollback_result @@ -552,7 +548,9 @@ def rollback(self): "rollback running-config file {}".format(self.rollback_cfg), "no terminal dont-ask", ] - result = self._send_command_list(commands, expect_string=r"[#>]") + result = self._send_command_list( + commands, expect_string=r"[#>]", read_timeout=90 + ) if "completed" not in result.lower(): raise ReplaceConfigException(result) # If hostname changes ensure Netmiko state is updated properly diff --git a/requirements.txt b/requirements.txt index 18530cdd5..fab372372 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ jinja2 netaddr pyYAML pyeapi>=0.8.2 -netmiko>=4.0.0 +netmiko>=4.1.0 junos-eznc>=2.6.3 scp lxml>=4.3.0 From 5b453685a45834b9b9ea65235fe6d143f1d20d94 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 17 Oct 2022 13:43:02 -0700 Subject: [PATCH 22/71] Fix py.test7 rootdir build issue with NAPALM docs (#1778) Co-authored-by: Ludovic Ortega --- docs/requirements.txt | 10 +++++----- docs/support/nxos.rst | 2 +- docs/test.sh | 3 ++- requirements-dev.txt | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index a5380314c..be904df24 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,8 +1,8 @@ -sphinx -sphinx-rtd-theme -sphinxcontrib-napoleon -invoke +sphinx==1.8.6 +sphinx-rtd-theme==1.0.0 +sphinxcontrib-napoleon==0.7 +invoke==1.7.1 jinja2==2.11.3 MarkupSafe==2.0.1 -pytest==6.2.5 +pytest==7.1.2 ansible==4.10.0 diff --git a/docs/support/nxos.rst b/docs/support/nxos.rst index 0dfff92be..9f9e5ee8b 100644 --- a/docs/support/nxos.rst +++ b/docs/support/nxos.rst @@ -71,7 +71,7 @@ One caveat of using netutils diff of configurations is that the diff is performe Example assuming that the device config contains: -.. code-block:: +.. code-block:: bash interface loopback0 ip address 10.1.4.4/32 diff --git a/docs/test.sh b/docs/test.sh index 99ad9c5e2..b911f782d 100755 --- a/docs/test.sh +++ b/docs/test.sh @@ -1,10 +1,11 @@ #!/bin/bash CWD=`pwd` TEST_RESULTS_PATH="$CWD/support/tests" +REPOBASE=$CWD/.. if [ ! -f "report.json" ]; then set -e - py.test -c /dev/null --cov=./ -vs --json=report.json ../test*/*/test_getters.py + py.test --rootdir $REPOBASE -c /dev/null --cov=./ -vs --json=report.json $REPOBASE/test*/*/test_getters.py set -e cp report.json $TEST_RESULTS_PATH/report.json diff --git a/requirements-dev.txt b/requirements-dev.txt index f4598915f..c44499733 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,11 +2,11 @@ black==22.6.0 coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.1 -pytest==6.2.5 +pytest==7.1.2 pytest-cov==3.0.0 pytest-json==0.4.0 -pyflakes==2.4.0 -pylama==8.2.1 +pyflakes==2.5.0 +pylama==8.4.1 mock==4.0.3 tox==3.25.1 mypy==0.982 From 1581e3a92058ef3573386434b4defc8b39dd58e9 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 17 Oct 2022 13:52:23 -0700 Subject: [PATCH 23/71] Fix linting --- napalm/base/utils/string_parsers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/napalm/base/utils/string_parsers.py b/napalm/base/utils/string_parsers.py index 830ec1d65..4a029bae1 100644 --- a/napalm/base/utils/string_parsers.py +++ b/napalm/base/utils/string_parsers.py @@ -50,7 +50,9 @@ def colon_separated_string_to_dict( dictionary[line_data[0].strip()] = None else: raise Exception( - "Something went wrong parsing the colon separated string {}".format(line) + "Something went wrong parsing the colon separated string {}".format( + line + ) ) return dictionary From 434cdf1f57adaa5ce8201c40a40bc4d53138cf86 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 17 Oct 2022 13:54:20 -0700 Subject: [PATCH 24/71] Make string a bit more readable --- napalm/base/utils/string_parsers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/napalm/base/utils/string_parsers.py b/napalm/base/utils/string_parsers.py index 4a029bae1..5e5df5f57 100644 --- a/napalm/base/utils/string_parsers.py +++ b/napalm/base/utils/string_parsers.py @@ -50,9 +50,7 @@ def colon_separated_string_to_dict( dictionary[line_data[0].strip()] = None else: raise Exception( - "Something went wrong parsing the colon separated string {}".format( - line - ) + f"Something went wrong parsing the colon separated string:\n\n{line}" ) return dictionary From 3304a3adb39b3f06f3795e87349647efbc9e2b53 Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Tue, 18 Oct 2022 09:45:30 +0200 Subject: [PATCH 25/71] [Fix] Readthedoc build config --- .readthedocs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 65fd950da..320d0121d 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -14,9 +14,10 @@ formats: all # Optionally set the version of Python and requirements required to build your docs python: - version: 3.7 + version: 3.8 install: - method: pip path: . - requirements: docs/requirements.txt + - requirements: requirements-dev.txt - requirements: requirements.txt From a802eafcd28421b408d50d06cf5f7c38318e12ac Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Thu, 20 Oct 2022 16:06:24 +0100 Subject: [PATCH 26/71] Revert "Pin to textfsm<=1.1.2" (#1783) Co-authored-by: Kirk Byers --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fab372372..57ecd72eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ cffi>=1.11.3 paramiko>=2.6.0 requests>=2.7.0 future -textfsm<=1.1.2 +textfsm jinja2 netaddr pyYAML From 734d5207a38510b519d7a5208d2c12257bc049f7 Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Tue, 25 Oct 2022 00:03:50 +0200 Subject: [PATCH 27/71] [Fix] swap IOS & NXOS-SSH version (#1785) --- docs/support/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/support/index.rst b/docs/support/index.rst index f869f592c..9fa7bd650 100644 --- a/docs/support/index.rst +++ b/docs/support/index.rst @@ -13,7 +13,7 @@ General support matrix ===================== ========== ============= ==================== ================== ============ ============ ============ **Driver Name** eos junos iosxr_netconf iosxr nxos nxos_ssh ios **Structured data** Yes Yes Yes No Yes No No - **Minimum version** 4.15.0F 12.1 7.0 5.1.0 6.1 [#g1]_ 12.4(20)T 6.3.2 + **Minimum version** 4.15.0F 12.1 7.0 5.1.0 6.1 [#g1]_ 6.3.2 12.4(20)T **Backend library** `pyeapi`_ `junos-eznc`_ `ncclient`_ `pyIOSXR`_ `pynxos`_ `netmiko`_ `netmiko`_ **Caveats** :doc:`eos` :doc:`iosxr_netconf` :doc:`nxos` :doc:`nxos` :doc:`ios` ===================== ========== ============= ==================== ================== ============ ============ ============ From 9b66011a4235dcb1982467ee621b9c11c27f6346 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 9 Jan 2023 11:00:03 -0700 Subject: [PATCH 28/71] Fix Netmiko argument processing for EOS-SSH driver (#1750) --- .github/workflows/commit.yaml | 2 +- napalm/eos/eos.py | 100 ++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index 508c38172..94de245e9 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -10,7 +10,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.7, 3.8, 3.9, 3.10.0] + python-version: [3.7, 3.8, 3.9, 3.10.9, 3.11] steps: - name: Checkout repository diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index f10290cd6..cb7f025e8 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -33,10 +33,11 @@ # third party libs import pyeapi from pyeapi.eapilib import ConnectionError, EapiConnection -from netmiko import BaseConnection, ConfigInvalidException +from netmiko import ConfigInvalidException # NAPALM base import napalm.base.helpers +from napalm.base.netmiko_helpers import netmiko_args from napalm.base.base import NetworkDriver from napalm.base.utils import string_parsers from napalm.base.exceptions import ( @@ -97,7 +98,8 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) management). * enable_password (True/False): Enable password for privilege elevation * eos_autoComplete (True/False): Allow for shortening of cli commands - * transport (string): pyeapi transport, defaults to eos_transport if set + * transport (string): transport, eos_transport is a fallback for compatibility. + - ssh (uses Netmiko) - socket - http_local - http @@ -123,45 +125,44 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.platform = "eos" self.profile = [self.platform] + self.optional_args = optional_args or {} - self._process_optional_args(optional_args or {}) + self.enablepwd = self.optional_args.pop("enable_password", "") + self.eos_autoComplete = self.optional_args.pop("eos_autoComplete", None) + self.fn0039_config = self.optional_args.pop("eos_fn0039_config", False) - def _process_optional_args(self, optional_args): # Define locking method - self.lock_disable = optional_args.get("lock_disable", False) + self.lock_disable = self.optional_args.pop("lock_disable", False) - self.enablepwd = optional_args.pop("enable_password", "") - self.eos_autoComplete = optional_args.pop("eos_autoComplete", None) # eos_transport is there for backwards compatibility, transport is the preferred method - transport = optional_args.get( - "transport", optional_args.get("eos_transport", "https") + transport = self.optional_args.get( + "transport", self.optional_args.get("eos_transport", "https") ) - self.fn0039_config = optional_args.pop("eos_fn0039_config", False) self.transport = transport + if transport == "ssh": - self.transport_class = "ssh" - init_args = ["port"] + self._process_optional_args_ssh(self.optional_args) else: - # Parse pyeapi transport class - self.transport_class = self._parse_transport(transport) - # ([1:]) to omit self - init_args = inspect.getfullargspec(self.transport_class.__init__)[0][1:] + self._process_optional_args_eapi(self.optional_args) - filter_args = ["host", "username", "password", "timeout", "lock_disable"] + def _process_optional_args_ssh(self, optional_args): + self.transport_class = None + self.netmiko_optional_args = netmiko_args(optional_args) - if transport == "ssh": - self.netmiko_optional_args = { - k: v - for k, v in optional_args.items() - if k in init_args and k not in filter_args - } - else: - init_args.append("enforce_verification") # Not an arg for unknown reason - self.eapi_kwargs = { - k: v - for k, v in optional_args.items() - if k in init_args and k not in filter_args - } + def _process_optional_args_eapi(self, optional_args): + + # Parse pyeapi transport class + self.transport_class = self._parse_transport(self.transport) + + # ([1:]) to omit self + init_args = inspect.getfullargspec(self.transport_class.__init__)[0][1:] + filter_args = ["host", "username", "password", "timeout"] + init_args.append("enforce_verification") # Not an arg for unknown reason + self.eapi_kwargs = { + k: v + for k, v in optional_args.items() + if k in init_args and k not in filter_args + } def _parse_transport(self, transport): if inspect.isclass(transport) and issubclass(transport, EapiConnection): @@ -192,7 +193,8 @@ def open(self): """Implementation of NAPALM method open.""" if self.transport == "ssh": self.device = self._netmiko_open( - "arista_eos", netmiko_optional_args=self.netmiko_optional_args + device_type="arista_eos", + netmiko_optional_args=self.netmiko_optional_args, ) # let's try to determine if we need to use new EOS cli syntax sh_ver = self._run_commands(["show version"]) @@ -205,7 +207,7 @@ def open(self): username=self.username, password=self.password, timeout=self.timeout, - **self.eapi_kwargs + **self.eapi_kwargs, ) if self.device is None: @@ -228,7 +230,7 @@ def open(self): def close(self): """Implementation of NAPALM method close.""" self.discard_config() - if isinstance(self.device, BaseConnection): + if self.transport == "ssh": self._netmiko_close() elif hasattr(self.device.connection, "close") and callable( self.device.connection.close @@ -281,6 +283,27 @@ def _run_commands(self, commands, **kwargs): else: return self.device.run_commands(commands, **kwargs) + def _obtain_lock(self, wait_time=None): + """ + EOS internally creates config sessions when using commit-confirm. + + This can cause issues obtaining the configuration lock: + + cfg-2034--574620864-0 completed + cfg-2034--574620864-1 pending + """ + if wait_time: + start_time = time.time() + while time.time() - start_time < wait_time: + try: + self._lock() + return + except SessionLockedException: + time.sleep(1) + + # One last try + return self._lock() + def _lock(self): sess = self._run_commands(["show configuration sessions"])[0]["sessions"] if [ @@ -384,7 +407,7 @@ def _load_config(self, filename=None, config=None, replace=True): self.config_session = "napalm_{}".format(datetime.now().microsecond) if not self.lock_disable: - self._lock() + self._obtain_lock(wait_time=10) commands = [] commands.append("configure session {}".format(self.config_session)) @@ -520,13 +543,8 @@ def confirm_commit(self): def discard_config(self): """Implementation of NAPALM method discard_config.""" if self.config_session is not None: - commands = ["configure session {}".format(self.config_session), "abort"] - if self.transport == "ssh": - # For some reason when testing with vEOS 4.26.1F this - # doesn't work with the normal wrapper. - self._run_commands(["", commands[0]]) - else: - self.device.run_commands(commands) + commands = [f"configure session {self.config_session} abort"] + self._run_commands(commands, encoding="text") self.config_session = None def rollback(self): From 9606c6e92a8ff258fc1337fc9553407adc3a2b9f Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Thu, 16 Feb 2023 15:37:50 -0800 Subject: [PATCH 29/71] Fix ios lldp discovery (rebase) (#1849) Co-authored-by: Carlo Maragno --- napalm/ios/ios.py | 23 ++++++- .../no_mac_support/expected_result.json | 15 ++++ .../no_mac_support/show_lldp_neighbors.txt | 8 +++ .../show_lldp_neighbors_detail.txt | 68 +++++++++++++++++++ 4 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/expected_result.json create mode 100644 test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors.txt create mode 100644 test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors_detail.txt diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index 6235f5880..6d6f8e540 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -44,6 +44,7 @@ generate_regex_or, sanitize_configs, ) +from netaddr.core import AddrFormatError from napalm.base.netmiko_helpers import netmiko_args # Easier to store these as constants @@ -984,10 +985,26 @@ def get_lldp_neighbors(self): hostname = lldp_entry["remote_system_name"] port = lldp_entry["remote_port"] # Match IOS behaviour of taking remote chassis ID - # When lacking a system name (in show lldp neighbors) + # when lacking a system name (in show lldp neighbors) + + # We can't assume remote_chassis_id or remote_port are MAC Addresses + # See IEEE 802.1AB-2005 and rfc2922, specifically PtopoChassisId if not hostname: - hostname = napalm.base.helpers.mac(lldp_entry["remote_chassis_id"]) - port = napalm.base.helpers.mac(port) + try: + hostname = napalm.base.helpers.mac( + lldp_entry["remote_chassis_id"] + ) + except AddrFormatError: + hostname = lldp_entry["remote_chassis_id"] + + # If port is a mac-address, normalize it. + # The MAC helper library will normalize "15" to "00:00:00:00:00:0F" + if port.count(":") == 5 or port.count("-") == 5 or port.count(".") == 2: + try: + port = napalm.base.helpers.mac(port) + except AddrFormatError: + pass + lldp_dict = {"port": port, "hostname": hostname} lldp[intf_name].append(lldp_dict) diff --git a/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/expected_result.json b/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/expected_result.json new file mode 100644 index 000000000..49bc80227 --- /dev/null +++ b/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/expected_result.json @@ -0,0 +1,15 @@ +{ + "GigabitEthernet9/48": [ + { + "port": "Gi0", + "hostname": "COMPUTER.company.example.com" + } + ] + , + "GigabitEthernet9/8": [ + { + "port": "A1:8B:95:B5:E4:6F", + "hostname": "NICEHOSTNAME" + } + ] +} diff --git a/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors.txt b/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors.txt new file mode 100644 index 000000000..f7074e0d7 --- /dev/null +++ b/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors.txt @@ -0,0 +1,8 @@ + +Capability codes: + (R) Router, (B) Bridge, (T) Telephone, (C) DOCSIS Cable Device + (W) WLAN Access Point, (P) Repeater, (S) Station, (O) Other + +Device ID Local Intf Hold-time Capability Port ID +ACOMPUTER.company.exGi9/48 120 B Gi0 +NICEHOSTNAME Gi9/8 3601 a18b.95b5.e46f diff --git a/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors_detail.txt b/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors_detail.txt new file mode 100644 index 000000000..5908277d6 --- /dev/null +++ b/test/ios/mocked_data/test_get_lldp_neighbors/no_mac_support/show_lldp_neighbors_detail.txt @@ -0,0 +1,68 @@ +------------------------------------------------ +Local Intf: Gi9/48 +Chassis id: 4a07.d0f3.fbb6 +Port id: Gi0 +Port Description: GigabitEthernet0 +System Name: COMPUTER.company.example.com + +System Description: +Cisco IOS Software, C3600 Software (AP3G2-K9W8-M), Version 15.3(3)JC15, RELEASE SOFTWARE (fc1) +Technical Support: http://www.cisco.com/techsupport +Copyright (c) 1986-2018 by Cisco Systems, Inc. +Compiled Thu 07-Jun-18 16:43 by prod_rel_team + +Time remaining: 95 seconds +System Capabilities: B +Enabled Capabilities: B +Management Addresses: + IP: 10.31.18.65 +Auto Negotiation - supported, enabled +Physical media capabilities: + 1000baseT(FD) + 1000baseT(HD) + 100base-TX(FD) + 100base-TX(HD) + 10base-T(FD) + 10base-T(HD) +Media Attachment Unit type: 30 +Vlan ID: - not advertised +PoE+ Power-via-MDI TLV: + Power Pair: Signal + Power Class: Class 4 + Power Device Type: Type 1 PD + Power Source: PSE + Power Priority: high + Power Requested: 13000 mW + Power Allocated: 13000 mW + +------------------------------------------------ +Local Intf: Gi9/8 +Chassis id: NICEHOSTNAME +Port id: a18b.95b5.e46f +Port Description - not advertised +System Name - not advertised +System Description - not advertised + +Time remaining: 2690 seconds +System Capabilities - not advertised +Enabled Capabilities - not advertised +Management Addresses - not advertised +Auto Negotiation - supported, enabled +Physical media capabilities: + 1000baseT(FD) +Media Attachment Unit type - not advertised +Vlan ID: - not advertised + +MED Information: + + MED Codes: + (NP) Network Policy, (LI) Location Identification + (PS) Power Source Entity, (PD) Power Device + (IN) Inventory + + Inventory information - not advertised + Capabilities: + Device type: Endpoint Class I + Network Policies - not advertised + Power requirements - not advertised + Location - not advertised From 22ae32783884c38c0460dcf541f03120792239b7 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Thu, 16 Feb 2023 16:20:39 -0800 Subject: [PATCH 30/71] Pylama was broke and not actually executing pycodestyle (#1850) --- napalm/eos/eos.py | 2 +- setup.cfg | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index cb7f025e8..7187fe368 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -452,7 +452,7 @@ def _load_config(self, filename=None, config=None, replace=True): return None try: - if not any(l == "end" for l in commands): + if not any(cmd == "end" for cmd in commands): commands.append("end") # exit config mode if self.eos_autoComplete is not None: self._run_commands( diff --git a/setup.cfg b/setup.cfg index 272f56d7f..871c4c939 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,11 +5,11 @@ universal = 1 license_file = LICENSE [pylama] -linters = mccabe,pep8,pyflakes +linters = mccabe,pycodestyle,pyflakes ignore = D203,C901,E203 skip = .tox/*,.env/*,.venv/* -[pylama:pep8] +[pylama:pycodestyle] max_line_length = 100 [tool:pytest] From 8b670fec41f02922e77022350d8c2f4a27c3ad80 Mon Sep 17 00:00:00 2001 From: bewing Date: Wed, 15 Mar 2023 11:53:26 -0500 Subject: [PATCH 31/71] remove tox in favor of gh actions/act (#1644) * remove tox in favor of gh actions/act * update testing docs with local testing info --- docs/development/testing_framework.rst | 55 ++++++++++++++++++++------ requirements-dev.txt | 1 - tox.ini | 39 ------------------ 3 files changed, 44 insertions(+), 51 deletions(-) delete mode 100644 tox.ini diff --git a/docs/development/testing_framework.rst b/docs/development/testing_framework.rst index 2b61cc9da..ef5a7ed7f 100644 --- a/docs/development/testing_framework.rst +++ b/docs/development/testing_framework.rst @@ -1,7 +1,7 @@ Testing Framework ----------------- -As napalm consists of multiple drivers and all of them have to provide similar functionality, we have developed a testing framework to provide a consistent test suite for all the drivers. +As NAPALM consists of multiple drivers and all of them have to provide similar functionality, we have developed a testing framework to provide a consistent test suite for all the drivers. Features ________ @@ -42,7 +42,7 @@ By default, the tests are going to be run against mocked data but you can change * ``NAPALM_USERNAME`` * ``NAPALM_PASSWORD`` * ``NAPALM_OPTIONAL_ARGS`` - + Mocking the ``open`` method ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,29 +56,29 @@ Multiple test cases:: (napalm) ➜ napalm-eos git:(test_framework) ✗ ls test/unit/mocked_data/test_get_bgp_neighbors lots_of_peers no_peers normal (napalm) ➜ napalm-eos git:(test_framework) ✗ py.test test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors - ... + ... test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[lots_of_peers] <- ../napalm/napalm.base/test/getters.py PASSED test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[no_peers] <- ../napalm/napalm.base/test/getters.py PASSED test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[normal] <- ../napalm/napalm.base/test/getters.py PASSED - + Missing test cases:: (napalm) ➜ napalm-eos git:(test_framework) ✗ ls test/unit/mocked_data/test_get_bgp_neighbors ls: test/unit/mocked_data/test_get_bgp_neighbors: No such file or directory (napalm) ➜ napalm-eos git:(test_framework) ✗ py.test test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors - ... + ... test/unit/test_getters.py::TestGetter::test_get_bgp_neighbors[no_test_case_found] <- ../napalm/napalm.base/test/getters.py FAILED - + ========================================================= FAILURES ========================================================== ___________________________________ TestGetter.test_get_bgp_neighbors[no_test_case_found] ___________________________________ - + cls = , test_case = 'no_test_case_found' - + @functools.wraps(func) def wrapper(cls, test_case): cls.device.device.current_test = func.__name__ cls.device.device.current_test_case = test_case - + try: # This is an ugly, ugly, ugly hack because some python objects don't load # as expected. For example, dicts where integers are strings @@ -87,7 +87,7 @@ Missing test cases:: if test_case == "no_test_case_found": > pytest.fail("No test case for '{}' found".format(func.__name__)) E Failed: No test case for 'test_get_bgp_neighbors' found - + ../napalm/napalm.base/test/getters.py:64: Failed ================================================= 1 failed in 0.12 seconds ================================================== @@ -96,8 +96,41 @@ Method not implemented:: (napalm) ➜ napalm-eos git:(test_framework) ✗ py.test test/unit/test_getters.py::TestGetter::test_get_probes_config ... test/unit/test_getters.py::TestGetter::test_get_probes_config[no_test_case_found] <- ../napalm/napalm.base/test/getters.py SKIPPED - + ================================================= 1 skipped in 0.09 seconds ================================================= +Testing Matrix +-------------- + +NAPALM leverages [Github Actions](https://docs.github.com/en/actions) to test and lint code on commits and pull requests. +If you want to test prior to opening a pull request, you can use [nektos/act](https://github.com/nektos/act) and Docker to locally run the tests + +.. code-block:: console + + $ act -j std_tests + [build/std_tests-4] 🚀 Start image=catthehacker/ubuntu:act-latest + [build/std_tests-3] 🚀 Start image=catthehacker/ubuntu:act-latest + [build/std_tests-1] 🚀 Start image=catthehacker/ubuntu:act-latest + [build/std_tests-2] 🚀 Start image=catthehacker/ubuntu:act-latest + [build/std_tests-5] 🚀 Start image=catthehacker/ubuntu:act-latest + [build/std_tests-4] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true + [build/std_tests-1] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true + [build/std_tests-3] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true + [build/std_tests-5] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true + [build/std_tests-2] 🐳 docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true + + ... + + | --------------------------------------------------------------------- + | TOTAL 9258 1836 80% + | + | ================= 619 passed, 80 skipped, 3 warnings in 19.97s ================= + [build/std_tests-5] ✅ Success - Main Run Tests + [build/std_tests-5] ⭐ Run Post Setup Python 3.11 + [build/std_tests-5] 🐳 docker exec cmd=[node /var/run/act/actions/actions-setup-python@v2/dist/cache-save/index.js] user= workdir= + [build/std_tests-5] ✅ Success - Post Setup Python 3.11 + [build/std_tests-5] 🏁 Job succeeded + + .. _`test_getters.py`: https://github.com/napalm-automation/napalm-eos/blob/a2fc2cf6a98b0851efe4cba907086191b8f1df02/test/unit/test_getters.py .. _`conftest.py`: https://github.com/napalm-automation/napalm-eos/blob/a2fc2cf6a98b0851efe4cba907086191b8f1df02/test/unit/conftest.py diff --git a/requirements-dev.txt b/requirements-dev.txt index c44499733..183e4e88c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,7 +8,6 @@ pytest-json==0.4.0 pyflakes==2.5.0 pylama==8.4.1 mock==4.0.3 -tox==3.25.1 mypy==0.982 types-requests==2.28.0 types-six==1.16.17 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index a6f11697f..000000000 --- a/tox.ini +++ /dev/null @@ -1,39 +0,0 @@ -[tox] -envlist = py3{6,7,8},black,pylama -skip_missing_interpreters = true - -[testenv] -deps = - -rrequirements.txt - -rrequirements-dev.txt -passenv = * - -commands = - py.test --cov=napalm --cov-report term-missing -vs --pylama {posargs} - -[testenv:black] -deps = black==20.8b1 - -basepython = python3.6 -commands = - black --check . - -[testenv:pylama] -deps = - -rrequirements-dev.txt - -basepython = python3.6 -commands = - pylama . - -[testenv:sphinx] -deps = - -rdocs/requirements.txt - -basepython = python3.6 - -commands = - make doctest - -whitelist_externals = - make From 53fc6b9fc18d1d19eebad959682c4f14af44c016 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Mar 2023 18:30:27 -0700 Subject: [PATCH 32/71] Bump types-setuptools from 57.4.18 to 67.5.0.0 (#1860) --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 183e4e88c..6cf55ef80 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,7 +11,7 @@ mock==4.0.3 mypy==0.982 types-requests==2.28.0 types-six==1.16.17 -types-setuptools==57.4.18 +types-setuptools==67.5.0.0 types-PyYAML==6.0.9 ttp==0.9.0 ttp_templates==0.3.0 From 344a01e74452d3e9768fa294e6d79bc51d46eae1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Mar 2023 18:40:04 -0700 Subject: [PATCH 33/71] Bump types-six from 1.16.17 to 1.16.21.6 (#1856) --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 6cf55ef80..278918627 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,7 @@ pylama==8.4.1 mock==4.0.3 mypy==0.982 types-requests==2.28.0 -types-six==1.16.17 +types-six==1.16.21.6 types-setuptools==67.5.0.0 types-PyYAML==6.0.9 ttp==0.9.0 From d849a49de6f7447a8742a8af7f708713473cce43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Mar 2023 18:48:09 -0700 Subject: [PATCH 34/71] Bump types-pyyaml from 6.0.9 to 6.0.12.8 (#1853) --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 278918627..acd331af6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -9,9 +9,9 @@ pyflakes==2.5.0 pylama==8.4.1 mock==4.0.3 mypy==0.982 +types-PyYAML==6.0.12.8 types-requests==2.28.0 types-six==1.16.21.6 types-setuptools==67.5.0.0 -types-PyYAML==6.0.9 ttp==0.9.0 ttp_templates==0.3.0 From a71569df66754427604404ee1bffd96155e89b35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Mar 2023 19:13:43 -0700 Subject: [PATCH 35/71] Bump ttp-templates from 0.3.0 to 0.3.2 (#1808) --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index acd331af6..ae84ab977 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -14,4 +14,4 @@ types-requests==2.28.0 types-six==1.16.21.6 types-setuptools==67.5.0.0 ttp==0.9.0 -ttp_templates==0.3.0 +ttp_templates==0.3.2 From 67067e383d990245aecb9c4718224ee8d927f414 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Mar 2023 19:36:20 -0700 Subject: [PATCH 36/71] Bump pytest-cov from 3.0.0 to 4.0.0 (#1779) Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/pytest-dev/pytest-cov/releases) - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index ae84ab977..617cc5d3f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,7 +3,7 @@ coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.1 pytest==7.1.2 -pytest-cov==3.0.0 +pytest-cov==4.0.0 pytest-json==0.4.0 pyflakes==2.5.0 pylama==8.4.1 From 92b7bab363e44a115a8e49bcf4b022a051d00b7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 10:18:19 -0700 Subject: [PATCH 37/71] Bump types-requests from 2.28.0 to 2.28.11.15 (#1864) Bumps [types-requests](https://github.com/python/typeshed) from 2.28.0 to 2.28.11.15. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 617cc5d3f..51d90d620 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,7 @@ pylama==8.4.1 mock==4.0.3 mypy==0.982 types-PyYAML==6.0.12.8 -types-requests==2.28.0 +types-requests==2.28.11.15 types-six==1.16.21.6 types-setuptools==67.5.0.0 ttp==0.9.0 From 90057c0d1138f5e129b5927cddc1b2e9ddff1a32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 10:54:07 -0700 Subject: [PATCH 38/71] Bump types-six from 1.16.21.6 to 1.16.21.7 (#1865) Bumps [types-six](https://github.com/python/typeshed) from 1.16.21.6 to 1.16.21.7. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-six dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 51d90d620..dfd5ddf20 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,7 +11,7 @@ mock==4.0.3 mypy==0.982 types-PyYAML==6.0.12.8 types-requests==2.28.11.15 -types-six==1.16.21.6 +types-six==1.16.21.7 types-setuptools==67.5.0.0 ttp==0.9.0 ttp_templates==0.3.2 From ee32766422b3494ae9afd11160a4b3dde1f271c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:01:04 -0700 Subject: [PATCH 39/71] Bump flake8-import-order from 0.18.1 to 0.18.2 (#1867) Bumps [flake8-import-order](https://github.com/PyCQA/flake8-import-order) from 0.18.1 to 0.18.2. - [Release notes](https://github.com/PyCQA/flake8-import-order/releases) - [Changelog](https://github.com/PyCQA/flake8-import-order/blob/master/CHANGELOG.rst) - [Commits](https://github.com/PyCQA/flake8-import-order/compare/0.18.1...0.18.2) --- updated-dependencies: - dependency-name: flake8-import-order dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index dfd5ddf20..524642c3d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,7 @@ black==22.6.0 coveralls==3.3.1 ddt==1.5.0 -flake8-import-order==0.18.1 +flake8-import-order==0.18.2 pytest==7.1.2 pytest-cov==4.0.0 pytest-json==0.4.0 From 41322481ecf9b00a147b925c8ab274fda32d3f0e Mon Sep 17 00:00:00 2001 From: Mark Huizer Date: Mon, 20 Mar 2023 21:16:10 +0100 Subject: [PATCH 40/71] add get_network_instances for nxos_ssh, based mostly on nxos version (#1842) --- napalm/nxos_ssh/nxos_ssh.py | 56 +++++++++++++ .../normal/expected_result.json | 36 +++++++++ .../normal/show_vrf_detail___json.txt | 58 ++++++++++++++ .../normal/show_vrf_interface___json.txt | 78 +++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json create mode 100644 test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt create mode 100644 test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py index 6c7489014..51aa2c690 100644 --- a/napalm/nxos_ssh/nxos_ssh.py +++ b/napalm/nxos_ssh/nxos_ssh.py @@ -18,6 +18,7 @@ import ipaddress import re import socket +from collections import defaultdict # import NAPALM Base from napalm.base import helpers @@ -794,6 +795,61 @@ def cli(self, commands, encoding="text"): cli_output[str(command)] = output return cli_output + def get_network_instances(self, name=""): + """ + get_network_instances implementation for NX-OS + """ + + # command 'show vrf detail | json' returns all VRFs with detailed information in JSON format + # format: list of dictionaries with keys such as 'vrf_name' and 'rd' + vrf_table_raw = self._get_command_table( + "show vrf detail | json", "TABLE_vrf", "ROW_vrf" + ) + + # command 'show vrf interface' returns all interfaces including their assigned VRF + # format: list of dictionaries with keys 'if_name', 'vrf_name', 'vrf_id' and 'soo' + intf_table_raw = self._get_command_table( + "show vrf interface | json", "TABLE_if", "ROW_if" + ) + + # create a dictionary with key = 'vrf_name' and value = list of interfaces + vrf_intfs = defaultdict(list) + for intf in intf_table_raw: + vrf_intfs[intf["vrf_name"]].append(str(intf["if_name"])) + + vrfs = {} + for vrf in vrf_table_raw: + vrf_name = str(vrf.get("vrf_name")) + vrfs[vrf_name] = {} + vrfs[vrf_name]["name"] = vrf_name + + # differentiate between VRF type 'DEFAULT_INSTANCE' and 'L3VRF' + if vrf_name == "default": + vrfs[vrf_name]["type"] = "DEFAULT_INSTANCE" + else: + vrfs[vrf_name]["type"] = "L3VRF" + + vrfs[vrf_name]["state"] = {"route_distinguisher": str(vrf.get("rd"))} + + # convert list of interfaces (vrf_intfs[vrf_name]) to expected format + # format = dict with key = interface name and empty values + vrfs[vrf_name]["interfaces"] = {} + vrfs[vrf_name]["interfaces"]["interface"] = dict.fromkeys( + vrf_intfs[vrf_name], {} + ) + + # if name of a specific VRF was passed as an argument + # only return results for this particular VRF + + if name: + if name in vrfs.keys(): + return {str(name): vrfs[name]} + else: + return {} + # else return results for all VRFs + else: + return vrfs + def get_environment(self): """ Get environment facts. diff --git a/test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json new file mode 100644 index 000000000..ca3d2f110 --- /dev/null +++ b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json @@ -0,0 +1,36 @@ +{ + "management": { + "name": "management", + "type": "L3VRF", + "state": { + "route_distinguisher": "0:0" + }, + "interfaces": { + "interface": { + "mgmt0": {} + } + } + }, + "default": { + "name": "default", + "type": "DEFAULT_INSTANCE", + "state": { + "route_distinguisher": "0:0" + }, + "interfaces": { + "interface": { + "Vlan1": {}, + "Vlan100": {}, + "Vlan101": {}, + "Vlan102": {}, + "Vlan103": {}, + "Vlan104": {}, + "Vlan105": {}, + "loopback1": {}, + "Null0": {}, + "Ethernet1/5": {}, + "Ethernet1/5.1": {} + } + } + } +} diff --git a/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt new file mode 100644 index 000000000..637f62365 --- /dev/null +++ b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt @@ -0,0 +1,58 @@ +{ + "TABLE_vrf": { + "ROW_vrf": [ + { + "vrf_name": "default", + "vrf_id": 1, + "vrf_state": "Up", + "vpnid": "unknown", + "rd": "0:0", + "vni": 0, + "max_routes": 0, + "mid_threshold": 0, + "TABLE_tib": { + "ROW_tib": [ + { + "tib_id": 80000001, + "tib_af": "IPv6", + "tib_nonce": 80000001, + "tib_state": "Up" + }, + { + "tib_id": 1, + "tib_af": "IPv4", + "tib_nonce": 1, + "tib_state": "Up" + } + ] + } + }, + { + "vrf_name": "management", + "vrf_id": 2, + "vrf_state": "Up", + "vpnid": "unknown", + "rd": "0:0", + "vni": 0, + "max_routes": 0, + "mid_threshold": 0, + "TABLE_tib": { + "ROW_tib": [ + { + "tib_id": 80000002, + "tib_af": "IPv6", + "tib_nonce": 80000002, + "tib_state": "Up" + }, + { + "tib_id": 2, + "tib_af": "IPv4", + "tib_nonce": 2, + "tib_state": "Up" + } + ] + } + } + ] + } +} diff --git a/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt new file mode 100644 index 000000000..72a325a0d --- /dev/null +++ b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt @@ -0,0 +1,78 @@ +{ + "TABLE_if": { + "ROW_if": [ + { + "if_name": "Vlan1", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Vlan100", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Vlan101", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Vlan102", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Vlan103", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Vlan104", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Vlan105", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "loopback1", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Null0", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Ethernet1/5", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "Ethernet1/5.1", + "vrf_name": "default", + "vrf_id": 1, + "soo": "--" + }, + { + "if_name": "mgmt0", + "vrf_name": "management", + "vrf_id": 2, + "soo": "--" + } + ] + } +} From 4b45fdae802ecb6c9c0ec67979f1a95186abbb93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:24:30 -0700 Subject: [PATCH 41/71] Bump pytest from 7.1.2 to 7.2.2 (#1868) Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.2 to 7.2.2. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.1.2...7.2.2) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- docs/requirements.txt | 2 +- requirements-dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index be904df24..96eb8cea6 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,5 +4,5 @@ sphinxcontrib-napoleon==0.7 invoke==1.7.1 jinja2==2.11.3 MarkupSafe==2.0.1 -pytest==7.1.2 +pytest==7.2.2 ansible==4.10.0 diff --git a/requirements-dev.txt b/requirements-dev.txt index 524642c3d..fc6044b93 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,7 +2,7 @@ black==22.6.0 coveralls==3.3.1 ddt==1.5.0 flake8-import-order==0.18.2 -pytest==7.1.2 +pytest==7.2.2 pytest-cov==4.0.0 pytest-json==0.4.0 pyflakes==2.5.0 From e74688f02b17f1b530b1b56604981465e24e401b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:42:51 -0700 Subject: [PATCH 42/71] Bump sphinx-rtd-theme from 1.0.0 to 1.2.0 (#1869) Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.0.0 to 1.2.0. - [Release notes](https://github.com/readthedocs/sphinx_rtd_theme/releases) - [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst) - [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.0.0...1.2.0) --- updated-dependencies: - dependency-name: sphinx-rtd-theme dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 96eb8cea6..827820adf 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx==1.8.6 -sphinx-rtd-theme==1.0.0 +sphinx-rtd-theme==1.2.0 sphinxcontrib-napoleon==0.7 invoke==1.7.1 jinja2==2.11.3 From d9b35a3de73274c724a502a6a915080b4b888426 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:52:34 -0700 Subject: [PATCH 43/71] Bump invoke from 1.7.1 to 2.0.0 (#1870) Bumps [invoke](https://github.com/pyinvoke/invoke) from 1.7.1 to 2.0.0. - [Release notes](https://github.com/pyinvoke/invoke/releases) - [Commits](https://github.com/pyinvoke/invoke/compare/1.7.1...2.0.0) --- updated-dependencies: - dependency-name: invoke dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 827820adf..482643959 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,7 @@ sphinx==1.8.6 sphinx-rtd-theme==1.2.0 sphinxcontrib-napoleon==0.7 -invoke==1.7.1 +invoke==2.0.0 jinja2==2.11.3 MarkupSafe==2.0.1 pytest==7.2.2 From 458c81dd3cff35d9a72356976c267d52b1536a9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:53:07 -0700 Subject: [PATCH 44/71] Bump ddt from 1.5.0 to 1.6.0 (#1871) Bumps [ddt](https://github.com/datadriventests/ddt) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/datadriventests/ddt/releases) - [Commits](https://github.com/datadriventests/ddt/compare/1.5.0...1.6.0) --- updated-dependencies: - dependency-name: ddt dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index fc6044b93..c63eb3885 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,6 @@ black==22.6.0 coveralls==3.3.1 -ddt==1.5.0 +ddt==1.6.0 flake8-import-order==0.18.2 pytest==7.2.2 pytest-cov==4.0.0 From 2bfee8bf48ae45bfade2a7ae66381f74365fa38d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:53:31 -0700 Subject: [PATCH 45/71] Bump mock from 4.0.3 to 5.0.1 (#1872) Bumps [mock](https://github.com/testing-cabal/mock) from 4.0.3 to 5.0.1. - [Release notes](https://github.com/testing-cabal/mock/releases) - [Changelog](https://github.com/testing-cabal/mock/blob/master/CHANGELOG.rst) - [Commits](https://github.com/testing-cabal/mock/compare/4.0.3...5.0.1) --- updated-dependencies: - dependency-name: mock dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index c63eb3885..0f526a300 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -7,7 +7,7 @@ pytest-cov==4.0.0 pytest-json==0.4.0 pyflakes==2.5.0 pylama==8.4.1 -mock==4.0.3 +mock==5.0.1 mypy==0.982 types-PyYAML==6.0.12.8 types-requests==2.28.11.15 From b0a5fb082aa2267d555cd809982434352eaffb75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 14:13:24 -0700 Subject: [PATCH 46/71] Bump types-setuptools from 67.5.0.0 to 67.6.0.5 (#1873) Bumps [types-setuptools](https://github.com/python/typeshed) from 67.5.0.0 to 67.6.0.5. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-setuptools dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 0f526a300..6006eb50b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,6 +12,6 @@ mypy==0.982 types-PyYAML==6.0.12.8 types-requests==2.28.11.15 types-six==1.16.21.7 -types-setuptools==67.5.0.0 +types-setuptools==67.6.0.5 ttp==0.9.0 ttp_templates==0.3.2 From ec2c4edc6e73728617fc502edd713cca88ba2331 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 09:01:40 -0700 Subject: [PATCH 47/71] Bump pyflakes from 2.5.0 to 3.0.1 (#1875) Bumps [pyflakes](https://github.com/PyCQA/pyflakes) from 2.5.0 to 3.0.1. - [Release notes](https://github.com/PyCQA/pyflakes/releases) - [Changelog](https://github.com/PyCQA/pyflakes/blob/main/NEWS.rst) - [Commits](https://github.com/PyCQA/pyflakes/compare/2.5.0...3.0.1) --- updated-dependencies: - dependency-name: pyflakes dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 6006eb50b..8e31b3374 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,7 @@ flake8-import-order==0.18.2 pytest==7.2.2 pytest-cov==4.0.0 pytest-json==0.4.0 -pyflakes==2.5.0 +pyflakes==3.0.1 pylama==8.4.1 mock==5.0.1 mypy==0.982 From 126486122169c0151bfd44f9a4273caa15675ae1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:17:20 -0700 Subject: [PATCH 48/71] Bump ttp-templates from 0.3.2 to 0.3.4 (#1880) Bumps [ttp-templates](https://github.com/dmulyalin/ttp_templates) from 0.3.2 to 0.3.4. - [Release notes](https://github.com/dmulyalin/ttp_templates/releases) - [Commits](https://github.com/dmulyalin/ttp_templates/compare/0.3.2...0.3.4) --- updated-dependencies: - dependency-name: ttp-templates dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 8e31b3374..5a71c949b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -14,4 +14,4 @@ types-requests==2.28.11.15 types-six==1.16.21.7 types-setuptools==67.6.0.5 ttp==0.9.0 -ttp_templates==0.3.2 +ttp_templates==0.3.4 From 8b46f0878231171bc5ee4e01135b3c304149e28b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:33:24 -0700 Subject: [PATCH 49/71] Bump types-requests from 2.28.11.15 to 2.28.11.16 (#1877) Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.15 to 2.28.11.16. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 5a71c949b..4139a9281 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,7 @@ pylama==8.4.1 mock==5.0.1 mypy==0.982 types-PyYAML==6.0.12.8 -types-requests==2.28.11.15 +types-requests==2.28.11.16 types-six==1.16.21.7 types-setuptools==67.6.0.5 ttp==0.9.0 From 8ecc4de6ee27a20f77558bbeff85a2a10416becd Mon Sep 17 00:00:00 2001 From: bewing Date: Tue, 28 Mar 2023 14:07:45 -0500 Subject: [PATCH 50/71] Update get_bgp_config to clarify return values (#1879) --- napalm/base/base.py | 3 +- napalm/eos/eos.py | 2 + napalm/ios/ios.py | 37 +++---- napalm/iosxr/iosxr.py | 47 +++++---- napalm/iosxr_netconf/iosxr_netconf.py | 46 +++++---- napalm/junos/junos.py | 24 +++++ napalm/junos/utils/junos_views.yml | 9 ++ .../expected_result.json | 15 +++ .../issue_1113_dot_asn/expected_result.json | 15 +++ .../normal/expected_result.json | 98 ++++++++++++++++++- .../expected_result.json | 8 +- .../no_afi/expected_result.json | 4 +- .../normal/expected_result.json | 21 +++- .../peers_without_groups/expected_result.json | 6 +- .../expected_result.json | 12 +-- .../normal/expected_result.json | 23 ++++- .../peers_without_groups/expected_result.json | 6 +- .../normal/expected_result.json | 39 +++++--- ...em____routing_options___configuration_.xml | 7 ++ .../nhs/expected_result.json | 74 +++++++++++++- ...em____routing_options___configuration_.xml | 7 ++ .../normal/expected_result.json | 87 +++++++++++++++- 22 files changed, 495 insertions(+), 95 deletions(-) create mode 100644 test/junos/mocked_data/test_get_bgp_config/nhs/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml create mode 100644 test/junos/mocked_data/test_get_bgp_config/normal/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml diff --git a/napalm/base/base.py b/napalm/base/base.py index 1259f6966..d1dbe0eea 100644 --- a/napalm/base/base.py +++ b/napalm/base/base.py @@ -647,7 +647,8 @@ def get_bgp_config( :param neighbor: Returns the configuration of a specific BGP neighbor. Main dictionary keys represent the group name and the values represent a dictionary having - the keys below. Neighbors which aren't members of a group will be stored in a key named "_": + the keys below. A default group named "_" will contain information regarding global + settings and any neighbors that are not members of a group. * type (string) * description (string) diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index 7187fe368..cb182ea8d 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -1187,6 +1187,8 @@ def parse_options(options, default_value=False): bgp_config[group_name] = default_group_dict(local_as) bgp_config[group_name].update(parse_options(options, default_value)) + bgp_config["_"] = default_group_dict(local_as) + for peer, peer_details in bgp_neighbors.items(): peer_group = peer_details.pop("__group", None) if not peer_group: diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index 6d6f8e540..682a9a990 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -1531,7 +1531,9 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): r" update-source (\w+)", neighbor_config ) local_as = napalm.base.helpers.regex_find_txt( - r"local-as (\d+)", neighbor_config, default=0 + r"local-as (\d+)", + neighbor_config, + default=bgp_asn, ) password = napalm.base.helpers.regex_find_txt( r"password (?:[0-9] )?([^\']+\')", neighbor_config @@ -1565,29 +1567,28 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): "route_reflector_client": route_reflector_client, } + bgp_config["_"] = { + "apply_groups": [], + "description": "", + "local_as": bgp_asn, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": False, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": False, + "prefix_limit": {}, + "neighbors": bgp_group_neighbors.get("_", {}), + } # Get the peer-group level config for each group for group_name in bgp_group_neighbors.keys(): # If a group is passed in params, only continue on that group if group: if group_name != group: continue - # Default no group if group_name == "_": - bgp_config["_"] = { - "apply_groups": [], - "description": "", - "local_as": 0, - "type": "", - "import_policy": "", - "export_policy": "", - "local_address": "", - "multipath": False, - "multihop_ttl": 0, - "remote_as": 0, - "remove_private_as": False, - "prefix_limit": {}, - "neighbors": bgp_group_neighbors.get("_", {}), - } continue neighbor_config = napalm.base.helpers.netutils_parse_objects( group_name, bgp_config_list @@ -1609,7 +1610,7 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): r" description ([^\']+)\'", neighbor_config ) local_as = napalm.base.helpers.regex_find_txt( - r"local-as (\d+)", neighbor_config, default=0 + r"local-as (\d+)", neighbor_config, default=bgp_asn ) import_policy = napalm.base.helpers.regex_find_txt( r"route-map ([^\s]+) in", neighbor_config diff --git a/napalm/iosxr/iosxr.py b/napalm/iosxr/iosxr.py index f491addfe..2ef1f6cb4 100644 --- a/napalm/iosxr/iosxr.py +++ b/napalm/iosxr/iosxr.py @@ -987,6 +987,15 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): default" result_tree = ETREE.fromstring(self.device.make_rpc_call(rpc_command)) + bgp_asn = napalm.base.helpers.convert( + int, + napalm.base.helpers.find_txt( + result_tree, + "Get/Configuration/BGP/Instance[1]/InstanceAS/FourByteAS/Naming/AS", + ), + 0, + ) + if not group: neighbor = "" @@ -1010,7 +1019,9 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): int, napalm.base.helpers.find_txt(bgp_neighbor, "RemoteAS/AS_YY"), 0 ) local_as = napalm.base.helpers.convert( - int, napalm.base.helpers.find_txt(bgp_neighbor, "LocalAS/AS_YY"), 0 + int, + napalm.base.helpers.find_txt(bgp_neighbor, "LocalAS/AS_YY"), + bgp_asn, ) af_table = napalm.base.helpers.find_txt( bgp_neighbor, "NeighborAFTable/NeighborAF/Naming/AFName" @@ -1102,7 +1113,7 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): int, napalm.base.helpers.find_txt(bgp_group, "RemoteAS/AS_YY"), 0 ) local_as = napalm.base.helpers.convert( - int, napalm.base.helpers.find_txt(bgp_group, "LocalAS/AS_YY"), 0 + int, napalm.base.helpers.find_txt(bgp_group, "LocalAS/AS_YY"), bgp_asn ) multihop_ttl = napalm.base.helpers.convert( int, @@ -1164,22 +1175,22 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): } if group and group == group_name: break - if "" in bgp_group_neighbors.keys(): - bgp_config["_"] = { - "apply_groups": [], - "description": "", - "local_as": 0, - "type": "", - "import_policy": "", - "export_policy": "", - "local_address": "", - "multipath": False, - "multihop_ttl": 0, - "remote_as": 0, - "remove_private_as": False, - "prefix_limit": {}, - "neighbors": bgp_group_neighbors.get("", {}), - } + + bgp_config["_"] = { + "apply_groups": [], + "description": "", + "local_as": bgp_asn, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": False, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": False, + "prefix_limit": {}, + "neighbors": bgp_group_neighbors.get("", {}), + } return bgp_config diff --git a/napalm/iosxr_netconf/iosxr_netconf.py b/napalm/iosxr_netconf/iosxr_netconf.py index 3f238a1b0..0640f4c82 100644 --- a/napalm/iosxr_netconf/iosxr_netconf.py +++ b/napalm/iosxr_netconf/iosxr_netconf.py @@ -1369,6 +1369,16 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): if not group: neighbor = "" + bgp_asn = napalm.base.helpers.convert( + int, + self._find_txt( + result_tree, + ".//bgpc:bgp/bgpc:instance/bgpc:instance-as/bgpc:four-byte-as/bgpc:as", + default=0, + namespaces=C.NS, + ), + ) + bgp_group_neighbors = {} bgp_neighbor_xpath = ".//bgpc:bgp/bgpc:instance/bgpc:instance-as/\ bgpc:four-byte-as/bgpc:default-vrf/bgpc:bgp-entity/bgpc:neighbors/bgpc:neighbor" @@ -1430,7 +1440,7 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): ), 0, ) - local_as = local_as_x * 65536 + local_as_y + local_as = (local_as_x * 65536 + local_as_y) or bgp_asn af_table = self._find_txt( bgp_neighbor, "./bgpc:neighbor-afs/bgpc:neighbor-af/bgpc:af-name", @@ -1597,7 +1607,7 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): ), 0, ) - local_as = local_as_x * 65536 + local_as_y + local_as = (local_as_x * 65536 + local_as_y) or bgp_asn multihop_ttl = napalm.base.helpers.convert( int, self._find_txt( @@ -1679,22 +1689,22 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): } if group and group == group_name: break - if "" in bgp_group_neighbors.keys(): - bgp_config["_"] = { - "apply_groups": [], - "description": "", - "local_as": 0, - "type": "", - "import_policy": "", - "export_policy": "", - "local_address": "", - "multipath": False, - "multihop_ttl": 0, - "remote_as": 0, - "remove_private_as": False, - "prefix_limit": {}, - "neighbors": bgp_group_neighbors.get("", {}), - } + + bgp_config["_"] = { + "apply_groups": [], + "description": "", + "local_as": bgp_asn, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": False, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": False, + "prefix_limit": {}, + "neighbors": bgp_group_neighbors.get("", {}), + } return bgp_config diff --git a/napalm/junos/junos.py b/napalm/junos/junos.py index 8d56b0fbc..fdb96e82d 100644 --- a/napalm/junos/junos.py +++ b/napalm/junos/junos.py @@ -1250,6 +1250,30 @@ def build_prefix_limit(**args): bgp_config = {} + routing_options = junos_views.junos_routing_config_table(self.device) + routing_options.get(options=self.junos_config_options) + + bgp_asn = int( + routing_options.xml.find( + "./routing-options/autonomous-system/as-number" + ).text + ) + + bgp_config["_"] = { + "apply_groups": [], + "description": "", + "local_as": bgp_asn, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": False, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": False, + "prefix_limit": {}, + "neighbors": {}, + } if group: bgp = junos_views.junos_bgp_config_group_table(self.device) bgp.get(group=group, options=self.junos_config_options) diff --git a/napalm/junos/utils/junos_views.yml b/napalm/junos/utils/junos_views.yml index 5d81ae2fc..3fd60b1f4 100644 --- a/napalm/junos/utils/junos_views.yml +++ b/napalm/junos/utils/junos_views.yml @@ -402,6 +402,15 @@ junos_bgp_config_peers_view: inet6_flow_teardown_timeout_prefix_limit: {family/inet6/flow/prefix-limit/teardown/idle-timeout/timeout: int} inet6_flow_novalidate_prefix_limit: {family/inet6/flow/prefix-limit/no-validate: unicode} +junos_routing_config_table: + get: "routing-options/autonomous-system" + view: junos_routing_config_view + +junos_routing_config_view: + fields: + local_system_as: autonomous-system + + #### #### BGP Neighbors and Routing Tables Stats #### diff --git a/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json index 8354f24ba..9a66039c0 100644 --- a/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json +++ b/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json @@ -1,4 +1,19 @@ { + "_": { + "type": "", + "multipath": false, + "apply_groups": [], + "remove_private_as": false, + "multihop_ttl": 0, + "remote_as": 0, + "local_address": "", + "local_as": 64496, + "description": "", + "import_policy": "", + "export_policy": "", + "prefix_limit": {}, + "neighbors": {} + }, "IPv6-PEERS-GROUP-NAME": { "type": "", "multipath": false, diff --git a/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json index 84f8c3bd8..c6c5353d9 100644 --- a/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json +++ b/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json @@ -1,4 +1,19 @@ { + "_": { + "type": "", + "multipath": false, + "apply_groups": [], + "remove_private_as": false, + "multihop_ttl": 0, + "remote_as": 0, + "local_address": "", + "local_as": 4266524237, + "description": "", + "import_policy": "", + "export_policy": "", + "prefix_limit": {}, + "neighbors": {} + }, "IPv4-PEERS-GROUP-NAME": { "type": "", "multipath": false, diff --git a/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json index de52578fe..0d22dfaf6 100644 --- a/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -1 +1,97 @@ -{"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}} +{ + "_": { + "type": "", + "multipath": false, + "apply_groups": [], + "remove_private_as": false, + "multihop_ttl": 0, + "remote_as": 0, + "local_address": "", + "local_as": 13335, + "description": "", + "import_policy": "", + "export_policy": "", + "prefix_limit": {}, + "neighbors": {} + }, + "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 + } +} diff --git a/test/ios/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json b/test/ios/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json index f74d5a593..d6a2343ac 100644 --- a/test/ios/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json +++ b/test/ios/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json @@ -5,7 +5,7 @@ "export_policy": "PASS-OUT", "import_policy": "PASS-IN", "local_address": "GigabitEthernet1", - "local_as": 0, + "local_as": 65001, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -15,7 +15,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "nhs": false, "prefix_limit": { "inet": { @@ -37,7 +37,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "nhs": false, "prefix_limit": { "inet": { @@ -75,7 +75,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "multihop_ttl": 0, "multipath": false, "neighbors": { diff --git a/test/ios/mocked_data/test_get_bgp_config/no_afi/expected_result.json b/test/ios/mocked_data/test_get_bgp_config/no_afi/expected_result.json index 6c5a9cbaa..b75943177 100644 --- a/test/ios/mocked_data/test_get_bgp_config/no_afi/expected_result.json +++ b/test/ios/mocked_data/test_get_bgp_config/no_afi/expected_result.json @@ -2,7 +2,7 @@ "_": { "apply_groups": [], "description": "", - "local_as": 0, + "local_as": 42, "type": "", "import_policy": "", "export_policy": "", @@ -20,7 +20,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 42, "authentication_key": "", "nhs": false, "route_reflector_client": false diff --git a/test/ios/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/ios/mocked_data/test_get_bgp_config/normal/expected_result.json index 3f4742397..f58f5e0c5 100644 --- a/test/ios/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/ios/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -1,11 +1,26 @@ { + "_": { + "apply_groups": [], + "description": "", + "local_as": 65001, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": false, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": false, + "prefix_limit": {}, + "neighbors": {} + }, "RR-CLIENTS": { "apply_groups": [], "description": "[ibgp - rr clients]", "export_policy": "PASS-OUT", "import_policy": "PASS-IN", "local_address": "GigabitEthernet1", - "local_as": 0, + "local_as": 65001, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -15,7 +30,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "nhs": false, "prefix_limit": { "inet": { @@ -37,7 +52,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "nhs": false, "prefix_limit": { "inet": { diff --git a/test/ios/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json b/test/ios/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json index d2dfbaf32..1f53b03ff 100644 --- a/test/ios/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json +++ b/test/ios/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json @@ -5,7 +5,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -15,7 +15,7 @@ "export_policy": "PASS-OUT", "import_policy": "PASS-IN", "local_address": "GigabitEthernet1", - "local_as": 0, + "local_as": 65001, "nhs": false, "prefix_limit": { "inet": { @@ -37,4 +37,4 @@ "remove_private_as": false, "type": "" } -} \ No newline at end of file +} diff --git a/test/iosxr/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json b/test/iosxr/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json index e39f06c91..60e669b26 100644 --- a/test/iosxr/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json +++ b/test/iosxr/mocked_data/test_get_bgp_config/mixed_with_without_groups/expected_result.json @@ -8,7 +8,7 @@ "description": "", "route_reflector_client": false, "nhs": false, - "local_as": 0, + "local_as": 65900, "import_policy": "pass-all", "local_address": "", "prefix_limit": { @@ -30,7 +30,7 @@ "description": "", "route_reflector_client": false, "nhs": false, - "local_as": 0, + "local_as": 65900, "import_policy": "pass-all", "local_address": "", "prefix_limit": { @@ -54,7 +54,7 @@ "remove_private_as": false, "description": "", "export_policy": "", - "local_as": 0, + "local_as": 65900, "apply_groups": [], "multipath": false, "prefix_limit": {} @@ -68,7 +68,7 @@ "description": "", "route_reflector_client": false, "nhs": false, - "local_as": 0, + "local_as": 65900, "import_policy": "RP-SPECIAL-SNOWFLAKE-IN", "local_address": "", "prefix_limit": { @@ -90,7 +90,7 @@ "description": "", "route_reflector_client": false, "nhs": false, - "local_as": 0, + "local_as": 65900, "import_policy": "", "local_address": "", "prefix_limit": {}, @@ -104,7 +104,7 @@ "remove_private_as": true, "description": "", "export_policy": "", - "local_as": 0, + "local_as": 65900, "apply_groups": [], "multipath": false, "prefix_limit": {} diff --git a/test/iosxr/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/iosxr/mocked_data/test_get_bgp_config/normal/expected_result.json index 20971ddf8..c850fe601 100644 --- a/test/iosxr/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/iosxr/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -1,13 +1,28 @@ { + "_": { + "local_as": 13335, + "remove_private_as": false, + "import_policy": "", + "multihop_ttl": 0, + "neighbors": {}, + "multipath": false, + "export_policy": "", + "type": "", + "apply_groups": [], + "remote_as": 0, + "prefix_limit": {}, + "description": "", + "local_address": "" + }, "4-public-anycast-peers": { - "local_as": 0, + "local_as": 13335, "remove_private_as": true, "import_policy": "4-public-anycast-peers-in", "multihop_ttl": 0, "neighbors": { "192.168.20.3": { "export_policy": "", - "local_as": 0, + "local_as": 13335, "prefix_limit": { "inet": { "unicast": { @@ -29,7 +44,7 @@ }, "172.17.17.50": { "export_policy": "", - "local_as": 0, + "local_as": 13335, "prefix_limit": { "inet": { "unicast": { @@ -51,7 +66,7 @@ }, "192.168.50.5": { "export_policy": "", - "local_as": 0, + "local_as": 13335, "prefix_limit": { "inet": { "unicast": { diff --git a/test/iosxr/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json b/test/iosxr/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json index bc0239416..30a30dd4c 100644 --- a/test/iosxr/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json +++ b/test/iosxr/mocked_data/test_get_bgp_config/peers_without_groups/expected_result.json @@ -10,7 +10,7 @@ "remove_private_as": false, "remote_as": 0, "multihop_ttl": 0, - "local_as": 0, + "local_as": 65900, "apply_groups": [], "neighbors": { "10.255.255.2": { @@ -26,7 +26,7 @@ } } }, - "local_as": 0, + "local_as": 65900, "description": "", "local_address": "", "import_policy": "pass-all", @@ -48,7 +48,7 @@ } } }, - "local_as": 0, + "local_as": 65900, "description": "", "local_address": "", "import_policy": "pass-all", diff --git a/test/iosxr_netconf/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/iosxr_netconf/mocked_data/test_get_bgp_config/normal/expected_result.json index 1d60e8893..4ed653140 100644 --- a/test/iosxr_netconf/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/iosxr_netconf/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -1,11 +1,26 @@ { + "_": { + "apply_groups": [], + "description": "", + "export_policy": "", + "import_policy": "", + "local_address": "", + "local_as": 65172, + "multihop_ttl": 0, + "multipath": false, + "neighbors": {}, + "prefix_limit": {}, + "remote_as": 0, + "remove_private_as": false, + "type": "" + }, "EBGP": { "apply_groups": [], "description": "", "export_policy": "EBGP-OUT-POLICY", "import_policy": "EBGP-IN-POLICY", "local_address": "", - "local_as": 0, + "local_as": 65172, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -15,7 +30,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "nhs": false, "prefix_limit": { "inet": { @@ -37,7 +52,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "nhs": false, "prefix_limit": { "inet": { @@ -65,7 +80,7 @@ "export_policy": "EBGP-VRF-OUT-POLICY", "import_policy": "EBGP-VRF-IN-POLICY", "local_address": "", - "local_as": 0, + "local_as": 65172, "multihop_ttl": 0, "multipath": false, "neighbors": {}, @@ -80,7 +95,7 @@ "export_policy": "IBGPv6-OUT-POLICY", "import_policy": "IBGPv6-IN-POLICY", "local_address": "", - "local_as": 0, + "local_as": 65172, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -90,7 +105,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "nhs": false, "prefix_limit": { "inet6": { @@ -112,7 +127,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "nhs": false, "prefix_limit": { "inet6": { @@ -140,7 +155,7 @@ "export_policy": "EBGPv6-VRF-OUT-POLICY", "import_policy": "EBGPv6-VRF-IN-POLICY", "local_address": "", - "local_as": 0, + "local_as": 65172, "multihop_ttl": 0, "multipath": false, "neighbors": {}, @@ -155,7 +170,7 @@ "export_policy": "IBGP-OUT-POLICY", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -165,7 +180,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "nhs": false, "prefix_limit": { "inet": { @@ -193,7 +208,7 @@ "export_policy": "IBGP-OUT-POLICY", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -203,7 +218,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65172, "nhs": false, "prefix_limit": { "inet6": { diff --git a/test/junos/mocked_data/test_get_bgp_config/nhs/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml b/test/junos/mocked_data/test_get_bgp_config/nhs/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml new file mode 100644 index 000000000..bd581bc2c --- /dev/null +++ b/test/junos/mocked_data/test_get_bgp_config/nhs/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml @@ -0,0 +1,7 @@ + + + + 65001 + + + diff --git a/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json b/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json index 93c77a2ec..507acf743 100644 --- a/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json +++ b/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json @@ -1 +1,73 @@ -{"internal":{"apply_groups":[],"description":"","export_policy":"","import_policy":"","local_address":"","local_as":0,"multihop_ttl":0,"multipath":false,"neighbors":{"10.10.10.1":{"authentication_key":"","description":"","export_policy":"nhs","import_policy":"","local_address":"","local_as":0,"nhs":true,"prefix_limit":{},"remote_as":0,"route_reflector_client":false}},"prefix_limit":{},"remote_as":0,"remove_private_as":false,"type":"internal"},"internal-2":{"apply_groups":[],"description":"","export_policy":"","import_policy":"","local_address":"","local_as":0,"multihop_ttl":0,"multipath":false,"neighbors":{"10.10.10.2":{"authentication_key":"","description":"","export_policy":"static","import_policy":"","local_address":"","local_as":0,"nhs":false,"prefix_limit":{},"remote_as":0,"route_reflector_client":false}},"prefix_limit":{},"remote_as":0,"remove_private_as":false,"type":"internal"}} +{ + "_": { + "export_policy": "", + "multipath": false, + "prefix_limit": {}, + "description": "", + "local_as": 65001, + "multihop_ttl": 0, + "apply_groups": [], + "remote_as": 0, + "remove_private_as": false, + "local_address": "", + "type": "", + "import_policy": "", + "neighbors": {} + }, + "internal": { + "apply_groups": [], + "description": "", + "export_policy": "", + "import_policy": "", + "local_address": "", + "local_as": 0, + "multihop_ttl": 0, + "multipath": false, + "neighbors": { + "10.10.10.1": { + "authentication_key": "", + "description": "", + "export_policy": "nhs", + "import_policy": "", + "local_address": "", + "local_as": 0, + "nhs": true, + "prefix_limit": {}, + "remote_as": 0, + "route_reflector_client": false + } + }, + "prefix_limit": {}, + "remote_as": 0, + "remove_private_as": false, + "type": "internal" + }, + "internal-2": { + "apply_groups": [], + "description": "", + "export_policy": "", + "import_policy": "", + "local_address": "", + "local_as": 0, + "multihop_ttl": 0, + "multipath": false, + "neighbors": { + "10.10.10.2": { + "authentication_key": "", + "description": "", + "export_policy": "static", + "import_policy": "", + "local_address": "", + "local_as": 0, + "nhs": false, + "prefix_limit": {}, + "remote_as": 0, + "route_reflector_client": false + } + }, + "prefix_limit": {}, + "remote_as": 0, + "remove_private_as": false, + "type": "internal" + } +} diff --git a/test/junos/mocked_data/test_get_bgp_config/normal/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml b/test/junos/mocked_data/test_get_bgp_config/normal/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml new file mode 100644 index 000000000..6ad44d234 --- /dev/null +++ b/test/junos/mocked_data/test_get_bgp_config/normal/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml @@ -0,0 +1,7 @@ + + + + 13335 + + + diff --git a/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json index 868ef99cc..9d41495fd 100644 --- a/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -1 +1,86 @@ -{"PEERS-GROUP-NAME": {"neighbors": {"192.168.0.1": {"export_policy": "", "prefix_limit": {"inet": {"unicast": {"limit": 100}}}, "route_reflector_client": false, "description": "Facebook [CDN]", "local_as": 0, "nhs": false, "local_address": "", "remote_as": 32934, "authentication_key": "", "import_policy": ""}, "172.17.17.1": {"export_policy": "", "prefix_limit": {"inet": {"unicast": {"limit": 500}}}, "route_reflector_client": false, "description": "Twitter [CDN]", "local_as": 0, "nhs": false, "local_address": "", "remote_as": 13414, "authentication_key": "", "import_policy": ""}}, "export_policy": "PUBLIC-PEER-OUT", "multipath": true, "prefix_limit": {}, "description": "", "local_as": 13335, "multihop_ttl": 0, "apply_groups": ["B", "G", "P", "-", "P", "R", "E", "F", "I", "X", "-", "L", "I", "M", "I", "T"], "remote_as": 0, "remove_private_as": true, "local_address": "", "type": "external", "import_policy": "PUBLIC-PEER-IN"}} +{ + "_": { + "export_policy": "", + "multipath": false, + "prefix_limit": {}, + "description": "", + "local_as": 13335, + "multihop_ttl": 0, + "apply_groups": [], + "remote_as": 0, + "remove_private_as": false, + "local_address": "", + "type": "", + "import_policy": "", + "neighbors": {} + }, + "PEERS-GROUP-NAME": { + "neighbors": { + "192.168.0.1": { + "export_policy": "", + "prefix_limit": { + "inet": { + "unicast": { + "limit": 100 + } + } + }, + "route_reflector_client": false, + "description": "Facebook [CDN]", + "local_as": 0, + "nhs": false, + "local_address": "", + "remote_as": 32934, + "authentication_key": "", + "import_policy": "" + }, + "172.17.17.1": { + "export_policy": "", + "prefix_limit": { + "inet": { + "unicast": { + "limit": 500 + } + } + }, + "route_reflector_client": false, + "description": "Twitter [CDN]", + "local_as": 0, + "nhs": false, + "local_address": "", + "remote_as": 13414, + "authentication_key": "", + "import_policy": "" + } + }, + "export_policy": "PUBLIC-PEER-OUT", + "multipath": true, + "prefix_limit": {}, + "description": "", + "local_as": 13335, + "multihop_ttl": 0, + "apply_groups": [ + "B", + "G", + "P", + "-", + "P", + "R", + "E", + "F", + "I", + "X", + "-", + "L", + "I", + "M", + "I", + "T" + ], + "remote_as": 0, + "remove_private_as": true, + "local_address": "", + "type": "external", + "import_policy": "PUBLIC-PEER-IN" + } +} From 322f208ed3b7a26aafdfcca154aaba812f34a9a8 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 28 Mar 2023 13:01:46 -0700 Subject: [PATCH 51/71] Fixing parsing error when there is no BGP configured on Junos (#1887) --- napalm/junos/junos.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/napalm/junos/junos.py b/napalm/junos/junos.py index fdb96e82d..3ce185e52 100644 --- a/napalm/junos/junos.py +++ b/napalm/junos/junos.py @@ -1253,11 +1253,10 @@ def build_prefix_limit(**args): routing_options = junos_views.junos_routing_config_table(self.device) routing_options.get(options=self.junos_config_options) - bgp_asn = int( - routing_options.xml.find( - "./routing-options/autonomous-system/as-number" - ).text + bgp_asn_obj = routing_options.xml.find( + "./routing-options/autonomous-system/as-number" ) + bgp_asn = int(bgp_asn_obj.text) if bgp_asn_obj is not None else 0 bgp_config["_"] = { "apply_groups": [], From 483efae794449082e4db6ef1da910ded22ac39cf Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 3 Apr 2023 09:18:34 -0700 Subject: [PATCH 52/71] Implement no BGP config behavior for Junos (get_bgp_config) (#1890) --- napalm/base/test/getters.py | 2 +- napalm/junos/junos.py | 96 +++++++++++-------- .../nhs/expected_result.json | 8 +- ...ent____policy_options___configuration_.xml | 2 + ...up____bgp___protocols___configuration_.xml | 2 + ...em____routing_options___configuration_.xml | 2 + .../no_bgp/expected_result.json | 1 + .../normal/expected_result.json | 23 +---- 8 files changed, 72 insertions(+), 64 deletions(-) create mode 100644 test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__policy_options__policy_statement____policy_options___configuration_.xml create mode 100644 test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__protocols__bgp__group____bgp___protocols___configuration_.xml create mode 100644 test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml create mode 100644 test/junos/mocked_data/test_get_bgp_config/no_bgp/expected_result.json diff --git a/napalm/base/test/getters.py b/napalm/base/test/getters.py index cc64f551e..0a2e47a66 100644 --- a/napalm/base/test/getters.py +++ b/napalm/base/test/getters.py @@ -244,7 +244,7 @@ def test_get_lldp_neighbors_detail(self, test_case): def test_get_bgp_config(self, test_case): """Test get_bgp_config.""" get_bgp_config = self.device.get_bgp_config() - assert len(get_bgp_config) > 0 + assert get_bgp_config == {} or len(get_bgp_config) > 0 for bgp_group in get_bgp_config.values(): assert helpers.test_model(models.BPGConfigGroupDict, bgp_group) diff --git a/napalm/junos/junos.py b/napalm/junos/junos.py index 3ce185e52..74b6e5efe 100644 --- a/napalm/junos/junos.py +++ b/napalm/junos/junos.py @@ -1256,30 +1256,34 @@ def build_prefix_limit(**args): bgp_asn_obj = routing_options.xml.find( "./routing-options/autonomous-system/as-number" ) - bgp_asn = int(bgp_asn_obj.text) if bgp_asn_obj is not None else 0 + system_bgp_asn = int(bgp_asn_obj.text) if bgp_asn_obj is not None else 0 - bgp_config["_"] = { - "apply_groups": [], - "description": "", - "local_as": bgp_asn, - "type": "", - "import_policy": "", - "export_policy": "", - "local_address": "", - "multipath": False, - "multihop_ttl": 0, - "remote_as": 0, - "remove_private_as": False, - "prefix_limit": {}, - "neighbors": {}, - } - if group: + # No BGP peer-group i.e. "_" key is a special case. + if group and group != "_": bgp = junos_views.junos_bgp_config_group_table(self.device) bgp.get(group=group, options=self.junos_config_options) else: bgp = junos_views.junos_bgp_config_table(self.device) bgp.get(options=self.junos_config_options) neighbor = "" # if no group is set, no neighbor should be set either + + # Only set no peer-group if BGP is actually configured. + if bgp.items() or system_bgp_asn: + bgp_config["_"] = { + "apply_groups": [], + "description": "", + "local_as": system_bgp_asn, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": False, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": False, + "prefix_limit": {}, + "neighbors": {}, + } bgp_items = bgp.items() if neighbor: @@ -1306,13 +1310,17 @@ def build_prefix_limit(**args): for field, datatype in _GROUP_FIELDS_DATATYPE_MAP_.items() if "_prefix_limit" not in field } - for elem in bgp_group_details: - if not ("_prefix_limit" not in elem[0] and elem[1] is not None): + + # Always overwrite with the system local_as (this will either be + # valid or will be zero i.e. the same as the default value). + bgp_config[bgp_group_name]["local_as"] = system_bgp_asn + + for key, value in bgp_group_details: + if "_prefix_limit" in key or value is None: continue - datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(elem[0]) + datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(key) default = _DATATYPE_DEFAULT_.get(datatype) - key = elem[0] - value = elem[1] + if key in ["export_policy", "import_policy"]: if isinstance(value, list): value = " ".join(value) @@ -1320,6 +1328,10 @@ def build_prefix_limit(**args): value = napalm.base.helpers.convert( napalm.base.helpers.ip, value, value ) + if key == "apply_groups": + # Ensure apply_groups value is wrapped in a list + if isinstance(value, str): + value = [value] if key == "neighbors": bgp_group_peers = value continue @@ -1327,15 +1339,15 @@ def build_prefix_limit(**args): {key: napalm.base.helpers.convert(datatype, value, default)} ) prefix_limit_fields = {} - for elem in bgp_group_details: - if "_prefix_limit" in elem[0] and elem[1] is not None: - datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(elem[0]) + for key, value in bgp_group_details: + if "_prefix_limit" in key and value is not None: + datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(key) default = _DATATYPE_DEFAULT_.get(datatype) prefix_limit_fields.update( { - elem[0].replace( + key.replace( "_prefix_limit", "" - ): napalm.base.helpers.convert(datatype, elem[1], default) + ): napalm.base.helpers.convert(datatype, value, default) } ) bgp_config[bgp_group_name]["prefix_limit"] = build_prefix_limit( @@ -1349,23 +1361,31 @@ def build_prefix_limit(**args): bgp_config[bgp_group_name]["multihop_ttl"] = 64 bgp_config[bgp_group_name]["neighbors"] = {} + bgp_group_remote_as = bgp_config[bgp_group_name]["remote_as"] for bgp_group_neighbor in bgp_group_peers.items(): bgp_peer_address = napalm.base.helpers.ip(bgp_group_neighbor[0]) if neighbor and bgp_peer_address != neighbor: continue # if filters applied, jump over all other neighbors bgp_group_details = bgp_group_neighbor[1] + + # Set defaults for this BGP peer bgp_peer_details = { field: _DATATYPE_DEFAULT_.get(datatype) for field, datatype in _PEER_FIELDS_DATATYPE_MAP_.items() if "_prefix_limit" not in field } - for elem in bgp_group_details: - if not ("_prefix_limit" not in elem[0] and elem[1] is not None): + + # Always overwrite with the system local_as (this will either be + # valid or will be zero i.e. the same as the default value). + bgp_peer_details["local_as"] = system_bgp_asn + # Always set the default remote-as as the Peer-Group remote-as + bgp_peer_details["remote_as"] = bgp_group_remote_as + + for key, value in bgp_group_details: + if "_prefix_limit" in key or value is None: continue - datatype = _PEER_FIELDS_DATATYPE_MAP_.get(elem[0]) + datatype = _PEER_FIELDS_DATATYPE_MAP_.get(key) default = _DATATYPE_DEFAULT_.get(datatype) - key = elem[0] - value = elem[1] if key in ["export_policy"]: # next-hop self is applied on export IBGP sessions bgp_peer_details["nhs"] = _check_nhs(value, nhs_policies) @@ -1393,17 +1413,15 @@ def build_prefix_limit(**args): if "cluster" in bgp_config[bgp_group_name].keys(): bgp_peer_details["route_reflector_client"] = True prefix_limit_fields = {} - for elem in bgp_group_details: - if "_prefix_limit" in elem[0] and elem[1] is not None: - datatype = _PEER_FIELDS_DATATYPE_MAP_.get(elem[0]) + for key, value in bgp_group_details: + if "_prefix_limit" in key and value is not None: + datatype = _PEER_FIELDS_DATATYPE_MAP_.get(key) default = _DATATYPE_DEFAULT_.get(datatype) prefix_limit_fields.update( { - elem[0].replace( + key.replace( "_prefix_limit", "" - ): napalm.base.helpers.convert( - datatype, elem[1], default - ) + ): napalm.base.helpers.convert(datatype, value, default) } ) bgp_peer_details["prefix_limit"] = build_prefix_limit( diff --git a/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json b/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json index 507acf743..a375a75a0 100644 --- a/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json +++ b/test/junos/mocked_data/test_get_bgp_config/nhs/expected_result.json @@ -20,7 +20,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -30,7 +30,7 @@ "export_policy": "nhs", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "nhs": true, "prefix_limit": {}, "remote_as": 0, @@ -48,7 +48,7 @@ "export_policy": "", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "multihop_ttl": 0, "multipath": false, "neighbors": { @@ -58,7 +58,7 @@ "export_policy": "static", "import_policy": "", "local_address": "", - "local_as": 0, + "local_as": 65001, "nhs": false, "prefix_limit": {}, "remote_as": 0, diff --git a/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__policy_options__policy_statement____policy_options___configuration_.xml b/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__policy_options__policy_statement____policy_options___configuration_.xml new file mode 100644 index 000000000..83138436e --- /dev/null +++ b/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__policy_options__policy_statement____policy_options___configuration_.xml @@ -0,0 +1,2 @@ + + diff --git a/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__protocols__bgp__group____bgp___protocols___configuration_.xml b/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__protocols__bgp__group____bgp___protocols___configuration_.xml new file mode 100644 index 000000000..83138436e --- /dev/null +++ b/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__protocols__bgp__group____bgp___protocols___configuration_.xml @@ -0,0 +1,2 @@ + + diff --git a/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml b/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml new file mode 100644 index 000000000..83138436e --- /dev/null +++ b/test/junos/mocked_data/test_get_bgp_config/no_bgp/_configuration__routing_options__autonomous_system____routing_options___configuration_.xml @@ -0,0 +1,2 @@ + + diff --git a/test/junos/mocked_data/test_get_bgp_config/no_bgp/expected_result.json b/test/junos/mocked_data/test_get_bgp_config/no_bgp/expected_result.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/junos/mocked_data/test_get_bgp_config/no_bgp/expected_result.json @@ -0,0 +1 @@ +{} diff --git a/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json index 9d41495fd..6c44290dd 100644 --- a/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/junos/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -27,7 +27,7 @@ }, "route_reflector_client": false, "description": "Facebook [CDN]", - "local_as": 0, + "local_as": 13335, "nhs": false, "local_address": "", "remote_as": 32934, @@ -45,7 +45,7 @@ }, "route_reflector_client": false, "description": "Twitter [CDN]", - "local_as": 0, + "local_as": 13335, "nhs": false, "local_address": "", "remote_as": 13414, @@ -59,24 +59,7 @@ "description": "", "local_as": 13335, "multihop_ttl": 0, - "apply_groups": [ - "B", - "G", - "P", - "-", - "P", - "R", - "E", - "F", - "I", - "X", - "-", - "L", - "I", - "M", - "I", - "T" - ], + "apply_groups": ["BGP-PREFIX-LIMIT"], "remote_as": 0, "remove_private_as": true, "local_address": "", From ba460d9b73c241a539ab33deedbccd6cf905053a Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Mon, 3 Apr 2023 16:17:44 -0500 Subject: [PATCH 53/71] eos: add test case for issue 905 --- .../expected_result.json | 57 +++++++++++++++++++ ...w_running_config___section_router_bgp.text | 11 ++++ 2 files changed, 68 insertions(+) create mode 100644 test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/expected_result.json create mode 100644 test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/show_running_config___section_router_bgp.text diff --git a/test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/expected_result.json new file mode 100644 index 000000000..4f2f36e4e --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/expected_result.json @@ -0,0 +1,57 @@ +{ + "_": { + "type": "", + "multipath": false, + "apply_groups": [], + "remove_private_as": false, + "multihop_ttl": 0, + "remote_as": 0, + "local_address": "", + "local_as": 65534, + "description": "", + "import_policy": "", + "export_policy": "", + "prefix_limit": {}, + "neighbors": {} + }, + "FOO-GROUP": { + "local_address": "", + "description": "FOO", + "type": "", + "local_as": 65534, + "apply_groups": [], + "multihop_ttl": 0, + "remove_private_as": false, + "remote_as": 65534, + "import_policy": "", + "export_policy": "", + "neighbors": { + "192.0.2.2": { + "local_address": "", + "authentication_key": "", + "description": "FOO", + "nhs": false, + "local_as": 65534, + "route_reflector_client": false, + "remote_as": 65534, + "import_policy": "", + "export_policy": "", + "prefix_limit": {} + }, + "192.0.2.3": { + "local_address": "", + "authentication_key": "", + "description": "SECOND-PEER", + "nhs": true, + "local_as": 65534, + "route_reflector_client": false, + "remote_as": 65534, + "import_policy": "", + "export_policy": "", + "prefix_limit": {} + } + }, + "prefix_limit": {}, + "multipath": false + } +} diff --git a/test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/show_running_config___section_router_bgp.text b/test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/show_running_config___section_router_bgp.text new file mode 100644 index 000000000..0db6d0c27 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_config/issue_905_group_copydown/show_running_config___section_router_bgp.text @@ -0,0 +1,11 @@ +router bgp 65534 + router-id 192.0.2.1 + neighbor FOO-GROUP peer group + neighbor FOO-GROUP next-hop-self + neighbor FOO-GROUP description FOO + neighbor FOO-GROUP remote-as 65534 + neighbor 192.0.2.2 peer group FOO-GROUP + no neighbor 192.0.2.2 next-hop-self + neighbor 192.0.2.3 peer group FOO-GROUP + neighbor 192.0.2.3 description SECOND-PEER +! From f7e83d352fbc2750183fcb8d676f98bce32fbee0 Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Mon, 3 Apr 2023 16:20:25 -0500 Subject: [PATCH 54/71] eos: use peer group dict to populate neighbors Since EOS outputs all peer group configuration prior to individual neighbor configurations, we can use the settings for NHS, remote-as, etc present in the group level dictionary when creating the neighbor dictionary, resulting in a consistent view of the configuration applied to the neighbor. Closes #905 --- napalm/eos/eos.py | 28 +++++++++++++++---- .../expected_result.json | 8 +++--- .../issue_1113_dot_asn/expected_result.json | 16 +++++------ .../normal/expected_result.json | 16 +++++------ 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index cb182ea8d..01793e1a7 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -994,6 +994,7 @@ def get_bgp_config(self, group="", neighbor=""): "local-v4-addr": "local_address", "local-v6-addr": "local_address", "local-as": "local_as", + "next-hop-self": "nhs", "description": "description", "import-policy": "import_policy", "export-policy": "export_policy", @@ -1051,7 +1052,7 @@ def default_group_dict(local_as): ) # few more default values return group_dict - def default_neighbor_dict(local_as): + def default_neighbor_dict(local_as, group_dict): neighbor_dict = {} neighbor_dict.update( { @@ -1062,6 +1063,13 @@ def default_neighbor_dict(local_as): neighbor_dict.update( {"prefix_limit": {}, "local_as": local_as, "authentication_key": ""} ) # few more default values + neighbor_dict.update( + { + key: group_dict.get(key) + for key in _GROUP_FIELD_MAP_.values() + if key in group_dict and key in _PEER_FIELD_MAP_.values() + } + ) # copy in values from group dict if present return neighbor_dict def parse_options(options, default_value=False): @@ -1152,14 +1160,20 @@ def parse_options(options, default_value=False): ipaddress.ip_address(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) + group_name = None if options[0] == "peer-group": - bgp_neighbors[peer_address]["__group"] = options[1] + group_name = options[1] # EOS > 4.23.0 only supports the new syntax # https://www.arista.com/en/support/advisories-notices/fieldnotices/7097-field-notice-39 elif options[0] == "peer" and options[1] == "group": - bgp_neighbors[peer_address]["__group"] = options[2] + group_name = options[2] + if peer_address not in bgp_neighbors: + bgp_neighbors[peer_address] = default_neighbor_dict( + local_as, bgp_config.get(group_name, {}) + ) + + if group_name: + bgp_neighbors[peer_address]["__group"] = group_name # in the config, neighbor details are lister after # the group is specified for the neighbor: @@ -1197,6 +1211,10 @@ def parse_options(options, default_value=False): bgp_config[peer_group] = default_group_dict(local_as) bgp_config[peer_group]["neighbors"][peer] = peer_details + [ + v.pop("nhs", None) for v in bgp_config.values() + ] # remove NHS from group-level dictionary + return bgp_config def get_arp_table(self, vrf=""): diff --git a/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json index 9a66039c0..1dbf0d43b 100644 --- a/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json +++ b/test/eos/mocked_data/test_get_bgp_config/issue1504_alt_peer_group_syntax/expected_result.json @@ -35,8 +35,8 @@ "local_as": 64496, "nhs": false, "route_reflector_client": false, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "reject-all", "authentication_key": "", "prefix_limit": {} }, @@ -47,8 +47,8 @@ "local_as": 64496, "nhs": false, "route_reflector_client": false, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "reject-all", "authentication_key": "", "prefix_limit": {} } diff --git a/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json index c6c5353d9..1f885538c 100644 --- a/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json +++ b/test/eos/mocked_data/test_get_bgp_config/issue_1113_dot_asn/expected_result.json @@ -35,8 +35,8 @@ "local_as": 4266524237, "nhs": false, "route_reflector_client": false, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "4-public-peer-anycast-out", "authentication_key": "", "prefix_limit": {} }, @@ -47,8 +47,8 @@ "local_as": 4266524237, "nhs": false, "route_reflector_client": false, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "4-public-peer-anycast-out", "authentication_key": "", "prefix_limit": {} } @@ -75,8 +75,8 @@ "local_as": 4266524237, "nhs": false, "route_reflector_client": false, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "reject-all", "authentication_key": "", "prefix_limit": {} }, @@ -87,8 +87,8 @@ "local_as": 4266524237, "nhs": false, "route_reflector_client": false, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "reject-all", "authentication_key": "", "prefix_limit": {} } diff --git a/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json index 0d22dfaf6..bdf8f2657 100644 --- a/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json +++ b/test/eos/mocked_data/test_get_bgp_config/normal/expected_result.json @@ -34,8 +34,8 @@ "local_as": 13335, "route_reflector_client": false, "remote_as": 13414, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "4-public-peer-anycast-out", "prefix_limit": {} }, "192.168.0.1": { @@ -46,8 +46,8 @@ "local_as": 13335, "route_reflector_client": false, "remote_as": 32934, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "4-public-peer-anycast-out", "prefix_limit": {} } }, @@ -74,8 +74,8 @@ "local_as": 13335, "route_reflector_client": false, "remote_as": 54113, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "reject-all", "prefix_limit": {} }, "2001:db8::0:1": { @@ -86,8 +86,8 @@ "local_as": 13335, "route_reflector_client": false, "remote_as": 8403, - "import_policy": "", - "export_policy": "", + "import_policy": "reject-all", + "export_policy": "reject-all", "prefix_limit": {} } }, From 02837c0827a9e00859cfc4af45df661cdedaa39c Mon Sep 17 00:00:00 2001 From: bewing Date: Tue, 4 Apr 2023 17:52:25 -0500 Subject: [PATCH 55/71] eos: get_bgp_config when BGP not running (#1891) Return an empty dictionary if we are unable to detect a local ASN, as this indicates that no BGP configuration is present on the device. --- napalm/eos/eos.py | 4 ++++ .../test_get_bgp_config/no_bgp_config/expected_result.json | 1 + .../show_running_config___section_router_bgp.text | 0 3 files changed, 5 insertions(+) create mode 100644 test/eos/mocked_data/test_get_bgp_config/no_bgp_config/expected_result.json create mode 100644 test/eos/mocked_data/test_get_bgp_config/no_bgp_config/show_running_config___section_router_bgp.text diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index cb182ea8d..3de3ed8a2 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -1197,6 +1197,10 @@ def parse_options(options, default_value=False): bgp_config[peer_group] = default_group_dict(local_as) bgp_config[peer_group]["neighbors"][peer] = peer_details + if local_as == 0: + # BGP not running + return {} + return bgp_config def get_arp_table(self, vrf=""): diff --git a/test/eos/mocked_data/test_get_bgp_config/no_bgp_config/expected_result.json b/test/eos/mocked_data/test_get_bgp_config/no_bgp_config/expected_result.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/eos/mocked_data/test_get_bgp_config/no_bgp_config/expected_result.json @@ -0,0 +1 @@ +{} diff --git a/test/eos/mocked_data/test_get_bgp_config/no_bgp_config/show_running_config___section_router_bgp.text b/test/eos/mocked_data/test_get_bgp_config/no_bgp_config/show_running_config___section_router_bgp.text new file mode 100644 index 000000000..e69de29bb From 7544274760451a002cb5bb068cd6b14accba34dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 10:52:40 -0700 Subject: [PATCH 56/71] Bump types-requests from 2.28.11.16 to 2.28.11.17 (#1882) Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.16 to 2.28.11.17. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 4139a9281..05a9f7a53 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,7 +10,7 @@ pylama==8.4.1 mock==5.0.1 mypy==0.982 types-PyYAML==6.0.12.8 -types-requests==2.28.11.16 +types-requests==2.28.11.17 types-six==1.16.21.7 types-setuptools==67.6.0.5 ttp==0.9.0 From 8e7d663e0f4432e7a896becc34c16b103d9a26d0 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Thu, 20 Apr 2023 09:31:43 -0700 Subject: [PATCH 57/71] Move canonical_interface_name, base_interfaces to netutils (#1904) Co-authored-by: itdependsnetworks --- napalm/base/base.py | 5 +- napalm/base/canonical_map.py | 157 +---------------------------------- napalm/base/helpers.py | 96 ++------------------- napalm/ios/ios.py | 8 +- napalm/nxos/nxos.py | 11 +-- napalm/nxos_ssh/nxos_ssh.py | 14 ++-- test/base/test_helpers.py | 81 ------------------ 7 files changed, 31 insertions(+), 341 deletions(-) diff --git a/napalm/base/base.py b/napalm/base/base.py index d1dbe0eea..7410bf6a8 100644 --- a/napalm/base/base.py +++ b/napalm/base/base.py @@ -19,6 +19,7 @@ from typing_extensions import Literal from netmiko import ConnectHandler, NetMikoTimeoutException +from netutils.interface import canonical_interface_name # local modules import napalm.base.exceptions @@ -1805,8 +1806,6 @@ def compliance_report( def _canonical_int(self, interface: str) -> str: """Expose the helper function within this class.""" if self.use_canonical_interface is True: - return napalm.base.helpers.canonical_interface_name( - interface, addl_name_map=None - ) + return canonical_interface_name(interface, addl_name_map=None) else: return interface diff --git a/napalm/base/canonical_map.py b/napalm/base/canonical_map.py index 29b50e714..fb9658213 100644 --- a/napalm/base/canonical_map.py +++ b/napalm/base/canonical_map.py @@ -1,153 +1,4 @@ -base_interfaces = { - "ATM": "ATM", - "AT": "ATM", - "B": "Bdi", - "Bd": "Bdi", - "Bdi": "Bdi", - "EOBC": "EOBC", - "EO": "EOBC", - "Ethernet": "Ethernet", - "Eth": "Ethernet", - "eth": "Ethernet", - "Et": "Ethernet", - "et": "Ethernet", - "FastEthernet": "FastEthernet", - "FastEth": "FastEthernet", - "FastE": "FastEthernet", - "Fast": "FastEthernet", - "Fas": "FastEthernet", - "FE": "FastEthernet", - "Fa": "FastEthernet", - "fa": "FastEthernet", - "Fddi": "Fddi", - "FD": "Fddi", - "FortyGigabitEthernet": "FortyGigabitEthernet", - "FortyGigEthernet": "FortyGigabitEthernet", - "FortyGigEth": "FortyGigabitEthernet", - "FortyGigE": "FortyGigabitEthernet", - "FortyGig": "FortyGigabitEthernet", - "FGE": "FortyGigabitEthernet", - "FO": "FortyGigabitEthernet", - "Fo": "FortyGigabitEthernet", - "FiftyGigabitEthernet": "FiftyGigabitEthernet", - "FiftyGigEthernet": "FiftyGigabitEthernet", - "FiftyGigEth": "FiftyGigabitEthernet", - "FiftyGigE": "FiftyGigabitEthernet", - "FI": "FiftyGigabitEthernet", - "Fi": "FiftyGigabitEthernet", - "fi": "FiftyGigabitEthernet", - "GigabitEthernet": "GigabitEthernet", - "GigEthernet": "GigabitEthernet", - "GigEth": "GigabitEthernet", - "GigE": "GigabitEthernet", - "Gig": "GigabitEthernet", - "GE": "GigabitEthernet", - "Ge": "GigabitEthernet", - "ge": "GigabitEthernet", - "Gi": "GigabitEthernet", - "gi": "GigabitEthernet", - "HundredGigabitEthernet": "HundredGigabitEthernet", - "HundredGigEthernet": "HundredGigabitEthernet", - "HundredGigEth": "HundredGigabitEthernet", - "HundredGigE": "HundredGigabitEthernet", - "HundredGig": "HundredGigabitEthernet", - "Hu": "HundredGigabitEthernet", - "TwentyFiveGigabitEthernet": "TwentyFiveGigabitEthernet", - "TwentyFiveGigEthernet": "TwentyFiveGigabitEthernet", - "TwentyFiveGigEth": "TwentyFiveGigabitEthernet", - "TwentyFiveGigE": "TwentyFiveGigabitEthernet", - "TwentyFiveGig": "TwentyFiveGigabitEthernet", - "TF": "TwentyFiveGigabitEthernet", - "Tf": "TwentyFiveGigabitEthernet", - "tf": "TwentyFiveGigabitEthernet", - "TwoHundredGigabitEthernet": "TwoHundredGigabitEthernet", - "TwoHundredGigEthernet": "TwoHundredGigabitEthernet", - "TwoHundredGigEth": "TwoHundredGigabitEthernet", - "TwoHundredGigE": "TwoHundredGigabitEthernet", - "TwoHundredGig": "TwoHundredGigabitEthernet", - "TH": "TwoHundredGigabitEthernet", - "Th": "TwoHundredGigabitEthernet", - "th": "TwoHundredGigabitEthernet", - "FourHundredGigabitEthernet": "FourHundredGigabitEthernet", - "FourHundredGigEthernet": "FourHundredGigabitEthernet", - "FourHundredGigEth": "FourHundredGigabitEthernet", - "FourHundredGigE": "FourHundredGigabitEthernet", - "FourHundredGig": "FourHundredGigabitEthernet", - "F": "FourHundredGigabitEthernet", - "f": "FourHundredGigabitEthernet", - "Loopback": "Loopback", - "loopback": "Loopback", - "Lo": "Loopback", - "lo": "Loopback", - "Management": "Management", - "Mgmt": "Management", - "mgmt": "Management", - "Ma": "Management", - "Management_short": "Ma", - "MFR": "MFR", - "Multilink": "Multilink", - "Mu": "Multilink", - "n": "nve", - "nv": "nve", - "nve": "nve", - "PortChannel": "Port-channel", - "Port-channel": "Port-channel", - "Port-Channel": "Port-channel", - "port-channel": "Port-channel", - "po": "Port-channel", - "Po": "Port-channel", - "POS": "POS", - "PO": "POS", - "Serial": "Serial", - "Se": "Serial", - "S": "Serial", - "TenGigabitEthernet": "TenGigabitEthernet", - "TenGigEthernet": "TenGigabitEthernet", - "TenGigEth": "TenGigabitEthernet", - "TenGig": "TenGigabitEthernet", - "TeGig": "TenGigabitEthernet", - "Ten": "TenGigabitEthernet", - "T": "TenGigabitEthernet", - "Te": "TenGigabitEthernet", - "te": "TenGigabitEthernet", - "Tunnel": "Tunnel", - "Tun": "Tunnel", - "Tu": "Tunnel", - "Twe": "TwentyFiveGigE", - "Tw": "TwoGigabitEthernet", - "Two": "TwoGigabitEthernet", - "Virtual-Access": "Virtual-Access", - "Vi": "Virtual-Access", - "Virtual-Template": "Virtual-Template", - "Vt": "Virtual-Template", - "VLAN": "VLAN", - "V": "VLAN", - "Vl": "VLAN", - "Wlan-GigabitEthernet": "Wlan-GigabitEthernet", -} - -reverse_mapping = { - "ATM": "At", - "EOBC": "EO", - "Ethernet": "Et", - "FastEthernet": "Fa", - "Fddi": "FD", - "FortyGigabitEthernet": "Fo", - "GigabitEthernet": "Gi", - "HundredGigabitEthernet": "Hu", - "Loopback": "Lo", - "Management": "Ma", - "MFR": "MFR", - "Multilink": "Mu", - "Port-channel": "Po", - "POS": "PO", - "Serial": "Se", - "TenGigabitEthernet": "Te", - "Tunnel": "Tu", - "TwoGigabitEthernet": "Two", - "TwentyFiveGigE": "Twe", - "Virtual-Access": "Vi", - "Virtual-Template": "Vt", - "VLAN": "Vl", - "Wlan-GigabitEthernet": "Wl-Gi", -} +# Do not remove the below imports, functions were moved to netutils, but to not +# break backwards compatibility, these should remain +from netutils.constants import BASE_INTERFACES as base_interfaces # noqa +from netutils.constants import REVERSE_MAPPING as reverse_mapping # noqa diff --git a/napalm/base/helpers.py b/napalm/base/helpers.py index e40b88a77..dd58ddc7a 100644 --- a/napalm/base/helpers.py +++ b/napalm/base/helpers.py @@ -18,6 +18,14 @@ from netaddr import mac_unix from netutils.config.parser import IOSConfigParser +# Do not remove the below imports, functions were moved to netutils, but to not +# break backwards compatibility, these should remain +from netutils.interface import abbreviated_interface_name # noqa +from netutils.interface import canonical_interface_name # noqa +from netutils.constants import BASE_INTERFACES as base_interfaces # noqa +from netutils.constants import REVERSE_MAPPING as reverse_mapping # noqa +from netutils.interface import split_interface as _split_interface + try: from ttp import quick_parse as ttp_quick_parse @@ -30,7 +38,6 @@ from napalm.base import constants from napalm.base.models import ConfigDict from napalm.base.utils.jinja_filters import CustomJinjaFilters -from napalm.base.canonical_map import base_interfaces, reverse_mapping T = TypeVar("T") R = TypeVar("R") @@ -564,92 +571,7 @@ def as_number(as_number_val: str) -> int: def split_interface(intf_name: str) -> Tuple[str, str]: """Split an interface name based on first digit, slash, or space match.""" - head = intf_name.rstrip(r"/\0123456789. ") - tail = intf_name[len(head) :].lstrip() - return (head, tail) - - -def canonical_interface_name( - interface: str, addl_name_map: Optional[Dict[str, str]] = None -) -> str: - """Function to return an interface's canonical name (fully expanded name). - - Use of explicit matches used to indicate a clear understanding on any potential - match. Regex and other looser matching methods were not implmented to avoid false - positive matches. As an example, it would make sense to do "[P|p][O|o]" which would - incorrectly match PO = POS and Po = Port-channel, leading to a false positive, not - easily troubleshot, found, or known. - - :param interface: The interface you are attempting to expand. - :param addl_name_map: A dict containing key/value pairs that updates - the base mapping. Used if an OS has specific differences. e.g. {"Po": "PortChannel"} vs - {"Po": "Port-Channel"} - :type addl_name_map: optional - """ - - name_map = {} - name_map.update(base_interfaces) - interface_type, interface_number = split_interface(interface) - - if isinstance(addl_name_map, dict): - name_map.update(addl_name_map) - # check in dict for mapping - if name_map.get(interface_type): - long_int = name_map.get(interface_type) - assert isinstance(long_int, str) - return long_int + str(interface_number) - # if nothing matched, return the original name - else: - return interface - - -def abbreviated_interface_name( - interface: str, - addl_name_map: Optional[Dict[str, str]] = None, - addl_reverse_map: Optional[Dict[str, str]] = None, -) -> str: - """Function to return an abbreviated representation of the interface name. - - :param interface: The interface you are attempting to abbreviate. - :param addl_name_map: A dict containing key/value pairs that updates - the base mapping. Used if an OS has specific differences. e.g. {"Po": "PortChannel"} vs - {"Po": "Port-Channel"} - :type addl_name_map: optional - :param addl_reverse_map: A dict containing key/value pairs that updates - the reverse mapping. Used if an OS has specific differences. e.g. {"PortChannel": "Po"} vs - {"PortChannel": "po"} - :type addl_reverse_map: optional - """ - - name_map = {} - name_map.update(base_interfaces) - interface_type, interface_number = split_interface(interface) - - if isinstance(addl_name_map, dict): - name_map.update(addl_name_map) - - rev_name_map = {} - rev_name_map.update(reverse_mapping) - - if isinstance(addl_reverse_map, dict): - rev_name_map.update(addl_reverse_map) - - # Try to ensure canonical type. - if name_map.get(interface_type): - canonical_type = name_map.get(interface_type) - else: - canonical_type = interface_type - - assert isinstance(canonical_type, str) - - try: - abbreviated_name = rev_name_map[canonical_type] + str(interface_number) - return abbreviated_name - except KeyError: - pass - - # If abbreviated name lookup fails, return original name - return interface + return _split_interface(interface=intf_name) def transform_lldp_capab(capabilities: Union[str, Any]) -> List[str]: diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index 682a9a990..7c01fc655 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -36,15 +36,17 @@ CommitConfirmException, ) from napalm.base.helpers import ( - canonical_interface_name, transform_lldp_capab, textfsm_extractor, - split_interface, - abbreviated_interface_name, generate_regex_or, sanitize_configs, ) from netaddr.core import AddrFormatError +from netutils.interface import ( + abbreviated_interface_name, + canonical_interface_name, + split_interface, +) from napalm.base.netmiko_helpers import netmiko_args # Easier to store these as constants diff --git a/napalm/nxos/nxos.py b/napalm/nxos/nxos.py index 7eac8077e..9668569ff 100644 --- a/napalm/nxos/nxos.py +++ b/napalm/nxos/nxos.py @@ -46,6 +46,7 @@ from netmiko import file_transfer from requests.exceptions import ConnectionError from netutils.config.compliance import diff_network_config +from netutils.interface import canonical_interface_name import napalm.base.constants as c @@ -682,7 +683,7 @@ def get_lldp_neighbors_detail( lldp_entry["remote_system_enable_capab"] ) # Turn the interfaces into their long version - local_intf = napalm.base.helpers.canonical_interface_name(local_intf) + local_intf = canonical_interface_name(local_intf) lldp.setdefault(local_intf, []) lldp[local_intf].append(lldp_entry) # type: ignore @@ -738,13 +739,9 @@ def _parse_vlan_ports(self, vlan_s: Union[str, List]) -> List: find = re.findall(find_regexp, vls.strip()) if find: for i in range(int(find[0][1]), int(find[0][2]) + 1): - vlans.append( - napalm.base.helpers.canonical_interface_name( - find[0][0] + str(i) - ) - ) + vlans.append(canonical_interface_name(find[0][0] + str(i))) else: - vlans.append(napalm.base.helpers.canonical_interface_name(vls.strip())) + vlans.append(canonical_interface_name(vls.strip())) return vlans @abstractmethod diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py index 51aa2c690..bdb01f5a9 100644 --- a/napalm/nxos_ssh/nxos_ssh.py +++ b/napalm/nxos_ssh/nxos_ssh.py @@ -20,6 +20,9 @@ import socket from collections import defaultdict +# import external lib +from netutils.interface import canonical_interface_name + # import NAPALM Base from napalm.base import helpers from napalm.base.exceptions import CommandErrorException, ReplaceConfigException @@ -116,7 +119,7 @@ def parse_intf_section(interface): else: # More standard is up, next line admin state is lines match = re.search(re_intf_name_state, interface) - intf_name = helpers.canonical_interface_name(match.group("intf_name")) + intf_name = canonical_interface_name(match.group("intf_name")) intf_state = match.group("intf_state").strip() is_up = True if intf_state == "up" else False @@ -516,7 +519,6 @@ def is_alive(self): return {"is_alive": self.device.remote_conn.transport.is_active()} def _copy_run_start(self): - output = self.device.save_config() if "complete" in output.lower(): return True @@ -525,7 +527,6 @@ def _copy_run_start(self): raise CommandErrorException(msg) def _load_cfg_from_checkpoint(self): - commands = [ "terminal dont-ask", "rollback running-config file {}".format(self.candidate_cfg), @@ -655,7 +656,7 @@ def get_facts(self): continue interface = line.split()[0] # Return canonical interface name - interface_list.append(helpers.canonical_interface_name(interface)) + interface_list.append(canonical_interface_name(interface)) return { "uptime": float(uptime), @@ -1190,7 +1191,7 @@ def process_mac_fields(vlan, mac, mac_type, interface): active = False return { "mac": helpers.mac(mac), - "interface": helpers.canonical_interface_name(interface), + "interface": canonical_interface_name(interface), "vlan": int(vlan), "static": static, "active": active, @@ -1209,7 +1210,6 @@ def process_mac_fields(vlan, mac, mac_type, interface): output = re.sub(r"vPC Peer-Link", "vPC-Peer-Link", output, flags=re.M) for line in output.splitlines(): - # Every 500 Mac's Legend is reprinted, regardless of terminal length if re.search(r"^Legend", line): continue @@ -1460,7 +1460,7 @@ def get_route_to(self, destination="", protocol="", longer=False): # routing protocol process number, for future use # nh_source_proc_nr = viastr.group('procnr) if nh_int: - nh_int_canon = helpers.canonical_interface_name(nh_int) + nh_int_canon = canonical_interface_name(nh_int) else: nh_int_canon = "" route_entry = { diff --git a/test/base/test_helpers.py b/test/base/test_helpers.py index 24bdb0f5f..96dbb86f5 100644 --- a/test/base/test_helpers.py +++ b/test/base/test_helpers.py @@ -493,87 +493,6 @@ def test_convert_uptime_string_seconds(self): self.assertEqual(convert_uptime_string_seconds("95w2d10h58m"), 57668280) self.assertEqual(convert_uptime_string_seconds("1h5m"), 3900) - def test_canonical_interface_name(self): - """Test the canonical_interface_name helper function.""" - self.assertEqual( - napalm.base.helpers.canonical_interface_name("Fa0/1"), "FastEthernet0/1" - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("FastEthernet0/1"), - "FastEthernet0/1", - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("TenGig1/1/1.5"), - "TenGigabitEthernet1/1/1.5", - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("Gi1/2"), "GigabitEthernet1/2" - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("HundredGigE105/1/1"), - "HundredGigabitEthernet105/1/1", - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("Lo0"), "Loopback0" - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("lo0"), "Loopback0" - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name("no_match0/1"), "no_match0/1" - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name( - "lo10", addl_name_map={"lo": "something_custom"} - ), - "something_custom10", - ) - self.assertEqual( - napalm.base.helpers.canonical_interface_name( - "uniq0/1/1", addl_name_map={"uniq": "something_custom"} - ), - "something_custom0/1/1", - ) - - def test_abbreviated_interface_name(self): - """Test the abbreviated_interface_name helper function.""" - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name("Fa0/1"), "Fa0/1" - ) - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name("FastEthernet0/1"), "Fa0/1" - ) - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name("TenGig1/1/1.5"), "Te1/1/1.5" - ) - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name("Gi1/2"), "Gi1/2" - ) - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name("HundredGigE105/1/1"), - "Hu105/1/1", - ) - self.assertEqual(napalm.base.helpers.abbreviated_interface_name("Lo0"), "Lo0") - self.assertEqual(napalm.base.helpers.abbreviated_interface_name("lo0"), "Lo0") - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name("something_custom0/1"), - "something_custom0/1", - ) - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name( - "loop10", addl_name_map={"loop": "Loopback"} - ), - "Lo10", - ) - self.assertEqual( - napalm.base.helpers.abbreviated_interface_name( - "loop10", - addl_name_map={"loop": "Loopback"}, - addl_reverse_map={"Loopback": "lo"}, - ), - "lo10", - ) - def test_netmiko_arguments(self): """Test the netmiko argument processing.""" self.assertEqual(netmiko_args(optional_args={}), {}) From 4af4391bdb85bc11f261afab2b1026e46350fac4 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 1 May 2023 10:01:59 -0700 Subject: [PATCH 58/71] get_bgp_config for Cisco when no BGP is configured (#1910) --- napalm/ios/ios.py | 39 +++-- .../no_bgp/expected_result.json | 1 + .../no_bgp/show_running_config.txt | 150 ++++++++++++++++++ 3 files changed, 175 insertions(+), 15 deletions(-) create mode 100644 test/ios/mocked_data/test_get_bgp_config/no_bgp/expected_result.json create mode 100644 test/ios/mocked_data/test_get_bgp_config/no_bgp/show_running_config.txt diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py index 7c01fc655..5e31c49f8 100644 --- a/napalm/ios/ios.py +++ b/napalm/ios/ios.py @@ -1463,6 +1463,11 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): bgp_config_list = napalm.base.helpers.netutils_parse_objects( "router bgp", cfg["running"] ) + + # No BGP configuration + if not bgp_config_list: + return {} + bgp_asn = napalm.base.helpers.regex_find_txt( r"router bgp (\d+)", bgp_config_list, default=0 ) @@ -1569,21 +1574,25 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): "route_reflector_client": route_reflector_client, } - bgp_config["_"] = { - "apply_groups": [], - "description": "", - "local_as": bgp_asn, - "type": "", - "import_policy": "", - "export_policy": "", - "local_address": "", - "multipath": False, - "multihop_ttl": 0, - "remote_as": 0, - "remove_private_as": False, - "prefix_limit": {}, - "neighbors": bgp_group_neighbors.get("_", {}), - } + # Do not include the no-group ("_") if a group argument is passed in + # unless group argument is "_" + if not group or group == "_": + bgp_config["_"] = { + "apply_groups": [], + "description": "", + "local_as": bgp_asn, + "type": "", + "import_policy": "", + "export_policy": "", + "local_address": "", + "multipath": False, + "multihop_ttl": 0, + "remote_as": 0, + "remove_private_as": False, + "prefix_limit": {}, + "neighbors": bgp_group_neighbors.get("_", {}), + } + # Get the peer-group level config for each group for group_name in bgp_group_neighbors.keys(): # If a group is passed in params, only continue on that group diff --git a/test/ios/mocked_data/test_get_bgp_config/no_bgp/expected_result.json b/test/ios/mocked_data/test_get_bgp_config/no_bgp/expected_result.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/ios/mocked_data/test_get_bgp_config/no_bgp/expected_result.json @@ -0,0 +1 @@ +{} diff --git a/test/ios/mocked_data/test_get_bgp_config/no_bgp/show_running_config.txt b/test/ios/mocked_data/test_get_bgp_config/no_bgp/show_running_config.txt new file mode 100644 index 000000000..50e08a544 --- /dev/null +++ b/test/ios/mocked_data/test_get_bgp_config/no_bgp/show_running_config.txt @@ -0,0 +1,150 @@ +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end From 27ccd5608b2425a9aaa3e04b85b88d93aa6c70d2 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Mon, 8 May 2023 17:38:46 +0200 Subject: [PATCH 59/71] Fix documentation of getter support matrix (#1913) Replace pytest-json with pytest-json-report and make modifications to support new format. --- .gitignore | 1 + docs/conf.py | 6 +++--- docs/test.sh | 6 +++--- requirements-dev.txt | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index a00f7f807..87330b57c 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ env test/unit/test_devices.py +.report.json report.json tags .pytest_cache/ diff --git a/docs/conf.py b/docs/conf.py index cf56e0537..d9b5774cd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -371,13 +371,13 @@ def build_getters_support_matrix(app): if not (m.startswith("_") or m in EXCLUDE_METHODS) } - regex_name = re.compile(r"(?P\w+)\/.*::test_(?P\w+)") + regex_name = re.compile(r"test.*/(?P\w+)\/.*::test_(?P\w+)") filename = "./support/tests/report.json" with open(filename, "r") as f: data = json.loads(f.read()) - for test in data["report"]["tests"]: - match = regex_name.search(test["name"]) + for test in data["tests"]: + match = regex_name.search(test["nodeid"]) if match: driver = match.group("driver") drivers.add(driver) diff --git a/docs/test.sh b/docs/test.sh index b911f782d..3d102c74a 100755 --- a/docs/test.sh +++ b/docs/test.sh @@ -3,10 +3,10 @@ CWD=`pwd` TEST_RESULTS_PATH="$CWD/support/tests" REPOBASE=$CWD/.. -if [ ! -f "report.json" ]; then +if [ ! -f ".report.json" ]; then set -e - py.test --rootdir $REPOBASE -c /dev/null --cov=./ -vs --json=report.json $REPOBASE/test*/*/test_getters.py + pytest --rootdir $REPOBASE -c /dev/null --json-report --cov=./ -vs $REPOBASE/test*/*/test_getters.py set -e - cp report.json $TEST_RESULTS_PATH/report.json + cp .report.json $TEST_RESULTS_PATH/report.json fi diff --git a/requirements-dev.txt b/requirements-dev.txt index 05a9f7a53..3d6b0cf20 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,7 +4,7 @@ ddt==1.6.0 flake8-import-order==0.18.2 pytest==7.2.2 pytest-cov==4.0.0 -pytest-json==0.4.0 +pytest-json-report==1.5.0 pyflakes==3.0.1 pylama==8.4.1 mock==5.0.1 From fa918367a0c6e533dbf50bd67d5ae67b8fef6ea4 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Mon, 8 May 2023 11:54:51 -0700 Subject: [PATCH 60/71] Pin docs dependencies to specific urllib3 version (#1915) --- docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index 482643959..24e3fa96b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,4 @@ +urllib3==1.26.15 # https://github.com/readthedocs/readthedocs.org/issues/10290 sphinx==1.8.6 sphinx-rtd-theme==1.2.0 sphinxcontrib-napoleon==0.7 From cb4845c40017a3e8e3c2b4e57838de2fd31a1348 Mon Sep 17 00:00:00 2001 From: Patrick Ogenstad Date: Fri, 12 May 2023 18:05:54 +0200 Subject: [PATCH 61/71] Update actions/checkout@v3 actions/setup-python@v4 (#1916) --- .github/workflows/commit.yaml | 8 ++++---- .github/workflows/pythonpublish.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index 94de245e9..0329a5554 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -14,10 +14,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -54,10 +54,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 12d829c1e..ed1ba114e 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -12,9 +12,9 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install dependencies From f1ce50eedbb2cf8b96d55002769ded54d68e1dd0 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Fri, 19 May 2023 13:04:50 -0700 Subject: [PATCH 62/71] EOS add force_cfg_session_invalid argument (#1927) Co-authored-by: Kevin Petremann --- docs/support/index.rst | 1 + napalm/eos/eos.py | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/support/index.rst b/docs/support/index.rst index 9fa7bd650..78ad1191a 100644 --- a/docs/support/index.rst +++ b/docs/support/index.rst @@ -141,6 +141,7 @@ ____________________________________ * :code:`eos_fn0039_config` (eos) - Transform old style configuration to the new style, available beginning with EOS release 4.23.0, as per FN 0039. Beware that enabling this option will change the configuration you're loading through NAPALM. Default: ``False`` (won't change your configuration commands). .. versionadded:: 3.0.1 +* :code:`force_cfg_session_invalid` (eos) - Force the config_session to be cleared in case of issues, like `discard_config` failure. (default: ``False``) The transport argument ______________________ diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index aaadec1c6..9f653850a 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -96,6 +96,8 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) Optional args: * lock_disable (True/False): force configuration lock to be disabled (for external lock management). + * force_cfg_session_invalid (True/False): force invalidation of the config session + in case of failure. * enable_password (True/False): Enable password for privilege elevation * eos_autoComplete (True/False): Allow for shortening of cli commands * transport (string): transport, eos_transport is a fallback for compatibility. @@ -134,6 +136,10 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) # Define locking method self.lock_disable = self.optional_args.pop("lock_disable", False) + self.force_cfg_session_invalid = self.optional_args.pop( + "force_cfg_session_invalid", False + ) + # eos_transport is there for backwards compatibility, transport is the preferred method transport = self.optional_args.get( "transport", self.optional_args.get("eos_transport", "https") @@ -150,7 +156,6 @@ def _process_optional_args_ssh(self, optional_args): self.netmiko_optional_args = netmiko_args(optional_args) def _process_optional_args_eapi(self, optional_args): - # Parse pyeapi transport class self.transport_class = self._parse_transport(self.transport) @@ -543,8 +548,15 @@ def confirm_commit(self): def discard_config(self): """Implementation of NAPALM method discard_config.""" if self.config_session is not None: - commands = [f"configure session {self.config_session} abort"] - self._run_commands(commands, encoding="text") + try: + commands = [f"configure session {self.config_session} abort"] + self._run_commands(commands, encoding="text") + except Exception: + # If discard fails, you might want to invalidate the config_session (esp. Salt) + # The config_session in EOS is used as the config lock. + if self.force_cfg_session_invalid: + self.config_session = None + raise self.config_session = None def rollback(self): From 40b1364e7c12e6bd3d6f7a0bedc6e3edb725f8a8 Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Mon, 15 May 2023 15:32:18 -0500 Subject: [PATCH 63/71] eos: refactor vrf parsing Add a fixed width table parser to base string utilities. Use the known dashed line to discern field widths of VRF text output. Use those values instead of TextFSM/regex parsing of the output to determine VRF RD and interface assignments. --- napalm/base/utils/string_parsers.py | 14 ++++++- napalm/eos/eos.py | 62 +++++++++++++++++++++-------- test/base/test_helpers.py | 36 ++++++++++++++++- 3 files changed, 93 insertions(+), 19 deletions(-) diff --git a/napalm/base/utils/string_parsers.py b/napalm/base/utils/string_parsers.py index 5e5df5f57..f14f10e8b 100644 --- a/napalm/base/utils/string_parsers.py +++ b/napalm/base/utils/string_parsers.py @@ -1,6 +1,7 @@ """ Common methods to normalize a string """ import re -from typing import Union, List, Iterable, Dict, Optional +import struct +from typing import Union, List, Iterable, Dict, Optional, Tuple def convert(text: str) -> Union[str, int]: @@ -133,3 +134,14 @@ def convert_uptime_string_seconds(uptime: str) -> int: raise Exception("Unrecognized uptime string:{}".format(uptime)) return uptime_seconds + + +def parse_fixed_width(text: str, *fields: int) -> List[Tuple[str, ...]]: + len = sum(fields) + fmtstring = " ".join(f"{fw}s" for fw in fields) + unpack = struct.Struct(fmtstring).unpack_from + + def parse(line: str) -> Tuple[str, ...]: + return tuple([str(s.decode()) for s in unpack(line.ljust(len).encode())]) + + return [parse(s) for s in text.splitlines()] diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index 9f653850a..3eb9935d8 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -2133,12 +2133,37 @@ def get_config(self, retrieve="all", full=False, sanitized=False): def _show_vrf(self): commands = ["show vrf"] - # This command has no JSON yet + # This command has no JSON in EOS < 4.23 raw_output = self._run_commands(commands, encoding="text")[0].get("output", "") - output = napalm.base.helpers.textfsm_extractor(self, "vrf", raw_output) + width_line = raw_output.splitlines()[2] # Line with dashes + fields = width_line.split(" ") + widths = [len(f) + 1 for f in fields] + widths[-1] -= 1 + + parsed_lines = string_parsers.parse_fixed_width(raw_output, *widths) + + vrfs = [] + vrf = {} + current_vrf = None + for line in parsed_lines[3:]: + line = [t.strip() for t in line] + if line[0]: + if current_vrf: + vrfs.append(vrf) + current_vrf = line[0] + vrf = { + "name": current_vrf, + "interfaces": list(), + } + if line[1]: + vrf["route_distinguisher"] = line[1] + if line[4]: + vrf["interfaces"].extend([t.strip() for t in line[4].split(",") if t]) + if current_vrf: + vrfs.append(vrf) - return output + return vrfs def _get_vrfs(self): output = self._show_vrf() @@ -2171,23 +2196,26 @@ def get_network_instances(self, name=""): interfaces[str(line.strip())] = {} all_vrf_interfaces[str(line.strip())] = {} - vrfs[str(vrf["name"])] = { - "name": str(vrf["name"]), - "type": "L3VRF", + vrfs[vrf["name"]] = { + "name": vrf["name"], + "type": "DEFAULT_INSTANCE" if vrf["name"] == "default" else "L3VRF", "state": {"route_distinguisher": vrf["route_distinguisher"]}, "interfaces": {"interface": interfaces}, } - all_interfaces = self.get_interfaces_ip().keys() - vrfs["default"] = { - "name": "default", - "type": "DEFAULT_INSTANCE", - "state": {"route_distinguisher": ""}, - "interfaces": { - "interface": { - k: {} for k in all_interfaces if k not in all_vrf_interfaces.keys() - } - }, - } + if "default" not in vrfs: + all_interfaces = self.get_interfaces_ip().keys() + vrfs["default"] = { + "name": "default", + "type": "DEFAULT_INSTANCE", + "state": {"route_distinguisher": ""}, + "interfaces": { + "interface": { + k: {} + for k in all_interfaces + if k not in all_vrf_interfaces.keys() + } + }, + } if name: if name in vrfs: diff --git a/test/base/test_helpers.py b/test/base/test_helpers.py index 96dbb86f5..cd2226877 100644 --- a/test/base/test_helpers.py +++ b/test/base/test_helpers.py @@ -57,7 +57,10 @@ from napalm.base.netmiko_helpers import netmiko_args import napalm.base.exceptions from napalm.base.base import NetworkDriver -from napalm.base.utils.string_parsers import convert_uptime_string_seconds +from napalm.base.utils.string_parsers import ( + convert_uptime_string_seconds, + parse_fixed_width, +) class TestBaseHelpers(unittest.TestCase): @@ -672,6 +675,37 @@ def test_ttp_parse(self): ) self.assertEqual(result, _EXPECTED_RESULT) + def test_parse_fixed_width(self): + _TEST_STRING = """ VRF RD Protocols State Interfaces +---------------- --------------- --------------- ------------------- --------------------------- +123456789012345671234567890123456123456789012345612345678901234567890123456789012345678901234567 +""" # noqa: E501 + _EXPECTED_RESULT = [ + ( + " VRF ", + " RD ", + " Protocols ", + " State ", + "Interfaces ", + ), + ( + "---------------- ", + "--------------- ", + "--------------- ", + "------------------- ", + "---------------------------", + ), + ( + "12345678901234567", + "1234567890123456", + "1234567890123456", + "12345678901234567890", + "123456789012345678901234567", + ), + ] + result = parse_fixed_width(_TEST_STRING, 17, 16, 16, 20, 27) + self.assertEqual(result, _EXPECTED_RESULT) + class FakeNetworkDriver(NetworkDriver): def __init__(self): From 8a9d43e36691a4d17f5c20d8ca4378e960bef714 Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Mon, 15 May 2023 16:41:32 -0500 Subject: [PATCH 64/71] eos: fix whitespace in test output for vrf I believe when I first collected the output for this test case 6 years ago, I didn't actually collect it from a router, and may have just copied an existing text file and edited it manually. This is an issue since we are trying to switch to fixed-width column parsing for the output. I have hand-edited it this time to match the format and spacing of the other test cases, as I do not have access to the router or config that was used as the source for this test case. --- .../issue-509/show_vrf.text | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/eos/mocked_data/test_get_network_instances/issue-509/show_vrf.text b/test/eos/mocked_data/test_get_network_instances/issue-509/show_vrf.text index e81cd6e11..65fdb6529 100644 --- a/test/eos/mocked_data/test_get_network_instances/issue-509/show_vrf.text +++ b/test/eos/mocked_data/test_get_network_instances/issue-509/show_vrf.text @@ -1,11 +1,11 @@ Maximum number of vrfs allowed: 14 - Vrf RD Protocols State Interfaces -------- ------------ ------------ ------------------- ------------------- -VRFA0 201:201 ipv4 v4:routing; multicast, Vlan2, Vlan102 - v6:no routing + Vrf RD Protocols State Interfaces +------- --------- ------------ ------------------------ ------------------- + VRFA0 201:201 ipv4 v4:routing; multicast, Vlan2, Vlan102 + v6:no routing -VRFA1 203:203 ipv4 v4:routing; multicast, Vlan3, Vlan103 - v6:no routing + VRFA1 203:203 ipv4 v4:routing; multicast, Vlan3, Vlan103 + v6:no routing -VRFA2 205:205 ipv4 v4:routing; multicast, Ethernet1, Vlan100 - v6:no routing + VRFA2 205:205 ipv4 v4:routing; multicast, Ethernet1, Vlan100 + v6:no routing From 333910e7ad9a3221876cf9ac28ae628d64abb4fd Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Mon, 15 May 2023 17:01:45 -0500 Subject: [PATCH 65/71] eos: add test case for issue 1922 --- .../issue-1922/expected_result.json | 30 +++++++++++++++++++ .../issue-1922/show_vrf.text | 12 ++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/eos/mocked_data/test_get_network_instances/issue-1922/expected_result.json create mode 100644 test/eos/mocked_data/test_get_network_instances/issue-1922/show_vrf.text diff --git a/test/eos/mocked_data/test_get_network_instances/issue-1922/expected_result.json b/test/eos/mocked_data/test_get_network_instances/issue-1922/expected_result.json new file mode 100644 index 000000000..413d219c4 --- /dev/null +++ b/test/eos/mocked_data/test_get_network_instances/issue-1922/expected_result.json @@ -0,0 +1,30 @@ +{ + "management": { + "name": "management", + "type": "L3VRF", + "state": { "route_distinguisher": "" }, + "interfaces": { "interface": { "Management1": {} } } + }, + "default": { + "interfaces": { + "interface": { + "Ethernet1": {}, + "Ethernet2": {}, + "Ethernet3": {}, + "Ethernet4": {}, + "Ethernet49/1": {}, + "Ethernet5": {}, + "Ethernet50/1": {}, + "Ethernet52/1": {}, + "Ethernet53/1": {}, + "Ethernet54/1": {}, + "Ethernet55/1": {}, + "Ethernet56/1": {}, + "Loopback0": {} + } + }, + "state": { "route_distinguisher": "" }, + "type": "DEFAULT_INSTANCE", + "name": "default" + } +} diff --git a/test/eos/mocked_data/test_get_network_instances/issue-1922/show_vrf.text b/test/eos/mocked_data/test_get_network_instances/issue-1922/show_vrf.text new file mode 100644 index 000000000..cd1dbbba4 --- /dev/null +++ b/test/eos/mocked_data/test_get_network_instances/issue-1922/show_vrf.text @@ -0,0 +1,12 @@ +Maximum number of vrfs allowed: 1023 + VRF RD Protocols State Interfaces +---------------- --------------- --------------- ------------------- --------------------------- + default ipv4,ipv6 v4:routing, Ethernet1, Ethernet2, + v6:no routing Ethernet3, Ethernet4, + Ethernet49/1, Ethernet5, + Ethernet50/1, Ethernet52/1, + Ethernet53/1, Ethernet54/1, + Ethernet55/1, Ethernet56/1, + Loopback0 + management ipv4,ipv6 v4:routing, Management1 + v6:no routing From 19622758791726773c0f26ca9adaf5bc4fb148bf Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Tue, 16 May 2023 16:45:47 -0500 Subject: [PATCH 66/71] eos: support setting cli_version in unit tests --- test/eos/conftest.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/eos/conftest.py b/test/eos/conftest.py index 7cf515f31..aff8e78a1 100644 --- a/test/eos/conftest.py +++ b/test/eos/conftest.py @@ -37,6 +37,19 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.patched_attrs = ["device"] self.device = FakeEOSDevice() + self._cli_version = 1 + + @property + def cli_version(self): + try: + full_path = self.device.find_file("cli_version.txt") + except IOError: + return self._cli_version + return int(self.device.read_txt_file(full_path)) + + @cli_version.setter + def cli_version(self, value): + self._cli_version = value class FakeEOSDevice(BaseTestDouble): From f9103a12ca344a3b85aa28ad71f11c8d8370113a Mon Sep 17 00:00:00 2001 From: Brandon Ewing Date: Tue, 16 May 2023 16:49:38 -0500 Subject: [PATCH 67/71] eos: support using json version of show vrf If version of EOS is new enough (>= 4.23.0), use the JSON output of "show vrf" to avoid issues with text parsing in 4.28+ Anecdotal evidence suggests that "default" was added to the text output of "show vrf" in 4.23, so this also resolves the double route issue in 1919. closes #1919 --- napalm/eos/eos.py | 21 ++++++- .../vrf/cli_version.txt | 1 + .../vrf/expected_result.json | 31 ++++++++++ .../vrf/show_vrf.json | 61 +++++++++++++++++++ 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 test/eos/mocked_data/test_get_network_instances/vrf/cli_version.txt create mode 100644 test/eos/mocked_data/test_get_network_instances/vrf/expected_result.json create mode 100644 test/eos/mocked_data/test_get_network_instances/vrf/show_vrf.json diff --git a/napalm/eos/eos.py b/napalm/eos/eos.py index 3eb9935d8..d5554f434 100644 --- a/napalm/eos/eos.py +++ b/napalm/eos/eos.py @@ -2130,7 +2130,20 @@ def get_config(self, retrieve="all", full=False, sanitized=False): else: raise Exception("Wrong retrieve filter: {}".format(retrieve)) - def _show_vrf(self): + def _show_vrf_json(self): + commands = ["show vrf"] + + vrfs = self._run_commands(commands)[0]["vrfs"] + return [ + { + "name": k, + "interfaces": [i for i in v["interfaces"]], + "route_distinguisher": v["routeDistinguisher"], + } + for k, v in vrfs.items() + ] + + def _show_vrf_text(self): commands = ["show vrf"] # This command has no JSON in EOS < 4.23 @@ -2165,6 +2178,12 @@ def _show_vrf(self): return vrfs + def _show_vrf(self): + if self.cli_version == 2: + return self._show_vrf_json() + else: + return self._show_vrf_text() + def _get_vrfs(self): output = self._show_vrf() diff --git a/test/eos/mocked_data/test_get_network_instances/vrf/cli_version.txt b/test/eos/mocked_data/test_get_network_instances/vrf/cli_version.txt new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/test/eos/mocked_data/test_get_network_instances/vrf/cli_version.txt @@ -0,0 +1 @@ +2 diff --git a/test/eos/mocked_data/test_get_network_instances/vrf/expected_result.json b/test/eos/mocked_data/test_get_network_instances/vrf/expected_result.json new file mode 100644 index 000000000..dc3f3d294 --- /dev/null +++ b/test/eos/mocked_data/test_get_network_instances/vrf/expected_result.json @@ -0,0 +1,31 @@ +{ + "default": { + "name": "default", + "type": "DEFAULT_INSTANCE", + "state": { "route_distinguisher": "" }, + "interfaces": { + "interface": { + "Ethernet1": {}, + "Ethernet2": {}, + "Loopback0": {}, + "Management0": {} + } + } + }, + "foo": { + "name": "foo", + "type": "L3VRF", + "state": { "route_distinguisher": "0:1" }, + "interfaces": { + "interface": {} + } + }, + "bar": { + "name": "bar", + "type": "L3VRF", + "state": { "route_distinguisher": "" }, + "interfaces": { + "interface": {} + } + } +} diff --git a/test/eos/mocked_data/test_get_network_instances/vrf/show_vrf.json b/test/eos/mocked_data/test_get_network_instances/vrf/show_vrf.json new file mode 100644 index 000000000..bbc04245a --- /dev/null +++ b/test/eos/mocked_data/test_get_network_instances/vrf/show_vrf.json @@ -0,0 +1,61 @@ +{ + "vrfs": { + "foo": { + "routeDistinguisher": "0:1", + "protocols": { + "ipv4": { + "supported": true, + "protocolState": "up", + "routingState": "up" + }, + "ipv6": { + "supported": true, + "protocolState": "up", + "routingState": "down" + } + }, + "vrfState": "up", + "interfacesV4": [], + "interfacesV6": [], + "interfaces": [] + }, + "bar": { + "routeDistinguisher": "", + "protocols": { + "ipv4": { + "supported": true, + "protocolState": "up", + "routingState": "down" + }, + "ipv6": { + "supported": true, + "protocolState": "up", + "routingState": "down" + } + }, + "vrfState": "up", + "interfacesV4": [], + "interfacesV6": [], + "interfaces": [] + }, + "default": { + "routeDistinguisher": "", + "protocols": { + "ipv4": { + "supported": true, + "protocolState": "up", + "routingState": "up" + }, + "ipv6": { + "supported": true, + "protocolState": "up", + "routingState": "down" + } + }, + "vrfState": "up", + "interfacesV4": ["Ethernet1", "Ethernet2", "Loopback0", "Management0"], + "interfacesV6": ["Management0"], + "interfaces": ["Ethernet1", "Ethernet2", "Loopback0", "Management0"] + } + } +} From 397d7f3605f15e31fb83eab1788a520cc6c511cc Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 23 May 2023 09:39:16 -0700 Subject: [PATCH 68/71] Fixing IOS-XR with no BGP configured (xml agent) (#1925) --- napalm/iosxr/iosxr.py | 7 +++++++ ...me___Naming___Instance___BGP___Configuration___Get_.txt | 2 ++ .../test_get_bgp_config/no_bgp/expected_result.json | 1 + 3 files changed, 10 insertions(+) create mode 100644 test/iosxr/mocked_data/test_get_bgp_config/no_bgp/_Get__Configuration__BGP__Instance__Naming__________InstanceName_default__InstanceName___Naming___Instance___BGP___Configuration___Get_.txt create mode 100644 test/iosxr/mocked_data/test_get_bgp_config/no_bgp/expected_result.json diff --git a/napalm/iosxr/iosxr.py b/napalm/iosxr/iosxr.py index 2ef1f6cb4..383e8ae00 100644 --- a/napalm/iosxr/iosxr.py +++ b/napalm/iosxr/iosxr.py @@ -987,6 +987,13 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): default" result_tree = ETREE.fromstring(self.device.make_rpc_call(rpc_command)) + # Check if BGP is not configured. + get_tag = result_tree.find("./Get") + if get_tag is not None: + bgp_not_found = get_tag.attrib.get("ItemNotFound") + if bgp_not_found: + return {} + bgp_asn = napalm.base.helpers.convert( int, napalm.base.helpers.find_txt( diff --git a/test/iosxr/mocked_data/test_get_bgp_config/no_bgp/_Get__Configuration__BGP__Instance__Naming__________InstanceName_default__InstanceName___Naming___Instance___BGP___Configuration___Get_.txt b/test/iosxr/mocked_data/test_get_bgp_config/no_bgp/_Get__Configuration__BGP__Instance__Naming__________InstanceName_default__InstanceName___Naming___Instance___BGP___Configuration___Get_.txt new file mode 100644 index 000000000..1bcd305b2 --- /dev/null +++ b/test/iosxr/mocked_data/test_get_bgp_config/no_bgp/_Get__Configuration__BGP__Instance__Naming__________InstanceName_default__InstanceName___Naming___Instance___BGP___Configuration___Get_.txt @@ -0,0 +1,2 @@ + +default diff --git a/test/iosxr/mocked_data/test_get_bgp_config/no_bgp/expected_result.json b/test/iosxr/mocked_data/test_get_bgp_config/no_bgp/expected_result.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/iosxr/mocked_data/test_get_bgp_config/no_bgp/expected_result.json @@ -0,0 +1 @@ +{} From b6de74e81db806670a165d7f0498c356f56840c7 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 23 May 2023 09:50:25 -0700 Subject: [PATCH 69/71] Implement no BGP for IOSXR-netconf (#1926) --- napalm/iosxr_netconf/iosxr_netconf.py | 8 +++++++- .../test_get_bgp_config/no_bgp/expected_result.json | 1 + .../no_bgp/ipv4-bgp-cfg_bgp__running.xml | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/expected_result.json create mode 100644 test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/ipv4-bgp-cfg_bgp__running.xml diff --git a/napalm/iosxr_netconf/iosxr_netconf.py b/napalm/iosxr_netconf/iosxr_netconf.py index 0640f4c82..ff7a06ef8 100644 --- a/napalm/iosxr_netconf/iosxr_netconf.py +++ b/napalm/iosxr_netconf/iosxr_netconf.py @@ -1366,6 +1366,12 @@ def build_prefix_limit(af_table, limit, prefix_percent, prefix_timeout): # Converts string to etree result_tree = ETREE.fromstring(rpc_reply) + data_ele = result_tree.find("./{*}data") + # If there are no children in "", then there is no BGP configured + bgp_configured = bool(len(data_ele.getchildren())) + if not bgp_configured: + return {} + if not group: neighbor = "" @@ -3148,7 +3154,7 @@ def get_config(self, retrieve="all", full=False, sanitized=False): if config[datastore] != "": if encoding == "cli": cli_tree = ETREE.XML(config[datastore], parser=parser)[0] - if cli_tree: + if len(cli_tree): config[datastore] = cli_tree[0].text.strip() else: config[datastore] = "" diff --git a/test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/expected_result.json b/test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/expected_result.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/expected_result.json @@ -0,0 +1 @@ +{} diff --git a/test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/ipv4-bgp-cfg_bgp__running.xml b/test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/ipv4-bgp-cfg_bgp__running.xml new file mode 100644 index 000000000..7a3a0b218 --- /dev/null +++ b/test/iosxr_netconf/mocked_data/test_get_bgp_config/no_bgp/ipv4-bgp-cfg_bgp__running.xml @@ -0,0 +1,6 @@ + + + + From c2d2e2063bb8bec8e9a06938306a98a35dbbe6e4 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 23 May 2023 10:11:34 -0700 Subject: [PATCH 70/71] Fix dependabot issues (#1934) --- requirements-dev.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 3d6b0cf20..62923790b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,16 +2,16 @@ black==22.6.0 coveralls==3.3.1 ddt==1.6.0 flake8-import-order==0.18.2 -pytest==7.2.2 +pytest==7.3.1 pytest-cov==4.0.0 pytest-json-report==1.5.0 pyflakes==3.0.1 pylama==8.4.1 -mock==5.0.1 +mock==5.0.2 mypy==0.982 -types-PyYAML==6.0.12.8 +types-PyYAML==6.0.12.10 types-requests==2.28.11.17 -types-six==1.16.21.7 -types-setuptools==67.6.0.5 -ttp==0.9.0 -ttp_templates==0.3.4 +types-six==1.16.21.8 +types-setuptools==67.8.0.0 +ttp==0.9.4 +ttp_templates==0.3.5 From 26b7bfb9c4affe8f2f9408f933d28b24520a655a Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 23 May 2023 10:23:36 -0700 Subject: [PATCH 71/71] NAPALM 4.1.0 (#1935) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9eb0865d0..0a3bbe374 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="napalm", - version="4.0.0", + version="4.1.0", packages=find_packages(exclude=("test*",)), test_suite="test_base", author="David Barroso, Kirk Byers, Mircea Ulinic",