diff options
| author | Johannes Erdfelt <johannes.erdfelt@rackspace.com> | 2011-10-27 13:53:18 +0000 |
|---|---|---|
| committer | Johannes Erdfelt <johannes.erdfelt@rackspace.com> | 2011-10-27 18:14:23 +0000 |
| commit | 3c3fbaf552948d07c80a5f22aada5f046c3be67b (patch) | |
| tree | a9bba9bfb9aeb573e4b1a7330fc17de525f1ada2 | |
| parent | 16bacc3252b9a792159b247dcf9d2f3ebb6842ac (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.py | 7 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/flavorextraspecs.py | 3 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/floating_ips.py | 5 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/keypairs.py | 3 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/multinic.py | 45 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/security_groups.py | 32 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/virtual_storage_arrays.py | 54 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/volumes.py | 25 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/volumetypes.py | 15 | ||||
| -rw-r--r-- | nova/api/openstack/extensions.py | 11 | ||||
| -rw-r--r-- | nova/tests/api/openstack/extensions/foxinsocks.py | 7 | ||||
| -rw-r--r-- | nova/tests/api/openstack/test_extensions.py | 80 |
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', |
