diff --git a/config/main.py b/config/main.py index c965992895..5f82713236 100644 --- a/config/main.py +++ b/config/main.py @@ -5118,6 +5118,22 @@ def unbind(ctx, interface_name): for ipaddress in interface_ipaddresses: remove_router_interface_ip_address(config_db, interface_name, ipaddress) if table_name == "VLAN_SUB_INTERFACE": + # First delete subinterface, once subinterface deletion successful, + # recreate same with same config on default vrf + if 'state_db' not in ctx.obj: + if ctx.obj['namespace'] is DEFAULT_NAMESPACE: + state_db = SonicV2Connector(use_unix_socket_path=True) + else: + state_db = SonicV2Connector(use_unix_socket_path=True, namespace=ctx.obj['namespace']) + state_db.connect(state_db.STATE_DB, False) + else: + state_db = ctx.obj['state_db'] + + config_db.set_entry(table_name, interface_name, None) + _hash = '{}{}'.format('INTERFACE_TABLE|', interface_name) + while state_db.exists(state_db.STATE_DB, _hash): + time.sleep(0.01) + state_db.close(state_db.STATE_DB) config_db.set_entry(table_name, interface_name, subintf_entry) else: config_db.set_entry(table_name, interface_name, None) diff --git a/tests/vrf_test.py b/tests/vrf_test.py index 954fbf692b..323f61dee7 100644 --- a/tests/vrf_test.py +++ b/tests/vrf_test.py @@ -6,7 +6,9 @@ import config.main as config import show.main as show +import threading +DEFAULT_NAMESPACE = '' test_path = os.path.dirname(os.path.abspath(__file__)) mock_db_path = os.path.join(test_path, "vrf_input") @@ -16,6 +18,11 @@ def setup_class(cls): print("SETUP") os.environ["UTILITIES_UNIT_TESTING"] = "1" + def update_statedb(self, db, db_name, key): + import time + time.sleep(0.5) + db.delete(db_name, key) + def test_vrf_show(self): from .mock_tables import dbconnector jsonfile_config = os.path.join(mock_db_path, "config_db") @@ -64,59 +71,81 @@ def test_vrf_bind_unbind(self): assert result.exit_code == 0 assert result.output == expected_output - obj = {'config_db':db.cfgdb} + + vrf_obj = {'config_db':db.cfgdb, 'namespace':db.db.namespace} expected_output_unbind = "Interface Ethernet4 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Ethernet4"], obj=obj) + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Ethernet4"], obj=vrf_obj) + print(result.exit_code, result.output) assert result.exit_code == 0 assert 'Ethernet4' not in db.cfgdb.get_table('INTERFACE') assert result.output == expected_output_unbind expected_output_unbind = "Interface Loopback0 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Loopback0"], obj=obj) + + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Loopback0"], obj=vrf_obj) + print(result.exit_code, result.output) assert result.exit_code == 0 assert 'Loopback0' not in db.cfgdb.get_table('LOOPBACK_INTERFACE') assert result.output == expected_output_unbind expected_output_unbind = "Interface Vlan40 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Vlan40"], obj=obj) + + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Vlan40"], obj=vrf_obj) + print(result.exit_code, result.output) assert result.exit_code == 0 assert 'Vlan40' not in db.cfgdb.get_table('VLAN_INTERFACE') assert result.output == expected_output_unbind expected_output_unbind = "Interface PortChannel0002 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["PortChannel0002"], obj=obj) + + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["PortChannel0002"], obj=vrf_obj) + print(result.exit_code, result.output) assert result.exit_code == 0 assert 'PortChannel002' not in db.cfgdb.get_table('PORTCHANNEL_INTERFACE') assert result.output == expected_output_unbind + vrf_obj = {'config_db':db.cfgdb, 'namespace':DEFAULT_NAMESPACE} + state_db = SonicV2Connector(use_unix_socket_path=True, namespace='') + state_db.connect(state_db.STATE_DB, False) + _hash = "INTERFACE_TABLE|Eth36.10" + state_db.set(db.db.STATE_DB, _hash, "state", "ok") + vrf_obj['state_db'] = state_db + expected_output_unbind = "Interface Eth36.10 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Eth36.10"], obj=obj) + T1 = threading.Thread( target = self.update_statedb, args = (state_db, db.db.STATE_DB, _hash)) + T1.start() + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Eth36.10"], obj=vrf_obj) + T1.join() print(result.exit_code, result.output) assert result.exit_code == 0 assert ('vrf_name', 'Vrf102') not in db.cfgdb.get_table('VLAN_SUB_INTERFACE')['Eth36.10'] assert result.output == expected_output_unbind + vrf_obj = {'config_db':db.cfgdb, 'namespace':DEFAULT_NAMESPACE} + expected_output_unbind = "Interface Ethernet0.10 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Ethernet0.10"], obj=obj) + + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Ethernet0.10"], obj=vrf_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'] assert result.output == expected_output_unbind expected_output_unbind = "Interface Po0002.101 IP disabled and address(es) removed due to unbinding VRF.\n" - result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Po0002.101"], obj=obj) + + result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["unbind"], ["Po0002.101"], obj=vrf_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'] assert result.output == expected_output_unbind - vrf_obj = {'config_db':db.cfgdb, 'namespace':db.db.namespace} - expected_output_bind = "Interface Ethernet0 IP disabled and address(es) removed due to binding VRF Vrf1.\n" result = runner.invoke(config.config.commands["interface"].commands["vrf"].commands["bind"], ["Ethernet0", "Vrf1"], obj=vrf_obj) assert result.exit_code == 0