From 080ebf66e2d4b191e6657f13cd12effc40ee0024 Mon Sep 17 00:00:00 2001 From: mssonicbld <79238446+mssonicbld@users.noreply.github.com> Date: Sat, 11 Apr 2026 07:13:58 +0800 Subject: [PATCH 1/2] Sfputil: don't abort eeprom-hexdump on single page read failure (#4447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a single EEPROM page fails to read during `sfputil show eeprom-hexdump`, the command no longer aborts. It continues dumping the remaining pages and returns success (exit 0), with the failed page’s error message included in the output. #### What I did - **Bug**: On some modules, `sfputil show eeprom-hexdump` failed with "Failed to read EEPROM for page" and exited with an error, so no EEPROM data was shown and techsupport dumps did not contain `dump/interface.xcvrs.eeprom.RAW`. - **Fix**: Treat a single-page read failure as non-fatal: append the error line to the output and continue with the next pages. The command still exits 0 so techsupport and scripts get a full/ partial dump. #### How I did it - **sfputil/main.py** - `eeprom_hexdump_pages_general()`: Removed early `return return_code, output` on page read failure. Always append `output` and continue, then return `(0, '\n'.join(lines))`. - `eeprom_hexdump_pages_sff8472()`: Same behavior for SFF8472 (A0h / A2h pages): no early return on failure, append output and continue. - **tests/sfputil_test.py** - `test_eeprom_hexdump_all_falure`: Updated to expect exit 0 and that both ports’ headers and error messages appear in output (continue-on-failure behavior). - Added `test_eeprom_hexdump_pages_general_continues_on_single_page_failure`: one page fails, others succeed, asserts rc == 0 and output contains both error and successful page content. - Added `test_eeprom_hexdump_pages_sff8472_continues_on_single_page_failure`: same for SFF8472 (A0h ok, A2h lower fail, A2h upper ok). #### How to verify it - Unit tests: new and updated tests in `tests/sfputil_test.py` for continue-on-single-page-failure behavior. - Manual: `sfputil show eeprom-hexdump` and `show techsupport` on some modules to confirm partial EEPROM dump and presence of `interface.xcvrs.eeprom.RAW`. On EEPROM page read failure, log which page failed and continue dumping other pages instead of returning. Fixes modules where e.g. some page fails but other pages are readable. Allows techsupport dumps to include interface.xcvrs.eeprom.RAW. #### Which release branch to backport (provide reason below if selected) - [x] 202511 ##### **Before this change:** Run "sfputil show eeprom-hexdump": Error "Failed to read EEPROM for page 10h", and stopped there. Run "show techsupport": In the generated dumps, the file dump/interface.xcvrs.eeprom.RAW does not exist. ##### **After this change:** Run "sfputil show eeprom-hexdump": ```bash EEPROM hexdump for port Ethernet0 Lower page 0h 00000000 80 53 45 07 00 00 00 00 00 00 00 00 00 00 00 00 |.SE.............| 00000010 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 |..........@.....| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 03 00 00 00 00 00 80 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 00 00 00 02 4c 14 11 ff 4b 14 11 ff 4e 1c |......L...K...N.| 00000060 22 55 4d 1c 22 55 50 1c 44 11 4f 1c 44 11 ff 00 |"UM."UP.D.O.D...| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Upper page 0h 00000080 80 4e 56 49 44 49 41 20 20 20 20 20 20 20 20 20 |.NVIDIA | 00000090 20 00 00 00 56 4d 4f 44 5f 53 50 43 35 5f 43 50 | ...VMOD_SPC5_CP| 000000a0 4f 20 20 20 00 00 56 4d 4f 44 5f 53 50 43 35 5f |O ..VMOD_SPC5_| 000000b0 43 50 4f 20 30 30 00 00 00 00 00 00 00 00 20 20 |CPO 00........ | 000000c0 20 20 20 20 20 20 20 20 50 00 00 00 00 00 00 00 | P.......| 000000d0 00 00 00 00 04 00 00 00 00 00 00 00 00 00 d1 00 |................| 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| Upper page 1h 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000090 00 80 46 00 00 00 9d 00 00 00 00 00 00 00 00 03 |..F.............| 000000a0 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 69 |...............i| Upper page 2h 00000080 5f 00 f6 00 5a 00 05 00 88 b8 79 18 87 5a 7a 76 |_...Z.....y..Zzv| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000b0 fc 35 27 10 ea 91 3d f9 00 00 00 00 00 00 00 00 |.5'...=.........| 000000c0 62 20 09 d0 4d ee 0c 5a 00 00 00 00 00 00 00 00 |b ..M..Z........| 000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6b |...............k| Upper page 10h Error: Failed to read EEPROM for page 10h, flat_offset 2176, page_offset 128, size 128! Upper page 11h Error: Failed to read EEPROM for page 11h, flat_offset 2304, page_offset 128, size 128! ``` Read Upper page 10h fail, but can continue to read latter page 11h, previously it will return directly. Multiple pages read failure are shown in page 10h and 11h. Run "show techsupport": In the generated dumps, the file dump/interface.xcvrs.eeprom.RAW exist. Signed-off-by: Sonic Build Admin --- sfputil/main.py | 12 ------ tests/sfputil_test.py | 97 ++++++++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/sfputil/main.py b/sfputil/main.py index be335cb97..94183c830 100644 --- a/sfputil/main.py +++ b/sfputil/main.py @@ -869,20 +869,14 @@ def eeprom_hexdump_pages_general(logical_port_name, pages, target_page): if page == 0: lines.append(f'{EEPROM_DUMP_INDENT}Lower page 0h') return_code, output = eeprom_dump_general(physical_port, page, 0, PAGE_SIZE, 0) - if return_code != 0: - return return_code, output lines.append(output) lines.append(f'\n{EEPROM_DUMP_INDENT}Upper page 0h') return_code, output = eeprom_dump_general(physical_port, page, PAGE_OFFSET, PAGE_SIZE, PAGE_OFFSET) - if return_code != 0: - return return_code, output lines.append(output) else: lines.append(f'\n{EEPROM_DUMP_INDENT}Upper page {page:x}h') return_code, output = eeprom_dump_general(physical_port, page, page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE, PAGE_OFFSET) - if return_code != 0: - return return_code, output lines.append(output) lines.append('') # add a new line @@ -915,20 +909,14 @@ def eeprom_hexdump_pages_sff8472(logical_port_name, pages, target_page): return_code, output = eeprom_dump_general(physical_port, page, 0, SFF8472_A0_SIZE, 0) else: return_code, output = eeprom_dump_general(physical_port, page, 0, PAGE_SIZE, 0) - if return_code != 0: - return return_code, 'Error: Failed to read EEPROM for A0h!' lines.append(output) elif page == 1: lines.append(f'\n{EEPROM_DUMP_INDENT}A2h dump (lower 128 bytes)') return_code, output = eeprom_dump_general(physical_port, page, SFF8472_A0_SIZE, PAGE_SIZE, 0) - if return_code != 0: - return ERROR_NOT_IMPLEMENTED, 'Error: Failed to read EEPROM for A2h!' lines.append(output) else: lines.append(f'\n{EEPROM_DUMP_INDENT}A2h dump (upper 128 bytes) page {page - 2:x}h') return_code, output = eeprom_dump_general(physical_port, page, SFF8472_A0_SIZE + PAGE_OFFSET + page * PAGE_SIZE, PAGE_SIZE, PAGE_SIZE) - if return_code != 0: - return ERROR_NOT_IMPLEMENTED, 'Error: Failed to read EEPROM for A2h upper page!' lines.append(output) lines.append('') # add a new line diff --git a/tests/sfputil_test.py b/tests/sfputil_test.py index 551584d4b..e6f347f5f 100644 --- a/tests/sfputil_test.py +++ b/tests/sfputil_test.py @@ -298,7 +298,7 @@ def test_convert_sfp_info_to_output_string(self, sfp_info_dict, expected_output) Vcc: 3.2577Volts ModuleThresholdValues: ''' - ), + ), ( 'QSFP-DD Double Density 8X Pluggable Transceiver', True, @@ -1044,15 +1044,11 @@ def test_eeprom_hexdump_all_falure(self, mock_sfputil, mock_chassis): runner = CliRunner() result = runner.invoke(sfputil.cli.commands['show'].commands['eeprom-hexdump']) + # With continue-on-failure behavior: exit 0 and failed pages are reported, not abort assert result.exit_code == 0 - expected_output = """EEPROM hexdump for port Ethernet0 - Error: Failed to read EEPROM for page 0h, flat_offset 0, page_offset 0, size 128! - -EEPROM hexdump for port Ethernet4 - Error: Failed to read EEPROM for A0h! - -""" - assert result.output == expected_output + assert "EEPROM hexdump for port Ethernet0" in result.output + assert "EEPROM hexdump for port Ethernet4" in result.output + assert "Error: Failed to read EEPROM" in result.output @patch('sfputil.main.platform_chassis') @patch('sfputil.main.platform_sfputil') @@ -1170,6 +1166,47 @@ def test_eeprom_hexdump_single_port(self, mock_isinstance, mock_dump, mock_chass sfputil.eeprom_hexdump_single_port('Ethernet0', 3) mock_dump.assert_called_with('Ethernet0', [0, 3], 3) + @patch('sfputil.main.logical_port_to_physical_port_index', MagicMock(return_value=0)) + @patch('sfputil.main.eeprom_dump_general') + def test_eeprom_hexdump_pages_general_continues_on_single_page_failure(self, mock_eeprom_dump_general): + """When one page read fails, dump continues and returns 0 with failure line in output.""" + # Call 1: Lower page 0h success, Call 2: Upper page 0h fail, Call 3: Upper page 1h success + mock_eeprom_dump_general.side_effect = [ + (0, " 00000000 00 01 02 03 ..."), + (1, "read error"), + (0, " 00000080 10 11 12 13 ..."), + ] + rc, output = sfputil.eeprom_hexdump_pages_general("Ethernet0", [0, 1], None) + assert rc == 0 + assert "Lower page 0h" in output + assert "00000000 00 01 02 03" in output + assert "read error" in output + assert "Upper page 1h" in output + assert "00000080 10 11 12 13" in output + + @patch('sfputil.main.platform_chassis') + @patch('sfputil.main.logical_port_to_physical_port_index', MagicMock(return_value=0)) + @patch('sfputil.main.eeprom_dump_general') + def test_eeprom_hexdump_pages_sff8472_continues_on_single_page_failure( + self, mock_eeprom_dump_general, mock_chassis): + """When one SFF8472 page (e.g. A2h lower) fails, dump continues and returns 0.""" + mock_api = MagicMock() + mock_api.is_flat_memory.return_value = False + mock_chassis.get_sfp.return_value.get_xcvr_api.return_value = mock_api + # A0h success, A2h lower fail, A2h upper success + mock_eeprom_dump_general.side_effect = [ + (0, " 00000000 03 04 07 ..."), + (1, "A2h lower read error"), + (0, " 00000100 00 00 00 ..."), + ] + rc, output = sfputil.eeprom_hexdump_pages_sff8472("Ethernet0", [0, 1, 2], None) + assert rc == 0 + assert "A0h dump" in output + assert "00000000 03 04 07" in output + assert "A2h lower read error" in output + assert "A2h dump (upper 128 bytes) page 0h" in output + assert "00000100 00 00 00" in output + @patch('sfputil.main.logical_port_name_to_physical_port_list', MagicMock(return_value=[1])) @patch('sfputil.main.platform_chassis') @patch('sfputil.main.is_port_type_rj45') @@ -1628,40 +1665,40 @@ def test_get_overall_offset_general(self, mock_chassis): mock_sfp.get_presence = MagicMock(return_value=True) mock_sfp.get_xcvr_api = MagicMock(return_value=api) - + runner = CliRunner() result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '-1', '-o', '0', '-d', '01']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '256', '-o', '0', '-d', '01']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '0', '-o', '-1', '-d', '01']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '0', '-o', '256', '-d', '01']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '1', '-o', '127', '-d', '01']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '1', '-o', '256', '-d', '01']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '-n', '0', '-o', '0', '-s', '0']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '-n', '0', '-o', '0', '-s', '257']) assert result.exit_code != 0 - + result = runner.invoke(sfputil.cli.commands['write-eeprom'], ['-p', "Ethernet0", '-n', '0', '-o', '1', '-d', '01']) assert result.exit_code == 0 @@ -1679,13 +1716,13 @@ def test_get_overall_offset_sff8472(self, mock_chassis): mock_sfp.get_presence = MagicMock(return_value=True) mock_sfp.get_xcvr_api = MagicMock(return_value=api) - + runner = CliRunner() result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '-n', '0', '-o', '0', '-s', '1']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'invalid', '-n', '0', '-o', '0', '-s', '1']) assert result.exit_code != 0 @@ -1700,49 +1737,49 @@ def test_get_overall_offset_sff8472(self, mock_chassis): ['-p', "Ethernet0", '--wire-addr', 'A0h', '-n', '0', '-o', '-1', '-s', '1']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'A0h', '-n', '0', '-o', '256', '-s', '1']) assert result.exit_code != 0 print(result.output) - result = runner.invoke(sfputil.cli.commands['read-eeprom'], + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'A0h', '-n', '0', '-o', '0', '-s', '0']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'A0h', '-n', '0', '-o', '0', '-s', '257']) assert result.exit_code != 0 print(result.output) - + assert sfputil.get_overall_offset_sff8472(api, 0, 2, 2, wire_addr='A0h') == 2 - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'a2h', '-n', '-1', '-o', '0', '-s', '1']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'a2h', '-n', '256', '-o', '0', '-s', '1']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'a2h', '-n', '0', '-o', '-1', '-s', '1']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'a2h', '-n', '0', '-o', '0', '-s', '0']) assert result.exit_code != 0 print(result.output) - + result = runner.invoke(sfputil.cli.commands['read-eeprom'], ['-p', "Ethernet0", '--wire-addr', 'a2h', '-n', '0', '-o', '0', '-s', '257']) assert result.exit_code != 0 print(result.output) - + assert sfputil.get_overall_offset_sff8472(api, 0, 2, 2, wire_addr='A2h') == 258 @patch('sfputil.main.platform_chassis') From 902205a760ba5c48b4b8c5b63af73fdb5033837a Mon Sep 17 00:00:00 2001 From: David Zhang Date: Fri, 10 Apr 2026 17:54:38 -0700 Subject: [PATCH 2/2] Show vnet route cli update on 202511 (#4448) * mertirc and vnetname code into 202511 Signed-off-by: alawing * fix merge issue Signed-off-by: alawing --------- Signed-off-by: alawing --- show/vnet.py | 97 +++++++++++++---------- tests/mock_tables/appl_db.json | 19 ++++- tests/show_vnet_test.py | 135 ++++++++++++++++++++++++++++----- 3 files changed, 188 insertions(+), 63 deletions(-) diff --git a/show/vnet.py b/show/vnet.py index a76845b0c..10c451b67 100644 --- a/show/vnet.py +++ b/show/vnet.py @@ -441,7 +441,8 @@ def routes(): """Show vnet routes related information""" pass -def pretty_print(table, r, epval, mac_addr, vni, state): + +def pretty_print(table, r, epval, mac_addr, vni, metric, state): endpoints = epval.split(',') row_width = 3 max_len = 0 @@ -458,28 +459,61 @@ def pretty_print(table, r, epval, mac_addr, vni, state): if iter == 0: r.append(mac_addr) r.append(vni) + r.append(metric) r.append(state) else: - r.extend(["", "", ""]) + r.extend(["", "", "", ""]) iter += row_width table.append(r) r = ["",""] @routes.command() -def all(): +@click.argument('vnet_name', required=False) +def all(vnet_name): """Show all vnet routes""" + appl_db = SonicV2Connector() - appl_db.connect(appl_db.APPL_DB) state_db = SonicV2Connector() - state_db.connect(state_db.STATE_DB) - header = ['vnet name', 'prefix', 'nexthop', 'interface'] - # Fetching data from appl_db for VNET ROUTES + _show_local_helper(vnet_name=vnet_name, appl_db=appl_db) + click.echo() + _show_tunnel_helper(vnet_name=vnet_name, appl_db=appl_db, state_db=state_db) + + +@routes.command() +@click.argument('vnet_name', required=False) +def local(vnet_name): + """Show local vnet routes""" + + appl_db = SonicV2Connector() + + _show_local_helper(vnet_name=vnet_name, appl_db=appl_db) + + +@routes.command() +@click.argument('vnet_name', required=False) +def tunnel(vnet_name): + """Show vnet tunnel routes""" + + appl_db = SonicV2Connector() + state_db = SonicV2Connector() + + _show_tunnel_helper(vnet_name=vnet_name, appl_db=appl_db, state_db=state_db) + + +def _show_local_helper(vnet_name=None, appl_db=None): + route_header = ['vnet name', 'prefix', 'nexthop', 'interface'] + + appl_db.connect(appl_db.APPL_DB) + + # VNET routes + table = [] vnet_rt_keys = appl_db.keys(appl_db.APPL_DB, "VNET_ROUTE_TABLE:*") vnet_rt_keys = natsorted(vnet_rt_keys) if vnet_rt_keys else [] - table = [] for k in vnet_rt_keys: + if vnet_name and k.split(":")[1] != vnet_name: + continue r = [] r.extend(k.split(":", 2)[1:]) val = appl_db.get_all(appl_db.APPL_DB, k) @@ -487,21 +521,26 @@ def all(): r.append(val.get('ifname')) table.append(r) - click.echo(tabulate(table, header)) + click.echo(tabulate(table, route_header)) - click.echo() - header = ['vnet name', 'prefix', 'endpoint', 'mac address', 'vni', 'status'] +def _show_tunnel_helper(vnet_name=None, appl_db=None, state_db=None): + tunnel_header = ['vnet name', 'prefix', 'endpoint', 'mac address', 'vni', 'metric', 'status'] - # Fetching data from appl_db for VNET TUNNEL ROUTES + appl_db.connect(appl_db.APPL_DB) + state_db.connect(state_db.STATE_DB) + + # VNET tunnel routes + table = [] vnet_rt_keys = appl_db.keys(appl_db.APPL_DB, "VNET_ROUTE_TUNNEL_TABLE:*") vnet_rt_keys = natsorted(vnet_rt_keys) if vnet_rt_keys else [] - table = [] for k in vnet_rt_keys: + if vnet_name and k.split(":")[1] != vnet_name: + continue r = [] r.extend(k.split(":", 2)[1:]) - state_db_key = '|'.join(k.split(":",2)) + state_db_key = '|'.join(k.split(":", 2)) val = appl_db.get_all(appl_db.APPL_DB, k) val_state = state_db.get_all(state_db.STATE_DB, state_db_key) epval = val.get('endpoint') @@ -509,36 +548,12 @@ def all(): r.append(epval) r.append(val.get('mac_address')) r.append(val.get('vni')) + r.append(val.get('metric')) if val_state: r.append(val_state.get('state')) table.append(r) continue state = val_state.get('state') if val_state else "" - pretty_print(table, r, epval, val.get('mac_address'), val.get('vni'), state ) - - click.echo(tabulate(table, header)) - - -@routes.command() -def tunnel(): - """Show vnet tunnel routes""" - appl_db = SonicV2Connector() - appl_db.connect(appl_db.APPL_DB) - - header = ['vnet name', 'prefix', 'endpoint', 'mac address', 'vni'] - - # Fetching data from appl_db for VNET TUNNEL ROUTES - vnet_rt_keys = appl_db.keys(appl_db.APPL_DB, "VNET_ROUTE_TUNNEL_TABLE:*") - vnet_rt_keys = natsorted(vnet_rt_keys) if vnet_rt_keys else [] - - table = [] - for k in vnet_rt_keys: - r = [] - r.extend(k.split(":", 2)[1:]) - val = appl_db.get_all(appl_db.APPL_DB, k) - r.append(val.get('endpoint')) - r.append(val.get('mac_address')) - r.append(val.get('vni')) - table.append(r) + pretty_print(table, r, epval, val.get('mac_address'), val.get('vni'), val.get('metric'), state) - click.echo(tabulate(table, header)) + click.echo(tabulate(table, tunnel_header)) diff --git a/tests/mock_tables/appl_db.json b/tests/mock_tables/appl_db.json index 8ea338717..06a64ff9b 100644 --- a/tests/mock_tables/appl_db.json +++ b/tests/mock_tables/appl_db.json @@ -371,9 +371,26 @@ "TUNNEL_ROUTE_TABLE:10.3.1.1": { "alias": "Vlan1000" }, + "VNET_ROUTE_TABLE:test_v4_in_v4-0:160.162.191.1/32": { + "nexthop": "100.100.4.1", + "ifname": "Ethernet1" + }, + "VNET_ROUTE_TABLE:test_v4_in_v4-0:160.163.191.1/32": { + "nexthop": "100.101.4.1, 100.101.4.2", + "ifname": "Ethernet1, Ethernet2" + }, + "VNET_ROUTE_TABLE:test_v4_in_v4-0:160.164.191.1/32": { + "nexthop": "100.102.4.1, 100.102.4.2, 100.102.4.3", + "ifname": "Ethernet1, Ethernet2, Ethernet3" + }, + "VNET_ROUTE_TABLE:test_v4_in_v4-1:160.165.191.1/32": { + "nexthop": "100.103.4.1, 100.103.4.2, 100.103.4.3", + "ifname": "Ethernet1, Ethernet2, Ethernet3" + }, "VNET_ROUTE_TUNNEL_TABLE:test_v4_in_v4-0:160.163.191.1/32": { "endpoint":"100.251.7.1", - "endpoint_monitor":"100.251.7.1" + "endpoint_monitor":"100.251.7.1", + "metric": "0" }, "VNET_ROUTE_TUNNEL_TABLE:Vnet_v6_in_v6-0:fddd:a156:a251::a6:1/128": { "endpoint": "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1,fddd:a102:a251::a10:1,fddd:a103:a251::a10:1", diff --git a/tests/show_vnet_test.py b/tests/show_vnet_test.py index eff75a583..ae8e5782b 100644 --- a/tests/show_vnet_test.py +++ b/tests/show_vnet_test.py @@ -1,3 +1,4 @@ +# flake8: noqa: E501 import os from click.testing import CliRunner from utilities_common.db import Db @@ -15,42 +16,43 @@ def test_Preety_print(self): row = ["Vnet_v6_in_v6-0", "fddd:a156:a251::a6:1/128"] mac_addr = "" vni = "" + metric = "0" state = "active" epval = "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1" - vnet.pretty_print(table, row, epval, mac_addr, vni, state) - expected_output = [['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', 'fddd:a100:a251::a10:1,fddd:a101:a251::a10:1', '', '', 'active']] + vnet.pretty_print(table, row, epval, mac_addr, vni, metric, state) + expected_output = [['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', 'fddd:a100:a251::a10:1,fddd:a101:a251::a10:1', '', '', '0', 'active']] assert table == expected_output table =[] row = ["Vnet_v6_in_v6-0", "fddd:a156:a251::a6:1/128"] epval = "fddd:a100:a251::a10:1,fddd:a101:a251::a10:1,fddd:a100:a251::a11:1,fddd:a100:a251::a12:1,fddd:a100:a251::a13:1" - vnet.pretty_print(table, row, epval, mac_addr, vni, state) + vnet.pretty_print(table, row, epval, mac_addr, vni, metric, state) expected_output = [ - ['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', 'fddd:a100:a251::a10:1,fddd:a101:a251::a10:1', '', '', 'active'], - ['', '', 'fddd:a100:a251::a11:1,fddd:a100:a251::a12:1', '', '', ''], - ['', '', 'fddd:a100:a251::a13:1', '', '', ''] + ['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', 'fddd:a100:a251::a10:1,fddd:a101:a251::a10:1', '', '', '0', 'active'], + ['', '', 'fddd:a100:a251::a11:1,fddd:a100:a251::a12:1', '', '', '', ''], + ['', '', 'fddd:a100:a251::a13:1', '', '', '', ''] ] assert table == expected_output table =[] row = ["Vnet_v6_in_v6-0", "fddd:a156:a251::a6:1/128"] epval = "192.168.1.1,192.168.1.2,192.168.1.3,192.168.1.4,192.168.1.5,192.168.1.6,192.168.1.7,192.168.1.8,192.168.1.9,192.168.1.10,192.168.1.11,192.168.1.12,192.168.1.13,192.168.1.14,192.168.1.15" - vnet.pretty_print(table, row, epval, mac_addr, vni, state) + vnet.pretty_print(table, row, epval, mac_addr, vni, metric, state) expected_output =[ - ['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', '192.168.1.1,192.168.1.2,192.168.1.3', '', '', 'active'], - ['', '', '192.168.1.4,192.168.1.5,192.168.1.6', '', '', ''], - ['', '', '192.168.1.7,192.168.1.8,192.168.1.9', '', '', ''], - ['', '', '192.168.1.10,192.168.1.11,192.168.1.12', '', '', ''], - ['', '', '192.168.1.13,192.168.1.14,192.168.1.15', '', '', '']] + ['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', '192.168.1.1,192.168.1.2,192.168.1.3', '', '', '0', 'active'], + ['', '', '192.168.1.4,192.168.1.5,192.168.1.6', '', '', '', ''], + ['', '', '192.168.1.7,192.168.1.8,192.168.1.9', '', '', '', ''], + ['', '', '192.168.1.10,192.168.1.11,192.168.1.12', '', '', '', ''], + ['', '', '192.168.1.13,192.168.1.14,192.168.1.15', '', '', '', '']] assert table == expected_output table =[] row = ["Vnet_v6_in_v6-0", "fddd:a156:a251::a6:1/128"] epval = "192.168.1.1" - vnet.pretty_print(table, row, epval, mac_addr, vni, state) + vnet.pretty_print(table, row, epval, mac_addr, vni, metric, state) expected_output =[ - ['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', '192.168.1.1', '', '', 'active']] + ['Vnet_v6_in_v6-0', 'fddd:a156:a251::a6:1/128', '192.168.1.1', '', '', '0', 'active']] assert table == expected_output def test_show_vnet_routes_all_basic(self): @@ -60,16 +62,107 @@ def test_show_vnet_routes_all_basic(self): result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['all'], [], obj=db) assert result.exit_code == 0 expected_output = """\ -vnet name prefix nexthop interface ------------ -------- --------- ----------- +vnet name prefix nexthop interface +--------------- ---------------- ------------------------------------- ------------------------------- +test_v4_in_v4-0 160.162.191.1/32 100.100.4.1 Ethernet1 +test_v4_in_v4-0 160.163.191.1/32 100.101.4.1, 100.101.4.2 Ethernet1, Ethernet2 +test_v4_in_v4-0 160.164.191.1/32 100.102.4.1, 100.102.4.2, 100.102.4.3 Ethernet1, Ethernet2, Ethernet3 +test_v4_in_v4-1 160.165.191.1/32 100.103.4.1, 100.103.4.2, 100.103.4.3 Ethernet1, Ethernet2, Ethernet3 -vnet name prefix endpoint mac address vni status ---------------- ------------------------ ------------------------------------------- ------------- ----- -------- -Vnet_v6_in_v6-0 fddd:a156:a251::a6:1/128 fddd:a100:a251::a10:1,fddd:a101:a251::a10:1 active +vnet name prefix endpoint mac address vni metric status +--------------- ------------------------ ------------------------------------------- ------------- ----- -------- -------- +Vnet_v6_in_v6-0 fddd:a156:a251::a6:1/128 fddd:a100:a251::a10:1,fddd:a101:a251::a10:1 active fddd:a102:a251::a10:1,fddd:a103:a251::a10:1 -test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active -test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 active +test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active +test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 0 active test_v4_in_v4-0 160.164.191.1/32 100.251.7.1 +""" + assert result.output == expected_output + + def test_show_vnet_routes_all_vnetname(self): + runner = CliRunner() + db = Db() + + result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['all'], + ['test_v4_in_v4-0'], obj=db) + assert result.exit_code == 0 + expected_output = """\ +vnet name prefix nexthop interface +--------------- ---------------- ------------------------------------- ------------------------------- +test_v4_in_v4-0 160.162.191.1/32 100.100.4.1 Ethernet1 +test_v4_in_v4-0 160.163.191.1/32 100.101.4.1, 100.101.4.2 Ethernet1, Ethernet2 +test_v4_in_v4-0 160.164.191.1/32 100.102.4.1, 100.102.4.2, 100.102.4.3 Ethernet1, Ethernet2, Ethernet3 + +vnet name prefix endpoint mac address vni metric status +--------------- ---------------- ----------- ------------- ----- -------- -------- +test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active +test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 0 active +test_v4_in_v4-0 160.164.191.1/32 100.251.7.1 +""" + assert result.output == expected_output + + def test_show_vnet_routes_tunnel_basic(self): + runner = CliRunner() + db = Db() + + result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['tunnel'], [], obj=db) + assert result.exit_code == 0 + expected_output = """\ +vnet name prefix endpoint mac address vni metric status +--------------- ------------------------ ------------------------------------------- ------------- ----- -------- -------- +Vnet_v6_in_v6-0 fddd:a156:a251::a6:1/128 fddd:a100:a251::a10:1,fddd:a101:a251::a10:1 active + fddd:a102:a251::a10:1,fddd:a103:a251::a10:1 +test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active +test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 0 active +test_v4_in_v4-0 160.164.191.1/32 100.251.7.1 +""" + assert result.output == expected_output + + def test_show_vnet_routes_tunnel_vnetname(self): + runner = CliRunner() + db = Db() + + result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['tunnel'], + ['test_v4_in_v4-0'], obj=db) + assert result.exit_code == 0 + expected_output = """\ +vnet name prefix endpoint mac address vni metric status +--------------- ---------------- ----------- ------------- ----- -------- -------- +test_v4_in_v4-0 160.162.191.1/32 100.251.7.1 active +test_v4_in_v4-0 160.163.191.1/32 100.251.7.1 0 active +test_v4_in_v4-0 160.164.191.1/32 100.251.7.1 +""" + assert result.output == expected_output + + def test_show_vnet_routes_local_basic(self): + runner = CliRunner() + db = Db() + + result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['local'], [], obj=db) + assert result.exit_code == 0 + expected_output = """\ +vnet name prefix nexthop interface +--------------- ---------------- ------------------------------------- ------------------------------- +test_v4_in_v4-0 160.162.191.1/32 100.100.4.1 Ethernet1 +test_v4_in_v4-0 160.163.191.1/32 100.101.4.1, 100.101.4.2 Ethernet1, Ethernet2 +test_v4_in_v4-0 160.164.191.1/32 100.102.4.1, 100.102.4.2, 100.102.4.3 Ethernet1, Ethernet2, Ethernet3 +test_v4_in_v4-1 160.165.191.1/32 100.103.4.1, 100.103.4.2, 100.103.4.3 Ethernet1, Ethernet2, Ethernet3 +""" + assert result.output == expected_output + + def test_show_vnet_routes_local_vnetname(self): + runner = CliRunner() + db = Db() + + result = runner.invoke(show.cli.commands['vnet'].commands['routes'].commands['local'], + ['test_v4_in_v4-0'], obj=db) + assert result.exit_code == 0 + expected_output = """\ +vnet name prefix nexthop interface +--------------- ---------------- ------------------------------------- ------------------------------- +test_v4_in_v4-0 160.162.191.1/32 100.100.4.1 Ethernet1 +test_v4_in_v4-0 160.163.191.1/32 100.101.4.1, 100.101.4.2 Ethernet1, Ethernet2 +test_v4_in_v4-0 160.164.191.1/32 100.102.4.1, 100.102.4.2, 100.102.4.3 Ethernet1, Ethernet2, Ethernet3 """ assert result.output == expected_output