def _convert_and_validate_segments(segments, valid_values=None):
- unique = set()
for segment in segments:
- unique.add(tuple(segment.iteritems()))
- network_type = segment.get(pnet.NETWORK_TYPE,
- 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
+ segment.setdefault(pnet.NETWORK_TYPE, attr.ATTR_NOT_SPECIFIED)
+ segment.setdefault(pnet.PHYSICAL_NETWORK, attr.ATTR_NOT_SPECIFIED)
segmentation_id = segment.get(pnet.SEGMENTATION_ID)
if segmentation_id:
segment[pnet.SEGMENTATION_ID] = attr.convert_to_int(
set([pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
pnet.SEGMENTATION_ID])))
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()
"""
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
def validate_provider_segment(self, segment):
"""Validate attributes of a provider network segment.
def initialize(self):
LOG.info(_("ML2 FlatTypeDriver initialization complete"))
+ def is_partial_segment(self, segment):
+ return False
+
def validate_provider_segment(self, segment):
physical_network = segment.get(api.PHYSICAL_NETWORK)
if not physical_network:
def initialize(self):
pass
+ def is_partial_segment(self, segment):
+ return False
+
def validate_provider_segment(self, segment):
for key, value in segment.iteritems():
if value and key not in [api.NETWORK_TYPE]:
LOG.info(_("Initializing driver for type '%s'"), network_type)
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):
network_type = segment[api.NETWORK_TYPE]
driver = self.drivers.get(network_type)
raise exc.InvalidInput(error_message=msg)
def _process_provider_create(self, network):
- segments = []
-
if any(attributes.is_attr_set(network.get(f))
for f in (provider.NETWORK_TYPE, provider.PHYSICAL_NETWORK,
provider.SEGMENTATION_ID)):
segments = [{provider.NETWORK_TYPE: network_type,
provider.PHYSICAL_NETWORK: physical_network,
provider.SEGMENTATION_ID: segmentation_id}]
+ return [self._process_provider_segment(s) for s in segments]
elif attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
- segments = network[mpnet.SEGMENTS]
- else:
- return
-
- return [self._process_provider_segment(s) for s in segments]
+ segments = [self._process_provider_segment(s)
+ for s in network[mpnet.SEGMENTS]]
+ mpnet.check_duplicate_segments(
+ segments,
+ self.type_manager.is_partial_segment)
+ return segments
def _get_attribute(self, attrs, key):
value = attrs.get(key)
webob.exc.HTTPBadRequest})
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
- for segment in network[mpnet.SEGMENTS]:
+ mpnet.check_duplicate_segments(segments)
+ for segment in segments:
network_type = segment.get(pnet.NETWORK_TYPE)
physical_network = segment.get(pnet.PHYSICAL_NETWORK)
segmentation_id = segment.get(pnet.SEGMENTATION_ID)
res = network_req.get_response(self.api)
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',
mpnet.SEGMENTS:
[{pnet.NETWORK_TYPE: 'vlan',
res = network_req.get_response(self.api)
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):
segment = {driver_api.NETWORK_TYPE: 'faketype',
driver_api.PHYSICAL_NETWORK: 'physnet1',
return session.query(type_flat.FlatAllocation).filter_by(
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):
segment = {api.NETWORK_TYPE: p_const.TYPE_FLAT,
api.PHYSICAL_NETWORK: 'flat_net1'}
self.driver = type_local.LocalTypeDriver()
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):
segment = {api.NETWORK_TYPE: p_const.TYPE_LOCAL}
self.driver.validate_provider_segment(segment)