diff --git a/networking_l2gw/db/l2gateway/ovsdb/lib.py b/networking_l2gw/db/l2gateway/ovsdb/lib.py index 806dc904..6194eb69 100644 --- a/networking_l2gw/db/l2gateway/ovsdb/lib.py +++ b/networking_l2gw/db/l2gateway/ovsdb/lib.py @@ -496,3 +496,12 @@ def get_all_pending_remote_macs_in_asc_order(context, ovsdb_identifier): ).filter_by(ovsdb_identifier=ovsdb_identifier ).order_by( asc(models.PendingUcastMacsRemote.timestamp)).all() + + +def get_all_ucast_mac_remote_by_ls(context, record_dict): + """Get ucast macs remote that matches ls_id and ovsdb_identifier.""" + session = context.session + with session.begin(): + return session.query(models.UcastMacsRemotes).filter_by( + ovsdb_identifier=record_dict['ovsdb_identifier'], + logical_switch_id=record_dict['logical_switch_id']).all() diff --git a/networking_l2gw/services/l2gateway/ovsdb/data.py b/networking_l2gw/services/l2gateway/ovsdb/data.py index 2b124b4c..379b6561 100644 --- a/networking_l2gw/services/l2gateway/ovsdb/data.py +++ b/networking_l2gw/services/l2gateway/ovsdb/data.py @@ -345,10 +345,48 @@ class OVSDBData(object): l2gw_id) vlan_bindings = db.get_all_vlan_bindings_by_physical_port( context, pp_dict) + ls_set = set() for vlan_binding in vlan_bindings: + vlan_binding['logical_switch_id'] = vlan_binding.get( + 'logical_switch_uuid') + if vlan_binding.get('logical_switch_uuid') in ls_set: + db.delete_vlan_binding(context, vlan_binding) + continue + bindings = db.get_all_vlan_bindings_by_logical_switch( + context, vlan_binding) + if bindings and len(bindings) == 1: + self._delete_macs_from_ovsdb( + context, + vlan_binding.get('logical_switch_uuid'), + self.ovsdb_identifier) + elif bindings and len(bindings) > 1: + flag = True + for binding in bindings: + if binding[ + 'ovsdb_identifier'] == self.ovsdb_identifier: + flag = False + break + if flag: + self._delete_macs_from_ovsdb( + context, + vlan_binding.get('logical_switch_uuid'), + self.ovsdb_identifier) + ls_set.add(vlan_binding.get('logical_switch_uuid')) db.delete_vlan_binding(context, vlan_binding) db.delete_physical_port(context, pp_dict) + def _delete_macs_from_ovsdb(self, context, logical_switch_id, + ovsdb_identifier): + mac_list = [] + ls_dict = {'logical_switch_id': logical_switch_id, + 'ovsdb_identifier': ovsdb_identifier} + macs = db.get_all_ucast_mac_remote_by_ls(context, ls_dict) + for mac in macs: + mac_list.append(mac.get('mac')) + self.agent_rpc.delete_vif_from_gateway( + context, ovsdb_identifier, + logical_switch_id, mac_list) + def _process_deleted_physical_locators(self, context, deleted_physical_locators): diff --git a/networking_l2gw/tests/unit/db/ovsdb/test_lib.py b/networking_l2gw/tests/unit/db/ovsdb/test_lib.py index d1659a1d..70e9184a 100644 --- a/networking_l2gw/tests/unit/db/ovsdb/test_lib.py +++ b/networking_l2gw/tests/unit/db/ovsdb/test_lib.py @@ -532,3 +532,14 @@ class OvsdbLibTestCase(testlib_api.SqlTestCase): record_dict['mac']) count = self.ctx.session.query(models.UcastMacsRemotes).count() self.assertEqual(count, 0) + + def test_get_all_ucast_mac_remote_by_ls(self): + record_dict = self._get_ucast_mac_remote_dict() + record_dict1 = self._create_ucast_mac_remote(record_dict) + record_dict = self._get_ucast_mac_remote_dict() + record_dict['mac'] = '00:11:22:33:44:55:66' + record_dict['logical_switch_id'] = record_dict1.get( + 'logical_switch_id') + self._create_ucast_mac_remote(record_dict) + mac_list = lib.get_all_ucast_mac_remote_by_ls(self.ctx, record_dict) + self.assertEqual(2, len(mac_list)) diff --git a/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py b/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py index f77b3832..41aabcc9 100644 --- a/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py +++ b/networking_l2gw/tests/unit/services/l2gateway/ovsdb/test_data.py @@ -418,6 +418,61 @@ class TestOVSDBData(base.BaseTestCase): l2gw_conn_del.assert_called_with(self.context, 'fake_uuid') delete_pp.assert_called_with(self.context, fake_dict) + def test_process_deleted_physical_ports_with_delete_macs(self): + fake_dict = {'uuid': 'fake_uuid', 'name': 'fake_name', + 'logical_switch_id': 'fake_ls_id', + 'ovsdb_identifier': 'fake_ovsdb_id'} + fake_deleted_physical_ports = [fake_dict] + fake_physical_port = {'uuid': 'fake_uuid', + 'name': 'fake_name', + 'ovsdb_identifier': 'fake_ovsdb_id'} + fake_physical_switch = {'uuid': 'fake_uuid', + 'ovsdb_identifier': 'fake_ovsdb_id', + 'name': 'fake_switch'} + vlan_binding_dict = {'logical_switch_uuid': 'fake_ls_id', + 'ovsdb_identifier': 'fake_ovsdb_id', + 'port_uuid': 'fake_uuid', + 'vlan': 'fake_vlan', + 'logical_switch_id': 'fake_ls_id'} + fake_vlan_binding_list = [vlan_binding_dict] + fake_binding_list = [vlan_binding_dict] + with contextlib.nested( + mock.patch.object(lib, + 'delete_physical_port'), + mock.patch.object(lib, + 'get_physical_port', + return_value=fake_physical_port), + mock.patch.object(lib, 'get_physical_switch', + return_vaue=fake_physical_switch), + mock.patch.object(l2gateway_db.L2GatewayMixin, + '_get_l2gw_ids_by_interface_switch', + return_value=['fake_uuid']), + mock.patch.object(l2gateway_db.L2GatewayMixin, + '_delete_connection_by_l2gw_id'), + mock.patch.object(lib, + 'get_all_vlan_bindings_by_physical_port', + return_value=fake_vlan_binding_list), + mock.patch.object(lib, + 'get_all_vlan_bindings_by_logical_switch', + return_value=fake_binding_list), + mock.patch.object(data.OVSDBData, '_delete_macs_from_ovsdb'), + mock.patch.object(lib, 'delete_vlan_binding') + ) as (delete_pp, get_pp, get_ps, get_l2gw, l2gw_conn_del, + get_vlan_by_pp, get_vlan_by_ls, del_macs, del_vlan): + self.ovsdb_data._process_deleted_physical_ports( + self.context, fake_deleted_physical_ports) + self.assertIn(n_const.OVSDB_IDENTIFIER, fake_dict) + self.assertEqual(fake_dict[n_const.OVSDB_IDENTIFIER], + 'fake_ovsdb_id') + l2gw_conn_del.assert_called_with(self.context, 'fake_uuid') + get_vlan_by_pp.assert_called_with(self.context, fake_dict) + del_vlan.assert_called_with(self.context, vlan_binding_dict) + get_vlan_by_ls.assert_called_with(self.context, vlan_binding_dict) + del_macs.assert_called_with(self.context, + 'fake_ls_id', 'fake_ovsdb_id') + del_vlan.assert_called_with(self.context, vlan_binding_dict) + delete_pp.assert_called_with(self.context, fake_dict) + def test_process_deleted_physical_locators(self): """Test case to test _process_deleted_physical_locators.