Merge lp:~rackspace-titan/nova/osapi_fault_wrap_webob_exc into lp:~hudson-openstack/nova/trunk

Proposed by Dan Prince
Status: Merged
Approved by: Brian Waldon
Approved revision: 1295
Merged at revision: 1301
Proposed branch: lp:~rackspace-titan/nova/osapi_fault_wrap_webob_exc
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 763 lines (+90/-102)
15 files modified
nova/api/openstack/accounts.py (+3/-3)
nova/api/openstack/backup_schedules.py (+4/-5)
nova/api/openstack/common.py (+12/-7)
nova/api/openstack/consoles.py (+3/-4)
nova/api/openstack/create_instance_helper.py (+3/-4)
nova/api/openstack/image_metadata.py (+2/-3)
nova/api/openstack/images.py (+1/-2)
nova/api/openstack/ips.py (+5/-6)
nova/api/openstack/server_metadata.py (+0/-1)
nova/api/openstack/servers.py (+42/-50)
nova/api/openstack/shared_ip_groups.py (+6/-7)
nova/api/openstack/users.py (+1/-2)
nova/api/openstack/wsgi.py (+5/-1)
nova/api/openstack/zones.py (+2/-6)
nova/tests/api/openstack/test_servers.py (+1/-1)
To merge this branch: bzr merge lp:~rackspace-titan/nova/osapi_fault_wrap_webob_exc
Reviewer Review Type Date Requested Status
Brian Waldon (community) Approve
Devin Carlen (community) Approve
Alex Meade (community) Approve
Review via email: mp+68698@code.launchpad.net

Description of the change

Perform fault wrapping in the openstack WSGI controller. This allows us to just raise webob Exceptions in OS API controllers with the appropriate explanations set. This resolves some inconsistencies with exception raising and returning that would cause HTML output to occur when faults weren't being handled correctly.

To post a comment you must log in.
Revision history for this message
Dan Prince (dan-prince) wrote :

This branch resolves some issues I was having where faults would return content like this (for a JSON request):

 <html> <head> <title>422 Unprocessable Entity</title> </head> <body> <h1>422 Unprocessable Entity</h1> Unable to process the contained instructions<br /><br /> </body> </html>

---

In this branch we basically treat 400 and 500 faults as exceptions and handle them in nova.api.openstack.wsgi. This branch doesn't touch the extensions and auth middlewares which still return fault.Faults directly where the rest of the OSAPI just raises webob Exceptions.

I'm open to suggestions. This HTML output really bugs me...

Revision history for this message
Alex Meade (alex-meade) wrote :

This is some great OSAPI cleanup, assuming you test it well, I approve

review: Approve
Revision history for this message
Devin Carlen (devcamcar) wrote :

lgtm, nice cleanup.

review: Approve
Revision history for this message
Brian Waldon (bcwaldon) wrote :

Great work, Dan. Two things:

1) One pep8 violation:

nova/api/openstack/common.py:80:14: E222 multiple spaces after operator
    msg = _('offset param must be an integer')

2) Since you'll already be in common.py, can you fix the i18n on line 112 (on the MP)? The '% marker' should be outside of the _()

review: Needs Fixing
1294. By Dan Prince

Merge w/ trunk.

1295. By Dan Prince

pep8 and stuff.

Revision history for this message
Dan Prince (dan-prince) wrote :

> Great work, Dan. Two things:
>
> 1) One pep8 violation:
>
> nova/api/openstack/common.py:80:14: E222 multiple spaces after operator
> msg = _('offset param must be an integer')
>
>
> 2) Since you'll already be in common.py, can you fix the i18n on line 112 (on
> the MP)? The '% marker' should be outside of the _()

Fixed. Should be all set.

Revision history for this message
Brian Waldon (bcwaldon) wrote :

Thank you, Dan Prince.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/api/openstack/accounts.py'
2--- nova/api/openstack/accounts.py 2011-07-06 20:28:10 +0000
3+++ nova/api/openstack/accounts.py 2011-07-21 18:52:39 +0000
4@@ -47,10 +47,10 @@
5 raise exception.AdminRequired()
6
7 def index(self, req):
8- raise faults.Fault(webob.exc.HTTPNotImplemented())
9+ raise webob.exc.HTTPNotImplemented()
10
11 def detail(self, req):
12- raise faults.Fault(webob.exc.HTTPNotImplemented())
13+ raise webob.exc.HTTPNotImplemented()
14
15 def show(self, req, id):
16 """Return data about the given account id"""
17@@ -65,7 +65,7 @@
18 def create(self, req, body):
19 """We use update with create-or-update semantics
20 because the id comes from an external source"""
21- raise faults.Fault(webob.exc.HTTPNotImplemented())
22+ raise webob.exc.HTTPNotImplemented()
23
24 def update(self, req, id, body):
25 """This is really create or update."""
26
27=== modified file 'nova/api/openstack/backup_schedules.py'
28--- nova/api/openstack/backup_schedules.py 2011-07-06 20:28:10 +0000
29+++ nova/api/openstack/backup_schedules.py 2011-07-21 18:52:39 +0000
30@@ -19,7 +19,6 @@
31
32 from webob import exc
33
34-from nova.api.openstack import faults
35 from nova.api.openstack import wsgi
36
37
38@@ -36,20 +35,20 @@
39
40 def index(self, req, server_id, **kwargs):
41 """ Returns the list of backup schedules for a given instance """
42- return faults.Fault(exc.HTTPNotImplemented())
43+ raise exc.HTTPNotImplemented()
44
45 def show(self, req, server_id, id, **kwargs):
46 """ Returns a single backup schedule for a given instance """
47- return faults.Fault(exc.HTTPNotImplemented())
48+ raise exc.HTTPNotImplemented()
49
50 def create(self, req, server_id, **kwargs):
51 """ No actual update method required, since the existing API allows
52 both create and update through a POST """
53- return faults.Fault(exc.HTTPNotImplemented())
54+ raise exc.HTTPNotImplemented()
55
56 def delete(self, req, server_id, id, **kwargs):
57 """ Deletes an existing backup schedule """
58- return faults.Fault(exc.HTTPNotImplemented())
59+ raise exc.HTTPNotImplemented()
60
61
62 def create_resource():
63
64=== modified file 'nova/api/openstack/common.py'
65--- nova/api/openstack/common.py 2011-07-15 03:09:28 +0000
66+++ nova/api/openstack/common.py 2011-07-21 18:52:39 +0000
67@@ -53,10 +53,10 @@
68 params[param] = int(request.GET[param])
69 except ValueError:
70 msg = _('%s param must be an integer') % param
71- raise webob.exc.HTTPBadRequest(msg)
72+ raise webob.exc.HTTPBadRequest(explanation=msg)
73 if params[param] < 0:
74 msg = _('%s param must be positive') % param
75- raise webob.exc.HTTPBadRequest(msg)
76+ raise webob.exc.HTTPBadRequest(explanation=msg)
77
78 return params
79
80@@ -77,18 +77,22 @@
81 try:
82 offset = int(request.GET.get('offset', 0))
83 except ValueError:
84- raise webob.exc.HTTPBadRequest(_('offset param must be an integer'))
85+ msg = _('offset param must be an integer')
86+ raise webob.exc.HTTPBadRequest(explanation=msg)
87
88 try:
89 limit = int(request.GET.get('limit', max_limit))
90 except ValueError:
91- raise webob.exc.HTTPBadRequest(_('limit param must be an integer'))
92+ msg = _('limit param must be an integer')
93+ raise webob.exc.HTTPBadRequest(explanation=msg)
94
95 if limit < 0:
96- raise webob.exc.HTTPBadRequest(_('limit param must be positive'))
97+ msg = _('limit param must be positive')
98+ raise webob.exc.HTTPBadRequest(explanation=msg)
99
100 if offset < 0:
101- raise webob.exc.HTTPBadRequest(_('offset param must be positive'))
102+ msg = _('offset param must be positive')
103+ raise webob.exc.HTTPBadRequest(explanation=msg)
104
105 limit = min(max_limit, limit or max_limit)
106 range_end = offset + limit
107@@ -111,7 +115,8 @@
108 start_index = i + 1
109 break
110 if start_index < 0:
111- raise webob.exc.HTTPBadRequest(_('marker [%s] not found' % marker))
112+ msg = _('marker [%s] not found') % marker
113+ raise webob.exc.HTTPBadRequest(explanation=msg)
114 range_end = start_index + limit
115 return items[start_index:range_end]
116
117
118=== modified file 'nova/api/openstack/consoles.py'
119--- nova/api/openstack/consoles.py 2011-07-20 17:52:22 +0000
120+++ nova/api/openstack/consoles.py 2011-07-21 18:52:39 +0000
121@@ -20,7 +20,6 @@
122
123 from nova import console
124 from nova import exception
125-from nova.api.openstack import faults
126 from nova.api.openstack import wsgi
127
128
129@@ -72,12 +71,12 @@
130 int(server_id),
131 int(id))
132 except exception.NotFound:
133- return faults.Fault(exc.HTTPNotFound())
134+ raise exc.HTTPNotFound()
135 return _translate_detail_keys(console)
136
137 def update(self, req, server_id, id):
138 """You can't update a console"""
139- raise faults.Fault(exc.HTTPNotImplemented())
140+ raise exc.HTTPNotImplemented()
141
142 def delete(self, req, server_id, id):
143 """Deletes a console"""
144@@ -86,7 +85,7 @@
145 int(server_id),
146 int(id))
147 except exception.NotFound:
148- return faults.Fault(exc.HTTPNotFound())
149+ raise exc.HTTPNotFound()
150 return webob.Response(status_int=202)
151
152
153
154=== modified file 'nova/api/openstack/create_instance_helper.py'
155--- nova/api/openstack/create_instance_helper.py 2011-07-06 20:28:10 +0000
156+++ nova/api/openstack/create_instance_helper.py 2011-07-21 18:52:39 +0000
157@@ -28,7 +28,6 @@
158 from nova import utils
159
160 from nova.compute import instance_types
161-from nova.api.openstack import faults
162 from nova.api.openstack import wsgi
163 from nova.auth import manager as auth_manager
164
165@@ -70,7 +69,7 @@
166 return type from this method is left to the caller.
167 """
168 if not body:
169- raise faults.Fault(exc.HTTPUnprocessableEntity())
170+ raise exc.HTTPUnprocessableEntity()
171
172 context = req.environ['nova.context']
173
174@@ -94,7 +93,7 @@
175 except Exception, e:
176 msg = _("Cannot find requested image %(image_href)s: %(e)s" %
177 locals())
178- raise faults.Fault(exc.HTTPBadRequest(explanation=msg))
179+ raise exc.HTTPBadRequest(explanation=msg)
180
181 personality = body['server'].get('personality')
182
183@@ -153,7 +152,7 @@
184 self._handle_quota_error(error)
185 except exception.ImageNotFound as error:
186 msg = _("Can not find requested image")
187- raise faults.Fault(exc.HTTPBadRequest(explanation=msg))
188+ raise exc.HTTPBadRequest(explanation=msg)
189
190 # Let the caller deal with unhandled exceptions.
191
192
193=== modified file 'nova/api/openstack/image_metadata.py'
194--- nova/api/openstack/image_metadata.py 2011-07-06 20:28:10 +0000
195+++ nova/api/openstack/image_metadata.py 2011-07-21 18:52:39 +0000
196@@ -22,7 +22,6 @@
197 from nova import image
198 from nova import quota
199 from nova import utils
200-from nova.api.openstack import faults
201 from nova.api.openstack import wsgi
202
203
204@@ -62,7 +61,7 @@
205 if id in metadata:
206 return {'meta': {id: metadata[id]}}
207 else:
208- return faults.Fault(exc.HTTPNotFound())
209+ raise exc.HTTPNotFound()
210
211 def create(self, req, image_id, body):
212 context = req.environ['nova.context']
213@@ -105,7 +104,7 @@
214 img = self.image_service.show(context, image_id)
215 metadata = self._get_metadata(context, image_id)
216 if not id in metadata:
217- return faults.Fault(exc.HTTPNotFound())
218+ raise exc.HTTPNotFound()
219 metadata.pop(id)
220 img['properties'] = metadata
221 self.image_service.update(context, image_id, img, None)
222
223=== modified file 'nova/api/openstack/images.py'
224--- nova/api/openstack/images.py 2011-07-14 13:29:27 +0000
225+++ nova/api/openstack/images.py 2011-07-21 18:52:39 +0000
226@@ -25,7 +25,6 @@
227 import nova.image
228 from nova import log
229 from nova.api.openstack import common
230-from nova.api.openstack import faults
231 from nova.api.openstack import image_metadata
232 from nova.api.openstack import servers
233 from nova.api.openstack.views import images as images_view
234@@ -85,7 +84,7 @@
235 image = self._image_service.show(context, id)
236 except (exception.NotFound, exception.InvalidImageRef):
237 explanation = _("Image not found.")
238- raise faults.Fault(webob.exc.HTTPNotFound(explanation=explanation))
239+ raise webob.exc.HTTPNotFound(explanation=explanation)
240
241 return dict(image=self.get_builder(req).build(image, detail=True))
242
243
244=== modified file 'nova/api/openstack/ips.py'
245--- nova/api/openstack/ips.py 2011-07-14 17:25:05 +0000
246+++ nova/api/openstack/ips.py 2011-07-21 18:52:39 +0000
247@@ -20,7 +20,6 @@
248 from webob import exc
249
250 import nova
251-from nova.api.openstack import faults
252 import nova.api.openstack.views.addresses
253 from nova.api.openstack import wsgi
254 from nova import db
255@@ -37,14 +36,14 @@
256 instance = self.compute_api.get(
257 req.environ['nova.context'], server_id)
258 except nova.exception.NotFound:
259- return faults.Fault(exc.HTTPNotFound())
260+ raise exc.HTTPNotFound()
261 return instance
262
263 def create(self, req, server_id, body):
264- return faults.Fault(exc.HTTPNotImplemented())
265+ raise exc.HTTPNotImplemented()
266
267 def delete(self, req, server_id, id):
268- return faults.Fault(exc.HTTPNotImplemented())
269+ raise exc.HTTPNotImplemented()
270
271
272 class ControllerV10(Controller):
273@@ -63,7 +62,7 @@
274 view = builder.build_public_parts(instance)
275 else:
276 msg = _("Only private and public networks available")
277- return faults.Fault(exc.HTTPNotFound(explanation=msg))
278+ raise exc.HTTPNotFound(explanation=msg)
279
280 return {id: view}
281
282@@ -86,7 +85,7 @@
283
284 if network is None:
285 msg = _("Instance is not a member of specified network")
286- return faults.Fault(exc.HTTPNotFound(explanation=msg))
287+ raise exc.HTTPNotFound(explanation=msg)
288
289 return network
290
291
292=== modified file 'nova/api/openstack/server_metadata.py'
293--- nova/api/openstack/server_metadata.py 2011-07-06 20:28:10 +0000
294+++ nova/api/openstack/server_metadata.py 2011-07-21 18:52:39 +0000
295@@ -18,7 +18,6 @@
296 from webob import exc
297
298 from nova import compute
299-from nova.api.openstack import faults
300 from nova.api.openstack import wsgi
301 from nova import exception
302 from nova import quota
303
304=== modified file 'nova/api/openstack/servers.py'
305--- nova/api/openstack/servers.py 2011-07-20 17:52:22 +0000
306+++ nova/api/openstack/servers.py 2011-07-21 18:52:39 +0000
307@@ -27,7 +27,6 @@
308 from nova import utils
309 from nova.api.openstack import common
310 from nova.api.openstack import create_instance_helper as helper
311-from nova.api.openstack import faults
312 import nova.api.openstack.views.addresses
313 import nova.api.openstack.views.flavors
314 import nova.api.openstack.views.images
315@@ -102,17 +101,14 @@
316 req.environ['nova.context'], id)
317 return self._build_view(req, instance, is_detail=True)
318 except exception.NotFound:
319- return faults.Fault(exc.HTTPNotFound())
320+ raise exc.HTTPNotFound()
321
322 def create(self, req, body):
323 """ Creates a new server for a given user """
324 extra_values = None
325 result = None
326- try:
327- extra_values, instances = self.helper.create_instance(
328- req, body, self.compute_api.create)
329- except faults.Fault, f:
330- return f
331+ extra_values, instances = self.helper.create_instance(
332+ req, body, self.compute_api.create)
333
334 # We can only return 1 instance via the API, if we happen to
335 # build more than one... instances is a list, so we'll just
336@@ -132,7 +128,7 @@
337 raise exc.HTTPUnprocessableEntity()
338
339 if not body:
340- return faults.Fault(exc.HTTPUnprocessableEntity())
341+ raise exc.HTTPUnprocessableEntity()
342
343 ctxt = req.environ['nova.context']
344 update_dict = {}
345@@ -147,7 +143,7 @@
346 try:
347 self.compute_api.update(ctxt, id, **update_dict)
348 except exception.NotFound:
349- return faults.Fault(exc.HTTPNotFound())
350+ raise exc.HTTPNotFound()
351
352 return exc.HTTPNoContent()
353
354@@ -171,7 +167,7 @@
355 for key in actions.keys():
356 if key in body:
357 return actions[key](body, req, id)
358- return faults.Fault(exc.HTTPNotImplemented())
359+ raise exc.HTTPNotImplemented()
360
361 def _action_change_password(self, input_dict, req, id):
362 return exc.HTTPNotImplemented()
363@@ -181,7 +177,7 @@
364 self.compute_api.confirm_resize(req.environ['nova.context'], id)
365 except Exception, e:
366 LOG.exception(_("Error in confirm-resize %s"), e)
367- return faults.Fault(exc.HTTPBadRequest())
368+ raise exc.HTTPBadRequest()
369 return exc.HTTPNoContent()
370
371 def _action_revert_resize(self, input_dict, req, id):
372@@ -189,7 +185,7 @@
373 self.compute_api.revert_resize(req.environ['nova.context'], id)
374 except Exception, e:
375 LOG.exception(_("Error in revert-resize %s"), e)
376- return faults.Fault(exc.HTTPBadRequest())
377+ raise exc.HTTPBadRequest()
378 return webob.Response(status_int=202)
379
380 def _action_resize(self, input_dict, req, id):
381@@ -200,14 +196,14 @@
382 reboot_type = input_dict['reboot']['type']
383 else:
384 LOG.exception(_("Missing argument 'type' for reboot"))
385- return faults.Fault(exc.HTTPUnprocessableEntity())
386+ raise exc.HTTPUnprocessableEntity()
387 try:
388 # TODO(gundlach): pass reboot_type, support soft reboot in
389 # virt driver
390 self.compute_api.reboot(req.environ['nova.context'], id)
391 except Exception, e:
392 LOG.exception(_("Error in reboot %s"), e)
393- return faults.Fault(exc.HTTPUnprocessableEntity())
394+ raise exc.HTTPUnprocessableEntity()
395 return webob.Response(status_int=202)
396
397 def _action_migrate(self, input_dict, req, id):
398@@ -215,7 +211,7 @@
399 self.compute_api.resize(req.environ['nova.context'], id)
400 except Exception, e:
401 LOG.exception(_("Error in migrate %s"), e)
402- return faults.Fault(exc.HTTPBadRequest())
403+ raise exc.HTTPBadRequest()
404 return webob.Response(status_int=202)
405
406 @scheduler_api.redirect_handler
407@@ -231,7 +227,7 @@
408 except:
409 readable = traceback.format_exc()
410 LOG.exception(_("Compute.api::lock %s"), readable)
411- return faults.Fault(exc.HTTPUnprocessableEntity())
412+ raise exc.HTTPUnprocessableEntity()
413 return webob.Response(status_int=202)
414
415 @scheduler_api.redirect_handler
416@@ -247,7 +243,7 @@
417 except:
418 readable = traceback.format_exc()
419 LOG.exception(_("Compute.api::unlock %s"), readable)
420- return faults.Fault(exc.HTTPUnprocessableEntity())
421+ raise exc.HTTPUnprocessableEntity()
422 return webob.Response(status_int=202)
423
424 @scheduler_api.redirect_handler
425@@ -262,7 +258,7 @@
426 except:
427 readable = traceback.format_exc()
428 LOG.exception(_("Compute.api::get_lock %s"), readable)
429- return faults.Fault(exc.HTTPUnprocessableEntity())
430+ raise exc.HTTPUnprocessableEntity()
431 return webob.Response(status_int=202)
432
433 @scheduler_api.redirect_handler
434@@ -277,7 +273,7 @@
435 except:
436 readable = traceback.format_exc()
437 LOG.exception(_("Compute.api::reset_network %s"), readable)
438- return faults.Fault(exc.HTTPUnprocessableEntity())
439+ raise exc.HTTPUnprocessableEntity()
440 return webob.Response(status_int=202)
441
442 @scheduler_api.redirect_handler
443@@ -292,7 +288,7 @@
444 except:
445 readable = traceback.format_exc()
446 LOG.exception(_("Compute.api::inject_network_info %s"), readable)
447- return faults.Fault(exc.HTTPUnprocessableEntity())
448+ raise exc.HTTPUnprocessableEntity()
449 return webob.Response(status_int=202)
450
451 @scheduler_api.redirect_handler
452@@ -304,7 +300,7 @@
453 except:
454 readable = traceback.format_exc()
455 LOG.exception(_("Compute.api::pause %s"), readable)
456- return faults.Fault(exc.HTTPUnprocessableEntity())
457+ raise exc.HTTPUnprocessableEntity()
458 return webob.Response(status_int=202)
459
460 @scheduler_api.redirect_handler
461@@ -316,7 +312,7 @@
462 except:
463 readable = traceback.format_exc()
464 LOG.exception(_("Compute.api::unpause %s"), readable)
465- return faults.Fault(exc.HTTPUnprocessableEntity())
466+ raise exc.HTTPUnprocessableEntity()
467 return webob.Response(status_int=202)
468
469 @scheduler_api.redirect_handler
470@@ -328,7 +324,7 @@
471 except:
472 readable = traceback.format_exc()
473 LOG.exception(_("compute.api::suspend %s"), readable)
474- return faults.Fault(exc.HTTPUnprocessableEntity())
475+ raise exc.HTTPUnprocessableEntity()
476 return webob.Response(status_int=202)
477
478 @scheduler_api.redirect_handler
479@@ -340,7 +336,7 @@
480 except:
481 readable = traceback.format_exc()
482 LOG.exception(_("compute.api::resume %s"), readable)
483- return faults.Fault(exc.HTTPUnprocessableEntity())
484+ raise exc.HTTPUnprocessableEntity()
485 return webob.Response(status_int=202)
486
487 @scheduler_api.redirect_handler
488@@ -352,7 +348,7 @@
489 except:
490 readable = traceback.format_exc()
491 LOG.exception(_("compute.api::rescue %s"), readable)
492- return faults.Fault(exc.HTTPUnprocessableEntity())
493+ raise exc.HTTPUnprocessableEntity()
494 return webob.Response(status_int=202)
495
496 @scheduler_api.redirect_handler
497@@ -364,7 +360,7 @@
498 except:
499 readable = traceback.format_exc()
500 LOG.exception(_("compute.api::unrescue %s"), readable)
501- return faults.Fault(exc.HTTPUnprocessableEntity())
502+ raise exc.HTTPUnprocessableEntity()
503 return webob.Response(status_int=202)
504
505 @scheduler_api.redirect_handler
506@@ -374,7 +370,7 @@
507 self.compute_api.get_ajax_console(req.environ['nova.context'],
508 int(id))
509 except exception.NotFound:
510- return faults.Fault(exc.HTTPNotFound())
511+ raise exc.HTTPNotFound()
512 return webob.Response(status_int=202)
513
514 @scheduler_api.redirect_handler
515@@ -384,7 +380,7 @@
516 self.compute_api.get_vnc_console(req.environ['nova.context'],
517 int(id))
518 except exception.NotFound:
519- return faults.Fault(exc.HTTPNotFound())
520+ raise exc.HTTPNotFound()
521 return webob.Response(status_int=202)
522
523 @scheduler_api.redirect_handler
524@@ -416,7 +412,7 @@
525 try:
526 self.compute_api.delete(req.environ['nova.context'], id)
527 except exception.NotFound:
528- return faults.Fault(exc.HTTPNotFound())
529+ raise exc.HTTPNotFound()
530 return webob.Response(status_int=202)
531
532 def _image_ref_from_req_data(self, data):
533@@ -440,17 +436,13 @@
534
535 def _action_resize(self, input_dict, req, id):
536 """ Resizes a given instance to the flavor size requested """
537- try:
538- if 'resize' in input_dict and 'flavorId' in input_dict['resize']:
539- flavor_id = input_dict['resize']['flavorId']
540- self.compute_api.resize(req.environ['nova.context'], id,
541- flavor_id)
542- else:
543- LOG.exception(_("Missing 'flavorId' argument for resize"))
544- return faults.Fault(exc.HTTPUnprocessableEntity())
545- except Exception, e:
546- LOG.exception(_("Error in resize %s"), e)
547- return faults.Fault(exc.HTTPBadRequest())
548+ if 'resize' in input_dict and 'flavorId' in input_dict['resize']:
549+ flavor_id = input_dict['resize']['flavorId']
550+ self.compute_api.resize(req.environ['nova.context'], id,
551+ flavor_id)
552+ else:
553+ LOG.exception(_("Missing 'flavorId' argument for resize"))
554+ raise exc.HTTPUnprocessableEntity()
555 return webob.Response(status_int=202)
556
557 def _action_rebuild(self, info, request, instance_id):
558@@ -462,14 +454,14 @@
559 except (KeyError, TypeError):
560 msg = _("Could not parse imageId from request.")
561 LOG.debug(msg)
562- return faults.Fault(exc.HTTPBadRequest(explanation=msg))
563+ raise exc.HTTPBadRequest(explanation=msg)
564
565 try:
566 self.compute_api.rebuild(context, instance_id, image_id)
567 except exception.BuildInProgress:
568 msg = _("Instance %d is currently being rebuilt.") % instance_id
569 LOG.debug(msg)
570- return faults.Fault(exc.HTTPConflict(explanation=msg))
571+ raise exc.HTTPConflict(explanation=msg)
572
573 return webob.Response(status_int=202)
574
575@@ -486,7 +478,7 @@
576 try:
577 self.compute_api.delete(req.environ['nova.context'], id)
578 except exception.NotFound:
579- return faults.Fault(exc.HTTPNotFound())
580+ raise exc.HTTPNotFound()
581
582 def _image_ref_from_req_data(self, data):
583 return data['server']['imageRef']
584@@ -530,7 +522,7 @@
585 except AttributeError as ex:
586 msg = _("Unable to parse metadata key/value pairs.")
587 LOG.debug(msg)
588- raise faults.Fault(exc.HTTPBadRequest(explanation=msg))
589+ raise exc.HTTPBadRequest(explanation=msg)
590
591 def _decode_personalities(self, personalities):
592 """Decode the Base64-encoded personalities."""
593@@ -541,14 +533,14 @@
594 except (KeyError, TypeError):
595 msg = _("Unable to parse personality path/contents.")
596 LOG.info(msg)
597- raise faults.Fault(exc.HTTPBadRequest(explanation=msg))
598+ raise exc.HTTPBadRequest(explanation=msg)
599
600 try:
601 personality["contents"] = base64.b64decode(contents)
602 except TypeError:
603 msg = _("Personality content could not be Base64 decoded.")
604 LOG.info(msg)
605- raise faults.Fault(exc.HTTPBadRequest(explanation=msg))
606+ raise exc.HTTPBadRequest(explanation=msg)
607
608 def _action_resize(self, input_dict, req, id):
609 """ Resizes a given instance to the flavor size requested """
610@@ -560,10 +552,10 @@
611 flavor_id)
612 else:
613 LOG.exception(_("Missing 'flavorRef' argument for resize"))
614- return faults.Fault(exc.HTTPUnprocessableEntity())
615+ raise exc.HTTPUnprocessableEntity()
616 except Exception, e:
617 LOG.exception(_("Error in resize %s"), e)
618- return faults.Fault(exc.HTTPBadRequest())
619+ raise exc.HTTPBadRequest()
620 return webob.Response(status_int=202)
621
622 def _action_rebuild(self, info, request, instance_id):
623@@ -575,7 +567,7 @@
624 except (KeyError, TypeError):
625 msg = _("Could not parse imageRef from request.")
626 LOG.debug(msg)
627- return faults.Fault(exc.HTTPBadRequest(explanation=msg))
628+ raise exc.HTTPBadRequest(explanation=msg)
629
630 personalities = info["rebuild"].get("personality", [])
631 metadata = info["rebuild"].get("metadata")
632@@ -591,7 +583,7 @@
633 except exception.BuildInProgress:
634 msg = _("Instance %d is currently being rebuilt.") % instance_id
635 LOG.debug(msg)
636- return faults.Fault(exc.HTTPConflict(explanation=msg))
637+ raise exc.HTTPConflict(explanation=msg)
638
639 return webob.Response(status_int=202)
640
641
642=== modified file 'nova/api/openstack/shared_ip_groups.py'
643--- nova/api/openstack/shared_ip_groups.py 2011-07-06 20:28:10 +0000
644+++ nova/api/openstack/shared_ip_groups.py 2011-07-21 18:52:39 +0000
645@@ -17,7 +17,6 @@
646
647 from webob import exc
648
649-from nova.api.openstack import faults
650 from nova.api.openstack import wsgi
651
652
653@@ -26,27 +25,27 @@
654
655 def index(self, req, **kwargs):
656 """ Returns a list of Shared IP Groups for the user """
657- raise faults.Fault(exc.HTTPNotImplemented())
658+ raise exc.HTTPNotImplemented()
659
660 def show(self, req, id, **kwargs):
661 """ Shows in-depth information on a specific Shared IP Group """
662- raise faults.Fault(exc.HTTPNotImplemented())
663+ raise exc.HTTPNotImplemented()
664
665 def update(self, req, id, **kwargs):
666 """ You can't update a Shared IP Group """
667- raise faults.Fault(exc.HTTPNotImplemented())
668+ raise exc.HTTPNotImplemented()
669
670 def delete(self, req, id, **kwargs):
671 """ Deletes a Shared IP Group """
672- raise faults.Fault(exc.HTTPNotImplemented())
673+ raise exc.HTTPNotImplemented()
674
675 def detail(self, req, **kwargs):
676 """ Returns a complete list of Shared IP Groups """
677- raise faults.Fault(exc.HTTPNotImplemented())
678+ raise exc.HTTPNotImplemented()
679
680 def create(self, req, **kwargs):
681 """ Creates a new Shared IP group """
682- raise faults.Fault(exc.HTTPNotImplemented())
683+ raise exc.HTTPNotImplemented()
684
685
686 def create_resource():
687
688=== modified file 'nova/api/openstack/users.py'
689--- nova/api/openstack/users.py 2011-07-06 20:28:10 +0000
690+++ nova/api/openstack/users.py 2011-07-21 18:52:39 +0000
691@@ -19,7 +19,6 @@
692 from nova import flags
693 from nova import log as logging
694 from nova.api.openstack import common
695-from nova.api.openstack import faults
696 from nova.api.openstack import wsgi
697 from nova.auth import manager
698
699@@ -69,7 +68,7 @@
700 user = None
701
702 if user is None:
703- raise faults.Fault(exc.HTTPNotFound())
704+ raise exc.HTTPNotFound()
705
706 return dict(user=_translate_keys(user))
707
708
709=== modified file 'nova/api/openstack/wsgi.py'
710--- nova/api/openstack/wsgi.py 2011-07-20 17:12:18 +0000
711+++ nova/api/openstack/wsgi.py 2011-07-21 18:52:39 +0000
712@@ -448,7 +448,11 @@
713 msg = _("Malformed request body")
714 return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg))
715
716- action_result = self.dispatch(request, action, args)
717+ try:
718+ action_result = self.dispatch(request, action, args)
719+ except webob.exc.HTTPException as ex:
720+ LOG.info(_("HTTP exception thrown: %s"), unicode(ex))
721+ action_result = faults.Fault(ex)
722
723 #TODO(bcwaldon): find a more elegant way to pass through non-dict types
724 if type(action_result) is dict or action_result is None:
725
726=== modified file 'nova/api/openstack/zones.py'
727--- nova/api/openstack/zones.py 2011-07-06 20:28:10 +0000
728+++ nova/api/openstack/zones.py 2011-07-21 18:52:39 +0000
729@@ -27,7 +27,6 @@
730
731 from nova.api.openstack import create_instance_helper as helper
732 from nova.api.openstack import common
733-from nova.api.openstack import faults
734 from nova.api.openstack import wsgi
735
736
737@@ -127,11 +126,8 @@
738 Returns a reservation ID (a UUID).
739 """
740 result = None
741- try:
742- extra_values, result = self.helper.create_instance(req, body,
743- self.compute_api.create_all_at_once)
744- except faults.Fault, f:
745- return f
746+ extra_values, result = self.helper.create_instance(req, body,
747+ self.compute_api.create_all_at_once)
748
749 reservation_id = result
750 return {'reservation_id': reservation_id}
751
752=== modified file 'nova/tests/api/openstack/test_servers.py'
753--- nova/tests/api/openstack/test_servers.py 2011-07-19 13:36:37 +0000
754+++ nova/tests/api/openstack/test_servers.py 2011-07-21 18:52:39 +0000
755@@ -1758,7 +1758,7 @@
756 self.stubs.Set(nova.compute.api.API, 'resize', resize_mock)
757
758 res = req.get_response(fakes.wsgi_app())
759- self.assertEqual(res.status_int, 400)
760+ self.assertEqual(res.status_int, 500)
761
762 def test_resized_server_has_correct_status(self):
763 req = self.webreq('/1', 'GET')