]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix for floatingip-delete not removing fip_gw port
authorSwaminathan Vasudevan <swaminathan.vasudevan@hp.com>
Thu, 31 Jul 2014 21:57:08 +0000 (14:57 -0700)
committerSwaminathan Vasudevan <swaminathan.vasudevan@hp.com>
Tue, 26 Aug 2014 00:03:53 +0000 (17:03 -0700)
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

neutron/db/l3_dvr_db.py
neutron/tests/unit/db/test_l3_dvr_db.py

index b73ad851827fdd7b2785745acfd63643d001035c..75b8ab356aff98377e154d553b3b94337ec92d89 100644 (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)
index 2bcfa01ecd157e5bffbd672da05037a9b3ec6e6c..9612aa7b2a9348d2b6c7f57199271fe9bd0a68e0 100644 (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)