diff options
author | Chris Behrens <cbehrens@codestud.com> | 2012-11-01 18:13:08 +0000 |
---|---|---|
committer | Chris Behrens <cbehrens@codestud.com> | 2012-11-01 19:15:09 +0000 |
commit | b946f22a866dfa1151fbbf70fad1d98dfceaefe8 (patch) | |
tree | df68a4fb151d1d12d56cb67e45bc85b96155d8d4 | |
parent | 6ee9883b8cb1ef8e503a03229a100e50813abe5a (diff) | |
download | nova-b946f22a866dfa1151fbbf70fad1d98dfceaefe8.tar.gz nova-b946f22a866dfa1151fbbf70fad1d98dfceaefe8.tar.xz nova-b946f22a866dfa1151fbbf70fad1d98dfceaefe8.zip |
Add some hooks for managers when service starts
Adds pre_start_hook() and post_start_hook() and fixes a couple of hard
coded binary name checks in service.py
Change-Id: I062790a88ed7f15a6f28961d6ddc1f230e19e0cb
-rw-r--r-- | nova/compute/manager.py | 7 | ||||
-rw-r--r-- | nova/manager.py | 22 | ||||
-rw-r--r-- | nova/scheduler/manager.py | 11 | ||||
-rw-r--r-- | nova/service.py | 9 | ||||
-rw-r--r-- | nova/tests/test_service.py | 98 |
5 files changed, 97 insertions, 50 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index dac9b58a0..7b2dc4d1d 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -342,6 +342,13 @@ class ComputeManager(manager.SchedulerDependentManager): self._report_driver_status(context) self.publish_service_capabilities(context) + def pre_start_hook(self): + """After the service is initialized, but before we fully bring + the service up by listening on RPC queues, make sure to update + our available resources. + """ + self.update_available_resource(nova.context.get_admin_context()) + def _get_power_state(self, context, instance): """Retrieve the power state for the given instance.""" LOG.debug(_('Checking state'), instance=instance) diff --git a/nova/manager.py b/nova/manager.py index 2a7570c3b..0e447c7c1 100644 --- a/nova/manager.py +++ b/nova/manager.py @@ -183,10 +183,30 @@ class Manager(base.Base): locals()) def init_host(self): - """Handle initialization if this is a standalone service. + """Hook to do additional manager initialization when one requests + the service be started. This is called before any service record + is created. Child classes should override this method. + """ + pass + + def pre_start_hook(self): + """Hook to provide the manager the ability to do additional + start-up work before any RPC queues/consumers are created. This is + called after other initialization has succeeded and a service + record is created. + Child classes should override this method. + """ + pass + + def post_start_hook(self): + """Hook to provide the manager the ability to do additional + start-up work immediately after a service creates RPC consumers + and starts 'running'. + + Child classes should override this method. """ pass diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 4c3f8025a..0703e030a 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -26,6 +26,7 @@ import sys from nova.compute import rpcapi as compute_rpcapi from nova.compute import utils as compute_utils from nova.compute import vm_states +import nova.context from nova import db from nova import exception from nova import flags @@ -62,6 +63,13 @@ class SchedulerManager(manager.Manager): self.driver = importutils.import_object(scheduler_driver) super(SchedulerManager, self).__init__(*args, **kwargs) + def post_start_hook(self): + """After we start up and can receive messages via RPC, tell all + compute nodes to send us their capabilities. + """ + ctxt = nova.context.get_admin_context() + compute_rpcapi.ComputeAPI().publish_service_capabilities(ctxt) + def update_service_capabilities(self, context, service_name, host, capabilities): """Process a capability update from a service node.""" @@ -259,6 +267,3 @@ class SchedulerManager(manager.Manager): @manager.periodic_task def _expire_reservations(self, context): QUOTAS.expire(context) - - def request_service_capabilities(self, context): - compute_rpcapi.ComputeAPI().publish_service_capabilities(context) diff --git a/nova/service.py b/nova/service.py index 26f430a80..41c1b0012 100644 --- a/nova/service.py +++ b/nova/service.py @@ -397,8 +397,7 @@ class Service(object): except exception.NotFound: self._create_service_ref(ctxt) - if 'nova-compute' == self.binary: - self.manager.update_available_resource(ctxt) + self.manager.pre_start_hook() self.conn = rpc.create_connection(new=True) LOG.debug(_("Creating Consumer connection for Service %s") % @@ -417,8 +416,7 @@ class Service(object): # Consume from all consumers in a thread self.conn.consume_in_thread() - if 'nova-scheduler' == self.binary: - self.manager.request_service_capabilities(ctxt) + self.manager.post_start_hook() if self.report_interval: pulse = utils.LoopingCall(self.report_state) @@ -612,7 +610,10 @@ class WSGIService(object): """ if self.manager: self.manager.init_host() + self.manager.pre_start_hook() self.server.start() + if self.manager: + self.manager.post_start_hook() def stop(self): """Stop serving this API. diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index 5e357deeb..3f31e8e01 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -21,6 +21,7 @@ Unit Tests for remote procedure calls using queue """ import mox +import sys from nova import context @@ -109,82 +110,95 @@ class ServiceTestCase(test.TestCase): def setUp(self): super(ServiceTestCase, self).setUp() + self.host = 'foo' + self.binary = 'nova-fake' + self.topic = 'fake' self.mox.StubOutWithMock(service, 'db') def test_create(self): - host = 'foo' - binary = 'nova-fake' - topic = 'fake' # NOTE(vish): Create was moved out of mox replay to make sure that # the looping calls are created in StartService. - app = service.Service.create(host=host, binary=binary, topic=topic) + app = service.Service.create(host=self.host, binary=self.binary, + topic=self.topic) self.assert_(app) - def test_report_state_newly_disconnected(self): - host = 'foo' - binary = 'bar' - topic = 'test' - service_create = {'host': host, - 'binary': binary, - 'topic': topic, + def _service_start_mocks(self): + service_create = {'host': self.host, + 'binary': self.binary, + 'topic': self.topic, 'report_count': 0, 'availability_zone': 'nova'} - service_ref = {'host': host, - 'binary': binary, - 'topic': topic, + service_ref = {'host': self.host, + 'binary': self.binary, + 'topic': self.topic, 'report_count': 0, 'availability_zone': 'nova', 'id': 1} service.db.service_get_by_args(mox.IgnoreArg(), - host, - binary).AndRaise(exception.NotFound()) + self.host, self.binary).AndRaise(exception.NotFound()) service.db.service_create(mox.IgnoreArg(), - service_create).AndReturn(service_ref) + service_create).AndReturn(service_ref) + return service_ref + + def test_init_and_start_hooks(self): + self.manager_mock = self.mox.CreateMock(FakeManager) + self.mox.StubOutWithMock(sys.modules[__name__], + 'FakeManager', use_mock_anything=True) + self.mox.StubOutWithMock(self.manager_mock, 'init_host') + self.mox.StubOutWithMock(self.manager_mock, 'pre_start_hook') + self.mox.StubOutWithMock(self.manager_mock, 'create_rpc_dispatcher') + self.mox.StubOutWithMock(self.manager_mock, 'post_start_hook') + + FakeManager(host=self.host).AndReturn(self.manager_mock) + + # init_host is called before any service record is created + self.manager_mock.init_host() + self._service_start_mocks() + # pre_start_hook is called after service record is created, + # but before RPC consumer is created + self.manager_mock.pre_start_hook() + self.manager_mock.create_rpc_dispatcher() + # post_start_hook is called after RPC consumer is created. + self.manager_mock.post_start_hook() + + self.mox.ReplayAll() + + serv = service.Service(self.host, + self.binary, + self.topic, + 'nova.tests.test_service.FakeManager') + serv.start() + + def test_report_state_newly_disconnected(self): + self._service_start_mocks() + service.db.service_get(mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(Exception()) self.mox.ReplayAll() - serv = service.Service(host, - binary, - topic, + serv = service.Service(self.host, + self.binary, + self.topic, 'nova.tests.test_service.FakeManager') serv.start() serv.report_state() self.assert_(serv.model_disconnected) def test_report_state_newly_connected(self): - host = 'foo' - binary = 'bar' - topic = 'test' - service_create = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova'} - service_ref = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova', - 'id': 1} + service_ref = self._service_start_mocks() - service.db.service_get_by_args(mox.IgnoreArg(), - host, - binary).AndRaise(exception.NotFound()) - service.db.service_create(mox.IgnoreArg(), - service_create).AndReturn(service_ref) service.db.service_get(mox.IgnoreArg(), service_ref['id']).AndReturn(service_ref) service.db.service_update(mox.IgnoreArg(), service_ref['id'], mox.ContainsKeyValue('report_count', 1)) self.mox.ReplayAll() - serv = service.Service(host, - binary, - topic, + serv = service.Service(self.host, + self.binary, + self.topic, 'nova.tests.test_service.FakeManager') serv.start() serv.model_disconnected = True |