Skip to content

Commit

Permalink
Updating Config vrf bind/unbind CLIs to skip deletion of subinterface
Browse files Browse the repository at this point in the history
instead update existing subinterface.
Updating unit testcases for subinterfaces.
  • Loading branch information
preetham-singh committed Jul 26, 2022
1 parent 4bbfa23 commit 7565284
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 2 deletions.
11 changes: 10 additions & 1 deletion config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4961,12 +4961,21 @@ def unbind(ctx, interface_name):
table_name = get_interface_table_name(interface_name)
if table_name == "":
ctx.fail("'interface_name' is not valid. Valid names [Ethernet/PortChannel/Vlan/Loopback]")

if is_interface_bind_to_vrf(config_db, interface_name) is False:
return
if table_name == "VLAN_SUB_INTERFACE":
subintf_entry = config_db.get_entry(table_name, interface_name)
if 'vrf_name' in subintf_entry:
subintf_entry.pop('vrf_name')

interface_ipaddresses = get_interface_ipaddresses(config_db, interface_name)
for ipaddress in interface_ipaddresses:
remove_router_interface_ip_address(config_db, interface_name, ipaddress)
config_db.set_entry(table_name, interface_name, None)
if table_name == "VLAN_SUB_INTERFACE":
config_db.set_entry(table_name, interface_name, subintf_entry)
else:
config_db.set_entry(table_name, interface_name, None)

#
# 'ipv6' subgroup ('config interface ipv6 ...')
Expand Down
18 changes: 17 additions & 1 deletion tests/intfutil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ def test_subintf_status(self):
"Sub port interface Speed MTU Vlan Admin Type\n"
"-------------------- ------- ----- ------ ------- --------------------\n"
" Eth32.10 40G 9100 100 up 802.1q-encapsulation\n"
" Ethernet0.10 25G 9100 10 up 802.1q-encapsulation"
" Ethernet0.10 25G 9100 10 up 802.1q-encapsulation\n"
" Po0001.10 40G 9100 100 up 802.1q-encapsulation"
)
self.assertEqual(result.output.strip(), expected_output)

Expand Down Expand Up @@ -254,6 +255,16 @@ def test_single_subintf_status(self):
print(output, file=sys.stderr)
self.assertEqual(output.strip(), expected_output)

expected_output = (
"Sub port interface Speed MTU Vlan Admin Type\n"
"-------------------- ------- ----- ------ ------- --------------------\n"
" Po0001.10 40G 9100 100 up 802.1q-encapsulation"
)
# Test 'intfutil status Po0001.10'
output = subprocess.check_output('intfutil -c status -i Po0001.10', stderr=subprocess.STDOUT, shell=True, text=True)
print(output, file=sys.stderr)
self.assertEqual(output.strip(), expected_output)

# Test '--verbose' status of single sub interface
def test_single_subintf_status_verbose(self):
result = self.runner.invoke(show.cli.commands["subinterfaces"].commands["status"], ["Ethernet0.10", "--verbose"])
Expand All @@ -266,6 +277,11 @@ def test_single_subintf_status_verbose(self):
expected_output = "Command: intfutil -c status -i Eth32.10"
self.assertEqual(result.output.split('\n')[0], expected_output)

result = self.runner.invoke(show.cli.commands["subinterfaces"].commands["status"], ["Po0001.10", "--verbose"])
print(result.output, file=sys.stderr)
expected_output = "Command: intfutil -c status -i Po0001.10"
self.assertEqual(result.output.split('\n')[0], expected_output)

# Test status of single sub interface in alias naming mode
def test_single_subintf_status_alias_mode(self):
os.environ["SONIC_CLI_IFACE_MODE"] = "alias"
Expand Down
44 changes: 44 additions & 0 deletions tests/ip_config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,36 @@ def test_add_del_interface_valid_ipv4(self):
assert result.exit_code == 0
assert ('Ethernet64', '10.10.10.1/24') in db.cfgdb.get_table('INTERFACE')

# config int ip add Ethernet0.10 10.11.10.1/24
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet0.10", "10.11.10.1/24"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('Ethernet0.10', '10.11.10.1/24') in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

# config int ip add Eth32.10 32.11.10.1/24
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Eth32.10", "32.11.10.1/24"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('Eth32.10', '32.11.10.1/24') in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

# config int ip remove Ethernet64 10.10.10.1/24
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet64", "10.10.10.1/24"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code != 0
assert ('Ethernet64', '10.10.10.1/24') not in db.cfgdb.get_table('INTERFACE')

# config int ip remove Ethernet0.10 10.11.10.1/24
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet0.10", "10.11.10.1/24"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code != 0
assert ('Ethernet0.10', '10.11.10.1/24') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

# config int ip remove Eth32.10 32.11.10.1/24
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Eth32.10", "32.11.10.1/24"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code != 0
assert ('Eth32.10', '32.11.10.1/24') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

def test_add_interface_invalid_ipv4(self):
db = Db()
runner = CliRunner()
Expand Down Expand Up @@ -81,12 +105,32 @@ def test_add_del_interface_valid_ipv6(self):
assert result.exit_code == 0
assert ('Ethernet72', '2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') in db.cfgdb.get_table('INTERFACE')

result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Ethernet0.10", "1010:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('Ethernet0.10', '1010:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["add"], ["Eth32.10", "3210:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('Eth32.10', '3210:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

# config int ip remove Ethernet72 2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34
result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet72", "2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code != 0
assert ('Ethernet72', '2001:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') not in db.cfgdb.get_table('INTERFACE')

result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Ethernet0.10", "1010:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code != 0
assert ('Ethernet0.10', '1010:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

result = runner.invoke(config.config.commands["interface"].commands["ip"].commands["remove"], ["Eth32.10", "3210:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code != 0
assert ('Eth32.10', '3210:1db8:11a3:19d7:1f34:8a2e:17a0:765d/34') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')

def test_del_interface_case_sensitive_ipv6(self):
db = Db()
runner = CliRunner()
Expand Down
26 changes: 26 additions & 0 deletions tests/mock_tables/appl_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,34 @@
},
"INTF_TABLE:Eth32.10": {
"admin_status": "up",
"vrf_name": "Vrf1",
"vlan": "100"
},
"INTF_TABLE:Po0001.10": {
"admin_status": "up",
"vrf_name": "Vrf1",
"vlan": "100"
},
"INTF_TABLE:Ethernet0.10|10.11.12.13/24": {
"family": "IPv4",
"scope": "global"
},
"INTF_TABLE:Eth32.10|32.10.11.12/24": {
"family": "IPv4",
"scope": "global"
},
"INTF_TABLE:Po0001.10|10.10.11.12/24": {
"family": "IPv4",
"scope": "global"
},
"INTF_TABLE:Eth32.10|3210::12/126": {
"family": "IPv6",
"scope": "global"
},
"INTF_TABLE:Po0001.10|1010::12/126": {
"family": "IPv6",
"scope": "global"
},
"_GEARBOX_TABLE:phy:1": {
"name": "sesto-1",
"phy_id": "1",
Expand Down
15 changes: 15 additions & 0 deletions tests/mock_tables/config_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,26 @@
"VLAN_SUB_INTERFACE|Eth32.10": {
"admin_status": "up",
"loopback_action": "drop",
"vrf_name": "Vrf1",
"vlan": "100"
},
"VLAN_SUB_INTERFACE|Eth32.10|32.10.11.12/24": {
"NULL" : "NULL"
},
"VLAN_SUB_INTERFACE|Eth32.10|3210::12/126": {
"NULL" : "NULL"
},
"VLAN_SUB_INTERFACE|Po0001.10": {
"admin_status": "up",
"vrf_name": "Vrf1",
"vlan": "100"
},
"VLAN_SUB_INTERFACE|Po0001.10|10.10.11.12/24": {
"NULL" : "NULL"
},
"VLAN_SUB_INTERFACE|Po0001.10|1010::12/126": {
"NULL" : "NULL"
},
"ACL_RULE|NULL_ROUTE_V4|DEFAULT_RULE": {
"PACKET_ACTION": "DROP",
"PRIORITY": "1"
Expand Down
66 changes: 66 additions & 0 deletions tests/show_vrf_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from swsscommon.swsscommon import SonicV2Connector
from utilities_common.db import Db

import config.main as config
import show.main as show

test_path = os.path.dirname(os.path.abspath(__file__))
Expand Down Expand Up @@ -31,6 +32,71 @@ def test_vrf_show(self):
Eth32.10
Vrf103 Ethernet4
Loopback0
Po0002.101
"""

result = runner.invoke(show.cli.commands['vrf'], [], obj=db)
dbconnector.dedicated_dbs = {}
assert result.exit_code == 0
assert result.output == expected_output

def test_vrf_bind_unbind(self):
from .mock_tables import dbconnector
jsonfile_config = os.path.join(mock_db_path, "config_db")
dbconnector.dedicated_dbs['CONFIG_DB'] = jsonfile_config
runner = CliRunner()
db = Db()
expected_output = """\
VRF Interfaces
------ ---------------
Vrf1
Vrf101 Ethernet0.10
Vrf102 PortChannel0002
Vlan40
Eth32.10
Vrf103 Ethernet4
Loopback0
Po0002.101
"""

result = runner.invoke(show.cli.commands['vrf'], [], obj=db)
dbconnector.dedicated_dbs = {}
assert result.exit_code == 0
assert result.output == expected_output

obj = {'config_db':db.cfgdb}
result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Eth32.10"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('vrf_name', 'Vrf102') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')['Eth32.10']

result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Ethernet0.10"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('vrf_name', 'Vrf101') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')['Ethernet0.10']

result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Po0002.101"], obj=obj)
print(result.exit_code, result.output)
assert result.exit_code == 0
assert ('vrf_name', 'Vrf103') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')['Po0002.101']


#Bind click CLI cannot be tested as it tries to connecte to statedb
#for verification of all IP address delete before applying new vrf configuration
jsonfile_config = os.path.join(mock_db_path, "config_db")
dbconnector.dedicated_dbs['CONFIG_DB'] = jsonfile_config

expected_output = """\
VRF Interfaces
------ ---------------
Vrf1
Vrf101 Ethernet0.10
Vrf102 PortChannel0002
Vlan40
Eth32.10
Vrf103 Ethernet4
Loopback0
Po0002.101
"""

result = runner.invoke(show.cli.commands['vrf'], [], obj=db)
Expand Down
5 changes: 5 additions & 0 deletions tests/vrf_input/config_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
"admin_status": "up",
"vlan": "100"
},
"VLAN_SUB_INTERFACE|Po0002.101": {
"vrf_name": "Vrf103",
"admin_status": "up",
"vlan": "1001"
},
"VLAN_INTERFACE|Vlan40": {
"vrf_name": "Vrf102"
},
Expand Down

0 comments on commit 7565284

Please sign in to comment.