1 # Copyright 2012 OpenStack Foundation
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
20 class BaseException(Exception):
21 """An error occurred."""
22 def __init__(self, message=None):
23 self.message = message
26 return self.message or self.__class__.__doc__
29 class CommandError(BaseException):
30 """Invalid usage of CLI."""
33 class InvalidEndpoint(BaseException):
34 """The provided endpoint is invalid."""
37 class CommunicationError(BaseException):
38 """Unable to communicate with server."""
41 class ClientException(Exception):
45 class HTTPException(ClientException):
46 """Base exception for all HTTP-derived exceptions."""
49 def __init__(self, details=None):
50 self.details = details or self.__class__.__name__
53 return "%s (HTTP %s)" % (self.details, self.code)
56 class HTTPMultipleChoices(HTTPException):
60 self.details = ("Requested version of OpenStack Images API is not "
62 return "%s (HTTP %s) %s" % (self.__class__.__name__, self.code,
66 class BadRequest(HTTPException):
71 class HTTPBadRequest(BadRequest):
75 class Unauthorized(HTTPException):
80 class HTTPUnauthorized(Unauthorized):
84 class Forbidden(HTTPException):
89 class HTTPForbidden(Forbidden):
93 class NotFound(HTTPException):
98 class HTTPNotFound(NotFound):
102 class HTTPMethodNotAllowed(HTTPException):
106 class Conflict(HTTPException):
111 class HTTPConflict(Conflict):
115 class OverLimit(HTTPException):
120 class HTTPOverLimit(OverLimit):
124 class HTTPInternalServerError(HTTPException):
128 class HTTPNotImplemented(HTTPException):
132 class HTTPBadGateway(HTTPException):
136 class ServiceUnavailable(HTTPException):
141 class HTTPServiceUnavailable(ServiceUnavailable):
145 # NOTE(bcwaldon): Build a mapping of HTTP codes to corresponding exception
148 for obj_name in dir(sys.modules[__name__]):
149 if obj_name.startswith('HTTP'):
150 obj = getattr(sys.modules[__name__], obj_name)
151 _code_map[obj.code] = obj
154 def from_response(response, body=None):
155 """Return an instance of an HTTPException based on httplib response."""
156 cls = _code_map.get(response.status_code, HTTPException)
157 if body and 'json' in response.headers['content-type']:
158 # Iterate over the nested objects and retreive the "message" attribute.
159 messages = [obj.get('message') for obj in response.json().values()]
160 # Join all of the messages together nicely and filter out any objects
161 # that don't have a "message" attr.
162 details = '\n'.join(i for i in messages if i is not None)
163 return cls(details=details)
164 elif body and 'html' in response.headers['content-type']:
165 # Split the lines, strip whitespace and inline HTML from the response.
166 details = [re.sub(r'<.+?>', '', i.strip())
167 for i in response.text.splitlines()]
168 details = [i for i in details if i]
169 # Remove duplicates from the list.
173 if i not in details_seen:
174 details_temp.append(i)
176 # Return joined string separated by colons.
177 details = ': '.join(details_temp)
178 return cls(details=details)
180 details = body.replace('\n\n', '\n')
181 return cls(details=details)
186 class NoTokenLookupException(Exception):
191 class EndpointNotFound(Exception):
196 class SSLConfigurationError(BaseException):
200 class SSLCertificateError(BaseException):