diff --git a/show/main.py b/show/main.py index 0c9fd46703..e8c607facc 100755 --- a/show/main.py +++ b/show/main.py @@ -1439,10 +1439,40 @@ def ports(portname, verbose): # 'bgp' subcommand ("show runningconfiguration bgp") @runningconfiguration.command() @click.option('--verbose', is_flag=True, help="Enable verbose output") -def bgp(verbose): - """Show BGP running configuration""" - cmd = 'sudo {} -c "show running-config"'.format(constants.RVTYSH_COMMAND) - run_command(cmd, display_cmd=verbose) +@click.option('--namespace', '-n', 'namespace', required=False, default=None, type=str, show_default=False, + help='Option needed for multi-asic only: provide namespace name', + callback=multi_asic_util.multi_asic_namespace_validation_callback) +def bgp(namespace, verbose): + """ + Show BGP running configuration + Note: + multi-asic can run 'show run bgp' and show from all asics, or 'show run bgp -n ' + single-asic only run 'show run bgp', '-n' is not available + """ + + if multi_asic.is_multi_asic(): + if namespace and namespace not in multi_asic.get_namespace_list(): + ctx = click.get_current_context() + ctx.fail("invalid value for -n/--namespace option. provide namespace from list {}".format(multi_asic.get_namespace_list())) + if not multi_asic.is_multi_asic() and namespace: + ctx = click.get_current_context() + ctx.fail("-n/--namespace is not available for single asic") + + output = "" + cmd = "show running-config bgp" + import utilities_common.bgp_util as bgp_util + if multi_asic.is_multi_asic(): + if not namespace: + ns_list = multi_asic.get_namespace_list() + for ns in ns_list: + output += "\n------------Showing running config bgp on {}------------\n".format(ns) + output += bgp_util.run_bgp_show_command(cmd, ns) + else: + output += "\n------------Showing running config bgp on {}------------\n".format(namespace) + output += bgp_util.run_bgp_show_command(cmd, namespace) + else: + output += bgp_util.run_bgp_show_command(cmd) + print(output) # 'interfaces' subcommand ("show runningconfiguration interfaces") diff --git a/tests/conftest.py b/tests/conftest.py index 96b80df3e1..bf4c2a401f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -169,6 +169,9 @@ def setup_single_bgp_instance(request): elif request.param == 'v6': bgp_mocked_json = os.path.join( test_path, 'mock_tables', 'ipv6_bgp_summary.json') + elif request.param == 'show_run_bgp': + bgp_mocked_json = os.path.join( + test_path, 'mock_tables', 'show_run_bgp.txt') elif request.param == 'ip_route': bgp_mocked_json = 'ip_route.json' elif request.param == 'ip_specific_route': @@ -193,6 +196,13 @@ def mock_show_bgp_summary(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RV return mock_frr_data return "" + def mock_show_run_bgp(request): + if os.path.isfile(bgp_mocked_json): + with open(bgp_mocked_json) as json_data: + mock_frr_data = json_data.read() + return mock_frr_data + return "" + def mock_run_bgp_command_for_static(vtysh_cmd, bgp_namespace="", vtysh_shell_cmd=constants.RVTYSH_COMMAND): if vtysh_cmd == "show ip route vrf all static": return config_int_ip_common.show_ip_route_with_static_expected_output @@ -239,6 +249,9 @@ def mock_run_bgp_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVT elif request.param == "show_bgp_summary_no_neigh": bgp_util.run_bgp_command = mock.MagicMock( return_value=mock_show_bgp_summary_no_neigh("", "")) + elif request.param.startswith('show_run_bgp'): + bgp_util.run_bgp_command = mock.MagicMock( + return_value=mock_show_run_bgp(request)) else: bgp_util.run_bgp_command = mock.MagicMock( return_value=mock_show_bgp_summary("", "")) @@ -270,6 +283,10 @@ def setup_multi_asic_bgp_instance(request): m_asic_json_file = 'ip_special_recursive_route.json' elif request.param == 'ip_route_summary': m_asic_json_file = 'ip_route_summary.txt' + elif request.param == 'show_run_bgp': + m_asic_json_file = 'show_run_bgp.txt' + elif request.param == 'show_not_running_bgp': + m_asic_json_file = 'show_not_running_bgp.txt' elif request.param.startswith('bgp_v4_network') or \ request.param.startswith('bgp_v6_network') or \ request.param.startswith('bgp_v4_neighbor') or \ diff --git a/tests/mock_tables/asic0/show_not_running_bgp.txt b/tests/mock_tables/asic0/show_not_running_bgp.txt new file mode 100644 index 0000000000..b156e857f1 --- /dev/null +++ b/tests/mock_tables/asic0/show_not_running_bgp.txt @@ -0,0 +1 @@ +Error response from daemon: Container 70e3d3bafd1ab5faf796892acff3e2ccbea3dcd5dcfefcc34f25f7cc916b67bb is not running diff --git a/tests/mock_tables/asic0/show_run_bgp.txt b/tests/mock_tables/asic0/show_run_bgp.txt new file mode 100644 index 0000000000..e5c9a9982c --- /dev/null +++ b/tests/mock_tables/asic0/show_run_bgp.txt @@ -0,0 +1,12 @@ +neighbor 10.0.0.1 remote-as 65200 +neighbor 10.0.0.1 peer-group TIER2_V4 +neighbor 10.0.0.1 description ARISTA01T2 +neighbor 10.0.0.5 remote-as 65200 +neighbor 10.0.0.5 peer-group TIER2_V4 +neighbor 10.0.0.5 description ARISTA03T2 +neighbor fc00::2 remote-as 65200 +neighbor fc00::2 peer-group TIER2_V6 +neighbor fc00::2 description ARISTA01T2 +neighbor fc00::6 remote-as 65200 +neighbor fc00::6 peer-group TIER2_V6 +neighbor fc00::6 description ARISTA03T2 diff --git a/tests/mock_tables/asic1/show_run_bgp.txt b/tests/mock_tables/asic1/show_run_bgp.txt new file mode 100644 index 0000000000..de81748cc6 --- /dev/null +++ b/tests/mock_tables/asic1/show_run_bgp.txt @@ -0,0 +1,12 @@ +neighbor 10.0.0.9 remote-as 65200 +neighbor 10.0.0.9 peer-group TIER2_V4 +neighbor 10.0.0.9 description ARISTA05T2 +neighbor 10.0.0.13 remote-as 65200 +neighbor 10.0.0.13 peer-group TIER2_V4 +neighbor 10.0.0.13 description ARISTA07T2 +neighbor fc00::a remote-as 65200 +neighbor fc00::a peer-group TIER2_V6 +neighbor fc00::a description ARISTA05T2 +neighbor fc00::e remote-as 65200 +neighbor fc00::e peer-group TIER2_V6 +neighbor fc00::e description ARISTA07T2 diff --git a/tests/mock_tables/show_run_bgp.txt b/tests/mock_tables/show_run_bgp.txt new file mode 100644 index 0000000000..9a3ae8b13e --- /dev/null +++ b/tests/mock_tables/show_run_bgp.txt @@ -0,0 +1,64 @@ +router bgp 65100 +bgp router-id 10.1.0.32 +bgp log-neighbor-changes +no bgp ebgp-requires-policy +no bgp default ipv4-unicast +bgp graceful-restart restart-time 240 +bgp graceful-restart select-defer-time 45 +bgp graceful-restart +bgp graceful-restart preserve-fw-state +bgp bestpath as-path multipath-relax +neighbor BGPSLBPassive peer-group +neighbor BGPSLBPassive remote-as 65432 +neighbor BGPSLBPassive passive +neighbor BGPSLBPassive ebgp-multihop 255 +neighbor BGPSLBPassive update-source 10.1.0.32 +neighbor BGPVac peer-group +neighbor BGPVac remote-as 65432 +neighbor BGPVac passive +neighbor BGPVac ebgp-multihop 255 +neighbor BGPVac update-source 10.1.0.32 +neighbor PEER_V4 peer-group +neighbor PEER_V6 peer-group +neighbor 10.0.0.57 remote-as 64600 +neighbor 10.0.0.57 peer-group PEER_V4 +neighbor 10.0.0.57 description ARISTA01T1 +neighbor 10.0.0.57 timers 3 10 +neighbor 10.0.0.57 timers connect 10 +neighbor 10.0.0.59 remote-as 64600 +neighbor 10.0.0.59 peer-group PEER_V4 +neighbor 10.0.0.59 description ARISTA02T1 +neighbor 10.0.0.59 timers 3 10 +neighbor 10.0.0.59 timers connect 10 +neighbor 10.0.0.61 remote-as 64600 +neighbor 10.0.0.61 peer-group PEER_V4 +neighbor 10.0.0.61 description ARISTA03T1 +neighbor 10.0.0.61 timers 3 10 +neighbor 10.0.0.61 timers connect 10 +neighbor 10.0.0.63 remote-as 64600 +neighbor 10.0.0.63 peer-group PEER_V4 +neighbor 10.0.0.63 description ARISTA04T1 +neighbor 10.0.0.63 timers 3 10 +neighbor 10.0.0.63 timers connect 10 +neighbor fc00::72 remote-as 64600 +neighbor fc00::72 peer-group PEER_V6 +neighbor fc00::72 description ARISTA01T1 +neighbor fc00::72 timers 3 10 +neighbor fc00::72 timers connect 10 +neighbor fc00::76 remote-as 64600 +neighbor fc00::76 peer-group PEER_V6 +neighbor fc00::76 description ARISTA02T1 +neighbor fc00::76 timers 3 10 +neighbor fc00::76 timers connect 10 +neighbor fc00::7a remote-as 64600 +neighbor fc00::7a peer-group PEER_V6 +neighbor fc00::7a description ARISTA03T1 +neighbor fc00::7a timers 3 10 +neighbor fc00::7a timers connect 10 +neighbor fc00::7e remote-as 64600 +neighbor fc00::7e peer-group PEER_V6 +neighbor fc00::7e description ARISTA04T1 +neighbor fc00::7e timers 3 10 +neighbor fc00::7e timers connect 10 +bgp listen range 10.255.0.0/25 peer-group BGPSLBPassive +bgp listen range 192.168.0.0/21 peer-group BGPVac diff --git a/tests/show_run_bgp_test.py b/tests/show_run_bgp_test.py new file mode 100644 index 0000000000..4d3ff843a0 --- /dev/null +++ b/tests/show_run_bgp_test.py @@ -0,0 +1,228 @@ +import os +import pytest +import importlib +from click.testing import CliRunner + +from utilities_common import multi_asic +from utilities_common import constants + +from unittest.mock import patch + +from sonic_py_common import device_info +import show.main as show + + +show_run_bgp_sasic = \ +"""router bgp 65100 +bgp router-id 10.1.0.32 +bgp log-neighbor-changes +no bgp ebgp-requires-policy +no bgp default ipv4-unicast +bgp graceful-restart restart-time 240 +bgp graceful-restart select-defer-time 45 +bgp graceful-restart +bgp graceful-restart preserve-fw-state +bgp bestpath as-path multipath-relax +neighbor BGPSLBPassive peer-group +neighbor BGPSLBPassive remote-as 65432 +neighbor BGPSLBPassive passive +neighbor BGPSLBPassive ebgp-multihop 255 +neighbor BGPSLBPassive update-source 10.1.0.32 +neighbor BGPVac peer-group +neighbor BGPVac remote-as 65432 +neighbor BGPVac passive +neighbor BGPVac ebgp-multihop 255 +neighbor BGPVac update-source 10.1.0.32 +neighbor PEER_V4 peer-group +neighbor PEER_V6 peer-group +neighbor 10.0.0.57 remote-as 64600 +neighbor 10.0.0.57 peer-group PEER_V4 +neighbor 10.0.0.57 description ARISTA01T1 +neighbor 10.0.0.57 timers 3 10 +neighbor 10.0.0.57 timers connect 10 +neighbor 10.0.0.59 remote-as 64600 +neighbor 10.0.0.59 peer-group PEER_V4 +neighbor 10.0.0.59 description ARISTA02T1 +neighbor 10.0.0.59 timers 3 10 +neighbor 10.0.0.59 timers connect 10 +neighbor 10.0.0.61 remote-as 64600 +neighbor 10.0.0.61 peer-group PEER_V4 +neighbor 10.0.0.61 description ARISTA03T1 +neighbor 10.0.0.61 timers 3 10 +neighbor 10.0.0.61 timers connect 10 +neighbor 10.0.0.63 remote-as 64600 +neighbor 10.0.0.63 peer-group PEER_V4 +neighbor 10.0.0.63 description ARISTA04T1 +neighbor 10.0.0.63 timers 3 10 +neighbor 10.0.0.63 timers connect 10 +neighbor fc00::72 remote-as 64600 +neighbor fc00::72 peer-group PEER_V6 +neighbor fc00::72 description ARISTA01T1 +neighbor fc00::72 timers 3 10 +neighbor fc00::72 timers connect 10 +neighbor fc00::76 remote-as 64600 +neighbor fc00::76 peer-group PEER_V6 +neighbor fc00::76 description ARISTA02T1 +neighbor fc00::76 timers 3 10 +neighbor fc00::76 timers connect 10 +neighbor fc00::7a remote-as 64600 +neighbor fc00::7a peer-group PEER_V6 +neighbor fc00::7a description ARISTA03T1 +neighbor fc00::7a timers 3 10 +neighbor fc00::7a timers connect 10 +neighbor fc00::7e remote-as 64600 +neighbor fc00::7e peer-group PEER_V6 +neighbor fc00::7e description ARISTA04T1 +neighbor fc00::7e timers 3 10 +neighbor fc00::7e timers connect 10 +bgp listen range 10.255.0.0/25 peer-group BGPSLBPassive +bgp listen range 192.168.0.0/21 peer-group BGPVac + +""" + +show_run_bgp_masic = \ +""" +------------Showing running config bgp on asic0------------ +neighbor 10.0.0.1 remote-as 65200 +neighbor 10.0.0.1 peer-group TIER2_V4 +neighbor 10.0.0.1 description ARISTA01T2 +neighbor 10.0.0.5 remote-as 65200 +neighbor 10.0.0.5 peer-group TIER2_V4 +neighbor 10.0.0.5 description ARISTA03T2 +neighbor fc00::2 remote-as 65200 +neighbor fc00::2 peer-group TIER2_V6 +neighbor fc00::2 description ARISTA01T2 +neighbor fc00::6 remote-as 65200 +neighbor fc00::6 peer-group TIER2_V6 +neighbor fc00::6 description ARISTA03T2 + +------------Showing running config bgp on asic1------------ +neighbor 10.0.0.9 remote-as 65200 +neighbor 10.0.0.9 peer-group TIER2_V4 +neighbor 10.0.0.9 description ARISTA05T2 +neighbor 10.0.0.13 remote-as 65200 +neighbor 10.0.0.13 peer-group TIER2_V4 +neighbor 10.0.0.13 description ARISTA07T2 +neighbor fc00::a remote-as 65200 +neighbor fc00::a peer-group TIER2_V6 +neighbor fc00::a description ARISTA05T2 +neighbor fc00::e remote-as 65200 +neighbor fc00::e peer-group TIER2_V6 +neighbor fc00::e description ARISTA07T2 + +""" + +show_run_bgp_masic_asic0 = \ +""" +------------Showing running config bgp on asic0------------ +neighbor 10.0.0.1 remote-as 65200 +neighbor 10.0.0.1 peer-group TIER2_V4 +neighbor 10.0.0.1 description ARISTA01T2 +neighbor 10.0.0.5 remote-as 65200 +neighbor 10.0.0.5 peer-group TIER2_V4 +neighbor 10.0.0.5 description ARISTA03T2 +neighbor fc00::2 remote-as 65200 +neighbor fc00::2 peer-group TIER2_V6 +neighbor fc00::2 description ARISTA01T2 +neighbor fc00::6 remote-as 65200 +neighbor fc00::6 peer-group TIER2_V6 +neighbor fc00::6 description ARISTA03T2 + +""" + +show_run_bgp_not_running = \ +""" +------------Showing running config bgp on asic0------------ +Error response from daemon: Container 70e3d3bafd1ab5faf796892acff3e2ccbea3dcd5dcfefcc34f25f7cc916b67bb is not running + +""" + +class TestShowRunBgpSingleAsic(object): + @classmethod + def setup_class(cls): + print("SETUP") + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_namespace_config() + + @pytest.mark.parametrize('setup_single_bgp_instance', + [ + 'show_run_bgp', + ], + indirect=['setup_single_bgp_instance']) + + def test_show_run_bgp_single(self, + setup_single_bgp_instance): + runner = CliRunner() + result = runner.invoke(show.cli.commands["runningconfiguration"].commands["bgp"], []) + print("{}".format(result.output)) + assert result.exit_code == 0 + assert result.output == show_run_bgp_sasic + + @classmethod + def teardown_class(cls): + print("TEARDOWN") + os.environ['UTILITIES_UNIT_TESTING'] = "0" + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_database_config() + + +class TestShowRunBgpMultiAsic(object): + @classmethod + def setup_class(cls): + print("SETUP") + from .mock_tables import mock_multi_asic + importlib.reload(mock_multi_asic) + from .mock_tables import dbconnector + dbconnector.load_namespace_config() + + @pytest.mark.parametrize('setup_multi_asic_bgp_instance', + [ + 'show_run_bgp', + ], + indirect=['setup_multi_asic_bgp_instance']) + def test_show_run_bgp_all_asics(self, + setup_multi_asic_bgp_instance): + runner = CliRunner() + result = runner.invoke(show.cli.commands["runningconfiguration"].commands["bgp"], []) + print("{}".format(result.output)) + assert result.exit_code == 0 + assert result.output == show_run_bgp_masic + + + @pytest.mark.parametrize('setup_multi_asic_bgp_instance', + [ + 'show_run_bgp', + ], + indirect=['setup_multi_asic_bgp_instance']) + def test_show_run_bgp_asic0(self, + setup_multi_asic_bgp_instance): + runner = CliRunner() + result = runner.invoke(show.cli.commands["runningconfiguration"].commands["bgp"], ["-nasic0"]) + print("{}".format(result.output)) + assert result.exit_code == 0 + assert result.output == show_run_bgp_masic_asic0 + + @pytest.mark.parametrize('setup_multi_asic_bgp_instance', + [ + 'show_not_running_bgp', + ], + indirect=['setup_multi_asic_bgp_instance']) + def test_bgp0_not_running(self, + setup_multi_asic_bgp_instance): + runner = CliRunner() + result = runner.invoke(show.cli.commands["runningconfiguration"].commands["bgp"], ["-nasic0"]) + print("{}".format(result.output)) + assert result.exit_code == 0 + assert result.output == show_run_bgp_not_running + + @classmethod + def teardown_class(cls): + print("TEARDOWN") + from .mock_tables import mock_single_asic + importlib.reload(mock_single_asic) + from .mock_tables import dbconnector + dbconnector.load_database_config