Browse Source

[L3] Check agent gateway port robustly

In patch [1] it introduced a binding of DB uniq constraint for L3
agent gateway. In some extreme case the DvrFipGatewayPortAgentBinding
is in DB while the gateway port not. The current code path only checks
the binding existence which will pass a "None" port to the following
code path that results an AttributeError. This patch adds a simple check
for that gateway port, if it is not created, new one.

[1] https://review.opendev.org/#/c/702547/

Closes-Bug: #1883089
Change-Id: Ia90f2ee435b0a3476dbea028d3200cefe11e35e4
changes/32/735432/3
LIU Yulong 2 years ago
parent
commit
5fdfd4cbfc
  1. 3
      neutron/db/l3_dvr_db.py
  2. 36
      neutron/tests/unit/db/test_l3_dvr_db.py

3
neutron/db/l3_dvr_db.py

@ -1065,13 +1065,14 @@ class _DVRAgentInterfaceMixin(object):
try:
fip_agent_port_obj.create()
except o_exc.NeutronDbObjectDuplicateEntry:
LOG.debug("Floating IP Agent Gateway port for network "
LOG.debug("Floating IP Gateway port agent binding for network "
"%(network)s already exists on host %(host)s. "
"Probably it was just created by other worker.",
{'network': network_id,
'host': host})
agent_port = self._get_agent_gw_ports_exist_for_network(
context, network_id, host, l3_agent_db['id'])
if agent_port:
LOG.debug("Floating IP Agent Gateway port %(gw)s found "
"for the destination host: %(dest_host)s",
{'gw': agent_port,

36
neutron/tests/unit/db/test_l3_dvr_db.py

@ -763,6 +763,42 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
mock.call(self.ctx, network_id, 'host', fipagent['id'])])
self.assertIsNotNone(fport)
def test_create_fip_agent_gw_port_agent_binding_exists(self):
network_id = _uuid()
fport_db = {'id': _uuid()}
self.mixin._get_agent_gw_ports_exist_for_network = mock.Mock(
side_effect=[None, None])
fipagent = agent_obj.Agent(
self.ctx,
id=_uuid(),
binary='foo-agent',
host='host',
agent_type='L3 agent',
topic='foo_topic',
configurations={"agent_mode": "dvr"})
self.mixin._get_agent_by_type_and_host = mock.Mock(
return_value=fipagent)
self.mixin._populate_mtu_and_subnets_for_ports = mock.Mock()
with mock.patch.object(
router_obj.DvrFipGatewayPortAgentBinding, 'create',
side_effect=o_exc.NeutronDbObjectDuplicateEntry(
mock.Mock(), mock.Mock())
) as dvr_fip_gateway_port_agent_binding_create,\
mock.patch.object(
plugin_utils, "create_port", return_value=fport_db):
fport = self.mixin.create_fip_agent_gw_port_if_not_exists(
self.ctx,
network_id,
'host')
dvr_fip_gateway_port_agent_binding_create.assert_called_once_with()
self.mixin._get_agent_gw_ports_exist_for_network.assert_has_calls([
mock.call(self.ctx, network_id, 'host', fipagent['id']),
mock.call(self.ctx, network_id, 'host', fipagent['id'])])
self.mixin._populate_mtu_and_subnets_for_ports.assert_has_calls([
mock.call(self.ctx, [fport_db])])
self.assertIsNotNone(fport)
def test_create_floatingip_agent_gw_port_with_non_dvr_router(self):
floatingip = {
'id': _uuid(),

Loading…
Cancel
Save