Merge lp:~vishvananda/nova/lp827024 into lp:~hudson-openstack/nova/trunk

Proposed by Vish Ishaya
Status: Merged
Approved by: Rick Harris
Approved revision: 1419
Merged at revision: 1448
Proposed branch: lp:~vishvananda/nova/lp827024
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 72 lines (+14/-12)
1 file modified
nova/image/s3.py (+14/-12)
To merge this branch: bzr merge lp:~vishvananda/nova/lp827024
Reviewer Review Type Date Requested Status
Rick Harris (community) Approve
Jason Kölker (community) Approve
Devin Carlen (community) Approve
Review via email: mp+71620@code.launchpad.net

Description of the change

Fixes issue with exceptions getting eaten in image/s3.py if there is a failure during register. The variables referenced with locals() were actually out of scope.

To post a comment you must log in.
lp:~vishvananda/nova/lp827024 updated
1419. By Vish Ishaya

log the full exception so we don't lose traceback through eventlet

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

lgtm

review: Approve
Revision history for this message
Jason Kölker (jason-koelker) wrote :

Is Bueno! The '% locals()' grated on my soul.
s/grated/grates/
;)

review: Approve
Revision history for this message
Rick Harris (rconradharris) wrote :

Vish:

A pattern we use elsewhere is to capture the traceback info before eventlet gets a chance to clear exceptions during its greenthread context switch. We then use a 3-arg raise to re-raise it, something like:

try:
  blah
except Exception as e:
  exc_info = sys.exc_info()
  handler_code() # <- Eventlet will clear exceptions here
  raise exc_info

What I like about that approach is that it continues to 'raise' instead of just logging, keeping the errors a bit more in your face.

Given that we were raising, should we try something like that here?

review: Needs Information
Revision history for this message
Vish Ishaya (vishvananda) wrote :

Rick:

I considered that, although in this case logging.exception logs a traceback in virtually the same way that a straight raise does. I think there is value in your version if there is something that needs to catch the exception, but in this case that method just runs in its own greenthread and nothing is keeping track of it, so I didn't feel like it was necessary to workaround it by reraising. I'm happy to switch it if you have a strong preference, though.

Revision history for this message
Rick Harris (rconradharris) wrote :

Vish: All that sounds reasonable--no strong preference here. I *slightly* prefer re-raising, but logging here seems like a good approach too.

Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'nova/image/s3.py'
--- nova/image/s3.py 2011-07-28 01:36:55 +0000
+++ nova/image/s3.py 2011-08-16 00:13:30 +0000
@@ -193,6 +193,8 @@
193193
194 def delayed_create():194 def delayed_create():
195 """This handles the fetching and decrypting of the part files."""195 """This handles the fetching and decrypting of the part files."""
196 log_vars = {'image_location': image_location,
197 'image_path': image_path}
196 metadata['properties']['image_state'] = 'downloading'198 metadata['properties']['image_state'] = 'downloading'
197 self.service.update(context, image_id, metadata)199 self.service.update(context, image_id, metadata)
198200
@@ -213,11 +215,11 @@
213 shutil.copyfileobj(part, combined)215 shutil.copyfileobj(part, combined)
214216
215 except Exception:217 except Exception:
216 LOG.error(_("Failed to download %(image_location)s "218 LOG.exception(_("Failed to download %(image_location)s "
217 "to %(image_path)s"), locals())219 "to %(image_path)s"), log_vars)
218 metadata['properties']['image_state'] = 'failed_download'220 metadata['properties']['image_state'] = 'failed_download'
219 self.service.update(context, image_id, metadata)221 self.service.update(context, image_id, metadata)
220 raise222 return
221223
222 metadata['properties']['image_state'] = 'decrypting'224 metadata['properties']['image_state'] = 'decrypting'
223 self.service.update(context, image_id, metadata)225 self.service.update(context, image_id, metadata)
@@ -237,11 +239,11 @@
237 encrypted_iv, cloud_pk,239 encrypted_iv, cloud_pk,
238 dec_filename)240 dec_filename)
239 except Exception:241 except Exception:
240 LOG.error(_("Failed to decrypt %(image_location)s "242 LOG.exception(_("Failed to decrypt %(image_location)s "
241 "to %(image_path)s"), locals())243 "to %(image_path)s"), log_vars)
242 metadata['properties']['image_state'] = 'failed_decrypt'244 metadata['properties']['image_state'] = 'failed_decrypt'
243 self.service.update(context, image_id, metadata)245 self.service.update(context, image_id, metadata)
244 raise246 return
245247
246 metadata['properties']['image_state'] = 'untarring'248 metadata['properties']['image_state'] = 'untarring'
247 self.service.update(context, image_id, metadata)249 self.service.update(context, image_id, metadata)
@@ -249,11 +251,11 @@
249 try:251 try:
250 unz_filename = self._untarzip_image(image_path, dec_filename)252 unz_filename = self._untarzip_image(image_path, dec_filename)
251 except Exception:253 except Exception:
252 LOG.error(_("Failed to untar %(image_location)s "254 LOG.exception(_("Failed to untar %(image_location)s "
253 "to %(image_path)s"), locals())255 "to %(image_path)s"), log_vars)
254 metadata['properties']['image_state'] = 'failed_untar'256 metadata['properties']['image_state'] = 'failed_untar'
255 self.service.update(context, image_id, metadata)257 self.service.update(context, image_id, metadata)
256 raise258 return
257259
258 metadata['properties']['image_state'] = 'uploading'260 metadata['properties']['image_state'] = 'uploading'
259 self.service.update(context, image_id, metadata)261 self.service.update(context, image_id, metadata)
@@ -262,11 +264,11 @@
262 self.service.update(context, image_id,264 self.service.update(context, image_id,
263 metadata, image_file)265 metadata, image_file)
264 except Exception:266 except Exception:
265 LOG.error(_("Failed to upload %(image_location)s "267 LOG.exception(_("Failed to upload %(image_location)s "
266 "to %(image_path)s"), locals())268 "to %(image_path)s"), log_vars)
267 metadata['properties']['image_state'] = 'failed_upload'269 metadata['properties']['image_state'] = 'failed_upload'
268 self.service.update(context, image_id, metadata)270 self.service.update(context, image_id, metadata)
269 raise271 return
270272
271 metadata['properties']['image_state'] = 'available'273 metadata['properties']['image_state'] = 'available'
272 metadata['status'] = 'active'274 metadata['status'] = 'active'