use flavors api def from neutron-lib
The flavors extension's API definition was rehomed into neutron-lib with commit I0229a80bb168bac8dc0fa17fb2b06f1b140d27b4 This patch consumes it by: - Removing the rehomed code and using neutron-lib's implementation instead. - Using the APIExtensionDescriptor for the extensions parent class. NeutronLibImpact Change-Id: I265ac1c0596d0fb0acaf99eeb7cfe9501732476f
This commit is contained in:
parent
cfc0a1ae5b
commit
a6617002e7
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.exceptions import flavors as flav_exc
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_log import log as logging
|
||||
|
||||
@ -19,7 +20,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 servicetype_db as sdb
|
||||
from neutron.extensions import flavors as ext_flavors
|
||||
from neutron.objects import base as base_obj
|
||||
from neutron.objects import flavor as obj_flavor
|
||||
|
||||
@ -34,14 +34,14 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
def _get_flavor(self, context, flavor_id):
|
||||
flavor = obj_flavor.Flavor.get_object(context, id=flavor_id)
|
||||
if not flavor:
|
||||
raise ext_flavors.FlavorNotFound(flavor_id=flavor_id)
|
||||
raise flav_exc.FlavorNotFound(flavor_id=flavor_id)
|
||||
return flavor
|
||||
|
||||
def _get_service_profile(self, context, sp_id):
|
||||
service_profile = obj_flavor.ServiceProfile.get_object(
|
||||
context, id=sp_id)
|
||||
if not service_profile:
|
||||
raise ext_flavors.ServiceProfileNotFound(sp_id=sp_id)
|
||||
raise flav_exc.ServiceProfileNotFound(sp_id=sp_id)
|
||||
return service_profile
|
||||
|
||||
@staticmethod
|
||||
@ -80,7 +80,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
"""Ensures no current bindings to flavors exist."""
|
||||
if obj_flavor.FlavorServiceProfileBinding.objects_exist(
|
||||
context, service_profile_id=sp_id):
|
||||
raise ext_flavors.ServiceProfileInUse(sp_id=sp_id)
|
||||
raise flav_exc.ServiceProfileInUse(sp_id=sp_id)
|
||||
|
||||
def _validate_driver(self, context, driver):
|
||||
"""Confirms a non-empty driver is a valid provider."""
|
||||
@ -90,7 +90,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
filters={'driver': driver})
|
||||
|
||||
if not providers:
|
||||
raise ext_flavors.ServiceProfileDriverNotFound(driver=driver)
|
||||
raise flav_exc.ServiceProfileDriverNotFound(driver=driver)
|
||||
|
||||
def create_flavor(self, context, flavor):
|
||||
fl = flavor['flavor']
|
||||
@ -122,7 +122,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
self._ensure_flavor_not_in_use(context, flavor_id)
|
||||
self._get_flavor(context, flavor_id).delete()
|
||||
except db_exc.DBReferenceError:
|
||||
raise ext_flavors.FlavorInUse(flavor_id=flavor_id)
|
||||
raise flav_exc.FlavorInUse(flavor_id=flavor_id)
|
||||
|
||||
def get_flavors(self, context, filters=None, fields=None,
|
||||
sorts=None, limit=None, marker=None, page_reverse=False):
|
||||
@ -139,7 +139,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
with db_api.context_manager.writer.using(context):
|
||||
if obj_flavor.FlavorServiceProfileBinding.objects_exist(
|
||||
context, service_profile_id=sp['id'], flavor_id=flavor_id):
|
||||
raise ext_flavors.FlavorServiceProfileBindingExists(
|
||||
raise flav_exc.FlavorServiceProfileBindingExists(
|
||||
sp_id=sp['id'], fl_id=flavor_id)
|
||||
obj_flavor.FlavorServiceProfileBinding(
|
||||
context, service_profile_id=sp['id'],
|
||||
@ -152,7 +152,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
if (obj_flavor.FlavorServiceProfileBinding.delete_objects(
|
||||
context, service_profile_id=service_profile_id,
|
||||
flavor_id=flavor_id) == 0):
|
||||
raise ext_flavors.FlavorServiceProfileBindingNotFound(
|
||||
raise flav_exc.FlavorServiceProfileBindingNotFound(
|
||||
sp_id=service_profile_id, fl_id=flavor_id)
|
||||
|
||||
@staticmethod
|
||||
@ -161,7 +161,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
if not obj_flavor.FlavorServiceProfileBinding.objects_exist(
|
||||
context, service_profile_id=service_profile_id,
|
||||
flavor_id=flavor_id):
|
||||
raise ext_flavors.FlavorServiceProfileBindingNotFound(
|
||||
raise flav_exc.FlavorServiceProfileBindingNotFound(
|
||||
sp_id=service_profile_id, fl_id=flavor_id)
|
||||
res = {'service_profile_id': service_profile_id,
|
||||
'flavor_id': flavor_id}
|
||||
@ -174,7 +174,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
self._validate_driver(context, sp['driver'])
|
||||
else:
|
||||
if not sp['metainfo']:
|
||||
raise ext_flavors.ServiceProfileEmpty()
|
||||
raise flav_exc.ServiceProfileEmpty()
|
||||
|
||||
obj = obj_flavor.ServiceProfile(
|
||||
context, description=sp['description'], driver=sp['driver'],
|
||||
@ -225,14 +225,14 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
objs = obj_flavor.FlavorServiceProfileBinding.get_objects(context,
|
||||
flavor_id=flavor_id)
|
||||
if not objs:
|
||||
raise ext_flavors.FlavorServiceProfileBindingNotFound(
|
||||
raise flav_exc.FlavorServiceProfileBindingNotFound(
|
||||
sp_id='', fl_id=flavor_id)
|
||||
# Get the service profile from the first binding
|
||||
# TODO(jwarendt) Should become a scheduling framework instead
|
||||
sp_obj = self._get_service_profile(context, objs[0].service_profile_id)
|
||||
|
||||
if not sp_obj.enabled:
|
||||
raise ext_flavors.ServiceProfileDisabled()
|
||||
raise flav_exc.ServiceProfileDisabled()
|
||||
|
||||
LOG.debug("Found driver %s.", sp_obj.driver)
|
||||
|
||||
@ -242,7 +242,7 @@ class FlavorsDbMixin(common_db_mixin.CommonDbMixin):
|
||||
filters={'driver': sp_obj.driver})
|
||||
|
||||
if not providers:
|
||||
raise ext_flavors.ServiceProfileDriverNotFound(
|
||||
raise flav_exc.ServiceProfileDriverNotFound(
|
||||
driver=sp_obj.driver)
|
||||
|
||||
LOG.debug("Found providers %s.", providers)
|
||||
|
@ -12,208 +12,37 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api import converters
|
||||
from neutron_lib.api.definitions import flavors as apidef
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
from neutron_lib.api import validators
|
||||
from neutron_lib.db import constants as db_const
|
||||
from neutron_lib import exceptions as nexception
|
||||
from neutron_lib.plugins import constants
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron._i18n import _
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import base
|
||||
from neutron.api.v2 import resource_helper
|
||||
|
||||
|
||||
# Flavor Exceptions
|
||||
class FlavorNotFound(nexception.NotFound):
|
||||
message = _("Flavor %(flavor_id)s could not be found.")
|
||||
class Flavors(api_extensions.APIExtensionDescriptor):
|
||||
|
||||
|
||||
class FlavorInUse(nexception.InUse):
|
||||
message = _("Flavor %(flavor_id)s is used by some service instance.")
|
||||
|
||||
|
||||
class ServiceProfileNotFound(nexception.NotFound):
|
||||
message = _("Service Profile %(sp_id)s could not be found.")
|
||||
|
||||
|
||||
class ServiceProfileInUse(nexception.InUse):
|
||||
message = _("Service Profile %(sp_id)s is used by some service instance.")
|
||||
|
||||
|
||||
class FlavorServiceProfileBindingExists(nexception.Conflict):
|
||||
message = _("Service Profile %(sp_id)s is already associated "
|
||||
"with flavor %(fl_id)s.")
|
||||
|
||||
|
||||
class FlavorServiceProfileBindingNotFound(nexception.NotFound):
|
||||
message = _("Service Profile %(sp_id)s is not associated "
|
||||
"with flavor %(fl_id)s.")
|
||||
|
||||
|
||||
class ServiceProfileDriverNotFound(nexception.NotFound):
|
||||
message = _("Service Profile driver %(driver)s could not be found.")
|
||||
|
||||
|
||||
class ServiceProfileEmpty(nexception.InvalidInput):
|
||||
message = _("Service Profile needs either a driver or metainfo.")
|
||||
|
||||
|
||||
class FlavorDisabled(nexception.ServiceUnavailable):
|
||||
message = _("Flavor is not enabled.")
|
||||
|
||||
|
||||
class ServiceProfileDisabled(nexception.ServiceUnavailable):
|
||||
message = _("Service Profile is not enabled.")
|
||||
|
||||
|
||||
class InvalidFlavorServiceType(nexception.InvalidInput):
|
||||
message = _("Invalid service type %(service_type)s.")
|
||||
|
||||
|
||||
def _validate_flavor_service_type(validate_type, valid_values=None):
|
||||
"""Ensure requested flavor service type plugin is loaded."""
|
||||
if not directory.get_plugin(validate_type):
|
||||
raise InvalidFlavorServiceType(service_type=validate_type)
|
||||
|
||||
validators.add_validator('validate_flavor_service_type',
|
||||
_validate_flavor_service_type)
|
||||
|
||||
FLAVORS = 'flavors'
|
||||
SERVICE_PROFILES = 'service_profiles'
|
||||
FLAVORS_PREFIX = ""
|
||||
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
FLAVORS: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
'primary_key': True},
|
||||
'name': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string': db_const.NAME_FIELD_SIZE},
|
||||
'is_visible': True, 'default': ''},
|
||||
'description': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string_or_none':
|
||||
db_const.LONG_DESCRIPTION_FIELD_SIZE},
|
||||
'is_visible': True, 'default': ''},
|
||||
'service_type': {'allow_post': True, 'allow_put': False,
|
||||
'validate':
|
||||
{'type:validate_flavor_service_type': None},
|
||||
'is_visible': True},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {
|
||||
'type:string': db_const.PROJECT_ID_FIELD_SIZE},
|
||||
'is_visible': True},
|
||||
'service_profiles': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:uuid_list': None},
|
||||
'is_visible': True, 'default': []},
|
||||
'enabled': {'allow_post': True, 'allow_put': True,
|
||||
'convert_to': converters.convert_to_boolean_if_not_none,
|
||||
'default': True,
|
||||
'is_visible': True},
|
||||
},
|
||||
SERVICE_PROFILES: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
'primary_key': True},
|
||||
'description': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string_or_none':
|
||||
db_const.LONG_DESCRIPTION_FIELD_SIZE},
|
||||
'is_visible': True, 'default': ''},
|
||||
'driver': {'allow_post': True, 'allow_put': True,
|
||||
'validate': {'type:string':
|
||||
db_const.LONG_DESCRIPTION_FIELD_SIZE},
|
||||
'is_visible': True,
|
||||
'default': ''},
|
||||
'metainfo': {'allow_post': True, 'allow_put': True,
|
||||
'is_visible': True,
|
||||
'default': ''},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {
|
||||
'type:string': db_const.PROJECT_ID_FIELD_SIZE},
|
||||
'is_visible': True},
|
||||
'enabled': {'allow_post': True, 'allow_put': True,
|
||||
'convert_to': converters.convert_to_boolean_if_not_none,
|
||||
'is_visible': True, 'default': True},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
SUB_RESOURCE_ATTRIBUTE_MAP = {
|
||||
'next_providers': {
|
||||
'parent': {'collection_name': 'flavors',
|
||||
'member_name': 'flavor'},
|
||||
'parameters': {'provider': {'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True},
|
||||
'driver': {'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True},
|
||||
'metainfo': {'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {
|
||||
'type:string':
|
||||
db_const.PROJECT_ID_FIELD_SIZE},
|
||||
'is_visible': True}}
|
||||
},
|
||||
'service_profiles': {
|
||||
'parent': {'collection_name': 'flavors',
|
||||
'member_name': 'flavor'},
|
||||
'parameters': {'id': {'allow_post': True, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True},
|
||||
'tenant_id': {'allow_post': True, 'allow_put': False,
|
||||
'required_by_policy': True,
|
||||
'validate': {
|
||||
'type:string':
|
||||
db_const.PROJECT_ID_FIELD_SIZE},
|
||||
'is_visible': True}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Flavors(api_extensions.ExtensionDescriptor):
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "Neutron Service Flavors"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return "flavors"
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Flavor specification for Neutron advanced services"
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2015-09-17T10:00:00-00:00"
|
||||
api_definition = apidef
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
"""Returns Ext Resources."""
|
||||
plural_mappings = resource_helper.build_plural_mappings(
|
||||
{}, RESOURCE_ATTRIBUTE_MAP)
|
||||
{}, apidef.RESOURCE_ATTRIBUTE_MAP)
|
||||
resources = resource_helper.build_resource_info(
|
||||
plural_mappings,
|
||||
RESOURCE_ATTRIBUTE_MAP,
|
||||
apidef.RESOURCE_ATTRIBUTE_MAP,
|
||||
constants.FLAVORS)
|
||||
plugin = directory.get_plugin(constants.FLAVORS)
|
||||
for collection_name in SUB_RESOURCE_ATTRIBUTE_MAP:
|
||||
for collection_name in apidef.SUB_RESOURCE_ATTRIBUTE_MAP:
|
||||
# Special handling needed for sub-resources with 'y' ending
|
||||
# (e.g. proxies -> proxy)
|
||||
resource_name = collection_name[:-1]
|
||||
parent = SUB_RESOURCE_ATTRIBUTE_MAP[collection_name].get('parent')
|
||||
params = SUB_RESOURCE_ATTRIBUTE_MAP[collection_name].get(
|
||||
parent = apidef.SUB_RESOURCE_ATTRIBUTE_MAP[collection_name].get(
|
||||
'parent')
|
||||
params = apidef.SUB_RESOURCE_ATTRIBUTE_MAP[collection_name].get(
|
||||
'parameters')
|
||||
|
||||
controller = base.create_resource(collection_name, resource_name,
|
||||
@ -224,18 +53,8 @@ class Flavors(api_extensions.ExtensionDescriptor):
|
||||
resource = extensions.ResourceExtension(
|
||||
collection_name,
|
||||
controller, parent,
|
||||
path_prefix=FLAVORS_PREFIX,
|
||||
path_prefix=apidef.API_PREFIX,
|
||||
attr_map=params)
|
||||
resources.append(resource)
|
||||
|
||||
return resources
|
||||
|
||||
def update_attributes_map(self, attributes):
|
||||
super(Flavors, self).update_attributes_map(
|
||||
attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return RESOURCE_ATTRIBUTE_MAP
|
||||
else:
|
||||
return {}
|
||||
|
@ -19,6 +19,7 @@ import fixtures
|
||||
import mock
|
||||
from neutron_lib import context
|
||||
from neutron_lib.db import constants as db_const
|
||||
from neutron_lib.exceptions import flavors as flav_exc
|
||||
from neutron_lib.plugins import constants
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
@ -53,7 +54,7 @@ class FlavorExtensionTestCase(extension.ExtensionTestCase):
|
||||
super(FlavorExtensionTestCase, self).setUp()
|
||||
self._setUpExtension(
|
||||
'neutron.services.flavors.flavors_plugin.FlavorsPlugin',
|
||||
constants.FLAVORS, flavors.RESOURCE_ATTRIBUTE_MAP,
|
||||
constants.FLAVORS, {},
|
||||
flavors.Flavors, '', supported_extension_aliases='flavors')
|
||||
|
||||
def test_create_flavor(self):
|
||||
@ -538,7 +539,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
'driver': "Broken",
|
||||
'enabled': True,
|
||||
'metainfo': '{"data": "value"}'}}
|
||||
self.assertRaises(flavors.ServiceProfileDriverNotFound,
|
||||
self.assertRaises(flav_exc.ServiceProfileDriverNotFound,
|
||||
self.plugin.create_service_profile,
|
||||
self.ctx,
|
||||
data)
|
||||
@ -549,7 +550,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
'driver': '',
|
||||
'enabled': True,
|
||||
'metainfo': ''}}
|
||||
self.assertRaises(flavors.ServiceProfileEmpty,
|
||||
self.assertRaises(flav_exc.ServiceProfileEmpty,
|
||||
self.plugin.create_service_profile,
|
||||
self.ctx,
|
||||
data)
|
||||
@ -616,7 +617,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
self.ctx,
|
||||
{'service_profile': {'id': sp['id']}},
|
||||
fl['id'])
|
||||
self.assertRaises(flavors.FlavorServiceProfileBindingExists,
|
||||
self.assertRaises(flav_exc.FlavorServiceProfileBindingExists,
|
||||
self.plugin.create_flavor_service_profile,
|
||||
self.ctx,
|
||||
{'service_profile': {'id': sp['id']}},
|
||||
@ -636,7 +637,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
flavor_obj.FlavorServiceProfileBinding.objects_exist(self.ctx))
|
||||
|
||||
self.assertRaises(
|
||||
flavors.FlavorServiceProfileBindingNotFound,
|
||||
flav_exc.FlavorServiceProfileBindingNotFound,
|
||||
self.plugin.delete_flavor_service_profile,
|
||||
self.ctx, sp['id'], fl['id'])
|
||||
|
||||
@ -648,7 +649,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
{'service_profile': {'id': sp['id']}},
|
||||
fl['id'])
|
||||
self.assertRaises(
|
||||
flavors.ServiceProfileInUse,
|
||||
flav_exc.ServiceProfileInUse,
|
||||
self.plugin.delete_service_profile,
|
||||
self.ctx,
|
||||
sp['id'])
|
||||
@ -659,7 +660,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
with self.ctx.session.begin():
|
||||
self.ctx.session.add(l3_models.Router(flavor_id=fl['id']))
|
||||
self.assertRaises(
|
||||
flavors.FlavorInUse,
|
||||
flav_exc.FlavorInUse,
|
||||
self.plugin.delete_flavor,
|
||||
self.ctx,
|
||||
fl['id'])
|
||||
@ -667,7 +668,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
def test_get_flavor_next_provider_no_binding(self):
|
||||
fl, data = self._create_flavor()
|
||||
self.assertRaises(
|
||||
flavors.FlavorServiceProfileBindingNotFound,
|
||||
flav_exc.FlavorServiceProfileBindingNotFound,
|
||||
self.plugin.get_flavor_next_provider,
|
||||
self.ctx,
|
||||
fl['id'])
|
||||
@ -686,7 +687,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
{'service_profile': {'id': sp['id']}},
|
||||
fl['id'])
|
||||
self.assertRaises(
|
||||
flavors.ServiceProfileDisabled,
|
||||
flav_exc.ServiceProfileDisabled,
|
||||
self.plugin.get_flavor_next_provider,
|
||||
self.ctx,
|
||||
fl['id'])
|
||||
@ -705,7 +706,7 @@ class FlavorPluginTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase,
|
||||
{'service_profile': {'id': sp['id']}},
|
||||
fl['id'])
|
||||
self.assertRaises(
|
||||
flavors.ServiceProfileDriverNotFound,
|
||||
flav_exc.ServiceProfileDriverNotFound,
|
||||
self.plugin.get_flavor_next_provider,
|
||||
self.ctx,
|
||||
fl['id'])
|
||||
|
Loading…
Reference in New Issue
Block a user