Move conductor wait_until_ready() delay before manager init

The Service base class already waits for conductor to be responsive
before allowing service startup to continue. However, it does this
after the manager __init__, which could do some things expecting
conductor to be up (and does now in compute). This moves the check
and wait loop above the manager init so we don't start anything in
the manager until we know conductor is alive.

Change-Id: Ib56fdb38839434d504fadccbeda65ab2e267b514
Closes-Bug: #1789484
This commit is contained in:
Dan Smith 2018-08-30 14:18:16 -07:00
parent e1edabc053
commit df05872043
2 changed files with 18 additions and 3 deletions

View File

@ -125,6 +125,9 @@ class Service(service.Service):
self.manager_class_name = manager
self.servicegroup_api = servicegroup.API()
manager_class = importutils.import_class(self.manager_class_name)
if objects_base.NovaObject.indirection_api:
conductor_api = conductor.API()
conductor_api.wait_until_ready(context.get_admin_context())
self.manager = manager_class(host=self.host, *args, **kwargs)
self.rpcserver = None
self.report_interval = report_interval
@ -133,9 +136,6 @@ class Service(service.Service):
self.periodic_interval_max = periodic_interval_max
self.saved_args, self.saved_kwargs = args, kwargs
self.backdoor_port = None
if objects_base.NovaObject.indirection_api:
conductor_api = conductor.API()
conductor_api.wait_until_ready(context.get_admin_context())
setup_profiler(binary, self.host)
def __repr__(self):

View File

@ -27,6 +27,7 @@ import testtools
from nova import exception
from nova import manager
from nova import objects
from nova.objects import base as obj_base
from nova import rpc
from nova import service
from nova import test
@ -138,6 +139,20 @@ class ServiceTestCase(test.NoDBTestCase):
# post_start_hook is called after RPC consumer is created.
serv.manager.post_start_hook.assert_called_once_with()
@mock.patch('nova.conductor.api.API.wait_until_ready')
def test_init_with_indirection_api_waits(self, mock_wait):
obj_base.NovaObject.indirection_api = mock.MagicMock()
with mock.patch.object(FakeManager, '__init__') as init:
def check(*a, **k):
self.assertTrue(mock_wait.called)
init.side_effect = check
service.Service(self.host, self.binary, self.topic,
'nova.tests.unit.test_service.FakeManager')
self.assertTrue(init.called)
mock_wait.assert_called_once_with(mock.ANY)
@mock.patch('nova.objects.service.Service.get_by_host_and_binary')
def test_start_updates_version(self, mock_get_by_host_and_binary):
# test that the service version gets updated on services startup