DVR: Moving router from dvr_snat node removes the qrouters

Removing the router from dvr_snat node removes the qrouters
that are servicing the VM and dhcp ports.

If there are still dvr serviceable ports in the dvr_snat node,
and if router remove command is executed to remove the router
association from the dvr_snat agent then only the snat
functionality should be moved to the the different agent
and the router namespaces should be untouched.

This patch checks if there are any dvr serviceable ports for
the dvr router and if exists, it will not send a router_remove
message to the agent, but instead will send an router_update
message to the agent.

Change-Id: I5a3ba329346ab0d5ea7b0296ec64cc8e5fb4056d
Closes-Bug: #1564575
(cherry picked from commit c198710dc5)
This commit is contained in:
Swaminathan Vasudevan 2016-03-31 17:48:09 -07:00
parent 6d1037cc30
commit 1f444899ca
2 changed files with 74 additions and 4 deletions

View File

@ -255,13 +255,25 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase,
self._unbind_router(context, router_id, agent_id)
router = self.get_router(context, router_id)
plugin = manager.NeutronManager.get_service_plugins().get(
service_constants.L3_ROUTER_NAT)
if router.get('ha'):
plugin = manager.NeutronManager.get_service_plugins().get(
service_constants.L3_ROUTER_NAT)
plugin.delete_ha_interfaces_on_host(context, router_id, agent.host)
# NOTE(Swami): Need to verify if there are DVR serviceable
# ports owned by this agent. If owned by this agent, then
# the routers should be retained. This flag will be used
# to check if there are valid routers in this agent.
retain_router = False
if router.get('distributed'):
subnet_ids = plugin.get_subnet_ids_on_router(context, router_id)
if subnet_ids and agent.host:
retain_router = plugin._check_dvr_serviceable_ports_on_host(
context, agent.host, subnet_ids)
l3_notifier = self.agent_notifiers.get(constants.AGENT_TYPE_L3)
if l3_notifier:
if retain_router and l3_notifier:
l3_notifier.routers_updated_on_host(
context, [router_id], agent.host)
elif l3_notifier:
l3_notifier.router_removed_from_agent(
context, router_id, agent.host)

View File

@ -831,6 +831,64 @@ class L3DvrTestCase(ml2_test_base.ML2TestFramework):
l3_notifier.router_removed_from_agent.assert_called_once_with(
mock.ANY, router['id'], HOST1)
def test_dvr_router_manual_rescheduling_removes_router(self):
router = self._create_router()
kwargs = {'arg_list': (external_net.EXTERNAL,),
external_net.EXTERNAL: True}
with self.network(**kwargs) as ext_net,\
self.subnet(network=ext_net),\
self.subnet(cidr='20.0.0.0/24') as subnet,\
self.port(subnet=subnet):
self.l3_plugin._update_router_gw_info(
self.context, router['id'],
{'network_id': ext_net['network']['id']})
self.l3_plugin.add_router_interface(
self.context, router['id'],
{'subnet_id': subnet['subnet']['id']})
self.l3_plugin.schedule_router(self.context,
router['id'],
candidates=[self.l3_agent])
# Now the VM should be also scheduled on the node
notifier = self.l3_plugin.agent_notifiers[
constants.AGENT_TYPE_L3]
with mock.patch.object(
notifier, 'router_removed_from_agent') as rtr_remove_mock:
self.l3_plugin.remove_router_from_l3_agent(
self.context, self.l3_agent['id'], router['id'])
rtr_remove_mock.assert_called_once_with(
self.context, router['id'], self.l3_agent['host'])
def test_dvr_router_manual_rescheduling_updates_router(self):
router = self._create_router()
kwargs = {'arg_list': (external_net.EXTERNAL,),
external_net.EXTERNAL: True}
with self.network(**kwargs) as ext_net,\
self.subnet(network=ext_net),\
self.subnet(cidr='20.0.0.0/24') as subnet,\
self.port(subnet=subnet,
device_owner=DEVICE_OWNER_COMPUTE) as port:
self.core_plugin.update_port(
self.context, port['port']['id'],
{'port': {'binding:host_id': self.l3_agent['host']}})
self.l3_plugin._update_router_gw_info(
self.context, router['id'],
{'network_id': ext_net['network']['id']})
self.l3_plugin.add_router_interface(
self.context, router['id'],
{'subnet_id': subnet['subnet']['id']})
self.l3_plugin.schedule_router(self.context,
router['id'],
candidates=[self.l3_agent])
# Now the VM should be also scheduled on the node
notifier = self.l3_plugin.agent_notifiers[
constants.AGENT_TYPE_L3]
with mock.patch.object(
notifier, 'routers_updated_on_host') as rtr_update_mock:
self.l3_plugin.remove_router_from_l3_agent(
self.context, self.l3_agent['id'], router['id'])
rtr_update_mock.assert_called_once_with(
self.context, [router['id']], self.l3_agent['host'])
def _test_router_remove_from_agent_on_vm_port_deletion(
self, non_admin_port=False):
# register l3 agent in dvr mode in addition to existing dvr_snat agent