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
(cherry picked from commit 5fdfd4cbfc)
changes/13/779613/3
LIU Yulong 1 year ago
committed by Hemanth N
parent
commit
4093727ae9
2 changed files with 38 additions and 1 deletions
  1. +2
    -1
      neutron/db/l3_dvr_db.py
  2. +36
    -0
      neutron/tests/unit/db/test_l3_dvr_db.py

+ 2
- 1
neutron/db/l3_dvr_db.py View File

@ -1096,13 +1096,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
- 0
neutron/tests/unit/db/test_l3_dvr_db.py View File

@ -762,6 +762,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