Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions show/vnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,29 @@ def routes():
pass


def pretty_print_local(table, r, nexthop_val, ifname_val):
nexthops = [nexthop.strip() for nexthop in nexthop_val.split(',')] if nexthop_val else []
interfaces = [interface.strip() for interface in ifname_val.split(',')] if ifname_val else []
if not nexthops:
nexthops = [""]

all_items = list(nexthops) + list(interfaces)
max_len = max((len(item) for item in all_items), default=0)
row_width = 2 if max_len > 15 else 3

max_entries = max(len(nexthops), len(interfaces))
i = 0
while i < max_entries:
r.append(",".join(nexthops[i:i + row_width]) if i < len(nexthops) else "")
if interfaces:
r.append(",".join(interfaces[i:i + row_width]) if i < len(interfaces) else "")
else:
r.append(ifname_val if i == 0 else "")
i += row_width
table.append(r)
r = ["", ""]


def pretty_print(table, r, epval, mac_addr, vni, metric, state):
endpoints = epval.split(',')
# When mac_address or vni is a per-endpoint list, split so all three fields
Expand Down Expand Up @@ -531,9 +554,9 @@ def _show_local_helper(vnet_name=None, appl_db=None):
r = []
r.extend(k.split(":", 2)[1:])
val = appl_db.get_all(appl_db.APPL_DB, k)
r.append(val.get('nexthop'))
r.append(val.get('ifname'))
table.append(r)
nexthop_val = val.get('nexthop') or ''
ifname_val = val.get('ifname') or ''
pretty_print_local(table, r, nexthop_val, ifname_val)

click.echo(tabulate(table, route_header))

Expand Down
4 changes: 4 additions & 0 deletions tests/mock_tables/appl_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@
"nexthop": "100.103.4.1, 100.103.4.2, 100.103.4.3",
"ifname": "Ethernet1, Ethernet2, Ethernet3"
},
"VNET_ROUTE_TABLE:Vnet_7959668:10.32.0.0/17": {
"nexthop": "10.33.254.1,10.33.254.3,10.33.254.5,10.33.254.7,10.33.254.9,10.33.254.11,10.33.254.13,10.33.254.15,10.33.254.17,10.33.254.19,10.33.254.23,10.33.254.25,10.33.254.27,10.33.254.29,10.33.254.31",
"ifname": "Po1031.106,Po1032.106,Po1033.106,Po1034.106,Po1035.106,Po1036.106,Po1037.106,Po1038.106,Po1039.106,Po1040.106,Po1042.106,Po1043.106,Po1044.106,Po1045.106,Po1046.106"
},
"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",
Expand Down
94 changes: 72 additions & 22 deletions tests/show_vnet_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,64 @@ def test_pretty_print_scale(self, N, vnet_name, prefix, metric):
assert ",".join(r[3] for r in table) == ",".join(macs_list)
assert ",".join(r[4] for r in table) == ",".join(vnis_list)

def test_pretty_print_local(self):
# Single nexthop, no wrapping
table = []
row = ["TestVnet", "10.0.0.0/24"]
vnet.pretty_print_local(table, row, "192.168.1.1", "Ethernet1")
assert table == [["TestVnet", "10.0.0.0/24", "192.168.1.1", "Ethernet1"]]

# 3 short nexthops, row_width=3, all fit on one row
table = []
row = ["TestVnet", "10.0.0.0/24"]
vnet.pretty_print_local(table, row, "1.1.1.1,2.2.2.2,3.3.3.3", "Eth1,Eth2,Eth3")
assert table == [["TestVnet", "10.0.0.0/24", "1.1.1.1,2.2.2.2,3.3.3.3", "Eth1,Eth2,Eth3"]]

# Spaces in DB values are stripped
table = []
row = ["TestVnet", "10.0.0.0/24"]
vnet.pretty_print_local(table, row, "1.1.1.1, 2.2.2.2, 3.3.3.3", "Eth1, Eth2, Eth3")
assert table == [["TestVnet", "10.0.0.0/24", "1.1.1.1,2.2.2.2,3.3.3.3", "Eth1,Eth2,Eth3"]]

# 5 short nexthops — wraps into 2 rows (3+2)
table = []
row = ["TestVnet", "10.0.0.0/24"]
vnet.pretty_print_local(table, row, "1.1.1.1,2.2.2.2,3.3.3.3,4.4.4.4,5.5.5.5",
"Eth1,Eth2,Eth3,Eth4,Eth5")
assert table == [
["TestVnet", "10.0.0.0/24", "1.1.1.1,2.2.2.2,3.3.3.3", "Eth1,Eth2,Eth3"],
["", "", "4.4.4.4,5.5.5.5", "Eth4,Eth5"],
]

# Long interface names (>15 chars) → row_width=2
table = []
row = ["TestVnet", "10.0.0.0/24"]
vnet.pretty_print_local(table, row,
"10.33.254.1,10.33.254.3,10.33.254.5",
"PortChannel1031.106,PortChannel1032.106,PortChannel1033.106")
assert table == [
["TestVnet", "10.0.0.0/24", "10.33.254.1,10.33.254.3", "PortChannel1031.106,PortChannel1032.106"],
["", "", "10.33.254.5", "PortChannel1033.106"],
]

def test_show_vnet_routes_all_basic(self):
runner = CliRunner()
db = Db()

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
--------------- ---------------- ------------------------------------- -------------------------------
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 nexthop interface
--------------- ---------------- -------------------------------------- --------------------------------
Vnet_7959668 10.32.0.0/17 10.33.254.1,10.33.254.3,10.33.254.5 Po1031.106,Po1032.106,Po1033.106
10.33.254.7,10.33.254.9,10.33.254.11 Po1034.106,Po1035.106,Po1036.106
10.33.254.13,10.33.254.15,10.33.254.17 Po1037.106,Po1038.106,Po1039.106
10.33.254.19,10.33.254.23,10.33.254.25 Po1040.106,Po1042.106,Po1043.106
10.33.254.27,10.33.254.29,10.33.254.31 Po1044.106,Po1045.106,Po1046.106
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 metric status
------------------ ------------------------ ------------------------------------------- ----------------------------------- --------------- -------- --------
Expand Down Expand Up @@ -171,11 +216,11 @@ def test_show_vnet_routes_all_vnetname(self):
['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 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
--------------- ---------------- ----------- ------------- ----- -------- --------
Expand Down Expand Up @@ -234,12 +279,17 @@ def test_show_vnet_routes_local_basic(self):
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
vnet name prefix nexthop interface
--------------- ---------------- -------------------------------------- --------------------------------
Vnet_7959668 10.32.0.0/17 10.33.254.1,10.33.254.3,10.33.254.5 Po1031.106,Po1032.106,Po1033.106
10.33.254.7,10.33.254.9,10.33.254.11 Po1034.106,Po1035.106,Po1036.106
10.33.254.13,10.33.254.15,10.33.254.17 Po1037.106,Po1038.106,Po1039.106
10.33.254.19,10.33.254.23,10.33.254.25 Po1040.106,Po1042.106,Po1043.106
10.33.254.27,10.33.254.29,10.33.254.31 Po1044.106,Po1045.106,Po1046.106
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

Expand All @@ -251,11 +301,11 @@ def test_show_vnet_routes_local_vnetname(self):
['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 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

Expand Down