use segment api def from neutron-lib

The segment extension's API definition was rehomed into neutron-lib with
commit I8b598c9aff2f0b28e5b11d3ab3570aeae2df1a4b

This patch consumes it by using lib's version of the module, removing
the rehomed code and updating the segment extension's test to mock
out standard_attr to ensure the description of segments isn't
overridden by the standardattrdescription extension.

NeutronLibImpact

Change-Id: Icea5981a5b920a30e159a0271052b9cc43236bc5
This commit is contained in:
Boden R 2018-03-12 15:20:43 -06:00
parent f2dced777a
commit ec1d5def67
5 changed files with 30 additions and 106 deletions

View File

@ -20,6 +20,7 @@ import itertools
import netaddr
from neutron_lib.api.definitions import ip_allocation as ipalloc_apidef
from neutron_lib.api.definitions import portbindings
from neutron_lib.api.definitions import segment as seg_apidef
from neutron_lib.api import validators
from neutron_lib import constants as const
from neutron_lib import exceptions as exc
@ -39,7 +40,6 @@ from neutron.db import db_base_plugin_common
from neutron.db.models import segment as segment_model
from neutron.db.models import subnet_service_type as sst_model
from neutron.db import models_v2
from neutron.extensions import segment
from neutron.ipam import exceptions as ipam_exceptions
from neutron.ipam import utils as ipam_utils
from neutron.objects import network as network_obj
@ -732,8 +732,8 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon):
def _make_subnet_args(self, detail, subnet, subnetpool_id):
args = super(IpamBackendMixin, self)._make_subnet_args(
detail, subnet, subnetpool_id)
if validators.is_attr_set(subnet.get(segment.SEGMENT_ID)):
args['segment_id'] = subnet[segment.SEGMENT_ID]
if validators.is_attr_set(subnet.get(seg_apidef.SEGMENT_ID)):
args['segment_id'] = subnet[seg_apidef.SEGMENT_ID]
if validators.is_attr_set(subnet.get('service_types')):
args['service_types'] = subnet['service_types']
return args

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.api.definitions import segment as seg_apidef
from neutron_lib.db import constants as db_const
from neutron_lib.db import model_base
import sqlalchemy as sa
@ -21,7 +22,6 @@ from sqlalchemy import orm
from neutron.db import models_v2
from neutron.db import standard_attr
from neutron.extensions import segment
# Some standalone plugins need a DB table to store provider
@ -51,7 +51,7 @@ class NetworkSegment(standard_attr.HasStandardAttributes,
backref=orm.backref("segments",
lazy='subquery',
cascade='delete'))
api_collections = [segment.SEGMENTS]
api_collections = [seg_apidef.COLLECTION_NAME]
class SegmentHostMapping(model_base.BASEV2):

View File

@ -14,120 +14,34 @@
import abc
from neutron_lib.api import converters
from neutron_lib.api.definitions import provider_net as providernet
from neutron_lib.api.definitions import subnet as subnet_def
from neutron_lib.api.definitions import segment as apidef
from neutron_lib.api import extensions as api_extensions
from neutron_lib import constants
from neutron_lib.db import constants as db_const
from neutron_lib.plugins import directory
import six
from neutron.api import extensions
from neutron.api.v2 import base
SEGMENT = 'segment'
SEGMENTS = '%ss' % SEGMENT
SEGMENT_ID = 'segment_id'
NETWORK_TYPE = 'network_type'
PHYSICAL_NETWORK = 'physical_network'
SEGMENTATION_ID = 'segmentation_id'
NAME_LEN = db_const.NAME_FIELD_SIZE
DESC_LEN = db_const.DESCRIPTION_FIELD_SIZE
# Attribute Map
RESOURCE_ATTRIBUTE_MAP = {
SEGMENTS: {
'id': {'allow_post': False,
'allow_put': False,
'validate': {'type:uuid': None},
'is_visible': True,
'primary_key': True},
'tenant_id': {'allow_post': True,
'allow_put': False,
'validate': {'type:string':
db_const.PROJECT_ID_FIELD_SIZE},
'is_visible': False},
'network_id': {'allow_post': True,
'allow_put': False,
'validate': {'type:uuid': None},
'is_visible': True},
PHYSICAL_NETWORK: {'allow_post': True,
'allow_put': False,
'default': constants.ATTR_NOT_SPECIFIED,
'validate': {'type:string':
providernet.PHYSICAL_NETWORK_MAX_LEN},
'is_visible': True},
NETWORK_TYPE: {'allow_post': True,
'allow_put': False,
'validate': {'type:string':
providernet.NETWORK_TYPE_MAX_LEN},
'is_visible': True},
SEGMENTATION_ID: {'allow_post': True,
'allow_put': False,
'default': constants.ATTR_NOT_SPECIFIED,
'convert_to': converters.convert_to_int,
'is_visible': True},
'name': {'allow_post': True,
'allow_put': True,
'default': constants.ATTR_NOT_SPECIFIED,
'validate': {'type:string_or_none': NAME_LEN},
'is_visible': True},
'description': {'allow_post': True,
'allow_put': True,
'default': constants.ATTR_NOT_SPECIFIED,
'validate': {'type:string_or_none': DESC_LEN},
'is_visible': True},
},
subnet_def.COLLECTION_NAME: {
SEGMENT_ID: {'allow_post': True,
'allow_put': False,
'default': None,
'validate': {'type:uuid_or_none': None},
'is_visible': True, },
},
}
class Segment(api_extensions.ExtensionDescriptor):
class Segment(api_extensions.APIExtensionDescriptor):
"""Extension class supporting Segments."""
@classmethod
def get_name(cls):
return "Segment"
@classmethod
def get_alias(cls):
return "segment"
@classmethod
def get_description(cls):
return "Segments extension."
@classmethod
def get_updated(cls):
return "2016-02-24T17:00:00-00:00"
api_definition = apidef
@classmethod
def get_resources(cls):
"""Returns Extended Resource for service type management."""
resource_attributes = RESOURCE_ATTRIBUTE_MAP[SEGMENTS]
resource_attributes = apidef.RESOURCE_ATTRIBUTE_MAP[
apidef.COLLECTION_NAME]
controller = base.create_resource(
SEGMENTS,
SEGMENT,
directory.get_plugin(SEGMENTS),
apidef.COLLECTION_NAME,
apidef.RESOURCE_NAME,
directory.get_plugin(apidef.COLLECTION_NAME),
resource_attributes)
return [extensions.ResourceExtension(SEGMENTS,
return [extensions.ResourceExtension(apidef.COLLECTION_NAME,
controller,
attr_map=resource_attributes)]
def get_extended_resources(self, version):
if version == "2.0":
return RESOURCE_ATTRIBUTE_MAP
else:
return {}
@six.add_metaclass(abc.ABCMeta)
class SegmentPluginBase(object):
@ -229,4 +143,4 @@ class SegmentPluginBase(object):
@classmethod
def get_plugin_type(cls):
return SEGMENTS
return apidef.COLLECTION_NAME

View File

@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib.api.definitions import segment as seg_apidef
from neutron_lib.callbacks import events
from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources
@ -29,7 +30,6 @@ from neutron.db import _utils as db_utils
from neutron.db import api as db_api
from neutron.db import common_db_mixin
from neutron.db import segments_db as db
from neutron.extensions import segment as extension
from neutron import manager
from neutron.objects import base as base_obj
from neutron.objects import network
@ -74,11 +74,11 @@ class SegmentDbMixin(common_db_mixin.CommonDbMixin):
def _create_segment_db(self, context, segment_id, segment):
with db_api.context_manager.writer.using(context):
network_id = segment['network_id']
physical_network = segment[extension.PHYSICAL_NETWORK]
physical_network = segment[seg_apidef.PHYSICAL_NETWORK]
if physical_network == constants.ATTR_NOT_SPECIFIED:
physical_network = None
network_type = segment[extension.NETWORK_TYPE]
segmentation_id = segment[extension.SEGMENTATION_ID]
network_type = segment[seg_apidef.NETWORK_TYPE]
segmentation_id = segment[seg_apidef.SEGMENTATION_ID]
if segmentation_id == constants.ATTR_NOT_SPECIFIED:
segmentation_id = None
name = segment['name']

View File

@ -20,6 +20,7 @@ import netaddr
from neutron_lib.api.definitions import ip_allocation as ipalloc_apidef
from neutron_lib.api.definitions import l2_adjacency as l2adj_apidef
from neutron_lib.api.definitions import portbindings
from neutron_lib.api.definitions import segment as seg_apidef
from neutron_lib.callbacks import events
from neutron_lib.callbacks import exceptions
from neutron_lib.callbacks import registry
@ -40,6 +41,7 @@ from neutron.db import agentschedulers_db
from neutron.db import db_base_plugin_v2
from neutron.db import portbindings_db
from neutron.db import segments_db
from neutron.db import standard_attr
from neutron.extensions import segment as ext_segment
from neutron.objects import network
from neutron.services.segments import db
@ -77,6 +79,13 @@ class SegmentTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
self.patch_notifier = mock.patch(
'neutron.notifiers.batch_notifier.BatchNotifier._notify')
self.patch_notifier.start()
# NOTE(boden): mock behavior of standardattrdescription to not
# overwrite description of segment API
mock.patch.object(standard_attr,
'get_standard_attr_resource_model_map',
return_value={}).start()
if not plugin:
plugin = TEST_PLUGIN_KLASS
service_plugins = {'segments_plugin_name': SERVICE_PLUGIN_KLASS}
@ -1470,7 +1479,8 @@ class TestNovaSegmentNotifier(SegmentAwareIpamTestCase):
# Need notifier here
self.patch_notifier.stop()
self._mock_keystone_auth()
self.segments_plugin = directory.get_plugin(ext_segment.SEGMENTS)
self.segments_plugin = directory.get_plugin(
seg_apidef.COLLECTION_NAME)
nova_updater = self.segments_plugin.nova_updater
nova_updater.p_client = mock.MagicMock()