Avoid redundant HA port creation during migration

When a router is migrated between DVR+HA and HA(i.e DVR+HA->HA and
HA->DVR+HA), redundant "network:router_ha_interface" ports are created.
For binding a HA router to a agent, existing code can create multiple
ports, but is using only one port and other ports remain still in DB
until router is deleted.

In this patch, when duplicate entry is detected while binding,
we remove the port which is created at that time for binding.

Closes-Bug: 1715370
Change-Id: I0c6c5f9dfce1bf2d99672b5cf9e072bfb0228a17
(cherry picked from commit 5b0165e940)
This commit is contained in:
venkata anil 2017-09-06 18:00:29 +00:00 committed by Ihar Hrachyshka
parent 82e13a257c
commit c169406778
2 changed files with 34 additions and 0 deletions

View File

@ -302,6 +302,11 @@ class L3Scheduler(object):
LOG.debug("Router %(router)s already scheduled for agent "
"%(agent)s", {'router': router_id,
'agent': agent['id']})
port_id = port_binding.port_id
# Below call will also delete entry from L3HARouterAgentPortBinding
# and RouterPort tables
plugin._core_plugin.delete_port(context, port_id,
l3_port_check=False)
except l3.RouterNotFound:
LOG.debug('Router %s has already been removed '
'by concurrent operation', router_id)

View File

@ -1368,6 +1368,35 @@ class L3HATestCaseMixin(testlib_api.SqlTestCase,
self.plugin, self.adminContext,
router['id'], router['tenant_id'], agent)
def test_create_ha_port_and_bind_wont_create_redundant_ports(self):
# When migrating from HA to DVR+HA router, create_ha_port_and_bind
# should create only one network:router_ha_interface port on a router
# when binding to same agent. So we need only one agent for testing
# (preferably with dvr_snat mode).
for agent in self.adminContext.session.query(
agent_model.Agent).all():
agent.admin_state_up = False
l3_dvr_snat_agent = helpers.register_l3_agent(
'fake_l3_host_dvr_snat', constants.L3_AGENT_MODE_DVR_SNAT)
router = self._create_ha_router(tenant_id='foo_tenant')
self.plugin.schedule_router(self.adminContext, router['id'])
router['admin_state_up'] = False
updated_router1 = self.plugin.update_router(
self.adminContext, router['id'], {'router': router})
updated_router1['distributed'] = True
self.plugin.update_router(
self.adminContext, router['id'], {'router': updated_router1})
self.plugin.router_scheduler.create_ha_port_and_bind(
self.plugin, self.adminContext, router['id'],
router['tenant_id'], l3_dvr_snat_agent)
filters = {'device_owner': ['network:router_ha_interface'],
'device_id': [router['id']]}
self.core_plugin = directory.get_plugin()
ports = self.core_plugin.get_ports(
self.adminContext, filters=filters)
self.assertEqual(1, len(ports))
def test_create_ha_port_and_bind_catch_router_not_found(self):
router = self._create_ha_router(tenant_id='foo_tenant')
self.plugin.schedule_router(self.adminContext, router['id'])