openstacksdk/shade/exc.py
Monty Taylor 127049fe53
Raise a more specific exception on nova 400 errors
We may want to take some actions in nodepool, such as cache
invalidation, when we specifically get BadRequest errors. We may not,
but throwing the more specific exception doesn't hurt.

Change-Id: I748519daba2781bf83d6dc0151a1c12dd12d0e3f
2017-03-03 08:18:20 -08:00

113 lines
3.6 KiB
Python

# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
#
# 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.
import sys
import munch
from requests import exceptions as _rex
from shade import _log
class OpenStackCloudException(Exception):
log_inner_exceptions = False
def __init__(self, message, extra_data=None, **kwargs):
args = [message]
if extra_data:
if isinstance(extra_data, munch.Munch):
extra_data = extra_data.toDict()
args.append("Extra: {0}".format(str(extra_data)))
super(OpenStackCloudException, self).__init__(*args, **kwargs)
self.extra_data = extra_data
self.inner_exception = sys.exc_info()
self.orig_message = message
def log_error(self, logger=None):
if not logger:
logger = _log.setup_logging(__name__)
if self.inner_exception and self.inner_exception[1]:
logger.error(self.orig_message, exc_info=self.inner_exception)
def __str__(self):
message = Exception.__str__(self)
if (self.inner_exception and self.inner_exception[1]
and not self.orig_message.endswith(
str(self.inner_exception[1]))):
message = "%s (Inner Exception: %s)" % (
message,
str(self.inner_exception[1]))
if self.log_inner_exceptions:
self.log_error()
return message
class OpenStackCloudTimeout(OpenStackCloudException):
pass
class OpenStackCloudUnavailableExtension(OpenStackCloudException):
pass
class OpenStackCloudUnavailableFeature(OpenStackCloudException):
pass
class OpenStackCloudHTTPError(OpenStackCloudException, _rex.HTTPError):
def __init__(self, *args, **kwargs):
OpenStackCloudException.__init__(self, *args, **kwargs)
_rex.HTTPError.__init__(self, *args, **kwargs)
class OpenStackCloudBadRequest(OpenStackCloudHTTPError):
"""There is something wrong with the request payload.
Possible reasons can include malformed json or invalid values to parameters
such as flavorRef to a server create.
"""
class OpenStackCloudURINotFound(OpenStackCloudHTTPError):
pass
# Backwards compat
OpenStackCloudResourceNotFound = OpenStackCloudURINotFound
# Logic shamelessly stolen from requests
def raise_from_response(response):
msg = ''
if 400 <= response.status_code < 500:
msg = '({code}) Client Error: {reason} for url: {url}'.format(
code=response.status_code,
reason=response.reason,
url=response.url)
elif 500 <= response.status_code < 600:
msg = '({code}) Server Error: {reason} for url: {url}'.format(
code=response.status_code,
reason=response.reason,
url=response.url)
# Special case 404 since we raised a specific one for neutron exceptions
# before
if response.status_code == 404:
raise OpenStackCloudURINotFound(msg, response=response)
elif response.status_code == 400:
raise OpenStackCloudBadRequest(msg, response=response)
if msg:
raise OpenStackCloudHTTPError(msg, response=response)