diff options
| author | Russell Bryant <rbryant@redhat.com> | 2013-01-11 11:56:09 -0500 |
|---|---|---|
| committer | Russell Bryant <rbryant@redhat.com> | 2013-01-11 18:06:54 -0500 |
| commit | 42f3d0bdbda3c54c0d3490e0f407e7dbb8f574ca (patch) | |
| tree | c5a05b4050bc47ec94fed6965ecef44dd399525a | |
| parent | 6ea308295a158b4700f4081913f66596fc769b36 (diff) | |
| download | nova-42f3d0bdbda3c54c0d3490e0f407e7dbb8f574ca.tar.gz nova-42f3d0bdbda3c54c0d3490e0f407e7dbb8f574ca.tar.xz nova-42f3d0bdbda3c54c0d3490e0f407e7dbb8f574ca.zip | |
Make pinging conductor a part of conductor API.
This patch moves the loop that pings the conductor over rpc until it
responds to be a part of the conductor API. This will allow it to be
used elsewhere in the code as needed.
Part of bp no-db-compute.
Change-Id: Ie027adef4a3af3059b4ab586e927c93ae1a86fe9
| -rw-r--r-- | nova/compute/manager.py | 30 | ||||
| -rw-r--r-- | nova/conductor/api.py | 36 | ||||
| -rw-r--r-- | nova/tests/compute/test_compute.py | 15 | ||||
| -rw-r--r-- | nova/tests/conductor/test_conductor.py | 21 |
4 files changed, 61 insertions, 41 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f138a3708..98ed1286e 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -358,32 +358,6 @@ class ComputeManager(manager.SchedulerDependentManager): 'trying to set it to ERROR'), instance_uuid=instance_uuid) - def _get_instances_at_startup(self, context): - '''Get instances for this host during service init.''' - attempt = 0 - timeout = 10 - while True: - # NOTE(danms): Try ten times with a short timeout, and then punt - # to the configured RPC timeout after that - if attempt == 10: - timeout = None - attempt += 1 - - # NOTE(russellb): This is running during service startup. If we - # allow an exception to be raised, the service will shut down. - # This may fail the first time around if nova-conductor wasn't - # running when nova-compute started. - try: - self.conductor_api.ping(context, '1.21 GigaWatts', - timeout=timeout) - break - except rpc_common.Timeout as e: - LOG.exception(_('Timed out waiting for nova-conductor. ' - 'Is it running? Or did nova-compute start ' - 'before nova-conductor?')) - - return self.conductor_api.instance_get_all_by_host(context, self.host) - def _get_instances_on_driver(self, context): """Return a list of instance records that match the instances found on the hypervisor. @@ -504,6 +478,10 @@ class ComputeManager(manager.SchedulerDependentManager): LOG.warning(_('Hypervisor driver does not support ' 'firewall rules'), instance=instance) + def _get_instances_at_startup(self, context): + self.conductor_api.wait_until_ready(context) + return self.conductor_api.instance_get_all_by_host(context, self.host) + def init_host(self): """Initialization for a standalone compute service.""" self.driver.init_host(host=self.host) diff --git a/nova/conductor/api.py b/nova/conductor/api.py index 04a4f3d9c..228876682 100644 --- a/nova/conductor/api.py +++ b/nova/conductor/api.py @@ -20,6 +20,7 @@ from nova.conductor import manager from nova.conductor import rpcapi from nova import exception as exc from nova.openstack.common import cfg +from nova.openstack.common import log as logging from nova.openstack.common.rpc import common as rpc_common conductor_opts = [ @@ -39,6 +40,8 @@ CONF = cfg.CONF CONF.register_group(conductor_group) CONF.register_opts(conductor_opts, conductor_group) +LOG = logging.getLogger(__name__) + class ExceptionHelper(object): """Class to wrap another and translate the ClientExceptions raised by its @@ -68,6 +71,10 @@ class LocalAPI(object): # other/future users of this sort of functionality. self._manager = ExceptionHelper(manager.ConductorManager()) + def wait_until_ready(self, context, *args, **kwargs): + # nothing to wait for in the local case. + pass + def ping(self, context, arg, timeout=None): return self._manager.ping(context, arg) @@ -255,6 +262,35 @@ class API(object): def __init__(self): self.conductor_rpcapi = rpcapi.ConductorAPI() + def wait_until_ready(self, context, early_timeout=10, early_attempts=10): + '''Wait until a conductor service is up and running. + + This method calls the remote ping() method on the conductor topic until + it gets a response. It starts with a shorter timeout in the loop + (early_timeout) up to early_attempts number of tries. It then drops + back to the globally configured timeout for rpc calls for each retry. + ''' + attempt = 0 + timeout = early_timeout + while True: + # NOTE(danms): Try ten times with a short timeout, and then punt + # to the configured RPC timeout after that + if attempt == early_attempts: + timeout = None + attempt += 1 + + # NOTE(russellb): This is running during service startup. If we + # allow an exception to be raised, the service will shut down. + # This may fail the first time around if nova-conductor wasn't + # running when this service started. + try: + self.ping(context, '1.21 GigaWatts', timeout=timeout) + break + except rpc_common.Timeout as e: + LOG.exception(_('Timed out waiting for nova-conductor. ' + 'Is it running? Or did this service start ' + 'before nova-conductor?')) + def ping(self, context, arg, timeout=None): return self.conductor_rpcapi.ping(context, arg, timeout) diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index bf619bbec..23df703be 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -3121,21 +3121,6 @@ class ComputeTestCase(BaseTestCase): instance = self._create_fake_instance(params) self.compute._instance_update(self.context, instance['uuid']) - def test_startup_conductor_ping(self): - timeouts = [] - calls = dict(count=0) - - def fake_ping(context, message, timeout): - timeouts.append(timeout) - calls['count'] += 1 - if calls['count'] < 15: - raise rpc_common.Timeout("fake") - - self.stubs.Set(self.compute.conductor_api, 'ping', fake_ping) - self.compute._get_instances_at_startup(self.context) - self.assertEqual(timeouts.count(10), 10) - self.assertTrue(None in timeouts) - def test_destroy_evacuated_instances(self): fake_context = context.get_admin_context() diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index ffe09c95e..7986fc583 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -650,6 +650,23 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase): def test_service_get_all_compute_by_host(self): self._test_stubbed('service_get_all_compute_by_host', 'host') + def test_ping(self): + timeouts = [] + calls = dict(count=0) + + def fake_ping(_self, context, message, timeout): + timeouts.append(timeout) + calls['count'] += 1 + if calls['count'] < 15: + raise rpc_common.Timeout("fake") + + self.stubs.Set(conductor_api.API, 'ping', fake_ping) + + self.conductor.wait_until_ready(self.context) + + self.assertEqual(timeouts.count(10), 10) + self.assertTrue(None in timeouts) + class ConductorLocalAPITestCase(ConductorAPITestCase): """Conductor LocalAPI Tests.""" @@ -667,6 +684,10 @@ class ConductorLocalAPITestCase(ConductorAPITestCase): self.assertRaises(KeyError, self._do_update, instance['uuid'], foo='bar') + def test_ping(self): + # Override test in ConductorAPITestCase + pass + class ConductorImportTest(test.TestCase): def test_import_conductor_local(self): |
