DVR: FloatingIP create throws an error if no l3 agent

FloatingIP create throws an error if the L3 agent is not running
on the given host for DVR Routers.
This happens when we try to create a DVR Router in the Legacy
Router deployed cloud.
FloatingIP create checks for the agent type based on the host,
and when agents are not available on the given host, it raises
an exception.
This patch will fixes by handling the exception raised, when the
agent is not available.

Change-Id: I80522d12087495861e832cf1c7a3fe9a7830d386
Closes-Bug: #1776566
(cherry picked from commit 5ceca4d9d1)
This commit is contained in:
Swaminathan Vasudevan 2018-06-12 15:22:57 -07:00
parent e8b937aca0
commit 65fcbc212d
2 changed files with 48 additions and 6 deletions

View File

@ -23,6 +23,7 @@ from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib import constants as const
from neutron_lib import exceptions as n_exc
from neutron_lib.exceptions import agent as agent_exc
from neutron_lib.exceptions import l3 as l3_exc
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
@ -860,8 +861,15 @@ class _DVRAgentInterfaceMixin(object):
will return the existing port and will not
create a new one.
"""
l3_agent_db = self._get_agent_by_type_and_host(
context, const.AGENT_TYPE_L3, host)
try:
l3_agent_db = self._get_agent_by_type_and_host(
context, const.AGENT_TYPE_L3, host)
except agent_exc.AgentNotFoundByTypeHost(
agent_type=const.AGENT_TYPE_L3, host=host):
LOG.warning("%(ag)s agent not found for the given host: %(host)s",
{'ag': const.AGENT_TYPE_L3,
'host': host})
return
l3_agent_mode = self._get_agent_mode(l3_agent_db)
if l3_agent_mode == l3_const.L3_AGENT_MODE_DVR_NO_EXTERNAL:
return
@ -1049,6 +1057,10 @@ class L3_NAT_with_dvr_db_mixin(_DVRAgentInterfaceMixin,
if host is not None:
l3_agent_on_host = self.get_dvr_agent_on_host(
context, host)
if not l3_agent_on_host:
LOG.warning("No valid L3 agent found for the given host: "
"%s", host)
return
agent_mode = self._get_agent_mode(l3_agent_on_host[0])
if agent_mode == l3_const.L3_AGENT_MODE_DVR_NO_EXTERNAL:
# If the agent hosting the fixed port is in

View File

@ -19,6 +19,7 @@ from neutron_lib.api.definitions import portbindings
from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
from neutron_lib.exceptions import agent as agent_exc
from neutron_lib import constants
from neutron_lib import context
@ -305,6 +306,10 @@ class L3DvrTestCase(L3DvrTestCaseBase):
self.l3_plugin._get_agent_gw_ports_exist_for_network(
self.context, ext_net_id, "", self.l3_agent['id']))
def test_create_floating_ip_with_no_dvr_agents(self):
self._test_create_floating_ip_agent_notification(
test_agent_mode=None)
def _test_create_floating_ip_agent_notification(
self, dvr=True, test_agent_mode=constants.L3_AGENT_MODE_DVR):
with self.subnet() as ext_subnet,\
@ -315,8 +320,9 @@ class L3DvrTestCase(L3DvrTestCaseBase):
self.context, int_port['port']['id'],
{'port': {portbindings.HOST_ID: 'host1'}})
# and create l3 agents on corresponding hosts
helpers.register_l3_agent(host='host1',
agent_mode=test_agent_mode)
if test_agent_mode is not None:
helpers.register_l3_agent(host='host1',
agent_mode=test_agent_mode)
# make net external
ext_net_id = ext_subnet['subnet']['network_id']
@ -331,6 +337,14 @@ class L3DvrTestCase(L3DvrTestCaseBase):
self.l3_plugin.add_router_interface(
self.context, router['id'],
{'subnet_id': int_subnet['subnet']['id']})
if test_agent_mode is None:
self.assertRaises(
agent_exc.AgentNotFoundByTypeHost,
self.l3_plugin.create_fip_agent_gw_port_if_not_exists,
self.context,
ext_net_id,
'host1')
return
floating_ip = {'floating_network_id': ext_net_id,
'router_id': router['id'],
'port_id': int_port['port']['id'],
@ -498,6 +512,10 @@ class L3DvrTestCase(L3DvrTestCaseBase):
def test_update_floating_ip_agent_notification_non_dvr(self):
self._test_update_floating_ip_agent_notification(dvr=False)
def test_delete_floating_ip_with_no_agents(self):
self._test_delete_floating_ip_agent_notification(
test_agent_mode=None)
def _test_delete_floating_ip_agent_notification(
self, dvr=True, test_agent_mode=constants.L3_AGENT_MODE_DVR):
with self.subnet() as ext_subnet,\
@ -531,8 +549,19 @@ class L3DvrTestCase(L3DvrTestCaseBase):
'dns_name': '', 'dns_domain': ''}
floating_ip = self.l3_plugin.create_floatingip(
self.context, {'floatingip': floating_ip})
if test_agent_mode is None:
with mock.patch.object(
self.l3_plugin, 'get_dvr_agent_on_host') as a_mock,\
mock.patch.object(self.l3_plugin,
'_l3_rpc_notifier') as l3_notif:
a_mock.return_value = None
self.l3_plugin.delete_floatingip(
self.context, floating_ip['id'])
self.assertFalse(
l3_notif.routers_updated_on_host.called)
return
with mock.patch.object(
self.l3_plugin, '_l3_rpc_notifier') as l3_notif:
self.l3_plugin, '_l3_rpc_notifier') as l3_notif:
self.l3_plugin.delete_floatingip(
self.context, floating_ip['id'])
if dvr:
@ -552,7 +581,8 @@ class L3DvrTestCase(L3DvrTestCaseBase):
assert_called_once_with(
self.context, [router['id']], 'host0')
self.assertFalse(l3_notif.routers_updated.called)
else:
if test_agent_mode == (
constants.L3_AGENT_MODE_DVR):
l3_notif.routers_updated_on_host.\
assert_called_once_with(
self.context, [router['id']], 'host1')