Fix for floatingip-delete not removing fip_gw port

fip_agent_gateway_port is created dynamically on a
compute node where FIP namespace is created. When
floatingip-disassociate is called this 'port' is
deleted.

But when we call floatingip-delete this port is
not deleted.

This patch fixes the issue mentioned above.

Closes-Bug: #1351066

Change-Id: I1aa51680394547390546fe362abfae7a5d25425b
This commit is contained in:
Swaminathan Vasudevan 2014-07-31 14:57:08 -07:00
parent 6f46e05d72
commit 6994ade726
2 changed files with 89 additions and 11 deletions

View File

@ -144,24 +144,41 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
previous_router_id = floatingip_db.router_id
port_id, internal_ip_address, router_id = (
self._check_and_get_fip_assoc(context, fip, floatingip_db))
agt_gw_port_check = False
admin_ctx = context.elevated()
if (not ('port_id' in fip and fip['port_id'])) and (
floatingip_db['fixed_port_id'] is not None):
port_db = self._core_plugin._get_port(
context, floatingip_db['fixed_port_id'])
LOG.debug("VM Port info: %s", port_db)
fip_hostid = self.get_vm_port_hostid(context, port_db['id'])
if fip_hostid:
agt_gw_port_check = self.check_fips_availability_on_host(
admin_ctx, fip['id'], fip_hostid)
self.clear_unused_fip_agent_gw_port(
admin_ctx, floatingip_db, fip['id'])
floatingip_db.update({'fixed_ip_address': internal_ip_address,
'fixed_port_id': port_id,
'router_id': router_id,
'last_known_router_id': previous_router_id})
if agt_gw_port_check:
LOG.debug('Deleting the Agent GW Port')
self.delete_floatingip_agent_gateway_port(admin_ctx, fip_hostid)
def clear_unused_fip_agent_gw_port(
self, context, floatingip_db, fip_id):
"""Helper function to check for fip agent gw port and delete.
This function checks on compute nodes to make sure if there
are any VMs using the FIP agent gateway port. If no VMs are
using the FIP agent gateway port, it will go ahead and delete
the FIP agent gateway port. If even a single VM is using the
port it will not delete.
"""
fip_hostid = self.get_vm_port_hostid(
context, floatingip_db['fixed_port_id'])
if fip_hostid and self.check_fips_availability_on_host(
context, fip_id, fip_hostid):
LOG.debug('Deleting the Agent GW Port on host: %s', fip_hostid)
self.delete_floatingip_agent_gateway_port(context, fip_hostid)
def delete_floatingip(self, context, id):
floatingip = self._get_floatingip(context, id)
if floatingip['fixed_port_id']:
admin_ctx = context.elevated()
self.clear_unused_fip_agent_gw_port(
admin_ctx, floatingip, id)
super(L3_NAT_with_dvr_db_mixin,
self).delete_floatingip(context, id)
def add_router_interface(self, context, router_id, interface_info):
add_by_port, add_by_sub = self._validate_interface_info(interface_info)

View File

@ -20,9 +20,13 @@ from neutron.common import constants as l3_const
from neutron import context
from neutron.db import l3_dvr_db
from neutron import manager
from neutron.openstack.common import uuidutils
from neutron.tests.unit import testlib_api
_uuid = uuidutils.generate_uuid
class L3DvrTestCase(testlib_api.SqlTestCase):
def setUp(self):
@ -170,3 +174,60 @@ class L3DvrTestCase(testlib_api.SqlTestCase):
gw_ports = {}
routers = self.mixin._build_routers_list(self.ctx, routers, gw_ports)
self.assertIsNone(routers[0].get('gw_port'))
def test_clear_unused_fip_agent_gw_port(self):
floatingip = {
'id': _uuid(),
'fixed_port_id': _uuid(),
'floating_network_id': _uuid()
}
fip_id = floatingip['id']
with contextlib.nested(
mock.patch.object(l3_dvr_db.l3_db.L3_NAT_db_mixin,
'_get_floatingip'),
mock.patch.object(self.mixin,
'get_vm_port_hostid'),
mock.patch.object(self.mixin,
'check_fips_availability_on_host'),
mock.patch.object(self.mixin,
'delete_floatingip_agent_gateway_port')
) as (gfips, gvm, cfips, dfips):
gfips.return_value = floatingip
gvm.return_value = 'my-host'
cfips.return_value = True
self.mixin.clear_unused_fip_agent_gw_port(
self.ctx, floatingip, fip_id)
self.assertTrue(dfips.called)
self.assertTrue(cfips.called)
self.assertTrue(gvm.called)
def _delete_floatingip_test_setup(self, floatingip):
fip_id = floatingip['id']
with contextlib.nested(
mock.patch.object(l3_dvr_db.l3_db.L3_NAT_db_mixin,
'_get_floatingip'),
mock.patch.object(self.mixin,
'clear_unused_fip_agent_gw_port'),
mock.patch.object(l3_dvr_db.l3_db.L3_NAT_db_mixin,
'delete_floatingip')) as (gf, vf, df):
gf.return_value = floatingip
self.mixin.delete_floatingip(self.ctx, fip_id)
return vf
def test_delete_floatingip_without_internal_port(self):
floatingip = {
'id': _uuid(),
'fixed_port_id': None,
'floating_network_id': _uuid()
}
mock_fip_clear = self._delete_floatingip_test_setup(floatingip)
self.assertFalse(mock_fip_clear.call_count)
def test_delete_floatingip_with_internal_port(self):
floatingip = {
'id': _uuid(),
'fixed_port_id': _uuid(),
'floating_network_id': _uuid()
}
mock_fip_clear = self._delete_floatingip_test_setup(floatingip)
self.assertTrue(mock_fip_clear.called)