support multi segment network for l2gw connection

Since l2gateway binds vxlan(virtual side) to vlan(physical side) segment.
We are extracting only vxlan segment from the virtual network.
Since multi segment network can have multiple segmentation id's belonging
to different network types(vlan, gre, vxlan, etc), we are extracting the
vxlan segment from it.
We are checking for multiple vxlan segments in the network since ovsdb
does not allow multiple vxlan segmentation id's to associate for same
vlan (physical side) while creating l2_gateway_connection.
For Ex: say multi segment network has two vxlan segment id's 1000 and 2000.
If we create a l2_gateway_connection for this network by providing physical
side vlan segment as 500, the bindings should be 1000:500 and 2000:500,
this is not allowed in ovsdb hardware vtep schema.

Closes-Bug:1511639

Change-Id: I5f704eaf40763686aa30320dff7a99a16b6c1772
stable/ocata
vikas 8 years ago
parent 61f74e1422
commit a381726b53

@ -16,7 +16,6 @@
from neutron.common import exceptions
from neutron.db import models_v2
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2 import models
import sqlalchemy as sa
from sqlalchemy.orm import exc
@ -94,14 +93,6 @@ class L2GatewayCommonDbMixin(object):
items.reverse()
return items
def _get_network_segments(self, context, network_id):
"""Get network segments for the given network_id."""
with context.session.begin(subtransactions=True):
query = (context.session.query(models.NetworkSegment).
filter_by(network_id=network_id))
records = query.all()
return [self._make_segment_dict(record) for record in records]
def _make_segment_dict(self, record):
"""Make a segment dictionary out of a DB record."""
return {api.ID: record.id,

@ -42,3 +42,4 @@ MAX_RETRIES = 1000
L2_GATEWAY_SERVICE_PLUGIN = "Neutron L2 gateway Service Plugin"
PORT_FAULT_STATUS_UP = "UP"
SWITCH_FAULT_STATUS_UP = "UP"
VXLAN = "vxlan"

@ -79,8 +79,14 @@ class L2gatewaySegmentationIDNotFound(exceptions.NotFound):
"'%(gateway_id)s'")
class MultipleSegmentsFound(exceptions.NeutronException):
message = _("Multiple segments found for the network '%(network_id)s'")
class MultipleVxlanSegmentsFound(exceptions.NeutronException):
message = _("Multiple Vxlan segments found for the network "
"'%(network_id)s'")
class VxlanSegmentationIDNotFound(exceptions.NotFound):
message = _("vxlan segmentation id not found for the "
"network '%(network_id)s'")
class L2GatewayInterfaceRequired(exceptions.NeutronException):
@ -108,7 +114,8 @@ base.FAULT_MAP.update({L2GatewayInUse: web_exc.HTTPConflict,
L2GatewayPortInUse: web_exc.HTTPConflict,
L2GatewayConnectionExists: web_exc.HTTPConflict,
L2GatewayConnectionNotFound: web_exc.HTTPNotFound,
MultipleSegmentsFound: web_exc.HTTPConflict,
MultipleVxlanSegmentsFound: web_exc.HTTPConflict,
VxlanSegmentationIDNotFound: web_exc.HTTPNotFound,
L2GatewaySegmentationRequired: web_exc.HTTPConflict,
L2MultipleGatewayConnections: web_exc.HTTPConflict,
L2GatewayDuplicateSegmentationID: web_exc.HTTPConflict,

@ -177,19 +177,6 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
physical_locator,
[mac_remote])
def _form_logical_switch_schema(self, context, network, ls_dict):
logical_switch_uuid = None
logical_switch = db.get_logical_switch_by_name(
context, ls_dict)
if logical_switch:
logical_switch_uuid = logical_switch.get('uuid')
logical_switch = self._get_dict(ovsdb_schema.LogicalSwitch(
uuid=logical_switch_uuid,
name=network['id'],
key=network['provider:segmentation_id'],
description=network['name']))
return logical_switch
def _form_physical_locator_schema(self, context, pl_dict):
locator_uuid = None
locator = db.get_physical_locator_by_dst_ip(
@ -359,10 +346,6 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
nw_map['l2_gateway_id'] = l2_gw_id
if seg_id:
nw_map[constants.SEG_ID] = gw_connection.get(constants.SEG_ID)
net_segments_list = self.service_plugin._get_network_segments(
context, network_id)
if len(net_segments_list) > 1:
raise l2gw_exc.MultipleSegmentsFound(network_id=network_id)
if not self.service_plugin._get_network(context, network_id):
raise exceptions.NetworkNotFound(net_id=network_id)
if self.service_plugin._retrieve_gateway_connections(context,
@ -515,12 +498,29 @@ class L2gwRpcDriver(service_drivers.L2gwDriver):
uuid = logical_switch.get('uuid')
else:
uuid = None
network_id = gw_connection.get('network_id')
ls_dict = {'uuid': uuid,
'name': gw_connection.get('network_id')}
'name': network_id}
network = self._get_network_details(context,
gw_connection.get('network_id'))
network_id)
ls_dict['description'] = network.get('name')
ls_dict['key'] = network.get('provider:segmentation_id')
logical_segments = network.get('segments')
if logical_segments:
vxlan_seg_id = None
for seg in logical_segments:
if seg.get('provider:network_type') == constants.VXLAN:
if vxlan_seg_id:
raise l2gw_exc.MultipleVxlanSegmentsFound(
network_id=network_id)
vxlan_seg_id = seg.get('provider:segmentation_id')
ls_dict['key'] = vxlan_seg_id
if not vxlan_seg_id:
raise l2gw_exc.VxlanSegmentationIDNotFound(
network_id=network_id)
elif network.get('provider:network_type') == constants.VXLAN:
ls_dict['key'] = network.get('provider:segmentation_id')
else:
raise l2gw_exc.VxlanSegmentationIDNotFound(network_id=network_id)
return ls_dict
def _get_physical_locator_dict(self, dst_ip,

@ -122,8 +122,6 @@ class TestL2gwRpcDriver(base.BaseTestCase):
self.plugin._validate_connection(self.context, fake_connection)
is_vlan.assert_called_with(self.context, 'fake_l2gw_id')
val_ntwk.assert_called_with(fake_connection, False)
get_net_seg.assert_called_with(self.context,
'fake_network_id')
get_network.assert_called_with(self.context, 'fake_network_id')
get_l2gw.assert_called_with(self.context, 'fake_l2gw_id')
check_pf_sf.assert_called_with(self.context, 'fake_l2gw_id')
@ -308,6 +306,7 @@ class TestL2gwRpcDriver(base.BaseTestCase):
'segmentation_id': 100L}
fake_network = {'id': 'fake_network_id',
'name': 'fake_network_name',
'provider:network_type': 'vxlan',
'provider:segmentation_id': 'fake_key'}
fake_ls_dict = {'uuid': 'fake_uuid',
'name': 'fake_network_id',
@ -328,6 +327,80 @@ class TestL2gwRpcDriver(base.BaseTestCase):
self.assertEqual(ret_ls_dict, fake_ls_dict)
self.assertEqual(ret_ls_dict_without_ls, fake_ls_dict_without_ls)
def test_get_logical_switch_dict_for_multi_segment_network(self):
fake_logical_switch = {'uuid': 'fake_uuid',
'name': 'fake_network_id'}
fake_ls = None
fake_connection = {'l2_gateway_id': 'fake_l2gw_id',
'network_id': 'fake_network_id',
'segmentation_id': 100L}
fake_network = {'id': 'fake_network_id',
'name': 'fake_network_name',
'segments': [{"provider:network_type": "vxlan",
"provider:segmentation_id": 'fake_key'},
{"provider:network_type": "vlan",
"provider:segmentation_id": 'fake_key'}]}
fake_ls_dict = {'uuid': 'fake_uuid',
'name': 'fake_network_id',
'description': 'fake_network_name',
'key': 'fake_key'}
fake_ls_dict_without_ls = {'uuid': None,
'name': 'fake_network_id',
'description': 'fake_network_name',
'key': 'fake_key'}
with mock.patch.object(self.plugin,
'_get_network_details',
return_value=fake_network) as get_network:
ret_ls_dict = self.plugin._get_logical_switch_dict(
self.context, fake_logical_switch, fake_connection)
ret_ls_dict_without_ls = self.plugin._get_logical_switch_dict(
self.context, fake_ls, fake_connection)
get_network.assert_called_with(self.context, 'fake_network_id')
self.assertEqual(fake_ls_dict, ret_ls_dict)
self.assertEqual(fake_ls_dict_without_ls, ret_ls_dict_without_ls)
def test_get_logical_switch_dict_for_non_Vxlan_networks(self):
fake_logical_switch = {'uuid': 'fake_uuid',
'name': 'fake_network_id'}
fake_connection = {'l2_gateway_id': 'fake_l2gw_id',
'network_id': 'fake_network_id',
'segmentation_id': 100L}
fake_network = {'id': 'fake_network_id',
'name': 'fake_network_name',
'segments': [{"provider:network_type": "vlan",
"provider:segmentation_id": 'fake_key'},
{"provider:network_type": "gre",
"provider:segmentation_id": 'fake_key'}]}
with mock.patch.object(self.plugin,
'_get_network_details',
return_value=fake_network) as get_network:
self.assertRaises(l2gw_exc.VxlanSegmentationIDNotFound,
self.plugin._get_logical_switch_dict,
self.context, fake_logical_switch,
fake_connection)
get_network.assert_called_with(self.context, 'fake_network_id')
def test_get_logical_switch_dict_for_multiple_vxlan_segments(self):
fake_logical_switch = {'uuid': 'fake_uuid',
'name': 'fake_network_id'}
fake_connection = {'l2_gateway_id': 'fake_l2gw_id',
'network_id': 'fake_network_id',
'segmentation_id': 100L}
fake_network = {'id': 'fake_network_id',
'name': 'fake_network_name',
'segments': [{"provider:network_type": "vxlan",
"provider:segmentation_id": 'seg_1'},
{"provider:network_type": "vxlan",
"provider:segmentation_id": 'seg_2'}]}
with mock.patch.object(self.plugin,
'_get_network_details',
return_value=fake_network) as get_network:
self.assertRaises(l2gw_exc.MultipleVxlanSegmentsFound,
self.plugin._get_logical_switch_dict,
self.context, fake_logical_switch,
fake_connection)
get_network.assert_called_with(self.context, 'fake_network_id')
def test_get_locator_list(self):
fake_dst_ip = 'fake_tun_ip'
fake_ovsdb_id = 'fake_ovsdb_id'

Loading…
Cancel
Save