Hyper-V: Trace original exception before converting exception

Reraising an exception causes the original traceback to be lost.
Logging the original trace before reraising will help greatly in
debugging.

Reraises nova Exception while maintaining the original traceback.

Change-Id: I247bcd22a8c26b947f523cfd33d9f97184eb52a9
This commit is contained in:
Claudiu Belu 2016-01-08 14:44:06 +02:00
parent e06b2192dd
commit e0f4662593
2 changed files with 28 additions and 1 deletions

View File

@ -18,6 +18,7 @@ Unit tests for the Hyper-V Driver.
"""
import platform
import sys
import mock
from os_win import exceptions as os_win_exc
@ -88,6 +89,25 @@ class HyperVDriverTestCase(test_base.HyperVBaseTestCase):
self.assertRaises(exception.InstanceNotFound,
self.driver.get_info, mock.sentinel.instance)
def test_assert_original_traceback_maintained(self):
def bar(self):
foo = "foofoo"
raise os_win_exc.HyperVVMNotFoundException(vm_name=foo)
self.driver._vmops.get_info.side_effect = bar
try:
self.driver.get_info(mock.sentinel.instance)
self.fail("Test expected exception, but it was not raised.")
except exception.InstanceNotFound:
# exception has been raised as expected.
_, _, trace = sys.exc_info()
while trace.tb_next:
# iterate until the original exception source, bar.
trace = trace.tb_next
# original frame will contain the 'foo' variable.
self.assertEqual('foofoo', trace.tb_frame.f_locals['foo'])
@mock.patch.object(driver.eventhandler, 'InstanceEventHandler')
def test_init_host(self, mock_InstanceEventHandler):
self.driver.init_host(mock.sentinel.host)

View File

@ -19,6 +19,7 @@ A Hyper-V Nova Compute driver.
import functools
import platform
import sys
from os_win import exceptions as os_win_exc
from os_win import utilsfactory
@ -56,7 +57,13 @@ def convert_exceptions(function, exception_map):
raised_exception = exception_map[expected]
break
raise raised_exception(six.text_type(ex))
exc_info = sys.exc_info()
# NOTE(claudiub): Python 3 raises the exception object given as
# the second argument in six.reraise.
# The original message will be maintained by passing the original
# exception.
exc = raised_exception(six.text_type(exc_info[1]))
six.reraise(raised_exception, exc, exc_info[2])
return wrapper