Fix unscheduling fail when concurrent port delete

When a network is removed from a dhcp agent, in some scenarios if the
agent releases its port concurrently, there is chance that the
unscheduling will fail due to that the target port is not found.

Catch the PortNotFound exception as an expected error under this type of
concurrent circumstance and logs it to move forward.

Closes-Bug: #1775496
Change-Id: Ib51b364f6ced0de7685c8ee07c1d292308d919f5
Signed-off-by: Kailun Qin <kailun.qin@intel.com>
This commit is contained in:
Kailun Qin 2018-06-07 20:29:48 +08:00
parent 9d056139a8
commit fe907b7fc6
2 changed files with 23 additions and 3 deletions

View File

@ -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:

View File

@ -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(