summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-11-02 23:01:26 +0000
committerGerrit Code Review <review@openstack.org>2012-11-02 23:01:26 +0000
commitcde64119f29a2e3f3ef01feeb53d4507f33e793f (patch)
treed65a82be0d2e6873dc48331651c709981625415e
parent73b115d98612f8d11ef0410356c2545a87cf1c47 (diff)
parentb946f22a866dfa1151fbbf70fad1d98dfceaefe8 (diff)
downloadnova-cde64119f29a2e3f3ef01feeb53d4507f33e793f.tar.gz
nova-cde64119f29a2e3f3ef01feeb53d4507f33e793f.tar.xz
nova-cde64119f29a2e3f3ef01feeb53d4507f33e793f.zip
Merge "Add some hooks for managers when service starts"
-rw-r--r--nova/compute/manager.py7
-rw-r--r--nova/manager.py22
-rw-r--r--nova/scheduler/manager.py11
-rw-r--r--nova/service.py9
-rw-r--r--nova/tests/test_service.py98
5 files changed, 97 insertions, 50 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 74f8aade2..39c3faddf 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -363,6 +363,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 b4d8e0a5c..531c54726 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."""
@@ -253,6 +261,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