From 22dd4fca3837d6cea3f983b021aa6907695a540b Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Thu, 13 Sep 2018 13:28:24 -0400 Subject: [PATCH] Noop CantStartEngineError in targets_cell if API DB not configured For reschedules during resize (migrate_server method), the InstanceMapping query in targets_cell is an "up call" to the API DB which will fail with a CantStartEngineError if the cell conductor is not configured for the API DB. This changes the targets_cell decorator to handle the CantStartEngineError and if the API DB is not configured, we assume we're in the cell conductor and just ignore the error, otherwise if the API DB is configured we assume we're in the super-conductor and reraise as before. Change-Id: I0a413eb4f8a94500941e53b9a294d7cdb45d2a1c Closes-Bug: #1781300 --- nova/conductor/manager.py | 8 ++++- nova/tests/unit/conductor/test_conductor.py | 36 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 1409720c914c..a8c4defe696b 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -20,6 +20,7 @@ import functools import sys from oslo_config import cfg +from oslo_db import exception as db_exc from oslo_log import log as logging import oslo_messaging as messaging from oslo_serialization import jsonutils @@ -74,7 +75,12 @@ def targets_cell(fn): except exception.InstanceMappingNotFound: LOG.error('InstanceMapping not found, unable to target cell', instance=instance) - im = None + except db_exc.CantStartEngineError: + # Check to see if we can ignore API DB connection failures + # because we might already be in the cell conductor. + with excutils.save_and_reraise_exception() as err_ctxt: + if CONF.api_database.connection is None: + err_ctxt.reraise = False else: LOG.debug('Targeting cell %(cell)s for conductor method %(meth)s', {'cell': im.cell_mapping.identity, diff --git a/nova/tests/unit/conductor/test_conductor.py b/nova/tests/unit/conductor/test_conductor.py index 9e2ea4a455eb..4b79a88cdd5c 100644 --- a/nova/tests/unit/conductor/test_conductor.py +++ b/nova/tests/unit/conductor/test_conductor.py @@ -18,6 +18,7 @@ import copy import mock +from oslo_db import exception as db_exc import oslo_messaging as messaging from oslo_serialization import jsonutils from oslo_utils.fixture import uuidsentinel as uuids @@ -2871,6 +2872,41 @@ class ConductorTaskRPCAPITestCase(_BaseTaskTestCase, test(None, ctxt, inst)) mock_im.assert_called_once_with(ctxt, inst.uuid) + @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid', + side_effect=db_exc.CantStartEngineError) + def test_targets_cell_no_api_db_conn_noop(self, mock_im): + """Tests that targets_cell noops on CantStartEngineError if the API + DB is not configured because we assume we're in the cell conductor. + """ + self.flags(connection=None, group='api_database') + + @conductor_manager.targets_cell + def _test(self, context, instance): + return mock.sentinel.iransofaraway + + ctxt = mock.MagicMock() + inst = mock.MagicMock() + self.assertEqual(mock.sentinel.iransofaraway, + _test(None, ctxt, inst)) + mock_im.assert_called_once_with(ctxt, inst.uuid) + + @mock.patch.object(objects.InstanceMapping, 'get_by_instance_uuid', + side_effect=db_exc.CantStartEngineError) + def test_targets_cell_no_api_db_conn_reraise(self, mock_im): + """Tests that targets_cell reraises CantStartEngineError if the + API DB is configured. + """ + self.flags(connection='mysql://dbhost?nova_api', group='api_database') + + @conductor_manager.targets_cell + def _test(self, context, instance): + return mock.sentinel.iransofaraway + + ctxt = mock.MagicMock() + inst = mock.MagicMock() + self.assertRaises(db_exc.CantStartEngineError, _test, None, ctxt, inst) + mock_im.assert_called_once_with(ctxt, inst.uuid) + def test_schedule_and_build_instances_with_tags(self): build_request = fake_build_request.fake_req_obj(self.context)