summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorMichael Gundlach <michael.gundlach@rackspace.com>2010-09-28 20:36:50 -0400
committerMichael Gundlach <michael.gundlach@rackspace.com>2010-09-28 20:36:50 -0400
commit05e3e188e03624884ed019fe9cd8f216c9262f98 (patch)
tree52ee12db708533223a02f3f4ccf52ea8bd5cd5ec /nova/api
parent7d6687e1e2811542c288e997359a278023a4c37f (diff)
Fault support
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/rackspace/__init__.py9
-rw-r--r--nova/api/rackspace/auth.py7
-rw-r--r--nova/api/rackspace/faults.py61
-rw-r--r--nova/api/rackspace/flavors.py3
-rw-r--r--nova/api/rackspace/images.py7
5 files changed, 77 insertions, 10 deletions
diff --git a/nova/api/rackspace/__init__.py b/nova/api/rackspace/__init__.py
index c24d08585..447037020 100644
--- a/nova/api/rackspace/__init__.py
+++ b/nova/api/rackspace/__init__.py
@@ -31,6 +31,7 @@ import webob
from nova import flags
from nova import utils
from nova import wsgi
+from nova.api.rackspace import faults
from nova.api.rackspace import flavors
from nova.api.rackspace import images
from nova.api.rackspace import ratelimiting
@@ -66,7 +67,7 @@ class AuthMiddleware(wsgi.Middleware):
user = self.auth_driver.authorize_token(req.headers["X-Auth-Token"])
if not user:
- return webob.exc.HTTPUnauthorized()
+ return faults.Fault(webob.exc.HTTPUnauthorized())
context = {'user': user}
req.environ['nova.context'] = context
return self.application
@@ -109,8 +110,10 @@ class RateLimitingMiddleware(wsgi.Middleware):
delay = self.get_delay(action_name, username)
if delay:
# TODO(gundlach): Get the retry-after format correct.
- raise webob.exc.HTTPRequestEntityTooLarge(headers={
- 'Retry-After': time.time() + delay})
+ exc = webob.exc.HTTPRequestEntityTooLarge(
+ explanation='Too many requests.',
+ headers={'Retry-After': time.time() + delay})
+ raise faults.Fault(exc)
return self.application
def get_delay(self, action_name, username):
diff --git a/nova/api/rackspace/auth.py b/nova/api/rackspace/auth.py
index ce5a967eb..519263367 100644
--- a/nova/api/rackspace/auth.py
+++ b/nova/api/rackspace/auth.py
@@ -9,6 +9,7 @@ from nova import auth
from nova import manager
from nova import db
from nova import utils
+from nova.api.rackspace import faults
FLAGS = flags.FLAGS
@@ -34,13 +35,13 @@ class BasicApiAuthManager(object):
# honor it
path_info = req.path_info
if len(path_info) > 1:
- return webob.exc.HTTPUnauthorized()
+ return faults.Fault(webob.exc.HTTPUnauthorized())
try:
username, key = req.headers['X-Auth-User'], \
req.headers['X-Auth-Key']
except KeyError:
- return webob.exc.HTTPUnauthorized()
+ return faults.Fault(webob.exc.HTTPUnauthorized())
username, key = req.headers['X-Auth-User'], req.headers['X-Auth-Key']
token, user = self._authorize_user(username, key)
@@ -55,7 +56,7 @@ class BasicApiAuthManager(object):
res.status = '204'
return res
else:
- return webob.exc.HTTPUnauthorized()
+ return faults.Fault(webob.exc.HTTPUnauthorized())
def authorize_token(self, token_hash):
""" retrieves user information from the datastore given a token
diff --git a/nova/api/rackspace/faults.py b/nova/api/rackspace/faults.py
new file mode 100644
index 000000000..fd6bc3623
--- /dev/null
+++ b/nova/api/rackspace/faults.py
@@ -0,0 +1,61 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC.
+# 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.
+
+
+import webob.dec
+
+from nova import wsgi
+
+
+class Fault(wsgi.Application):
+
+ """An RS API fault response."""
+
+ _fault_names = {
+ 400: "badRequest",
+ 401: "unauthorized",
+ 403: "resizeNotAllowed",
+ 404: "itemNotFound",
+ 405: "badMethod",
+ 409: "inProgress",
+ 413: "overLimit",
+ 415: "badMediaType",
+ 501: "notImplemented",
+ 503: "serviceUnavailable"}
+
+ def __init__(self, exception):
+ """Create a Fault for the given webob.exc.exception."""
+ self.exception = exception
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ """Generate a WSGI response based on self.exception."""
+ # Replace the body with fault details.
+ code = self.exception.status_int
+ fault_name = self._fault_names.get(code, "cloudServersFault")
+ fault_data = {
+ fault_name: {
+ 'code': code,
+ 'message': self.exception.explanation}}
+ if code == 413:
+ retry = self.exception.headers['Retry-After']
+ fault_data[fault_name]['retryAfter'] = retry
+ # 'code' is an attribute on the fault tag itself
+ metadata = {'application/xml': {'attributes': {fault_name: 'code'}}}
+ serializer = wsgi.Serializer(req.environ, metadata)
+ self.exception.body = serializer.to_content_type(fault_data)
+ return self.exception
diff --git a/nova/api/rackspace/flavors.py b/nova/api/rackspace/flavors.py
index 60b35c939..6cc57be33 100644
--- a/nova/api/rackspace/flavors.py
+++ b/nova/api/rackspace/flavors.py
@@ -16,6 +16,7 @@
# under the License.
from nova.api.rackspace import base
+from nova.api.rackspace import faults
from nova.compute import instance_types
from webob import exc
@@ -47,7 +48,7 @@ class Controller(base.Controller):
item = dict(ram=val['memory_mb'], disk=val['local_gb'],
id=val['flavorid'], name=name)
return dict(flavor=item)
- raise exc.HTTPNotFound()
+ raise faults.Fault(exc.HTTPNotFound())
def _all_ids(self):
"""Return the list of all flavorids."""
diff --git a/nova/api/rackspace/images.py b/nova/api/rackspace/images.py
index 2f3e928b9..1c50d0bec 100644
--- a/nova/api/rackspace/images.py
+++ b/nova/api/rackspace/images.py
@@ -18,6 +18,7 @@
import nova.image.service
from nova.api.rackspace import base
from nova.api.rackspace import _id_translator
+from nova.api.rackspace import faults
from webob import exc
class Controller(base.Controller):
@@ -57,14 +58,14 @@ class Controller(base.Controller):
def delete(self, req, id):
# Only public images are supported for now.
- raise exc.HTTPNotFound()
+ raise faults.Fault(exc.HTTPNotFound())
def create(self, req):
# Only public images are supported for now, so a request to
# make a backup of a server cannot be supproted.
- raise exc.HTTPNotFound()
+ raise faults.Fault(exc.HTTPNotFound())
def update(self, req, id):
# Users may not modify public images, and that's all that
# we support for now.
- raise exc.HTTPNotFound()
+ raise faults.Fault(exc.HTTPNotFound())