diff --git a/neutron/extensions/multiprovidernet.py b/neutron/extensions/multiprovidernet.py index f1f9e029c2f..2bc7307a18e 100644 --- a/neutron/extensions/multiprovidernet.py +++ b/neutron/extensions/multiprovidernet.py @@ -13,76 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -from neutron_lib.api import converters -from neutron_lib.api.definitions import provider_net as pnet +from neutron_lib.api.definitions import multiprovidernet as apidef from neutron_lib.api import extensions -from neutron_lib.api import validators -from neutron_lib import constants -from neutron_lib import exceptions as nexception -import webob.exc - -from neutron._i18n import _ - -SEGMENTS = 'segments' -class SegmentsSetInConjunctionWithProviders(nexception.InvalidInput): - message = _("Segments and provider values cannot both be set.") - - -class SegmentsContainDuplicateEntry(nexception.InvalidInput): - message = _("Duplicate segment entry in request.") - - -def _convert_and_validate_segments(segments, valid_values=None): - for segment in segments: - segment.setdefault(pnet.NETWORK_TYPE, constants.ATTR_NOT_SPECIFIED) - segment.setdefault(pnet.PHYSICAL_NETWORK, constants.ATTR_NOT_SPECIFIED) - segmentation_id = segment.get(pnet.SEGMENTATION_ID) - if segmentation_id: - segment[pnet.SEGMENTATION_ID] = converters.convert_to_int( - segmentation_id) - else: - segment[pnet.SEGMENTATION_ID] = constants.ATTR_NOT_SPECIFIED - if len(segment.keys()) != 3: - msg = (_("Unrecognized attribute(s) '%s'") % - ', '.join(set(segment.keys()) - - set([pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, - pnet.SEGMENTATION_ID]))) - raise webob.exc.HTTPBadRequest(msg) - - -def check_duplicate_segments(segments, is_partial_func=None): - """Helper function checking duplicate segments. - - If is_partial_funcs is specified and not None, then - SegmentsContainDuplicateEntry is raised if two segments are identical and - non partially defined (is_partial_func(segment) == False). - Otherwise SegmentsContainDuplicateEntry is raised if two segment are - identical. - """ - if is_partial_func is not None: - segments = [s for s in segments if not is_partial_func(s)] - fully_specifieds = [tuple(sorted(s.items())) for s in segments] - if len(set(fully_specifieds)) != len(fully_specifieds): - raise SegmentsContainDuplicateEntry() - -validators.add_validator('convert_segments', - _convert_and_validate_segments) - -EXTENDED_ATTRIBUTES_2_0 = { - 'networks': { - SEGMENTS: {'allow_post': True, 'allow_put': True, - 'validate': {'type:convert_segments': None}, - 'convert_list_to': converters.convert_kvp_list_to_dict, - 'default': constants.ATTR_NOT_SPECIFIED, - 'enforce_policy': True, - 'is_visible': True}, - } -} - - -class Multiprovidernet(extensions.ExtensionDescriptor): +class Multiprovidernet(extensions.APIExtensionDescriptor): """Extension class supporting multiple provider networks. This class is used by neutron's extension framework to make @@ -95,25 +30,4 @@ class Multiprovidernet(extensions.ExtensionDescriptor): 'segments' attribute. """ - @classmethod - def get_name(cls): - return "Multi Provider Network" - - @classmethod - def get_alias(cls): - return "multi-provider" - - @classmethod - def get_description(cls): - return ("Expose mapping of virtual networks to multiple physical " - "networks") - - @classmethod - def get_updated(cls): - return "2013-06-27T10:00:00-00:00" - - def get_extended_resources(self, version): - if version == "2.0": - return EXTENDED_ATTRIBUTES_2_0 - else: - return {} + api_definition = apidef diff --git a/neutron/plugins/ml2/managers.py b/neutron/plugins/ml2/managers.py index a7b6e7d8a34..f75b5bc643a 100644 --- a/neutron/plugins/ml2/managers.py +++ b/neutron/plugins/ml2/managers.py @@ -14,11 +14,13 @@ # under the License. from neutron_lib.api.definitions import external_net as extnet_apidef +from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef from neutron_lib.api.definitions import portbindings from neutron_lib.api.definitions import provider_net as provider from neutron_lib.api import validators from neutron_lib import constants from neutron_lib import exceptions as exc +from neutron_lib.exceptions import multiprovidernet as mpnet_exc from neutron_lib.exceptions import vlantransparent as vlan_exc from neutron_lib.plugins.ml2 import api from oslo_config import cfg @@ -30,7 +32,6 @@ from neutron._i18n import _ from neutron.conf.plugins.ml2 import config from neutron.db import api as db_api from neutron.db import segments_db -from neutron.extensions import multiprovidernet as mpnet from neutron.plugins.ml2.common import exceptions as ml2_exc from neutron.plugins.ml2 import models @@ -108,14 +109,15 @@ class TypeManager(stevedore.named.NamedExtensionManager): for attr in provider.ATTRIBUTES): # Verify that multiprovider and provider attributes are not set # at the same time. - if validators.is_attr_set(network.get(mpnet.SEGMENTS)): - raise mpnet.SegmentsSetInConjunctionWithProviders() + if validators.is_attr_set(network.get(mpnet_apidef.SEGMENTS)): + raise mpnet_exc.SegmentsSetInConjunctionWithProviders() segment = self._get_provider_segment(network) return [self._process_provider_segment(segment)] - elif validators.is_attr_set(network.get(mpnet.SEGMENTS)): + elif validators.is_attr_set(network.get(mpnet_apidef.SEGMENTS)): segments = [self._process_provider_segment(s) - for s in network[mpnet.SEGMENTS]] - mpnet.check_duplicate_segments(segments, self.is_partial_segment) + for s in network[mpnet_apidef.SEGMENTS]] + mpnet_apidef.check_duplicate_segments( + segments, self.is_partial_segment) return segments def _match_segment(self, segment, filters): @@ -137,8 +139,8 @@ class TypeManager(stevedore.named.NamedExtensionManager): if any(validators.is_attr_set(network.get(attr)) for attr in provider.ATTRIBUTES): segments = [self._get_provider_segment(network)] - elif validators.is_attr_set(network.get(mpnet.SEGMENTS)): - segments = self._get_attribute(network, mpnet.SEGMENTS) + elif validators.is_attr_set(network.get(mpnet_apidef.SEGMENTS)): + segments = self._get_attribute(network, mpnet_apidef.SEGMENTS) else: return True return any(self._match_segment(s, filters) for s in segments) @@ -167,7 +169,7 @@ class TypeManager(stevedore.named.NamedExtensionManager): for attr in provider.ATTRIBUTES: network[attr] = None elif len(segments) > 1: - network[mpnet.SEGMENTS] = [ + network[mpnet_apidef.SEGMENTS] = [ {provider.NETWORK_TYPE: segment[api.NETWORK_TYPE], provider.PHYSICAL_NETWORK: segment[api.PHYSICAL_NETWORK], provider.SEGMENTATION_ID: segment[api.SEGMENTATION_ID]} diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index d8a930c4eaf..5bd47f9339e 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -20,6 +20,7 @@ import mock import netaddr from neutron_lib.api.definitions import availability_zone as az_def from neutron_lib.api.definitions import external_net as extnet_apidef +from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef from neutron_lib.api.definitions import portbindings from neutron_lib.api.definitions import provider_net as pnet from neutron_lib.callbacks import events @@ -46,7 +47,6 @@ from neutron.db import models_v2 from neutron.db import provisioning_blocks from neutron.db import securitygroups_db as sg_db from neutron.db import segments_db -from neutron.extensions import multiprovidernet as mpnet from neutron.objects import base as base_obj from neutron.objects import router as l3_obj from neutron.plugins.ml2.common import exceptions as ml2_exc @@ -192,7 +192,7 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, ] # multiprovider networks self.mp_nets = [{'name': 'net4', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet2', pnet.SEGMENTATION_ID: 1}, @@ -306,13 +306,13 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, # verify network = self.deserialize(self.fmt, req.get_response(self.api))['network'] - if mpnet.SEGMENTS not in net: + if mpnet_apidef.SEGMENTS not in net: for k, v in net.items(): self.assertEqual(net[k], network[k]) - self.assertNotIn(mpnet.SEGMENTS, network) + self.assertNotIn(mpnet_apidef.SEGMENTS, network) else: - segments = network[mpnet.SEGMENTS] - expected_segments = net[mpnet.SEGMENTS] + segments = network[mpnet_apidef.SEGMENTS] + expected_segments = net[mpnet_apidef.SEGMENTS] self.assertEqual(len(expected_segments), len(segments)) for expected, actual in zip(expected_segments, segments): self.assertEqual(expected, actual) @@ -349,11 +349,12 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, networks = self._lookup_network_by_segmentation_id(lookup_vlan_id, 2) # get the mpnet - networks = [n for n in networks['networks'] if mpnet.SEGMENTS in n] + networks = [n for n in networks['networks'] + if mpnet_apidef.SEGMENTS in n] network = networks.pop() # verify attributes of the looked up item - segments = network[mpnet.SEGMENTS] - expected_segments = self.mp_nets[0][mpnet.SEGMENTS] + segments = network[mpnet_apidef.SEGMENTS] + expected_segments = self.mp_nets[0][mpnet_apidef.SEGMENTS] self.assertEqual(len(expected_segments), len(segments)) for expected, actual in zip(expected_segments, segments): self.assertEqual(expected, actual) @@ -401,7 +402,7 @@ class TestExternalNetwork(Ml2PluginV2TestCase): # External network will not have a segmentation id. self.assertIsNone(network['network'][pnet.SEGMENTATION_ID]) # External network will not have multiple segments. - self.assertNotIn(mpnet.SEGMENTS, network['network']) + self.assertNotIn(mpnet_apidef.SEGMENTS, network['network']) def test_external_network_type_vlan(self): cfg.CONF.set_default('external_network_type', @@ -417,12 +418,12 @@ class TestExternalNetwork(Ml2PluginV2TestCase): # External network will have a segmentation id. self.assertIsNotNone(network['network'][pnet.SEGMENTATION_ID]) # External network will not have multiple segments. - self.assertNotIn(mpnet.SEGMENTS, network['network']) + self.assertNotIn(mpnet_apidef.SEGMENTS, network['network']) class TestMl2NetworksWithVlanTransparencyBase(TestMl2NetworksV2): data = {'network': {'name': 'net1', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1'}], 'tenant_id': 'tenant_one', @@ -1553,7 +1554,7 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): net = { 'name': 'net1', - mpnet.SEGMENTS: [ + mpnet_apidef.SEGMENTS: [ { 'network_type': 'driver1', 'physical_network': 'physnet1' @@ -1569,7 +1570,7 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): net = { 'name': 'net1', - mpnet.SEGMENTS: [ + mpnet_apidef.SEGMENTS: [ { 'network_type': 'driver1', 'physical_network': 'physnet1' @@ -1611,7 +1612,7 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): net = { 'name': 'net1', - mpnet.SEGMENTS: [ + mpnet_apidef.SEGMENTS: [ { 'network_type': 'driver1', 'physical_network': 'physnet1' @@ -2118,11 +2119,11 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): self.assertEqual('vlan', network['network'][pnet.NETWORK_TYPE]) self.assertEqual('physnet1', network['network'][pnet.PHYSICAL_NETWORK]) self.assertEqual(1, network['network'][pnet.SEGMENTATION_ID]) - self.assertNotIn(mpnet.SEGMENTS, network['network']) + self.assertNotIn(mpnet_apidef.SEGMENTS, network['network']) def test_create_network_single_multiprovider(self): data = {'network': {'name': 'net1', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: 1}], @@ -2132,7 +2133,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): self.assertEqual('vlan', network['network'][pnet.NETWORK_TYPE]) self.assertEqual('physnet1', network['network'][pnet.PHYSICAL_NETWORK]) self.assertEqual(1, network['network'][pnet.SEGMENTATION_ID]) - self.assertNotIn(mpnet.SEGMENTS, network['network']) + self.assertNotIn(mpnet_apidef.SEGMENTS, network['network']) # Tests get_network() net_req = self.new_show_request('networks', network['network']['id']) @@ -2140,11 +2141,11 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): self.assertEqual('vlan', network['network'][pnet.NETWORK_TYPE]) self.assertEqual('physnet1', network['network'][pnet.PHYSICAL_NETWORK]) self.assertEqual(1, network['network'][pnet.SEGMENTATION_ID]) - self.assertNotIn(mpnet.SEGMENTS, network['network']) + self.assertNotIn(mpnet_apidef.SEGMENTS, network['network']) def test_create_network_multiprovider(self): data = {'network': {'name': 'net1', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: 1}, @@ -2155,9 +2156,9 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): network_req = self.new_create_request('networks', data) network = self.deserialize(self.fmt, network_req.get_response(self.api)) - segments = network['network'][mpnet.SEGMENTS] + segments = network['network'][mpnet_apidef.SEGMENTS] for segment_index, segment in enumerate(data['network'] - [mpnet.SEGMENTS]): + [mpnet_apidef.SEGMENTS]): for field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, pnet.SEGMENTATION_ID]: self.assertEqual(segment.get(field), @@ -2166,9 +2167,9 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): # Tests get_network() net_req = self.new_show_request('networks', network['network']['id']) network = self.deserialize(self.fmt, net_req.get_response(self.api)) - segments = network['network'][mpnet.SEGMENTS] + segments = network['network'][mpnet_apidef.SEGMENTS] for segment_index, segment in enumerate(data['network'] - [mpnet.SEGMENTS]): + [mpnet_apidef.SEGMENTS]): for field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, pnet.SEGMENTATION_ID]: self.assertEqual(segment.get(field), @@ -2176,7 +2177,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): def test_create_network_with_provider_and_multiprovider_fail(self): data = {'network': {'name': 'net1', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: 1}], @@ -2191,7 +2192,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): def test_create_network_duplicate_full_segments(self): data = {'network': {'name': 'net1', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: 1}, @@ -2205,7 +2206,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): def test_create_network_duplicate_partial_segments(self): data = {'network': {'name': 'net1', - mpnet.SEGMENTS: + mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1'}, {pnet.NETWORK_TYPE: 'vlan', @@ -2380,7 +2381,7 @@ class TestMl2HostsNetworkAccess(Ml2PluginV2TestCase): net = self.driver.create_network( self.context, {'network': {'name': 'net1', - mpnet.SEGMENTS: [ + mpnet_apidef.SEGMENTS: [ {pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: 1}, @@ -2880,7 +2881,8 @@ class TestML2Segments(Ml2PluginV2TestCase): mock.ANY, event, segments_plugin.Plugin(), self.context, seg1) # Make sure the mechanism manager can get the right amount of # segments of network - self.assertEqual(3, len(self.net_context.current[mpnet.SEGMENTS])) + self.assertEqual( + 3, len(self.net_context.current[mpnet_apidef.SEGMENTS])) def test_reserve_segment_nofity_mechanism_manager(self): self._test_nofity_mechanism_manager(events.PRECOMMIT_CREATE)