summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/plugins/v3/fixed_ips.py2
-rw-r--r--nova/api/openstack/compute/plugins/v3/keypairs.py3
-rw-r--r--nova/api/openstack/extensions.py40
3 files changed, 45 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/plugins/v3/fixed_ips.py b/nova/api/openstack/compute/plugins/v3/fixed_ips.py
index e98b830bd..5fa4ae3c2 100644
--- a/nova/api/openstack/compute/plugins/v3/fixed_ips.py
+++ b/nova/api/openstack/compute/plugins/v3/fixed_ips.py
@@ -28,6 +28,7 @@ authorize = extensions.extension_authorizer('compute', 'v3:' + ALIAS)
class FixedIPController(object):
+ @extensions.expected_errors(404)
def show(self, req, id):
"""Return data about the given fixed ip."""
context = req.environ['nova.context']
@@ -55,6 +56,7 @@ class FixedIPController(object):
return fixed_ip_info
+ @extensions.expected_errors((400, 404))
def action(self, req, id, body):
context = req.environ['nova.context']
authorize(context)
diff --git a/nova/api/openstack/compute/plugins/v3/keypairs.py b/nova/api/openstack/compute/plugins/v3/keypairs.py
index bf740641e..ab40b051c 100644
--- a/nova/api/openstack/compute/plugins/v3/keypairs.py
+++ b/nova/api/openstack/compute/plugins/v3/keypairs.py
@@ -55,6 +55,7 @@ class KeypairController(object):
self.api = compute_api.KeypairAPI()
@wsgi.serializers(xml=KeypairTemplate)
+ @extensions.expected_errors((400, 409, 413))
def create(self, req, body):
"""
Create or import keypair.
@@ -100,6 +101,7 @@ class KeypairController(object):
except exception.KeyPairExists as exc:
raise webob.exc.HTTPConflict(explanation=exc.format_message())
+ @extensions.expected_errors(404)
def delete(self, req, id):
"""
Delete a keypair with a given name
@@ -113,6 +115,7 @@ class KeypairController(object):
return webob.Response(status_int=202)
@wsgi.serializers(xml=KeypairTemplate)
+ @extensions.expected_errors(404)
def show(self, req, id):
"""Return data for the given key name."""
context = req.environ['nova.context']
diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py
index 6cbc5bb78..6fea5d35e 100644
--- a/nova/api/openstack/extensions.py
+++ b/nova/api/openstack/extensions.py
@@ -17,6 +17,7 @@
# under the License.
import abc
+import functools
import os
import webob.dec
@@ -451,3 +452,42 @@ class V3APIExtensionBase(object):
def version(self):
"""Version of the extension."""
pass
+
+
+def expected_errors(errors):
+ """Decorator for v3 API methods which specifies expected exceptions.
+
+ Specify which exceptions may occur when an API method is called. If an
+ unexpected exception occurs then return a 500 instead and ask the user
+ of the API to file a bug report.
+ """
+ def decorator(f):
+ @functools.wraps(f)
+ def wrapped(*args, **kwargs):
+ try:
+ return f(*args, **kwargs)
+ except Exception as exc:
+ if isinstance(exc, webob.exc.WSGIHTTPException):
+ if isinstance(errors, int):
+ t_errors = (errors,)
+ else:
+ t_errors = errors
+ if exc.code in t_errors:
+ raise
+ elif isinstance(exc, exception.PolicyNotAuthorized):
+ # Note(cyeoh): Special case to handle
+ # PolicyNotAuthorized exceptions so every
+ # extension method does not need to wrap authorize
+ # calls. ResourceExceptionHandler silently
+ # converts NotAuthorized to HTTPForbidden
+ raise
+
+ LOG.exception(_("Unexpected exception in API method"))
+ msg = _('Unexpected API Error. Please report this at '
+ 'http://bugs.launchpad.net/nova/ and attach the Nova '
+ 'API log if possible.\n%s') % type(exc)
+ raise webob.exc.HTTPInternalServerError(explanation=msg)
+
+ return wrapped
+
+ return decorator