Browse Source

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
changes/68/300268/17
Swaminathan Vasudevan 6 years ago committed by Oleg Bondarev
parent
commit
c198710dc5
  1. 20
      neutron/db/l3_agentschedulers_db.py
  2. 58
      neutron/tests/functional/services/l3_router/test_l3_dvr_router_plugin.py

20
neutron/db/l3_agentschedulers_db.py

@ -252,13 +252,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)

58
neutron/tests/functional/services/l3_router/test_l3_dvr_router_plugin.py

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

Loading…
Cancel
Save