Skip to content

Commit

Permalink
Make create_floatingip support transaction
Browse files Browse the repository at this point in the history
Fixes bug #1064748
Also added unit test

Change-Id: I82b2031af0a87a92ace9a8b86f89772beaca5e8f
  • Loading branch information
Nachi Ueno authored and Gary Kotton committed Oct 28, 2012
1 parent ee0fbe3 commit 7c8a55c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 21 deletions.
39 changes: 18 additions & 21 deletions quantum/db/l3_db.py
Expand Up @@ -538,27 +538,26 @@ def create_floatingip(self, context, floatingip):
# 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,
Expand All @@ -580,8 +579,6 @@ def create_floatingip(self, context, floatingip):
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)
Expand Down
39 changes: 39 additions & 0 deletions quantum/tests/unit/test_l3_plugin.py
Expand Up @@ -31,6 +31,7 @@

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
Expand Down Expand Up @@ -804,6 +805,44 @@ def test_floatingip_crd_ops(self):
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':
Expand Down

0 comments on commit 7c8a55c

Please sign in to comment.