diff --git a/neutron/db/agentschedulers_db.py b/neutron/db/agentschedulers_db.py index 99018ff21c0..e39fcbcbc78 100644 --- a/neutron/db/agentschedulers_db.py +++ b/neutron/db/agentschedulers_db.py @@ -19,6 +19,7 @@ import time from neutron_lib import constants from neutron_lib import context as ncontext +from neutron_lib import exceptions as n_exc from neutron_lib.exceptions import agent as agent_exc from neutron_lib.exceptions import dhcpagentscheduler as das_exc from oslo_config import cfg @@ -408,7 +409,11 @@ class DhcpAgentSchedulerDbMixin(dhcpagentscheduler # update_port passing and another failing for port in ports: port['device_id'] = constants.DEVICE_ID_RESERVED_DHCP_PORT - self.update_port(context, port['id'], dict(port=port)) + try: + self.update_port(context, port['id'], dict(port=port)) + except n_exc.PortNotFound: + LOG.debug("DHCP port %s has been deleted concurrently", + port['id']) binding_obj.delete() if not notify: diff --git a/neutron/tests/unit/db/test_agentschedulers_db.py b/neutron/tests/unit/db/test_agentschedulers_db.py index c46f98552dc..23feb75dd65 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -600,13 +600,22 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): 'enable_services_on_agents_with_admin_state_down', True) self._test_network_add_to_dhcp_agent(admin_state_up=False) - def test_network_remove_from_dhcp_agent(self): + def _test_network_remove_from_dhcp_agent(self, + concurrent_port_delete=False): agent = helpers.register_dhcp_agent(DHCP_HOSTA) hosta_id = agent.id - with self.port() as port1: + with self.port(device_owner=constants.DEVICE_OWNER_DHCP, + host=DHCP_HOSTA) as port1: num_before_remove = len( self._list_networks_hosted_by_dhcp_agent( hosta_id)['networks']) + if concurrent_port_delete: + plugin = directory.get_plugin() + # Return a foo port to emulate the port not found scenario + # caused by a concurrent port deletion during unscheduling + port = {'id': 'foo_port_id', 'device_id': 'foo_device_id'} + mock.patch.object(plugin, 'get_ports', + return_value=[port]).start() self._remove_network_from_dhcp_agent(hosta_id, port1['port']['network_id']) num_after_remove = len( @@ -615,6 +624,12 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self.assertEqual(1, num_before_remove) self.assertEqual(0, num_after_remove) + def test_network_remove_from_dhcp_agent(self): + self._test_network_remove_from_dhcp_agent() + + def test_network_remove_from_dhcp_agent_on_concurrent_port_delete(self): + self._test_network_remove_from_dhcp_agent(concurrent_port_delete=True) + def test_list_active_networks_on_not_registered_yet_dhcp_agent(self): plugin = directory.get_plugin() nets = plugin.list_active_networks_on_active_dhcp_agent(