Merge "Add partial specs support in ML2 for multiprovider extension"
This commit is contained in:
commit
ff9a801bc2
@ -32,15 +32,9 @@ class SegmentsContainDuplicateEntry(qexception.InvalidInput):
|
|||||||
|
|
||||||
|
|
||||||
def _convert_and_validate_segments(segments, valid_values=None):
|
def _convert_and_validate_segments(segments, valid_values=None):
|
||||||
unique = set()
|
|
||||||
for segment in segments:
|
for segment in segments:
|
||||||
unique.add(tuple(segment.iteritems()))
|
segment.setdefault(pnet.NETWORK_TYPE, attr.ATTR_NOT_SPECIFIED)
|
||||||
network_type = segment.get(pnet.NETWORK_TYPE,
|
segment.setdefault(pnet.PHYSICAL_NETWORK, attr.ATTR_NOT_SPECIFIED)
|
||||||
attr.ATTR_NOT_SPECIFIED)
|
|
||||||
segment[pnet.NETWORK_TYPE] = network_type
|
|
||||||
physical_network = segment.get(pnet.PHYSICAL_NETWORK,
|
|
||||||
attr.ATTR_NOT_SPECIFIED)
|
|
||||||
segment[pnet.PHYSICAL_NETWORK] = physical_network
|
|
||||||
segmentation_id = segment.get(pnet.SEGMENTATION_ID)
|
segmentation_id = segment.get(pnet.SEGMENTATION_ID)
|
||||||
if segmentation_id:
|
if segmentation_id:
|
||||||
segment[pnet.SEGMENTATION_ID] = attr.convert_to_int(
|
segment[pnet.SEGMENTATION_ID] = attr.convert_to_int(
|
||||||
@ -53,7 +47,21 @@ def _convert_and_validate_segments(segments, valid_values=None):
|
|||||||
set([pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
|
set([pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
|
||||||
pnet.SEGMENTATION_ID])))
|
pnet.SEGMENTATION_ID])))
|
||||||
raise webob.exc.HTTPBadRequest(msg)
|
raise webob.exc.HTTPBadRequest(msg)
|
||||||
if len(unique) != len(segments):
|
|
||||||
|
|
||||||
|
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()
|
raise SegmentsContainDuplicateEntry()
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,6 +63,14 @@ class TypeDriver(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def is_partial_segment(self, segment):
|
||||||
|
"""Return True if segment is a partially specified segment.
|
||||||
|
|
||||||
|
:param segment: segment dictionary
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def validate_provider_segment(self, segment):
|
def validate_provider_segment(self, segment):
|
||||||
"""Validate attributes of a provider network segment.
|
"""Validate attributes of a provider network segment.
|
||||||
|
@ -81,6 +81,9 @@ class FlatTypeDriver(api.TypeDriver):
|
|||||||
def initialize(self):
|
def initialize(self):
|
||||||
LOG.info(_("ML2 FlatTypeDriver initialization complete"))
|
LOG.info(_("ML2 FlatTypeDriver initialization complete"))
|
||||||
|
|
||||||
|
def is_partial_segment(self, segment):
|
||||||
|
return False
|
||||||
|
|
||||||
def validate_provider_segment(self, segment):
|
def validate_provider_segment(self, segment):
|
||||||
physical_network = segment.get(api.PHYSICAL_NETWORK)
|
physical_network = segment.get(api.PHYSICAL_NETWORK)
|
||||||
if not physical_network:
|
if not physical_network:
|
||||||
|
@ -40,6 +40,9 @@ class LocalTypeDriver(api.TypeDriver):
|
|||||||
def initialize(self):
|
def initialize(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def is_partial_segment(self, segment):
|
||||||
|
return False
|
||||||
|
|
||||||
def validate_provider_segment(self, segment):
|
def validate_provider_segment(self, segment):
|
||||||
for key, value in segment.iteritems():
|
for key, value in segment.iteritems():
|
||||||
if value and key not in [api.NETWORK_TYPE]:
|
if value and key not in [api.NETWORK_TYPE]:
|
||||||
|
@ -73,6 +73,15 @@ class TypeManager(stevedore.named.NamedExtensionManager):
|
|||||||
LOG.info(_("Initializing driver for type '%s'"), network_type)
|
LOG.info(_("Initializing driver for type '%s'"), network_type)
|
||||||
driver.obj.initialize()
|
driver.obj.initialize()
|
||||||
|
|
||||||
|
def is_partial_segment(self, segment):
|
||||||
|
network_type = segment[api.NETWORK_TYPE]
|
||||||
|
driver = self.drivers.get(network_type)
|
||||||
|
if driver:
|
||||||
|
return driver.obj.is_partial_segment(segment)
|
||||||
|
else:
|
||||||
|
msg = _("network_type value '%s' not supported") % network_type
|
||||||
|
raise exc.InvalidInput(error_message=msg)
|
||||||
|
|
||||||
def validate_provider_segment(self, segment):
|
def validate_provider_segment(self, segment):
|
||||||
network_type = segment[api.NETWORK_TYPE]
|
network_type = segment[api.NETWORK_TYPE]
|
||||||
driver = self.drivers.get(network_type)
|
driver = self.drivers.get(network_type)
|
||||||
|
@ -157,8 +157,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
raise exc.InvalidInput(error_message=msg)
|
raise exc.InvalidInput(error_message=msg)
|
||||||
|
|
||||||
def _process_provider_create(self, network):
|
def _process_provider_create(self, network):
|
||||||
segments = []
|
|
||||||
|
|
||||||
if any(attributes.is_attr_set(network.get(f))
|
if any(attributes.is_attr_set(network.get(f))
|
||||||
for f in (provider.NETWORK_TYPE, provider.PHYSICAL_NETWORK,
|
for f in (provider.NETWORK_TYPE, provider.PHYSICAL_NETWORK,
|
||||||
provider.SEGMENTATION_ID)):
|
provider.SEGMENTATION_ID)):
|
||||||
@ -175,12 +173,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
segments = [{provider.NETWORK_TYPE: network_type,
|
segments = [{provider.NETWORK_TYPE: network_type,
|
||||||
provider.PHYSICAL_NETWORK: physical_network,
|
provider.PHYSICAL_NETWORK: physical_network,
|
||||||
provider.SEGMENTATION_ID: segmentation_id}]
|
provider.SEGMENTATION_ID: segmentation_id}]
|
||||||
|
return [self._process_provider_segment(s) for s in segments]
|
||||||
elif attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
|
elif attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
|
||||||
segments = network[mpnet.SEGMENTS]
|
segments = [self._process_provider_segment(s)
|
||||||
else:
|
for s in network[mpnet.SEGMENTS]]
|
||||||
return
|
mpnet.check_duplicate_segments(
|
||||||
|
segments,
|
||||||
return [self._process_provider_segment(s) for s in segments]
|
self.type_manager.is_partial_segment)
|
||||||
|
return segments
|
||||||
|
|
||||||
def _get_attribute(self, attrs, key):
|
def _get_attribute(self, attrs, key):
|
||||||
value = attrs.get(key)
|
value = attrs.get(key)
|
||||||
|
@ -746,10 +746,12 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
webob.exc.HTTPBadRequest})
|
webob.exc.HTTPBadRequest})
|
||||||
|
|
||||||
def _validate_provider_create(self, context, network):
|
def _validate_provider_create(self, context, network):
|
||||||
if not attr.is_attr_set(network.get(mpnet.SEGMENTS)):
|
segments = network.get(mpnet.SEGMENTS)
|
||||||
|
if not attr.is_attr_set(segments):
|
||||||
return
|
return
|
||||||
|
|
||||||
for segment in network[mpnet.SEGMENTS]:
|
mpnet.check_duplicate_segments(segments)
|
||||||
|
for segment in segments:
|
||||||
network_type = segment.get(pnet.NETWORK_TYPE)
|
network_type = segment.get(pnet.NETWORK_TYPE)
|
||||||
physical_network = segment.get(pnet.PHYSICAL_NETWORK)
|
physical_network = segment.get(pnet.PHYSICAL_NETWORK)
|
||||||
segmentation_id = segment.get(pnet.SEGMENTATION_ID)
|
segmentation_id = segment.get(pnet.SEGMENTATION_ID)
|
||||||
|
@ -326,7 +326,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase):
|
|||||||
res = network_req.get_response(self.api)
|
res = network_req.get_response(self.api)
|
||||||
self.assertEqual(400, res.status_int)
|
self.assertEqual(400, res.status_int)
|
||||||
|
|
||||||
def test_create_network_duplicate_segments(self):
|
def test_create_network_duplicate_full_segments(self):
|
||||||
data = {'network': {'name': 'net1',
|
data = {'network': {'name': 'net1',
|
||||||
mpnet.SEGMENTS:
|
mpnet.SEGMENTS:
|
||||||
[{pnet.NETWORK_TYPE: 'vlan',
|
[{pnet.NETWORK_TYPE: 'vlan',
|
||||||
@ -340,6 +340,18 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase):
|
|||||||
res = network_req.get_response(self.api)
|
res = network_req.get_response(self.api)
|
||||||
self.assertEqual(400, res.status_int)
|
self.assertEqual(400, res.status_int)
|
||||||
|
|
||||||
|
def test_create_network_duplicate_partial_segments(self):
|
||||||
|
data = {'network': {'name': 'net1',
|
||||||
|
mpnet.SEGMENTS:
|
||||||
|
[{pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.PHYSICAL_NETWORK: 'physnet1'},
|
||||||
|
{pnet.NETWORK_TYPE: 'vlan',
|
||||||
|
pnet.PHYSICAL_NETWORK: 'physnet1'}],
|
||||||
|
'tenant_id': 'tenant_one'}}
|
||||||
|
network_req = self.new_create_request('networks', data)
|
||||||
|
res = network_req.get_response(self.api)
|
||||||
|
self.assertEqual(201, res.status_int)
|
||||||
|
|
||||||
def test_release_segment_no_type_driver(self):
|
def test_release_segment_no_type_driver(self):
|
||||||
segment = {driver_api.NETWORK_TYPE: 'faketype',
|
segment = {driver_api.NETWORK_TYPE: 'faketype',
|
||||||
driver_api.PHYSICAL_NETWORK: 'physnet1',
|
driver_api.PHYSICAL_NETWORK: 'physnet1',
|
||||||
|
@ -40,6 +40,11 @@ class FlatTypeTest(base.BaseTestCase):
|
|||||||
return session.query(type_flat.FlatAllocation).filter_by(
|
return session.query(type_flat.FlatAllocation).filter_by(
|
||||||
physical_network=segment[api.PHYSICAL_NETWORK]).first()
|
physical_network=segment[api.PHYSICAL_NETWORK]).first()
|
||||||
|
|
||||||
|
def test_is_partial_segment(self):
|
||||||
|
segment = {api.NETWORK_TYPE: p_const.TYPE_FLAT,
|
||||||
|
api.PHYSICAL_NETWORK: 'flat_net1'}
|
||||||
|
self.assertFalse(self.driver.is_partial_segment(segment))
|
||||||
|
|
||||||
def test_validate_provider_segment(self):
|
def test_validate_provider_segment(self):
|
||||||
segment = {api.NETWORK_TYPE: p_const.TYPE_FLAT,
|
segment = {api.NETWORK_TYPE: p_const.TYPE_FLAT,
|
||||||
api.PHYSICAL_NETWORK: 'flat_net1'}
|
api.PHYSICAL_NETWORK: 'flat_net1'}
|
||||||
|
@ -27,6 +27,10 @@ class LocalTypeTest(base.BaseTestCase):
|
|||||||
self.driver = type_local.LocalTypeDriver()
|
self.driver = type_local.LocalTypeDriver()
|
||||||
self.session = None
|
self.session = None
|
||||||
|
|
||||||
|
def test_is_partial_segment(self):
|
||||||
|
segment = {api.NETWORK_TYPE: p_const.TYPE_LOCAL}
|
||||||
|
self.assertFalse(self.driver.is_partial_segment(segment))
|
||||||
|
|
||||||
def test_validate_provider_segment(self):
|
def test_validate_provider_segment(self):
|
||||||
segment = {api.NETWORK_TYPE: p_const.TYPE_LOCAL}
|
segment = {api.NETWORK_TYPE: p_const.TYPE_LOCAL}
|
||||||
self.driver.validate_provider_segment(segment)
|
self.driver.validate_provider_segment(segment)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user