diff --git a/networking_l2gw/db/l2gateway/db_query.py b/networking_l2gw/db/l2gateway/db_query.py index d69e660..19ce9fb 100644 --- a/networking_l2gw/db/l2gateway/db_query.py +++ b/networking_l2gw/db/l2gateway/db_query.py @@ -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, diff --git a/networking_l2gw/services/l2gateway/common/constants.py b/networking_l2gw/services/l2gateway/common/constants.py index 74585d0..41398cb 100644 --- a/networking_l2gw/services/l2gateway/common/constants.py +++ b/networking_l2gw/services/l2gateway/common/constants.py @@ -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" diff --git a/networking_l2gw/services/l2gateway/exceptions.py b/networking_l2gw/services/l2gateway/exceptions.py index 01bfed6..0f02403 100644 --- a/networking_l2gw/services/l2gateway/exceptions.py +++ b/networking_l2gw/services/l2gateway/exceptions.py @@ -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, diff --git a/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py b/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py index 4673d4f..9a4c921 100644 --- a/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py +++ b/networking_l2gw/services/l2gateway/service_drivers/rpc_l2gw.py @@ -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, diff --git a/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py b/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py index 060cc16..e8856d9 100644 --- a/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py +++ b/networking_l2gw/tests/unit/services/l2gateway/service_drivers/test_rpc_l2gw.py @@ -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'