summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Erdfelt <johannes.erdfelt@rackspace.com>2011-10-27 13:53:18 +0000
committerJohannes Erdfelt <johannes.erdfelt@rackspace.com>2011-10-27 18:14:23 +0000
commit3c3fbaf552948d07c80a5f22aada5f046c3be67b (patch)
treea9bba9bfb9aeb573e4b1a7330fc17de525f1ada2
parent16bacc3252b9a792159b247dcf9d2f3ebb6842ac (diff)
Fix overzealous use of faults.Fault() wrapper
wsgi.Resource will automatically wrap HTTP exceptions in faults.Fault() but many extensions will unnecessarily wrap HTTP exceptions manually. Also, let's raise exceptions instead of returning them to be consistent. Change-Id: I297a4decbd4a00fb12ec471a5e76aeea3dda6d34
-rw-r--r--nova/api/openstack/contrib/diskconfig.py7
-rw-r--r--nova/api/openstack/contrib/flavorextraspecs.py3
-rw-r--r--nova/api/openstack/contrib/floating_ips.py5
-rw-r--r--nova/api/openstack/contrib/keypairs.py3
-rw-r--r--nova/api/openstack/contrib/multinic.py45
-rw-r--r--nova/api/openstack/contrib/security_groups.py32
-rw-r--r--nova/api/openstack/contrib/virtual_storage_arrays.py54
-rw-r--r--nova/api/openstack/contrib/volumes.py25
-rw-r--r--nova/api/openstack/contrib/volumetypes.py15
-rw-r--r--nova/api/openstack/extensions.py11
-rw-r--r--nova/tests/api/openstack/extensions/foxinsocks.py7
-rw-r--r--nova/tests/api/openstack/test_extensions.py80
12 files changed, 178 insertions, 109 deletions
diff --git a/nova/api/openstack/contrib/diskconfig.py b/nova/api/openstack/contrib/diskconfig.py
index 2225a30fb..c0ba70363 100644
--- a/nova/api/openstack/contrib/diskconfig.py
+++ b/nova/api/openstack/contrib/diskconfig.py
@@ -25,7 +25,6 @@ import nova.image
from nova import log as logging
from nova import network
from nova import rpc
-from nova.api.openstack import faults
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
@@ -46,19 +45,19 @@ class DiskConfigController(object):
server = self.compute_api.routing_get(context, server_id)
except exception.NotFound:
explanation = _("Server not found.")
- return faults.Fault(exc.HTTPNotFound(explanation=explanation))
+ raise exc.HTTPNotFound(explanation=explanation)
managed_disk = server['managed_disk'] or False
return self._return_dict(server_id, managed_disk)
def update(self, req, server_id, body=None):
if not body:
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
context = req.environ['nova.context']
try:
server = self.compute_api.routing_get(context, server_id)
except exception.NotFound:
explanation = _("Server not found.")
- return faults.Fault(exc.HTTPNotFound(explanation=explanation))
+ raise exc.HTTPNotFound(explanation=explanation)
managed_disk = str(body['server'].get('managed_disk', False)).lower()
managed_disk = managed_disk == 'true' or False
diff --git a/nova/api/openstack/contrib/flavorextraspecs.py b/nova/api/openstack/contrib/flavorextraspecs.py
index b40ef5aa3..8a756f04a 100644
--- a/nova/api/openstack/contrib/flavorextraspecs.py
+++ b/nova/api/openstack/contrib/flavorextraspecs.py
@@ -22,7 +22,6 @@ from webob import exc
from nova import db
from nova import quota
from nova.api.openstack import extensions
-from nova.api.openstack import faults
from nova.api.openstack import wsgi
@@ -83,7 +82,7 @@ class FlavorExtraSpecsController(object):
if id in specs['extra_specs']:
return {id: specs['extra_specs'][id]}
else:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
def delete(self, req, flavor_id, id):
""" Deletes an existing extra spec """
diff --git a/nova/api/openstack/contrib/floating_ips.py b/nova/api/openstack/contrib/floating_ips.py
index c6d0a80d2..b64251e53 100644
--- a/nova/api/openstack/contrib/floating_ips.py
+++ b/nova/api/openstack/contrib/floating_ips.py
@@ -22,7 +22,6 @@ from nova import exception
from nova import log as logging
from nova import network
from nova import rpc
-from nova.api.openstack import faults
from nova.api.openstack import extensions
@@ -72,7 +71,7 @@ class FloatingIPController(object):
try:
floating_ip = self.network_api.get_floating_ip(context, id)
except exception.NotFound:
- return faults.Fault(webob.exc.HTTPNotFound())
+ raise webob.exc.HTTPNotFound()
return _translate_floating_ip_view(floating_ip)
@@ -113,7 +112,7 @@ class FloatingIPController(object):
self.network_api.release_floating_ip(context,
address=floating_ip['address'])
- return webob.exc.HTTPAccepted()
+ return webob.Response(status_int=202)
def _get_ip_by_id(self, context, value):
"""Checks that value is id and then returns its address."""
diff --git a/nova/api/openstack/contrib/keypairs.py b/nova/api/openstack/contrib/keypairs.py
index c7965b8c4..ee5cad530 100644
--- a/nova/api/openstack/contrib/keypairs.py
+++ b/nova/api/openstack/contrib/keypairs.py
@@ -21,6 +21,7 @@ import os
import shutil
import tempfile
+import webob
from webob import exc
from nova import crypto
@@ -97,7 +98,7 @@ class KeypairController(object):
"""
context = req.environ['nova.context']
db.key_pair_destroy(context, context.user_id, id)
- return exc.HTTPAccepted()
+ return webob.Response(status_int=202)
def index(self, req):
"""
diff --git a/nova/api/openstack/contrib/multinic.py b/nova/api/openstack/contrib/multinic.py
index c39b87b84..85ff423aa 100644
--- a/nova/api/openstack/contrib/multinic.py
+++ b/nova/api/openstack/contrib/multinic.py
@@ -21,7 +21,6 @@ import webob
from nova import compute
from nova import log as logging
from nova.api.openstack import extensions
-from nova.api.openstack import faults
LOG = logging.getLogger("nova.api.multinic")
@@ -67,36 +66,32 @@ class Multinic(extensions.ExtensionDescriptor):
def _add_fixed_ip(self, input_dict, req, id):
"""Adds an IP on a given network to an instance."""
- try:
- # Validate the input entity
- if 'networkId' not in input_dict['addFixedIp']:
- LOG.exception(_("Missing 'networkId' argument for addFixedIp"))
- return faults.Fault(exc.HTTPUnprocessableEntity())
-
- # Add the fixed IP
- network_id = input_dict['addFixedIp']['networkId']
- self.compute_api.add_fixed_ip(req.environ['nova.context'], id,
- network_id)
- except Exception, e:
- LOG.exception(_("Error in addFixedIp %s"), e)
- return faults.Fault(exc.HTTPBadRequest())
+ # Validate the input entity
+ if 'networkId' not in input_dict['addFixedIp']:
+ msg = _("Missing 'networkId' argument for addFixedIp")
+ raise exc.HTTPUnprocessableEntity(explanation=msg)
+
+ # Add the fixed IP
+ network_id = input_dict['addFixedIp']['networkId']
+ self.compute_api.add_fixed_ip(req.environ['nova.context'], id,
+ network_id)
return webob.Response(status_int=202)
def _remove_fixed_ip(self, input_dict, req, id):
"""Removes an IP from an instance."""
+ # Validate the input entity
+ if 'address' not in input_dict['removeFixedIp']:
+ msg = _("Missing 'address' argument for removeFixedIp")
+ raise exc.HTTPUnprocessableEntity(explanation=msg)
+
+ # Remove the fixed IP
+ address = input_dict['removeFixedIp']['address']
try:
- # Validate the input entity
- if 'address' not in input_dict['removeFixedIp']:
- LOG.exception(_("Missing 'address' argument for "
- "removeFixedIp"))
- return faults.Fault(exc.HTTPUnprocessableEntity())
-
- # Remove the fixed IP
- address = input_dict['removeFixedIp']['address']
self.compute_api.remove_fixed_ip(req.environ['nova.context'], id,
address)
- except Exception, e:
- LOG.exception(_("Error in removeFixedIp %s"), e)
- return faults.Fault(exc.HTTPBadRequest())
+ except exceptions.FixedIpNotFoundForSpecificInstance:
+ LOG.exception(_("Unable to find address %r") % address)
+ raise exc.HTTPBadRequest()
+
return webob.Response(status_int=202)
diff --git a/nova/api/openstack/contrib/security_groups.py b/nova/api/openstack/contrib/security_groups.py
index dd8333525..d8462b02c 100644
--- a/nova/api/openstack/contrib/security_groups.py
+++ b/nova/api/openstack/contrib/security_groups.py
@@ -99,7 +99,7 @@ class SecurityGroupController(object):
LOG.audit(_("Delete security group %s"), id, context=context)
db.security_group_destroy(context, security_group.id)
- return exc.HTTPAccepted()
+ return webob.Response(status_int=202)
def index(self, req):
"""Returns a list of security groups"""
@@ -120,12 +120,12 @@ class SecurityGroupController(object):
"""Creates a new security group."""
context = req.environ['nova.context']
if not body:
- return exc.HTTPUnprocessableEntity()
+ raise exc.HTTPUnprocessableEntity()
security_group = body.get('security_group', None)
if security_group is None:
- return exc.HTTPUnprocessableEntity()
+ raise exc.HTTPUnprocessableEntity()
group_name = security_group.get('name', None)
group_description = security_group.get('description', None)
@@ -189,10 +189,10 @@ class SecurityGroupRulesController(SecurityGroupController):
security_group = db.security_group_get(context, parent_group_id)
except ValueError:
msg = _("Parent group id is not integer")
- return exc.HTTPBadRequest(explanation=msg)
+ raise exc.HTTPBadRequest(explanation=msg)
except exception.NotFound as exp:
msg = _("Security group (%s) not found") % parent_group_id
- return exc.HTTPNotFound(explanation=msg)
+ raise exc.HTTPNotFound(explanation=msg)
msg = _("Authorize security group ingress %s")
LOG.audit(msg, security_group['name'], context=context)
@@ -312,10 +312,10 @@ class SecurityGroupRulesController(SecurityGroupController):
rule = db.security_group_rule_get(context, id)
except ValueError:
msg = _("Rule id is not integer")
- return exc.HTTPBadRequest(explanation=msg)
+ raise exc.HTTPBadRequest(explanation=msg)
except exception.NotFound as exp:
msg = _("Rule (%s) not found") % id
- return exc.HTTPNotFound(explanation=msg)
+ raise exc.HTTPNotFound(explanation=msg)
group_id = rule.parent_group_id
self.compute_api.ensure_default_security_group(context)
@@ -328,7 +328,7 @@ class SecurityGroupRulesController(SecurityGroupController):
self.compute_api.trigger_security_group_rules_refresh(context,
security_group_id=security_group['id'])
- return exc.HTTPAccepted()
+ return webob.Response(status_int=202)
class Security_groups(extensions.ExtensionDescriptor):
@@ -368,13 +368,13 @@ class Security_groups(extensions.ExtensionDescriptor):
self.compute_api.add_security_group(context, instance_id,
group_name)
except exception.SecurityGroupNotFound as exp:
- return exc.HTTPNotFound(explanation=unicode(exp))
+ raise exc.HTTPNotFound(explanation=unicode(exp))
except exception.InstanceNotFound as exp:
- return exc.HTTPNotFound(explanation=unicode(exp))
+ raise exc.HTTPNotFound(explanation=unicode(exp))
except exception.Invalid as exp:
- return exc.HTTPBadRequest(explanation=unicode(exp))
+ raise exc.HTTPBadRequest(explanation=unicode(exp))
- return exc.HTTPAccepted()
+ return webob.Response(status_int=202)
def _removeSecurityGroup(self, input_dict, req, instance_id):
context = req.environ['nova.context']
@@ -401,13 +401,13 @@ class Security_groups(extensions.ExtensionDescriptor):
self.compute_api.remove_security_group(context, instance_id,
group_name)
except exception.SecurityGroupNotFound as exp:
- return exc.HTTPNotFound(explanation=unicode(exp))
+ raise exc.HTTPNotFound(explanation=unicode(exp))
except exception.InstanceNotFound as exp:
- return exc.HTTPNotFound(explanation=unicode(exp))
+ raise exc.HTTPNotFound(explanation=unicode(exp))
except exception.Invalid as exp:
- return exc.HTTPBadRequest(explanation=unicode(exp))
+ raise exc.HTTPBadRequest(explanation=unicode(exp))
- return exc.HTTPAccepted()
+ return webob.Response(status_int=202)
def get_actions(self):
"""Return the actions the extensions adds"""
diff --git a/nova/api/openstack/contrib/virtual_storage_arrays.py b/nova/api/openstack/contrib/virtual_storage_arrays.py
index 5c5afdd22..a6bf72960 100644
--- a/nova/api/openstack/contrib/virtual_storage_arrays.py
+++ b/nova/api/openstack/contrib/virtual_storage_arrays.py
@@ -18,6 +18,7 @@
""" The virtul storage array extension"""
+import webob
from webob import exc
from nova import vsa
@@ -30,7 +31,6 @@ from nova import exception
from nova import log as logging
from nova.api.openstack import common
from nova.api.openstack import extensions
-from nova.api.openstack import faults
from nova.api.openstack import wsgi
from nova.api.openstack import servers
from nova.api.openstack.contrib import volumes
@@ -137,7 +137,7 @@ class VsaController(object):
try:
vsa = self.vsa_api.get(context, vsa_id=id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
instances = self._get_instances_by_vsa_id(context, vsa.get('id'))
return {'vsa': _vsa_view(context, vsa, True, instances)}
@@ -148,7 +148,7 @@ class VsaController(object):
if not body or 'vsa' not in body:
LOG.debug(_("No body provided"), context=context)
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
vsa = body['vsa']
@@ -157,7 +157,7 @@ class VsaController(object):
try:
instance_type = instance_types.get_instance_type_by_name(vc_type)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
LOG.audit(_("Create VSA %(display_name)s of type %(vc_type)s"),
locals(), context=context)
@@ -184,7 +184,7 @@ class VsaController(object):
try:
self.vsa_api.delete(context, vsa_id=id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
def associate_address(self, req, id, body):
""" /zadr-vsa/{vsa_id}/associate_address
@@ -203,7 +203,7 @@ class VsaController(object):
try:
instances = self._get_instances_by_vsa_id(context, id)
if instances is None or len(instances) == 0:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
for instance in instances:
self.network_api.allocate_for_instance(context, instance,
@@ -212,7 +212,7 @@ class VsaController(object):
return
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
def disassociate_address(self, req, id, body):
""" /zadr-vsa/{vsa_id}/disassociate_address
@@ -313,7 +313,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
context = req.environ['nova.context']
if not body:
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
vol = body[self.object]
size = vol['size']
@@ -323,7 +323,7 @@ class VsaVolumeDriveController(volumes.VolumeController):
# create is supported for volumes only (drives created through VSA)
volume_type = self.vsa_api.get_vsa_volume_type(context)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
new_volume = self.volume_api.create(context,
size,
@@ -343,9 +343,9 @@ class VsaVolumeDriveController(volumes.VolumeController):
try:
self._check_volume_ownership(context, vsa_id, id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
except exception.Invalid:
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
vol = body[self.object]
updatable_fields = [{'displayName': 'display_name'},
@@ -367,8 +367,8 @@ class VsaVolumeDriveController(volumes.VolumeController):
try:
self.volume_api.update(context, volume_id=id, fields=changes)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
- return exc.HTTPAccepted()
+ raise exc.HTTPNotFound()
+ return webob.Response(status_int=202)
def delete(self, req, vsa_id, id):
"""Delete a volume."""
@@ -379,9 +379,9 @@ class VsaVolumeDriveController(volumes.VolumeController):
try:
self._check_volume_ownership(context, vsa_id, id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
except exception.Invalid:
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
return super(VsaVolumeDriveController, self).delete(req, id)
@@ -394,9 +394,9 @@ class VsaVolumeDriveController(volumes.VolumeController):
try:
self._check_volume_ownership(context, vsa_id, id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
except exception.Invalid:
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
return super(VsaVolumeDriveController, self).show(req, id)
@@ -432,15 +432,15 @@ class VsaDriveController(VsaVolumeDriveController):
def create(self, req, vsa_id, body):
"""Create a new drive for VSA. Should be done through VSA APIs"""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def update(self, req, vsa_id, id, body):
"""Update a drive. Should be done through VSA APIs"""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def delete(self, req, vsa_id, id):
"""Delete a volume. Should be done through VSA APIs"""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
class VsaVPoolController(object):
@@ -474,19 +474,19 @@ class VsaVPoolController(object):
def create(self, req, vsa_id, body):
"""Create a new vPool for VSA."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def update(self, req, vsa_id, id, body):
"""Update vPool parameters."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def delete(self, req, vsa_id, id):
"""Delete a vPool."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def show(self, req, vsa_id, id):
"""Return data about the given vPool."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
class VsaVCController(servers.Controller):
@@ -529,15 +529,15 @@ class VsaVCController(servers.Controller):
def create(self, req, vsa_id, body):
"""Create a new instance for VSA."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def update(self, req, vsa_id, id, body):
"""Update VSA instance."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def delete(self, req, vsa_id, id):
"""Delete VSA instance."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def show(self, req, vsa_id, id):
"""Return data about the given instance."""
diff --git a/nova/api/openstack/contrib/volumes.py b/nova/api/openstack/contrib/volumes.py
index da856b4a1..cd10aaa99 100644
--- a/nova/api/openstack/contrib/volumes.py
+++ b/nova/api/openstack/contrib/volumes.py
@@ -28,7 +28,6 @@ from nova import volume
from nova.volume import volume_types
from nova.api.openstack import common
from nova.api.openstack import extensions
-from nova.api.openstack import faults
from nova.api.openstack import servers
@@ -113,7 +112,7 @@ class VolumeController(object):
try:
vol = self.volume_api.get(context, id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
return {'volume': _translate_volume_detail_view(context, vol)}
@@ -126,7 +125,7 @@ class VolumeController(object):
try:
self.volume_api.delete(context, volume_id=id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
return webob.Response(status_int=202)
def index(self, req):
@@ -151,7 +150,7 @@ class VolumeController(object):
context = req.environ['nova.context']
if not body:
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
vol = body['volume']
size = vol['size']
@@ -163,7 +162,7 @@ class VolumeController(object):
vol_type = volume_types.get_volume_type_by_name(context,
vol_type)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
metadata = vol.get('metadata', None)
@@ -244,12 +243,12 @@ class VolumeAttachmentController(object):
vol = self.volume_api.get(context, volume_id)
except exception.NotFound:
LOG.debug("volume_id not found")
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
instance = vol['instance']
if instance is None or str(instance['uuid']) != server_id:
LOG.debug("instance_id != server_id")
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
return {'volumeAttachment': _translate_attachment_detail_view(context,
vol)}
@@ -259,7 +258,7 @@ class VolumeAttachmentController(object):
context = req.environ['nova.context']
if not body:
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
instance_id = server_id
volume_id = body['volumeAttachment']['volumeId']
@@ -275,7 +274,7 @@ class VolumeAttachmentController(object):
volume_id=volume_id,
device=device)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
# The attach is async
attachment = {}
@@ -295,7 +294,7 @@ class VolumeAttachmentController(object):
def update(self, req, server_id, id, body):
"""Update a volume attachment. We don't currently support this."""
- return faults.Fault(exc.HTTPBadRequest())
+ raise exc.HTTPBadRequest()
def delete(self, req, server_id, id):
"""Detach a volume from an instance."""
@@ -307,12 +306,12 @@ class VolumeAttachmentController(object):
try:
vol = self.volume_api.get(context, volume_id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
instance = vol['instance']
if instance is None or str(instance['uuid']) != server_id:
LOG.debug("instance_id != server_id")
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
self.compute_api.detach_volume(context,
volume_id=volume_id)
@@ -326,7 +325,7 @@ class VolumeAttachmentController(object):
try:
instance = self.compute_api.get(context, server_id)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
volumes = instance['volumes']
limited_list = common.limited(volumes, req)
diff --git a/nova/api/openstack/contrib/volumetypes.py b/nova/api/openstack/contrib/volumetypes.py
index 45f257ce7..d63104a29 100644
--- a/nova/api/openstack/contrib/volumetypes.py
+++ b/nova/api/openstack/contrib/volumetypes.py
@@ -24,7 +24,6 @@ from nova import exception
from nova import quota
from nova.volume import volume_types
from nova.api.openstack import extensions
-from nova.api.openstack import faults
from nova.api.openstack import wsgi
@@ -41,17 +40,17 @@ class VolumeTypesController(object):
context = req.environ['nova.context']
if not body or body == "":
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
vol_type = body.get('volume_type', None)
if vol_type is None or vol_type == "":
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
name = vol_type.get('name', None)
specs = vol_type.get('extra_specs', {})
if name is None or name == "":
- return faults.Fault(exc.HTTPUnprocessableEntity())
+ raise exc.HTTPUnprocessableEntity()
try:
volume_types.create(context, name, specs)
@@ -59,7 +58,7 @@ class VolumeTypesController(object):
except quota.QuotaError as error:
self._handle_quota_error(error)
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
return {'volume_type': vol_type}
@@ -70,7 +69,7 @@ class VolumeTypesController(object):
try:
vol_type = volume_types.get_volume_type(context, id)
except exception.NotFound or exception.ApiError:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
return {'volume_type': vol_type}
@@ -82,7 +81,7 @@ class VolumeTypesController(object):
vol_type = volume_types.get_volume_type(context, id)
volume_types.destroy(context, vol_type['name'])
except exception.NotFound:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
def _handle_quota_error(self, error):
"""Reraise quota errors as api-specific http exceptions."""
@@ -148,7 +147,7 @@ class VolumeTypeExtraSpecsController(object):
if id in specs['extra_specs']:
return {id: specs['extra_specs'][id]}
else:
- return faults.Fault(exc.HTTPNotFound())
+ raise exc.HTTPNotFound()
def delete(self, req, vol_type_id, id):
""" Deletes an existing extra spec """
diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py
index 23e8f71ed..382404309 100644
--- a/nova/api/openstack/extensions.py
+++ b/nova/api/openstack/extensions.py
@@ -34,7 +34,6 @@ from nova import utils
from nova import wsgi as base_wsgi
import nova.api.openstack
from nova.api.openstack import common
-from nova.api.openstack import faults
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
@@ -193,15 +192,15 @@ class ExtensionsResource(wsgi.Resource):
# NOTE(dprince): the extensions alias is used as the 'id' for show
ext = self.extension_manager.extensions[id]
except KeyError:
- return faults.Fault(webob.exc.HTTPNotFound())
+ raise webob.exc.HTTPNotFound()
return dict(extension=self._translate(ext))
def delete(self, req, id):
- raise faults.Fault(webob.exc.HTTPNotFound())
+ raise webob.exc.HTTPNotFound()
def create(self, req):
- raise faults.Fault(webob.exc.HTTPNotFound())
+ raise webob.exc.HTTPNotFound()
class ExtensionMiddleware(base_wsgi.Middleware):
@@ -517,7 +516,7 @@ def admin_only(fnc):
def _wrapped(self, *args, **kwargs):
if FLAGS.allow_admin_api:
return fnc(self, *args, **kwargs)
- return faults.Fault(webob.exc.HTTPNotFound())
+ raise webob.exc.HTTPNotFound()
_wrapped.func_name = fnc.func_name
return _wrapped
@@ -528,5 +527,5 @@ def wrap_errors(fn):
try:
return fn(*args)
except Exception, e:
- return faults.Fault(webob.exc.HTTPInternalServerError())
+ raise webob.exc.HTTPInternalServerError()
return wrapped
diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py
index d72365620..cbf101f47 100644
--- a/nova/tests/api/openstack/extensions/foxinsocks.py
+++ b/nova/tests/api/openstack/extensions/foxinsocks.py
@@ -16,6 +16,7 @@
# under the License.
import json
+import webob.exc
from nova.api.openstack import extensions
@@ -50,6 +51,8 @@ class Foxinsocks(object):
self._add_tweedle))
actions.append(extensions.ActionExtension('servers', 'delete_tweedle',
self._delete_tweedle))
+ actions.append(extensions.ActionExtension('servers', 'fail',
+ self._fail))
return actions
def get_request_extensions(self):
@@ -85,3 +88,7 @@ class Foxinsocks(object):
def _delete_tweedle(self, input_dict, req, id):
return "Tweedle Beetle Deleted."
+
+ def _fail(self, input_dict, req, id):
+
+ raise webob.exc.HTTPBadRequest(explanation='Tweedle fail')
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index d96a67d7d..cb44288c7 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -46,6 +46,13 @@ class StubController(object):
def index(self, req):
return self.body
+ def create(self, req):
+ msg = 'All aboard the fail train!'
+ raise webob.exc.HTTPBadRequest(explanation=msg)
+
+ def show(self, req, id):
+ raise webob.exc.HTTPNotFound()
+
class StubExtensionManager(object):
"""Provides access to Tweedle Beetles"""
@@ -252,6 +259,47 @@ class ResourceExtensionTest(ExtensionTestCase):
self.assertEqual(200, response.status_int)
self.assertEqual(response_body, response.body)
+ def test_bad_request(self):
+ res_ext = extensions.ResourceExtension('tweedles',
+ StubController(response_body))
+ manager = StubExtensionManager(res_ext)
+ app = openstack.APIRouter()
+ ext_midware = extensions.ExtensionMiddleware(app, manager)
+ ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
+ request = webob.Request.blank("/123/tweedles")
+ request.method = "POST"
+ response = request.get_response(ser_midware)
+ self.assertEqual(400, response.status_int)
+ self.assertEqual('application/json', response.content_type)
+ body = json.loads(response.body)
+ expected = {
+ "badRequest": {
+ "message": "All aboard the fail train!",
+ "code": 400
+ }
+ }
+ self.assertDictMatch(expected, body)
+
+ def test_non_exist_resource(self):
+ res_ext = extensions.ResourceExtension('tweedles',
+ StubController(response_body))
+ manager = StubExtensionManager(res_ext)
+ app = openstack.APIRouter()
+ ext_midware = extensions.ExtensionMiddleware(app, manager)
+ ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
+ request = webob.Request.blank("/123/tweedles/1")
+ response = request.get_response(ser_midware)
+ self.assertEqual(404, response.status_int)
+ self.assertEqual('application/json', response.content_type)
+ body = json.loads(response.body)
+ expected = {
+ "itemNotFound": {
+ "message": "The resource could not be found.",
+ "code": 404
+ }
+ }
+ self.assertDictMatch(expected, body)
+
class InvalidExtension(object):
@@ -307,18 +355,42 @@ class ActionExtensionTest(ExtensionTestCase):
self.assertEqual(200, response.status_int)
self.assertEqual("Tweedle Beetle Deleted.", response.body)
- def test_invalid_action_body(self):
+ def test_invalid_action(self):
body = dict(blah=dict(name="test")) # Doesn't exist
url = "/123/servers/abcd/action"
response = self._send_server_action_request(url, body)
self.assertEqual(400, response.status_int)
-
- def test_invalid_action(self):
+ self.assertEqual('application/json', response.content_type)
+ body = json.loads(response.body)
+ expected = {
+ "badRequest": {
+ "message": "There is no such server action: blah",
+ "code": 400
+ }
+ }
+ self.assertDictMatch(expected, body)
+
+ def test_non_exist_action(self):
body = dict(blah=dict(name="test"))
url = "/123/fdsa/1/action"
response = self._send_server_action_request(url, body)
self.assertEqual(404, response.status_int)
+ def test_failed_action(self):
+ body = dict(fail=dict(name="test"))
+ url = "/123/servers/abcd/action"
+ response = self._send_server_action_request(url, body)
+ self.assertEqual(400, response.status_int)
+ self.assertEqual('application/json', response.content_type)
+ body = json.loads(response.body)
+ expected = {
+ "badRequest": {
+ "message": "Tweedle fail",
+ "code": 400
+ }
+ }
+ self.assertDictMatch(expected, body)
+
class RequestExtensionTest(ExtensionTestCase):
@@ -360,7 +432,7 @@ class RequestExtensionTest(ExtensionTestCase):
class ExtensionsXMLSerializerTest(test.TestCase):
- def test_serialize_extenstion(self):
+ def test_serialize_extension(self):
serializer = extensions.ExtensionsXMLSerializer()
data = {'extension': {
'name': 'ext1',