BigSwitch: Fixes floating IP backend updates
Changes BigSwitch plugin to correctly use admin context on floating IP updates to the backend controller so they correctly contain floating IPs for all tenants. Closes-Bug: #1262488 Change-Id: I6f2666c242e6d9b0684943db073a2284d01fa1e0
This commit is contained in:
parent
b0c83077aa
commit
a77d24d155
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user