From 69d348d1bc71429ac6cce5137a86dfa9d10f6234 Mon Sep 17 00:00:00 2001 From: Dev Ojha <47282568+developfast@users.noreply.github.com> Date: Tue, 4 Jul 2023 13:37:30 -0700 Subject: [PATCH] [CLI][Show][BGP] Show BGP Change for no neighbor scenario (#2885) --- tests/bgp_commands_test.py | 135 +++++++++++++++++-- tests/conftest.py | 52 ++++--- tests/mock_tables/asic0/device_bgp_info.json | 30 +++++ tests/mock_tables/asic0/no_bgp_neigh.json | 1 + tests/mock_tables/asic1/device_bgp_info.json | 30 +++++ tests/mock_tables/asic1/no_bgp_neigh.json | 1 + tests/mock_tables/device_bgp_info.json | 30 +++++ tests/mock_tables/no_bgp_neigh.json | 1 + utilities_common/bgp_util.py | 122 ++++++++++------- 9 files changed, 329 insertions(+), 73 deletions(-) create mode 100644 tests/mock_tables/asic0/device_bgp_info.json create mode 100644 tests/mock_tables/asic0/no_bgp_neigh.json create mode 100644 tests/mock_tables/asic1/device_bgp_info.json create mode 100644 tests/mock_tables/asic1/no_bgp_neigh.json create mode 100644 tests/mock_tables/device_bgp_info.json create mode 100644 tests/mock_tables/no_bgp_neigh.json diff --git a/tests/bgp_commands_test.py b/tests/bgp_commands_test.py index 67c05a2fd3..837ced3bcc 100644 --- a/tests/bgp_commands_test.py +++ b/tests/bgp_commands_test.py @@ -1,6 +1,7 @@ import os import pytest +import importlib from click.testing import CliRunner @@ -97,12 +98,72 @@ Error: bgp summary from bgp container not in json format """ -show_error_no_v6_neighbor = """\ -No IPv6 neighbor is configured +show_error_no_v6_neighbor_single_asic = """\ + +IPv6 Unicast Summary: +BGP router identifier 10.1.0.32, local AS number 65100 vrf-id 0 +BGP table version 8972 +RIB entries 0, using 0 bytes of memory +Peers 0, using 0 KiB of memory +Peer groups 0, using 0 bytes of memory + + +Neighbhor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd NeighborName +----------- --- ---- --------- --------- -------- ----- ------ --------- -------------- -------------- + +Total number of neighbors 0 +""" + +show_error_no_v4_neighbor_single_asic = """\ + +IPv4 Unicast Summary: +BGP router identifier 10.1.0.32, local AS number 65100 vrf-id 0 +BGP table version 8972 +RIB entries 0, using 0 bytes of memory +Peers 0, using 0 KiB of memory +Peer groups 0, using 0 bytes of memory + + +Neighbhor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd NeighborName +----------- --- ---- --------- --------- -------- ----- ------ --------- -------------- -------------- + +Total number of neighbors 0 """ -show_error_no_v4_neighbor = """\ -No IPv4 neighbor is configured +show_error_no_v6_neighbor_multi_asic = """\ + +IPv6 Unicast Summary: +asic0: BGP router identifier 10.1.0.32, local AS number 65100 vrf-id 0 +BGP table version 8972 +asic1: BGP router identifier 10.1.0.32, local AS number 65100 vrf-id 0 +BGP table version 8972 +RIB entries 0, using 0 bytes of memory +Peers 0, using 0 KiB of memory +Peer groups 0, using 0 bytes of memory + + +Neighbhor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd NeighborName +----------- --- ---- --------- --------- -------- ----- ------ --------- -------------- -------------- + +Total number of neighbors 0 +""" + +show_error_no_v4_neighbor_multi_asic = """\ + +IPv4 Unicast Summary: +asic0: BGP router identifier 10.1.0.32, local AS number 65100 vrf-id 0 +BGP table version 8972 +asic1: BGP router identifier 10.1.0.32, local AS number 65100 vrf-id 0 +BGP table version 8972 +RIB entries 0, using 0 bytes of memory +Peers 0, using 0 KiB of memory +Peer groups 0, using 0 bytes of memory + + +Neighbhor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd NeighborName +----------- --- ---- --------- --------- -------- ----- ------ --------- -------------- -------------- + +Total number of neighbors 0 """ show_bgp_summary_v4_chassis = """\ @@ -217,11 +278,14 @@ """ -class TestBgpCommands(object): +class TestBgpCommandsSingleAsic(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', ['v4'], indirect=['setup_single_bgp_instance']) @@ -337,10 +401,10 @@ def test_bgp_summary_no_v4_neigh( show = setup_bgp_commands runner = CliRunner() result = runner.invoke( - show.cli.commands["ipv6"].commands["bgp"].commands["summary"], []) + show.cli.commands["ip"].commands["bgp"].commands["summary"], []) print("{}".format(result.output)) assert result.exit_code == 0 - assert result.output == show_error_no_v6_neighbor + assert result.output == show_error_no_v4_neighbor_single_asic @pytest.mark.parametrize('setup_single_bgp_instance', ['show_bgp_summary_no_neigh'], indirect=['setup_single_bgp_instance']) @@ -350,8 +414,63 @@ def test_bgp_summary_no_v6_neigh( setup_single_bgp_instance): show = setup_bgp_commands runner = CliRunner() + result = runner.invoke( + show.cli.commands["ipv6"].commands["bgp"].commands["summary"], []) + print("{}".format(result.output)) + assert result.exit_code == 0 + assert result.output == show_error_no_v6_neighbor_single_asic + + @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 TestBgpCommandsMultiAsic(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_bgp_summary_no_neigh'], indirect=['setup_multi_asic_bgp_instance']) + def test_bgp_summary_multi_asic_no_v4_neigh( + self, + setup_bgp_commands, + setup_multi_asic_bgp_instance): + show = setup_bgp_commands + runner = CliRunner() result = runner.invoke( show.cli.commands["ip"].commands["bgp"].commands["summary"], []) print("{}".format(result.output)) assert result.exit_code == 0 - assert result.output == show_error_no_v4_neighbor + assert result.output == show_error_no_v4_neighbor_multi_asic + + @pytest.mark.parametrize('setup_multi_asic_bgp_instance', + ['show_bgp_summary_no_neigh'], indirect=['setup_multi_asic_bgp_instance']) + def test_bgp_summary_multi_asic_no_v6_neigh( + self, + setup_bgp_commands, + setup_multi_asic_bgp_instance): + show = setup_bgp_commands + runner = CliRunner() + result = runner.invoke( + show.cli.commands["ipv6"].commands["bgp"].commands["summary"], []) + print("{}".format(result.output)) + assert result.exit_code == 0 + assert result.output == show_error_no_v6_neighbor_multi_asic + + @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 diff --git a/tests/conftest.py b/tests/conftest.py index 6e70f8c9aa..e6e5468d39 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -170,6 +170,11 @@ 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_bgp_summary_no_neigh': + bgp_neigh_mocked_json = os.path.join( + test_path, 'mock_tables', 'no_bgp_neigh.json') + bgp_mocked_json = os.path.join( + test_path, 'mock_tables', 'device_bgp_info.json') elif request.param == 'show_run_bgp': bgp_mocked_json = os.path.join( test_path, 'mock_tables', 'show_run_bgp.txt') @@ -187,12 +192,9 @@ def setup_single_bgp_instance(request): bgp_mocked_json = os.path.join( test_path, 'mock_tables', 'dummy.json') - def mock_show_bgp_summary_no_neigh(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVTYSH_COMMAND): - return "{}" - - def mock_show_bgp_summary(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVTYSH_COMMAND): - if os.path.isfile(bgp_mocked_json): - with open(bgp_mocked_json) as json_data: + def mock_run_bgp_command(mock_bgp_file): + if os.path.isfile(mock_bgp_file): + with open(mock_bgp_file) as json_data: mock_frr_data = json_data.read() return mock_frr_data return "" @@ -218,7 +220,7 @@ def mock_run_show_ip_route_commands(request): else: return "" - def mock_run_bgp_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVTYSH_COMMAND): + def mock_run_bgp_route_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVTYSH_COMMAND): bgp_mocked_json_file = os.path.join( test_path, 'mock_tables', bgp_mocked_json) if os.path.isfile(bgp_mocked_json_file): @@ -229,11 +231,11 @@ def mock_run_bgp_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVT return "" _old_run_bgp_command = bgp_util.run_bgp_command - if any ([request.param == 'ip_route',\ - request.param == 'ip_specific_route', request.param == 'ip_special_route',\ - request.param == 'ipv6_route', request.param == 'ipv6_specific_route']): + if any([request.param == 'ip_route', + request.param == 'ip_specific_route', request.param == 'ip_special_route', + request.param == 'ipv6_route', request.param == 'ipv6_specific_route']): bgp_util.run_bgp_command = mock.MagicMock( - return_value=mock_run_bgp_command("","")) + return_value=mock_run_bgp_route_command("", "")) elif request.param.startswith('ipv6_route_err'): bgp_util.run_bgp_command = mock.MagicMock( return_value=mock_run_show_ip_route_commands(request)) @@ -242,20 +244,21 @@ def mock_run_bgp_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVT bgp_util.run_bgp_command = mock.MagicMock( return_value=mock_show_bgp_neighbor_single_asic(request)) elif request.param.startswith('bgp_v4_network') or \ - request.param.startswith('bgp_v6_network'): + request.param.startswith('bgp_v6_network'): bgp_util.run_bgp_command = mock.MagicMock( return_value=mock_show_bgp_network_single_asic(request)) elif request.param == 'ip_route_for_int_ip': bgp_util.run_bgp_command = mock_run_bgp_command_for_static - 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)) + elif request.param == 'show_bgp_summary_no_neigh': + functions_to_call = [mock_run_bgp_command(bgp_neigh_mocked_json), mock_run_bgp_command(bgp_mocked_json)] + bgp_util.run_bgp_command = mock.MagicMock( + side_effect=functions_to_call) else: bgp_util.run_bgp_command = mock.MagicMock( - return_value=mock_show_bgp_summary("", "")) + return_value=mock_run_bgp_command(bgp_mocked_json)) yield @@ -325,9 +328,26 @@ def mock_run_bgp_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.RVT else: return "" + def mock_run_show_sum_bgp_command(vtysh_cmd, bgp_namespace, vtysh_shell_cmd=constants.VTYSH_COMMAND): + if vtysh_cmd == "show ip bgp summary json": + m_asic_json_file = 'no_bgp_neigh.json' + else: + m_asic_json_file = 'device_bgp_info.json' + + bgp_mocked_json = os.path.join( + test_path, 'mock_tables', bgp_namespace, m_asic_json_file) + 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 + else: + return "" + _old_run_bgp_command = bgp_util.run_bgp_command if request.param == 'ip_route_for_int_ip': bgp_util.run_bgp_command = mock_run_bgp_command_for_static + elif request.param == 'show_bgp_summary_no_neigh': + bgp_util.run_bgp_command = mock_run_show_sum_bgp_command else: bgp_util.run_bgp_command = mock_run_bgp_command diff --git a/tests/mock_tables/asic0/device_bgp_info.json b/tests/mock_tables/asic0/device_bgp_info.json new file mode 100644 index 0000000000..5bc28cf8e5 --- /dev/null +++ b/tests/mock_tables/asic0/device_bgp_info.json @@ -0,0 +1,30 @@ +{ +"vrfId": 0, +"vrfName": "default", +"tableVersion": 8972, +"routerId": "10.1.0.32", +"defaultLocPrf": 100, +"localAS": 65100, +"routes": { "10.1.0.32/32": [ + { + "valid":true, + "bestpath":true, + "pathFrom":"external", + "prefix":"10.1.0.32", + "prefixLen":32, + "network":"10.1.0.32\/32", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"0.0.0.0", + "hostname":"STR-8102-C19-U24", + "afi":"ipv4", + "used":true + } + ] + } +] } } \ No newline at end of file diff --git a/tests/mock_tables/asic0/no_bgp_neigh.json b/tests/mock_tables/asic0/no_bgp_neigh.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/tests/mock_tables/asic0/no_bgp_neigh.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/mock_tables/asic1/device_bgp_info.json b/tests/mock_tables/asic1/device_bgp_info.json new file mode 100644 index 0000000000..5bc28cf8e5 --- /dev/null +++ b/tests/mock_tables/asic1/device_bgp_info.json @@ -0,0 +1,30 @@ +{ +"vrfId": 0, +"vrfName": "default", +"tableVersion": 8972, +"routerId": "10.1.0.32", +"defaultLocPrf": 100, +"localAS": 65100, +"routes": { "10.1.0.32/32": [ + { + "valid":true, + "bestpath":true, + "pathFrom":"external", + "prefix":"10.1.0.32", + "prefixLen":32, + "network":"10.1.0.32\/32", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"0.0.0.0", + "hostname":"STR-8102-C19-U24", + "afi":"ipv4", + "used":true + } + ] + } +] } } \ No newline at end of file diff --git a/tests/mock_tables/asic1/no_bgp_neigh.json b/tests/mock_tables/asic1/no_bgp_neigh.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/tests/mock_tables/asic1/no_bgp_neigh.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/mock_tables/device_bgp_info.json b/tests/mock_tables/device_bgp_info.json new file mode 100644 index 0000000000..5bc28cf8e5 --- /dev/null +++ b/tests/mock_tables/device_bgp_info.json @@ -0,0 +1,30 @@ +{ +"vrfId": 0, +"vrfName": "default", +"tableVersion": 8972, +"routerId": "10.1.0.32", +"defaultLocPrf": 100, +"localAS": 65100, +"routes": { "10.1.0.32/32": [ + { + "valid":true, + "bestpath":true, + "pathFrom":"external", + "prefix":"10.1.0.32", + "prefixLen":32, + "network":"10.1.0.32\/32", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"0.0.0.0", + "hostname":"STR-8102-C19-U24", + "afi":"ipv4", + "used":true + } + ] + } +] } } \ No newline at end of file diff --git a/tests/mock_tables/no_bgp_neigh.json b/tests/mock_tables/no_bgp_neigh.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/tests/mock_tables/no_bgp_neigh.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/utilities_common/bgp_util.py b/utilities_common/bgp_util.py index 3897d4a103..b9ebb28623 100644 --- a/utilities_common/bgp_util.py +++ b/utilities_common/bgp_util.py @@ -196,6 +196,7 @@ def run_bgp_command(vtysh_cmd, bgp_namespace=multi_asic.DEFAULT_NAMESPACE, vtysh return output + def run_bgp_show_command(vtysh_cmd, bgp_namespace=multi_asic.DEFAULT_NAMESPACE): output = run_bgp_command(vtysh_cmd, bgp_namespace, constants.RVTYSH_COMMAND) # handle the the alias mode in the following code @@ -216,6 +217,7 @@ def run_bgp_show_command(vtysh_cmd, bgp_namespace=multi_asic.DEFAULT_NAMESPACE): output= json.dumps(route_info) return output + def get_bgp_summary_from_all_bgp_instances(af, namespace, display): device = multi_asic_util.MultiAsic(display, namespace) @@ -229,21 +231,29 @@ def get_bgp_summary_from_all_bgp_instances(af, namespace, display): bgp_summary = {} cmd_output_json = {} + for ns in device.get_ns_list_based_on_options(): + has_bgp_neighbors = True cmd_output = run_bgp_show_command(vtysh_cmd, ns) + device.current_namespace = ns try: cmd_output_json = json.loads(cmd_output) except ValueError: ctx.fail("bgp summary from bgp container not in json format") - # exit cli command without printing the error message + # no bgp neighbors found so print basic device bgp info if key not in cmd_output_json: - click.echo("No IP{} neighbor is configured".format(af)) - exit() + has_bgp_neighbors = False + vtysh_cmd = "show ip bgp json" + no_neigh_cmd_output = run_bgp_show_command(vtysh_cmd, ns) + try: + no_neigh_cmd_output_json = json.loads(no_neigh_cmd_output) + except ValueError: + ctx.fail("bgp summary from bgp container not in json format") - device.current_namespace = ns + out_cmd = cmd_output_json[key] if has_bgp_neighbors else no_neigh_cmd_output_json + process_bgp_summary_json(bgp_summary, out_cmd, device, has_bgp_neighbors=has_bgp_neighbors) - process_bgp_summary_json(bgp_summary, cmd_output_json[key], device) return bgp_summary @@ -265,7 +275,7 @@ def display_bgp_summary(bgp_summary, af): for router_info in bgp_summary['router_info']: for k in router_info: v = router_info[k] - instance = "{}: ".format(k) if k is not "" else "" + instance = "{}: ".format(k) if k != "" else "" click.echo( "{}BGP router identifier {}, local AS number {} vrf-id {}" .format( instance, v['router_id'], v['as'], v['vrf'])) @@ -289,66 +299,80 @@ def display_bgp_summary(bgp_summary, af): ctx.fail("{} missing in the bgp_summary".format(e.args[0])) -def process_bgp_summary_json(bgp_summary, cmd_output, device): +def process_bgp_summary_json(bgp_summary, cmd_output, device, has_bgp_neighbors=True): ''' This function process the frr output in json format from a bgp instance and stores the need values in the a bgp_summary ''' - static_neighbors, dynamic_neighbors = get_bgp_neighbors_dict( - device.current_namespace) + if has_bgp_neighbors: + static_neighbors, dynamic_neighbors = get_bgp_neighbors_dict( + device.current_namespace) try: # add all the router level fields - bgp_summary['peerCount'] = bgp_summary.get( - 'peerCount', 0) + cmd_output['peerCount'] - bgp_summary['peerMemory'] = bgp_summary.get( - 'peerMemory', 0) + cmd_output['peerMemory'] - bgp_summary['ribCount'] = bgp_summary.get( - 'ribCount', 0) + cmd_output['ribCount'] - bgp_summary['ribMemory'] = bgp_summary.get( - 'ribMemory', 0) + cmd_output['ribMemory'] - bgp_summary['peerGroupCount'] = bgp_summary.get( - 'peerGroupCount', 0) + cmd_output['peerGroupCount'] - bgp_summary['peerGroupMemory'] = bgp_summary.get( - 'peerGroupMemory', 0) + cmd_output['peerGroupMemory'] + if has_bgp_neighbors: + # when there are bgp neighbors, fill information from the dict + bgp_summary['peerCount'] = bgp_summary.get( + 'peerCount', 0) + cmd_output['peerCount'] + bgp_summary['peerMemory'] = bgp_summary.get( + 'peerMemory', 0) + cmd_output['peerMemory'] + bgp_summary['ribCount'] = bgp_summary.get( + 'ribCount', 0) + cmd_output['ribCount'] + bgp_summary['ribMemory'] = bgp_summary.get( + 'ribMemory', 0) + cmd_output['ribMemory'] + bgp_summary['peerGroupCount'] = bgp_summary.get( + 'peerGroupCount', 0) + cmd_output['peerGroupCount'] + bgp_summary['peerGroupMemory'] = bgp_summary.get( + 'peerGroupMemory', 0) + cmd_output['peerGroupMemory'] + else: + # when there are no bgp neighbors, all values are zero + bgp_summary['peerCount'] = 0 + bgp_summary['peerMemory'] = 0 + bgp_summary['ribCount'] = 0 + bgp_summary['ribMemory'] = 0 + bgp_summary['peerGroupCount'] = 0 + bgp_summary['peerGroupMemory'] = 0 # store instance level field is seperate dict router_info = {} router_info['router_id'] = cmd_output['routerId'] router_info['vrf'] = cmd_output['vrfId'] - router_info['as'] = cmd_output['as'] + router_info['as'] = cmd_output['as'] if has_bgp_neighbors else cmd_output['localAS'] router_info['tbl_ver'] = cmd_output['tableVersion'] bgp_summary.setdefault('router_info', []).append( {device.current_namespace: router_info}) # store all the peers in the list - for peer_ip, value in cmd_output['peers'].items(): - peers = [] - # if display option is 'frontend', internal bgp neighbors will not - # be displayed - if device.skip_display(constants.BGP_NEIGH_OBJ, peer_ip): - continue - - peers.append(peer_ip) - peers.append(value['version']) - peers.append(value['remoteAs']) - peers.append(value['msgRcvd']) - peers.append(value['msgSent']) - peers.append(value['tableVersion']) - peers.append(value['inq']) - peers.append(value['outq']) - peers.append(value['peerUptime']) - if value['state'] == 'Established': - peers.append(value['pfxRcd']) - else: - peers.append(value['state']) - - # Get the bgp neighbour name ans store it - neigh_name = get_bgp_neighbor_ip_to_name( - peer_ip, static_neighbors, dynamic_neighbors) - peers.append(neigh_name) - - bgp_summary.setdefault('peers', []).append(peers) + if has_bgp_neighbors: + for peer_ip, value in cmd_output['peers'].items(): + peers = [] + # if display option is 'frontend', internal bgp neighbors will not + # be displayed + if device.skip_display(constants.BGP_NEIGH_OBJ, peer_ip): + continue + + peers.append(peer_ip) + peers.append(value['version']) + peers.append(value['remoteAs']) + peers.append(value['msgRcvd']) + peers.append(value['msgSent']) + peers.append(value['tableVersion']) + peers.append(value['inq']) + peers.append(value['outq']) + peers.append(value['peerUptime']) + if value['state'] == 'Established': + peers.append(value['pfxRcd']) + else: + peers.append(value['state']) + + # Get the bgp neighbour name ans store it + neigh_name = get_bgp_neighbor_ip_to_name( + peer_ip, static_neighbors, dynamic_neighbors) + peers.append(neigh_name) + + bgp_summary.setdefault('peers', []).append(peers) + else: + bgp_summary['peers'] = [] except KeyError as e: ctx = click.get_current_context() ctx.fail("{} missing in the bgp_summary".format(e.args[0]))