diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 327ec6f9a8..313a0dbe5f 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -2338,6 +2338,11 @@ class ComputeManager(manager.Manager): def _build_succeeded(self, node): self.rt.build_succeeded(node) + # NOTE(gibi): The normal RPC handler decorators are here but please note + # that build_and_run_instance immediately spawns and returns. So any + # error from the real work is not propagated back to these decorators. + # All those error needs to be handled by _locked_do_build_and_run_instance + # and _do_build_and_run_instance @wrap_exception() @reverts_task_state @wrap_instance_fault diff --git a/nova/tests/fixtures/nova.py b/nova/tests/fixtures/nova.py index 3ceb8f1316..f5e9f95c8e 100644 --- a/nova/tests/fixtures/nova.py +++ b/nova/tests/fixtures/nova.py @@ -1245,7 +1245,12 @@ class IsolatedGreenPoolFixture(fixtures.Fixture): class _FakeGreenThread(object): def __init__(self, func, *args, **kwargs): - self._result = func(*args, **kwargs) + try: + self._result = func(*args, **kwargs) + self.raised = False + except Exception as e: + self.raised = True + self._result = e def cancel(self, *args, **kwargs): # This method doesn't make sense for a synchronous call, it's just @@ -1266,6 +1271,9 @@ class _FakeGreenThread(object): pass def wait(self): + if self.raised: + raise self._result + return self._result diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 0a64a47d74..e91973ae1a 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -14506,10 +14506,12 @@ class ComputeInjectedFilesTestCase(BaseTestCase): ] self.assertRaises(exception.Base64Exception, - self.compute.build_and_run_instance, - self.context, self.instance, {}, {}, {}, [], - block_device_mapping=[], - injected_files=injected_files) + self.compute._do_build_and_run_instance, + self.context, self.instance, {}, {}, {}, + block_device_mapping=[], injected_files=injected_files, + admin_password=None, requested_networks=None, + security_groups=None, node=None, limits=None, host_list=None, + accel_uuids=[]) class CheckConfigDriveTestCase(test.NoDBTestCase): diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 2a7eb012ea..1c5d501bb3 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -9577,14 +9577,6 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase): mock_succeeded.assert_not_called() @mock.patch.object(manager.ComputeManager, '_do_build_and_run_instance') - @mock.patch( - 'nova.exception_wrapper._emit_versioned_exception_notification', - new=mock.Mock()) - @mock.patch( - 'nova.exception_wrapper._emit_legacy_exception_notification', - new=mock.Mock()) - @mock.patch( - 'nova.compute.utils.add_instance_fault_from_exc', new=mock.Mock()) @mock.patch.object(manager.ComputeManager, '_build_failed') @mock.patch.object(manager.ComputeManager, '_build_succeeded') def test_build_exceptions_reported( @@ -9594,10 +9586,8 @@ class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase): instance = objects.Instance(uuid=uuids.instance, task_state=None) for i in range(0, 10): - self.assertRaises(test.TestingException, - self.compute.build_and_run_instance, - self.context, instance, None, - None, None, []) + self.compute.build_and_run_instance( + self.context, instance, None, None, None, []) self.assertEqual(10, mock_failed.call_count) mock_succeeded.assert_not_called()