]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Make create_floatingip support transaction
authorNachi Ueno <nachi@nttmcl.com>
Thu, 25 Oct 2012 21:14:48 +0000 (21:14 +0000)
committerNachi Ueno <nachi@nttmcl.com>
Fri, 26 Oct 2012 03:28:59 +0000 (03:28 +0000)
Fixes bug #1064748
Also added unit test

Change-Id: I82b2031af0a87a92ace9a8b86f89772beaca5e8f

quantum/db/l3_db.py
quantum/tests/unit/test_l3_plugin.py

index d03d9501d9461a90db5e2641679be1ece3939354..bd74a4d398ad7fb0bb79969f27a855da767099bd 100644 (file)
@@ -536,27 +536,26 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
         # This external port is never exposed to the tenant.
         # it is used purely for internal system and admin use when
         # managing floating IPs.
-        external_port = self.create_port(context.elevated(), {
-            'port':
-            {'tenant_id': '',  # tenant intentionally not set
-             'network_id': f_net_id,
-             'mac_address': attributes.ATTR_NOT_SPECIFIED,
-             'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
-             'admin_state_up': True,
-             'device_id': fip_id,
-             'device_owner': DEVICE_OWNER_FLOATINGIP,
-             'name': ''}})
-        # Ensure IP addresses are allocated on external port
-        if not external_port['fixed_ips']:
-            msg = "Unable to find any IP address on external network"
-            # remove the external port
-            self.delete_port(context.elevated(), external_port['id'],
-                             l3_port_check=False)
-            raise q_exc.BadRequest(resource='floatingip', msg=msg)
-
-        floating_ip_address = external_port['fixed_ips'][0]['ip_address']
         try:
             with context.session.begin(subtransactions=True):
+                external_port = self.create_port(context.elevated(), {
+                    'port':
+                    {'tenant_id': '',  # tenant intentionally not set
+                     'network_id': f_net_id,
+                     'mac_address': attributes.ATTR_NOT_SPECIFIED,
+                     'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
+                     'admin_state_up': True,
+                     'device_id': fip_id,
+                     'device_owner': DEVICE_OWNER_FLOATINGIP,
+                     'name': ''}})
+                # Ensure IP addresses are allocated on external port
+                if not external_port['fixed_ips']:
+                    msg = "Unable to find any IP address on external network"
+                    # remove the external port
+                    raise q_exc.BadRequest(resource='floatingip', msg=msg)
+
+                floating_fixed_ip = external_port['fixed_ips'][0]
+                floating_ip_address = floating_fixed_ip['ip_address']
                 floatingip_db = FloatingIP(
                     id=fip_id,
                     tenant_id=tenant_id,
@@ -578,8 +577,6 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
         except Exception:
             LOG.exception("Floating IP association failed")
             # Remove the port created for internal purposes
-            self.delete_port(context.elevated(), external_port['id'],
-                             l3_port_check=False)
             raise
 
         return self._make_floatingip_dict(floatingip_db)
index 6482a9f3e18e299a2c318a85724a8330ca3d16de..6133bcffd13775b3f07c1eda8e427a0be14de407 100644 (file)
@@ -31,6 +31,7 @@ from webob import exc
 
 from quantum.api.v2 import attributes
 from quantum.common import config
+from quantum.common import exceptions as q_exc
 from quantum.common.test_lib import test_config
 from quantum.common import utils
 from quantum import context
@@ -773,6 +774,44 @@ class L3NatDBTestCase(test_db_plugin.QuantumDbPluginV2TestCase):
         self._show('floatingips', fip['floatingip']['id'],
                    expected_code=exc.HTTPNotFound.code)
 
+    def test_floatingip_with_assoc_fails(self):
+        fmt = 'json'
+        with self.subnet() as public_sub:
+            self._set_net_external(public_sub['subnet']['network_id'])
+            with self.port() as private_port:
+                with self.router() as r:
+                    sid = private_port['port']['fixed_ips'][0]['subnet_id']
+                    private_sub = {'subnet': {'id': sid}}
+                    self._add_external_gateway_to_router(
+                        r['router']['id'],
+                        public_sub['subnet']['network_id'])
+                    self._router_interface_action('add', r['router']['id'],
+                                                  private_sub['subnet']['id'],
+                                                  None)
+                    PLUGIN_CLASS = 'quantum.db.l3_db.L3_NAT_db_mixin'
+                    METHOD = PLUGIN_CLASS + '._update_fip_assoc'
+                    with mock.patch(METHOD) as pl:
+                        pl.side_effect = q_exc.BadRequest(
+                            resource='floatingip',
+                            msg='fake_error')
+                        res = self._create_floatingip(
+                            fmt,
+                            public_sub['subnet']['network_id'],
+                            port_id=private_port['port']['id'])
+                        self.assertEqual(res.status_int, 400)
+
+                    for p in self._list('ports')['ports']:
+                        if p['device_owner'] == 'network:floatingip':
+                            self.fail('garbage port is not deleted')
+
+                    self._remove_external_gateway_from_router(
+                        r['router']['id'],
+                        public_sub['subnet']['network_id'])
+                    self._router_interface_action('remove',
+                                                  r['router']['id'],
+                                                  private_sub['subnet']['id'],
+                                                  None)
+
     def test_floatingip_update(self):
         with self.port() as p:
             private_sub = {'subnet': {'id':