rehome multi provider net extension api definition
This patch rehomes the multi provider net extension's API definition and exceptions into neutron-lib. In addition a new validation and type is added as well as a utility function for checking duplicate segments. UTs and a release note are also included. Change-Id: If3367e6a14074a6225bba527e8f7e38c51280f85
This commit is contained in:
@@ -40,6 +40,7 @@ from neutron_lib.api.definitions import l3_flavors
|
||||
from neutron_lib.api.definitions import logging
|
||||
from neutron_lib.api.definitions import logging_resource
|
||||
from neutron_lib.api.definitions import metering
|
||||
from neutron_lib.api.definitions import multiprovidernet
|
||||
from neutron_lib.api.definitions import network
|
||||
from neutron_lib.api.definitions import network_availability_zone
|
||||
from neutron_lib.api.definitions import network_ip_availability
|
||||
@@ -93,6 +94,7 @@ _ALL_API_DEFINITIONS = {
|
||||
logging,
|
||||
logging_resource,
|
||||
metering,
|
||||
multiprovidernet,
|
||||
network,
|
||||
network_availability_zone,
|
||||
network_ip_availability,
|
||||
|
71
neutron_lib/api/definitions/multiprovidernet.py
Normal file
71
neutron_lib/api/definitions/multiprovidernet.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# Copyright (c) 2013 OpenStack Foundation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api import converters
|
||||
from neutron_lib.api.definitions import network
|
||||
from neutron_lib.api import validators
|
||||
from neutron_lib.api.validators import multiprovidernet as mp_validator
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.exceptions import multiprovidernet as mp_exc
|
||||
|
||||
|
||||
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 mp_exc.SegmentsContainDuplicateEntry()
|
||||
|
||||
|
||||
validators.add_validator(
|
||||
'network_segments', mp_validator.convert_and_validate_segments)
|
||||
|
||||
SEGMENTS = 'segments'
|
||||
|
||||
ALIAS = 'multi-provider'
|
||||
IS_SHIM_EXTENSION = False
|
||||
IS_STANDARD_ATTR_EXTENSION = False
|
||||
NAME = 'Multi Provider Network'
|
||||
API_PREFIX = ''
|
||||
DESCRIPTION = ("Expose mapping of virtual networks to multiple physical "
|
||||
"networks")
|
||||
UPDATED_TIMESTAMP = '2013-06-27T10:00:00-00:00'
|
||||
RESOURCE_NAME = network.RESOURCE_NAME
|
||||
COLLECTION_NAME = network.COLLECTION_NAME
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
COLLECTION_NAME: {
|
||||
SEGMENTS: {
|
||||
'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:network_segments': None},
|
||||
'convert_list_to': converters.convert_kvp_list_to_dict,
|
||||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'enforce_policy': True,
|
||||
'is_visible': True
|
||||
},
|
||||
}
|
||||
}
|
||||
SUB_RESOURCE_ATTRIBUTE_MAP = {}
|
||||
ACTION_MAP = {}
|
||||
REQUIRED_EXTENSIONS = []
|
||||
OPTIONAL_EXTENSIONS = []
|
||||
ACTION_STATUS = {}
|
39
neutron_lib/api/validators/multiprovidernet.py
Normal file
39
neutron_lib/api/validators/multiprovidernet.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2013 OpenStack Foundation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from webob import exc
|
||||
|
||||
from neutron_lib._i18n import _
|
||||
from neutron_lib.api import converters
|
||||
from neutron_lib.api.definitions import provider_net as pnet
|
||||
from neutron_lib import constants
|
||||
|
||||
|
||||
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) != 3:
|
||||
msg = (_("Unrecognized attribute(s) '%s'") %
|
||||
', '.join(set(segment.keys()) -
|
||||
set([pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
|
||||
pnet.SEGMENTATION_ID])))
|
||||
raise exc.HTTPBadRequest(msg)
|
25
neutron_lib/exceptions/multiprovidernet.py
Normal file
25
neutron_lib/exceptions/multiprovidernet.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2013 OpenStack Foundation.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib._i18n import _
|
||||
from neutron_lib import exceptions
|
||||
|
||||
|
||||
class SegmentsSetInConjunctionWithProviders(exceptions.InvalidInput):
|
||||
message = _("Segments and provider values cannot both be set.")
|
||||
|
||||
|
||||
class SegmentsContainDuplicateEntry(exceptions.InvalidInput):
|
||||
message = _("Duplicate segment entry in request.")
|
@@ -0,0 +1,46 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api.definitions import multiprovidernet
|
||||
from neutron_lib.api.definitions import provider_net
|
||||
from neutron_lib.exceptions import multiprovidernet as mp_exc
|
||||
from neutron_lib.tests.unit.api.definitions import base
|
||||
from neutron_lib.tests.unit.api.validators import test_multiprovidernet \
|
||||
as test_mpnet
|
||||
|
||||
|
||||
class MultiProviderNetworkDefinitionTestCase(base.DefinitionBaseTestCase):
|
||||
extension_module = multiprovidernet
|
||||
extension_attributes = (multiprovidernet.SEGMENTS,)
|
||||
|
||||
def test_check_duplicate_segments_with_dups(self):
|
||||
self.assertRaises(mp_exc.SegmentsContainDuplicateEntry,
|
||||
multiprovidernet.check_duplicate_segments,
|
||||
[test_mpnet._build_segment('nt0', 'pn0', 2),
|
||||
test_mpnet._build_segment('nt0', 'pn0', 2)])
|
||||
|
||||
def test_check_duplicate_segments_with_dups_and_partial(self):
|
||||
|
||||
def _seg_partial(seg):
|
||||
return seg[provider_net.PHYSICAL_NETWORK] == 'pn0'
|
||||
|
||||
self.assertIsNone(
|
||||
multiprovidernet.check_duplicate_segments(
|
||||
[test_mpnet._build_segment('nt0', 'pn0', 2),
|
||||
test_mpnet._build_segment('nt1', 'pn1', 2)],
|
||||
is_partial_func=_seg_partial))
|
||||
|
||||
def test_check_duplicate_segments_no_dups(self):
|
||||
self.assertIsNone(
|
||||
multiprovidernet.check_duplicate_segments(
|
||||
[test_mpnet._build_segment('nt0', 'pn0', 2),
|
||||
test_mpnet._build_segment('nt0', 'pn0', 3)]))
|
@@ -0,0 +1,49 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from webob import exc
|
||||
|
||||
from neutron_lib.api.definitions import provider_net
|
||||
from neutron_lib.api.validators import multiprovidernet as mp_validator
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.tests import _base as base
|
||||
|
||||
|
||||
def _build_segment(net_type=constants.ATTR_NOT_SPECIFIED,
|
||||
phy_net=constants.ATTR_NOT_SPECIFIED,
|
||||
seg_id=constants.ATTR_NOT_SPECIFIED):
|
||||
return {
|
||||
provider_net.NETWORK_TYPE: net_type,
|
||||
provider_net.PHYSICAL_NETWORK: phy_net,
|
||||
provider_net.SEGMENTATION_ID: seg_id
|
||||
}
|
||||
|
||||
|
||||
class TestMultiprovidernetValidators(base.BaseTestCase):
|
||||
|
||||
def test_convert_and_validate_segments_default_values(self):
|
||||
segs = [{}]
|
||||
mp_validator.convert_and_validate_segments(segs)
|
||||
self.assertEqual(
|
||||
[_build_segment()], segs)
|
||||
|
||||
def test_convert_and_validate_segments_seg_id_to_int(self):
|
||||
segs = [_build_segment(seg_id="9")]
|
||||
mp_validator.convert_and_validate_segments(segs)
|
||||
self.assertEqual(_build_segment(seg_id=9), segs[0])
|
||||
|
||||
def test_convert_and_validate_segments_invalid_key(self):
|
||||
segs = [_build_segment(seg_id=2)]
|
||||
segs[0]['some_key'] = 'some_value'
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
mp_validator.convert_and_validate_segments,
|
||||
segs)
|
@@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- The ``multi-provider`` extension's API definition is available in
|
||||
``neutron_lib.api.defintions.multiprovidernet``.
|
||||
- Exceptions for the ``multi-provider`` extension can be found in
|
||||
``neutron_lib.exceptions.multiprovidernet``.
|
||||
- The validation type ``type:network_segments`` is now available for
|
||||
API attribute validation.
|
Reference in New Issue
Block a user