diff --git a/nova/compute/api.py b/nova/compute/api.py index 43a0f66a10..8170fd8f24 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2857,9 +2857,11 @@ class API: # spec has been archived is being queried. raise exception.InstanceNotFound(instance_id=uuid) else: + if isinstance(result[cell_uuid], exception.NovaException): + LOG.exception(result[cell_uuid]) raise exception.NovaException( - _("Cell %s is not responding and hence instance " - "info is not available.") % cell_uuid) + _("Cell %s is not responding or returned an exception, " + "hence instance info is not available.") % cell_uuid) def _get_instance(self, context, instance_uuid, expected_attrs, cell_down_support=False): diff --git a/nova/context.py b/nova/context.py index 619c39e212..dc42b38b5b 100644 --- a/nova/context.py +++ b/nova/context.py @@ -424,7 +424,7 @@ def scatter_gather_cells(context, cell_mappings, timeout, fn, *args, **kwargs): # Only log the exception traceback for non-nova exceptions. if not isinstance(e, exception.NovaException): LOG.exception('Error gathering result from cell %s', cell_uuid) - result = e.__class__(e.args) + result = e # The queue is already synchronized. queue.put((cell_uuid, result)) diff --git a/nova/tests/unit/compute/test_api.py b/nova/tests/unit/compute/test_api.py index 4297fcff66..5a3f5d01b4 100644 --- a/nova/tests/unit/compute/test_api.py +++ b/nova/tests/unit/compute/test_api.py @@ -6371,8 +6371,9 @@ class _ComputeAPIUnitTestMixIn(object): self.assertEqual(uuids.inst, result.uuid) mock_get_inst.assert_called_once() + @mock.patch('nova.compute.api.LOG.exception') @mock.patch.object(objects.Instance, 'get_by_uuid') - def test_get_instance_from_cell_failure(self, mock_get_inst): + def test_get_instance_from_cell_failure(self, mock_get_inst, mock_log_exp): # Make sure InstanceNotFound is bubbled up and not treated like # other errors mock_get_inst.side_effect = exception.InstanceNotFound( @@ -6385,6 +6386,15 @@ class _ComputeAPIUnitTestMixIn(object): self.compute_api._get_instance_from_cell, self.context, im, [], False) self.assertIn('could not be found', str(exp)) + # Make sure other unexpected NovaException are logged for debugging + mock_get_inst.side_effect = exception.NovaException() + exp = self.assertRaises( + exception.NovaException, self.compute_api._get_instance_from_cell, + self.context, im, [], False) + msg = (f'Cell {cell_mapping.uuid} is not responding or returned an ' + 'exception, hence instance info is not available.') + self.assertIn(msg, str(exp)) + mock_log_exp.assert_called_once_with(mock_get_inst.side_effect) @mock.patch('nova.compute.api.API._save_user_id_in_instance_mapping') @mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')