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
|
||||||
from neutron_lib.api.definitions import logging_resource
|
from neutron_lib.api.definitions import logging_resource
|
||||||
from neutron_lib.api.definitions import metering
|
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
|
||||||
from neutron_lib.api.definitions import network_availability_zone
|
from neutron_lib.api.definitions import network_availability_zone
|
||||||
from neutron_lib.api.definitions import network_ip_availability
|
from neutron_lib.api.definitions import network_ip_availability
|
||||||
@@ -93,6 +94,7 @@ _ALL_API_DEFINITIONS = {
|
|||||||
logging,
|
logging,
|
||||||
logging_resource,
|
logging_resource,
|
||||||
metering,
|
metering,
|
||||||
|
multiprovidernet,
|
||||||
network,
|
network,
|
||||||
network_availability_zone,
|
network_availability_zone,
|
||||||
network_ip_availability,
|
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