use multiprovidernet api definition from neutron-lib

The multiprovidernet API extension's definition was rehomed into
neutron-lib with commit If3367e6a14074a6225bba527e8f7e38c51280f85
This patch consumes it by:
- Using the APIExtensionDescriptor and API definition for the extension.
- Removing the rehomed (now duplicated) code from neutron.
- Using lib's code were applicable.

NeutronLibImpact

Change-Id: I12c15c360f8bf5a45fbe70e5ed1202ef0e7ec0f0
This commit is contained in:
Boden R 2018-01-18 13:14:13 -07:00
parent 93851ee6ff
commit b78d47927e
3 changed files with 45 additions and 127 deletions

View File

@ -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

View File

@ -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]}

View File

@ -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)