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
(cherry picked from commit 22dd4fca38)
(cherry picked from commit d4bc147c38)
This commit is contained in:
Matt Riedemann 2018-09-13 13:28:24 -04:00
parent 6782c61fcb
commit 20de81c7c0
2 changed files with 43 additions and 1 deletions

View File

@ -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
@ -76,7 +77,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,

View File

@ -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 import timeutils
@ -3047,6 +3048,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)