
Refactory the exception class to include the failure code, and parameter format for output, and deal with the exception during the parameter formatting. BP: https://blueprints.launchpad.net/tricircle/+spec/implement-stateless Change-Id: Iec54fc66589199a3dbfc15c4df283466a62e4a10 Signed-off-by: Chaoyi Huang <joehuang@huawei.com>
271 lines
7.6 KiB
Python
271 lines
7.6 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__
|
|
for name, value in kwargs.items():
|
|
exc_info = exc_info + _(' ; ') + \
|
|
name + _(' : ') + six.text_type(value)
|
|
|
|
exc_info = self.message + _(' ; ') + 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
|