Merge "BigSwitch: Fixes floating IP backend updates"

This commit is contained in:
Jenkins 2013-12-23 16:13:25 +00:00 committed by Gerrit Code Review
commit dd3141f2bc
3 changed files with 110 additions and 15 deletions

View File

@ -1032,12 +1032,9 @@ class NeutronRestProxyV2(db_base_plugin_v2.NeutronDbPluginV2,
new_fl_ip = super(NeutronRestProxyV2,
self).create_floatingip(context, floatingip)
net_id = new_fl_ip['floating_network_id']
orig_net = super(NeutronRestProxyV2, self).get_network(context,
net_id)
# create floatingip on the network controller
try:
self._send_update_network(orig_net, context)
self._send_floatingip_update(context)
except RemoteRestError as e:
with excutils.save_and_reraise_exception():
LOG.error(
@ -1054,32 +1051,27 @@ class NeutronRestProxyV2(db_base_plugin_v2.NeutronDbPluginV2,
new_fl_ip = super(NeutronRestProxyV2,
self).update_floatingip(context, id, floatingip)
net_id = new_fl_ip['floating_network_id']
orig_net = super(NeutronRestProxyV2, self).get_network(context,
net_id)
# update network on network controller
self._send_update_network(orig_net, context)
self._send_floatingip_update(context)
return new_fl_ip
def delete_floatingip(self, context, id):
LOG.debug(_("NeutronRestProxyV2: delete_floatingip() called"))
orig_fl_ip = super(NeutronRestProxyV2, self).get_floatingip(context,
id)
with context.session.begin(subtransactions=True):
# delete floating IP in DB
net_id = orig_fl_ip['floating_network_id']
super(NeutronRestProxyV2, self).delete_floatingip(context, id)
orig_net = super(NeutronRestProxyV2, self).get_network(context,
net_id)
# update network on network controller
self._send_update_network(orig_net, context)
self._send_floatingip_update(context)
def disassociate_floatingips(self, context, port_id):
LOG.debug(_("NeutronRestProxyV2: diassociate_floatingips() called"))
super(NeutronRestProxyV2, self).disassociate_floatingips(context,
port_id)
self._send_floatingip_update(context)
def _send_floatingip_update(self, context):
try:
ext_net_id = self.get_external_network_id(context)
if ext_net_id:

View File

@ -17,6 +17,12 @@
# @author: Kevin Benton, <kevin.benton@bigswitch.com>
#
import json
from neutron.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class HTTPResponseMock():
status = 200
@ -50,7 +56,7 @@ class HTTPResponseMock500(HTTPResponseMock):
return "{'status': '%s'}" % self.errmsg
class HTTPConnectionMock():
class HTTPConnectionMock(object):
def __init__(self, server, port, timeout):
self.response = None
@ -62,6 +68,10 @@ class HTTPConnectionMock():
self.response = HTTPResponseMock500(None, errmsg=errmsg)
def request(self, action, uri, body, headers):
LOG.debug(_("Request: action=%(action)s, uri=%(uri)r, "
"body=%(body)s, headers=%(headers)s"),
{'action': action, 'uri': uri,
'body': body, 'headers': headers})
if self.broken and "ExceptOnBadServer" in uri:
raise Exception("Broken server got an unexpected request")
if self.response:
@ -94,3 +104,27 @@ class HTTPConnectionMock500(HTTPConnectionMock):
def __init__(self, server, port, timeout):
self.response = HTTPResponseMock500(None)
self.broken = True
class VerifyMultiTenantFloatingIP(HTTPConnectionMock):
def request(self, action, uri, body, headers):
# Only handle network update requests
if 'network' in uri and 'tenant' in uri and 'ports' not in uri:
req = json.loads(body)
if 'network' not in req or 'floatingips' not in req['network']:
msg = _("No floating IPs in request"
"uri=%(uri)s, body=%(body)s") % {'uri': uri,
'body': body}
raise Exception(msg)
distinct_tenants = []
for flip in req['network']['floatingips']:
if flip['tenant_id'] not in distinct_tenants:
distinct_tenants.append(flip['tenant_id'])
if len(distinct_tenants) < 2:
msg = _("Expected floating IPs from multiple tenants."
"uri=%(uri)s, body=%(body)s") % {'uri': uri,
'body': body}
raise Exception(msg)
super(VerifyMultiTenantFloatingIP,
self).request(action, uri, body, headers)

View File

@ -18,6 +18,7 @@
# @author: Sumit Naiksatam, sumitnaiksatam@gmail.com
#
import contextlib
import copy
import os
@ -31,6 +32,7 @@ from neutron.extensions import l3
from neutron.manager import NeutronManager
from neutron.openstack.common.notifier import api as notifier_api
from neutron.openstack.common.notifier import test_notifier
from neutron.openstack.common import uuidutils
from neutron.plugins.bigswitch.extensions import routerrule
from neutron.tests.unit.bigswitch import fake_server
from neutron.tests.unit.bigswitch import test_base
@ -39,6 +41,9 @@ from neutron.tests.unit import test_extension_extradhcpopts as test_extradhcp
from neutron.tests.unit import test_l3_plugin
_uuid = uuidutils.generate_uuid
def new_L3_setUp(self):
test_config['plugin_name_v2'] = (
'neutron.plugins.bigswitch.plugin.NeutronRestProxyV2')
@ -141,6 +146,70 @@ class RouterDBTestCase(test_base.BigSwitchTestBase,
# remove extra port created
self._delete('ports', p2['port']['id'])
def test_multi_tenant_flip_alllocation(self):
tenant1_id = _uuid()
tenant2_id = _uuid()
with contextlib.nested(
self.network(tenant_id=tenant1_id),
self.network(tenant_id=tenant2_id)) as (n1, n2):
with contextlib.nested(
self.subnet(network=n1, cidr='11.0.0.0/24'),
self.subnet(network=n2, cidr='12.0.0.0/24'),
self.subnet(cidr='13.0.0.0/24')) as (s1, s2, psub):
with contextlib.nested(
self.router(tenant_id=tenant1_id),
self.router(tenant_id=tenant2_id),
self.port(subnet=s1, tenant_id=tenant1_id),
self.port(subnet=s2, tenant_id=tenant2_id)) as (r1, r2,
p1, p2):
self._set_net_external(psub['subnet']['network_id'])
s1id = p1['port']['fixed_ips'][0]['subnet_id']
s2id = p2['port']['fixed_ips'][0]['subnet_id']
s1 = {'subnet': {'id': s1id}}
s2 = {'subnet': {'id': s2id}}
self._add_external_gateway_to_router(
r1['router']['id'],
psub['subnet']['network_id'])
self._add_external_gateway_to_router(
r2['router']['id'],
psub['subnet']['network_id'])
self._router_interface_action(
'add', r1['router']['id'],
s1['subnet']['id'], None)
self._router_interface_action(
'add', r2['router']['id'],
s2['subnet']['id'], None)
fl1 = self._make_floatingip_for_tenant_port(
net_id=psub['subnet']['network_id'],
port_id=p1['port']['id'],
tenant_id=tenant1_id)
multiFloatPatch = patch(
'httplib.HTTPConnection',
create=True,
new=fake_server.VerifyMultiTenantFloatingIP)
multiFloatPatch.start()
fl2 = self._make_floatingip_for_tenant_port(
net_id=psub['subnet']['network_id'],
port_id=p2['port']['id'],
tenant_id=tenant2_id)
multiFloatPatch.stop()
self._delete('floatingips', fl1['floatingip']['id'])
self._delete('floatingips', fl2['floatingip']['id'])
self._router_interface_action(
'remove', r1['router']['id'],
s1['subnet']['id'], None)
self._router_interface_action(
'remove', r2['router']['id'],
s2['subnet']['id'], None)
def _make_floatingip_for_tenant_port(self, net_id, port_id, tenant_id):
data = {'floatingip': {'floating_network_id': net_id,
'tenant_id': tenant_id,
'port_id': port_id}}
floatingip_req = self.new_create_request('floatingips', data, self.fmt)
res = floatingip_req.get_response(self.ext_api)
return self.deserialize(self.fmt, res)
def test_floatingip_with_invalid_create_port(self):
self._test_floatingip_with_invalid_create_port(
'neutron.plugins.bigswitch.plugin.NeutronRestProxyV2')