
The purpose of this patch set is to provide the end users with the following functionalities: 1. Create volume type resources, only admin is able to create volume type 2. Show details for a volume type by id 3. List volume types 4. Update a volume type, only admin is able to update volume type 5. Delete a volume type, only admin is able to delete volume type Change-Id: I6e3188018eff6db155ec02dbd2af6aefc0363df9
302 lines
8.5 KiB
Python
302 lines
8.5 KiB
Python
# Copyright 2015 Huawei Technologies Co., Ltd.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""
|
|
Tricircle base exception handling.
|
|
"""
|
|
|
|
import six
|
|
|
|
from oslo_log import log as logging
|
|
from tricircle.common.i18n import _
|
|
from tricircle.common.i18n import _LE
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class TricircleException(Exception):
|
|
"""Base Tricircle Exception.
|
|
|
|
To correctly use this class, inherit from it and define
|
|
a 'message' property. That message will get printf'd
|
|
with the keyword arguments provided to the constructor.
|
|
"""
|
|
message = _("An unknown exception occurred.")
|
|
code = 500
|
|
headers = {}
|
|
safe = False
|
|
|
|
def __init__(self, message=None, **kwargs):
|
|
|
|
self.kwargs = kwargs
|
|
self.kwargs['message'] = message
|
|
|
|
if 'code' not in self.kwargs:
|
|
self.kwargs['code'] = self.code
|
|
|
|
for k, v in self.kwargs.items():
|
|
if isinstance(v, Exception):
|
|
self.kwargs[k] = six.text_type(v)
|
|
|
|
if self._should_format():
|
|
try:
|
|
message = self.message % kwargs
|
|
except Exception:
|
|
|
|
# kwargs doesn't match a variable in the message
|
|
# log the issue and the kwargs
|
|
exc_info = _('Exception class %s in string '
|
|
'format operation') % type(self).__name__
|
|
format_str = _('%(exception_info)s ; %(format_key)s : '
|
|
'%(format_value)s')
|
|
for name, value in kwargs.items():
|
|
exc_info = format_str % {
|
|
'exception_info': exc_info,
|
|
'format_key': name,
|
|
'format_value': six.text_type(value)}
|
|
|
|
exc_info = _('%(message)s ; %(exception_info)s') % {
|
|
'message': self.message, 'exception_info': exc_info}
|
|
LOG.exception(exc_info)
|
|
|
|
# no rerasie
|
|
# exc_info = sys.exc_info()
|
|
# if CONF.fatal_exception_format_errors:
|
|
# six.reraise(*exc_info)
|
|
|
|
# at least get the core message out if something happened
|
|
message = self.message
|
|
|
|
elif isinstance(message, Exception):
|
|
message = six.text_type(message)
|
|
|
|
self.msg = message
|
|
super(TricircleException, self).__init__(message)
|
|
|
|
def _should_format(self):
|
|
|
|
if self.kwargs['message'] is None and '%(message)' in self.message:
|
|
LOG.error(_LE('\%(message)s in message '
|
|
'but init parameter is None'))
|
|
|
|
return self.kwargs['message'] is None or '%(message)' in self.message
|
|
|
|
def __unicode__(self):
|
|
return six.text_type(self.msg)
|
|
|
|
|
|
class BadRequest(TricircleException):
|
|
message = _('Bad %(resource)s request: %(msg)s')
|
|
|
|
|
|
class NotFound(TricircleException):
|
|
message = _("Resource could not be found.")
|
|
code = 404
|
|
safe = True
|
|
|
|
|
|
class Conflict(TricircleException):
|
|
pass
|
|
|
|
|
|
class NotAuthorized(TricircleException):
|
|
message = _("Not authorized.")
|
|
|
|
|
|
class ServiceUnavailable(TricircleException):
|
|
message = _("The service is unavailable")
|
|
|
|
|
|
class AdminRequired(NotAuthorized):
|
|
message = _("User does not have admin privileges")
|
|
|
|
|
|
class InUse(TricircleException):
|
|
message = _("The resource is inuse")
|
|
|
|
|
|
class InvalidConfigurationOption(TricircleException):
|
|
message = _("An invalid value was provided for %(opt_name)s: "
|
|
"%(opt_value)s")
|
|
|
|
|
|
class EndpointNotAvailable(TricircleException):
|
|
message = "Endpoint %(url)s for %(service)s is not available"
|
|
|
|
def __init__(self, service, url):
|
|
super(EndpointNotAvailable, self).__init__(service=service, url=url)
|
|
|
|
|
|
class EndpointNotUnique(TricircleException):
|
|
message = "Endpoint for %(service)s in %(pod)s not unique"
|
|
|
|
def __init__(self, pod, service):
|
|
super(EndpointNotUnique, self).__init__(pod=pod, service=service)
|
|
|
|
|
|
class EndpointNotFound(TricircleException):
|
|
message = "Endpoint for %(service)s in %(pod)s not found"
|
|
|
|
def __init__(self, pod, service):
|
|
super(EndpointNotFound, self).__init__(pod=pod, service=service)
|
|
|
|
|
|
class ResourceNotFound(TricircleException):
|
|
message = "Could not find %(resource_type)s: %(unique_key)s"
|
|
|
|
def __init__(self, model, unique_key):
|
|
resource_type = model.__name__.lower()
|
|
super(ResourceNotFound, self).__init__(resource_type=resource_type,
|
|
unique_key=unique_key)
|
|
|
|
|
|
class ResourceNotSupported(TricircleException):
|
|
message = "%(method)s method not supported for %(resource)s"
|
|
|
|
def __init__(self, resource, method):
|
|
super(ResourceNotSupported, self).__init__(resource=resource,
|
|
method=method)
|
|
|
|
|
|
class Invalid(TricircleException):
|
|
message = _("Unacceptable parameters.")
|
|
code = 400
|
|
|
|
|
|
class InvalidInput(Invalid):
|
|
message = _("Invalid input received: %(reason)s")
|
|
|
|
|
|
class InvalidMetadata(Invalid):
|
|
message = _("Invalid metadata: %(reason)s")
|
|
|
|
|
|
class InvalidMetadataSize(Invalid):
|
|
message = _("Invalid metadata size: %(reason)s")
|
|
|
|
|
|
class MetadataLimitExceeded(TricircleException):
|
|
message = _("Maximum number of metadata items exceeds %(allowed)d")
|
|
|
|
|
|
class InvalidReservationExpiration(Invalid):
|
|
message = _("Invalid reservation expiration %(expire)s.")
|
|
|
|
|
|
class InvalidQuotaValue(Invalid):
|
|
message = _("Change would make usage less than 0 for the following "
|
|
"resources: %(unders)s")
|
|
|
|
|
|
class QuotaNotFound(NotFound):
|
|
message = _("Quota could not be found")
|
|
|
|
|
|
class QuotaResourceUnknown(QuotaNotFound):
|
|
message = _("Unknown quota resources %(unknown)s.")
|
|
|
|
|
|
class ProjectQuotaNotFound(QuotaNotFound):
|
|
message = _("Quota for project %(project_id)s could not be found.")
|
|
|
|
|
|
class QuotaClassNotFound(QuotaNotFound):
|
|
message = _("Quota class %(class_name)s could not be found.")
|
|
|
|
|
|
class QuotaUsageNotFound(QuotaNotFound):
|
|
message = _("Quota usage for project %(project_id)s could not be found.")
|
|
|
|
|
|
class ReservationNotFound(QuotaNotFound):
|
|
message = _("Quota reservation %(uuid)s could not be found.")
|
|
|
|
|
|
class OverQuota(TricircleException):
|
|
message = _("Quota exceeded for resources: %(overs)s")
|
|
|
|
|
|
class TooManyInstances(TricircleException):
|
|
message = _("Quota exceeded for %(overs)s: Requested %(req)s,"
|
|
" but already used %(used)s of %(allowed)s %(overs)s")
|
|
|
|
|
|
class OnsetFileLimitExceeded(TricircleException):
|
|
message = _("Personality file limit exceeded")
|
|
|
|
|
|
class OnsetFilePathLimitExceeded(OnsetFileLimitExceeded):
|
|
message = _("Personality file path too long")
|
|
|
|
|
|
class OnsetFileContentLimitExceeded(OnsetFileLimitExceeded):
|
|
message = _("Personality file content too long")
|
|
|
|
|
|
class ExternalNetPodNotSpecify(TricircleException):
|
|
message = "Pod for external network not specified"
|
|
|
|
def __init__(self):
|
|
super(ExternalNetPodNotSpecify, self).__init__()
|
|
|
|
|
|
class PodNotFound(NotFound):
|
|
message = "Pod %(pod_name)s could not be found."
|
|
|
|
def __init__(self, pod_name):
|
|
super(PodNotFound, self).__init__(pod_name=pod_name)
|
|
|
|
|
|
class ChildQuotaNotZero(TricircleException):
|
|
message = _("Child projects having non-zero quota")
|
|
|
|
|
|
# parameter validation error
|
|
class ValidationError(TricircleException):
|
|
message = _("%(msg)s")
|
|
code = 400
|
|
|
|
|
|
# parameter validation error
|
|
class HTTPForbiddenError(TricircleException):
|
|
message = _("%(msg)s")
|
|
code = 403
|
|
|
|
|
|
class VolumeTypeNotFound(NotFound):
|
|
message = _("Volume type %(volume_type_id)s could not be found.")
|
|
|
|
|
|
class VolumeTypeNotFoundByName(VolumeTypeNotFound):
|
|
message = _("Volume type with name %(volume_type_name)s "
|
|
"could not be found.")
|
|
|
|
|
|
class VolumeTypeExtraSpecsNotFound(NotFound):
|
|
message = _("Volume Type %(volume_type_id)s has no extra specs with "
|
|
"key %(extra_specs_key)s.")
|
|
|
|
|
|
class Duplicate(TricircleException):
|
|
pass
|
|
|
|
|
|
class VolumeTypeExists(Duplicate):
|
|
message = _("Volume Type %(id)s already exists.")
|
|
|
|
|
|
class VolumeTypeUpdateFailed(TricircleException):
|
|
message = _("Cannot update volume_type %(id)s")
|