From 3987f597823c8760e953717d0a7d9ab64a913435 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Thu, 30 Aug 2018 14:18:16 -0700 Subject: [PATCH] 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 (cherry picked from commit df058720434cdca2726eb8c16f323a98bfc73ce3) --- nova/service.py | 6 +++--- nova/tests/unit/test_service.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/nova/service.py b/nova/service.py index 260a1d66cf75..b0655c051342 100644 --- a/nova/service.py +++ b/nova/service.py @@ -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): diff --git a/nova/tests/unit/test_service.py b/nova/tests/unit/test_service.py index 66d7a647a29e..1071f5441c29 100644 --- a/nova/tests/unit/test_service.py +++ b/nova/tests/unit/test_service.py @@ -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