Merge "Add SIGHUP handlers to reset RPC version pins"

This commit is contained in:
Jenkins 2016-02-22 13:13:48 +00:00 committed by Gerrit Code Review
commit 09134ba4f3
10 changed files with 115 additions and 0 deletions

View File

@ -123,6 +123,11 @@ class BackupManager(manager.SchedulerDependentManager):
LOG.exception(_LE("Problem cleaning incomplete backup "
"operations."))
def reset(self):
super(BackupManager, self).reset()
self.backup_rpcapi = backup_rpcapi.BackupAPI()
self.volume_rpcapi = volume_rpcapi.VolumeAPI()
def _cleanup_incomplete_backup_operations(self, ctxt):
LOG.info(_LI("Cleaning up incomplete backup operations."))

View File

@ -58,6 +58,8 @@ import oslo_messaging as messaging
from oslo_service import periodic_task
from cinder.db import base
from cinder.i18n import _LI
from cinder import rpc
from cinder.scheduler import rpcapi as scheduler_rpcapi
from cinder import version
@ -127,6 +129,16 @@ class Manager(base.Base, PeriodicTasks):
"""
return True
def reset(self):
"""Method executed when SIGHUP is caught by the process.
We're utilizing it to reset RPC API version pins to avoid restart of
the service when rolling upgrade is completed.
"""
LOG.info(_LI('Resetting cached RPC version pins.'))
rpc.LAST_OBJ_VERSIONS = {}
rpc.LAST_RPC_VERSIONS = {}
class SchedulerDependentManager(Manager):
"""Periodically send capability updates to the Scheduler services.
@ -162,3 +174,7 @@ class SchedulerDependentManager(Manager):
def _add_to_threadpool(self, func, *args, **kwargs):
self._tp.spawn_n(func, *args, **kwargs)
def reset(self):
super(SchedulerDependentManager, self).reset()
self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()

View File

@ -74,6 +74,10 @@ class Scheduler(object):
CONF.scheduler_host_manager)
self.volume_rpcapi = volume_rpcapi.VolumeAPI()
def reset(self):
"""Reset volume RPC API object to load new version pins."""
self.volume_rpcapi = volume_rpcapi.VolumeAPI()
def is_ready(self):
"""Returns True if Scheduler is ready to accept requests.

View File

@ -75,6 +75,10 @@ class SchedulerManager(manager.Manager):
eventlet.sleep(CONF.periodic_interval)
self._startup_delay = False
def reset(self):
super(SchedulerManager, self).reset()
self.driver.reset()
def update_service_capabilities(self, context, service_name=None,
host=None, capabilities=None, **kwargs):
"""Process a capability update from a service node."""

View File

@ -362,6 +362,10 @@ class Service(service.Service):
self.model_disconnected = True
LOG.exception(_LE('Exception encountered: '))
def reset(self):
self.manager.reset()
super(Service, self).reset()
class WSGIService(service.ServiceBase):
"""Provides ability to launch API from a 'paste' configuration."""

View File

@ -69,6 +69,21 @@ class SchedulerManagerTestCase(test.TestCase):
sleep_mock.assert_called_once_with(CONF.periodic_interval)
self.assertFalse(self.manager._startup_delay)
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-volume': '1.3'})
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-volume': '1.5'})
def test_reset(self):
mgr = self.manager_cls()
volume_rpcapi = mgr.driver.volume_rpcapi
self.assertEqual('1.3', volume_rpcapi.client.version_cap)
self.assertEqual('1.5',
volume_rpcapi.client.serializer._base.version_cap)
mgr.reset()
volume_rpcapi = mgr.driver.volume_rpcapi
self.assertIsNone(volume_rpcapi.client.version_cap)
self.assertIsNone(volume_rpcapi.client.serializer._base.version_cap)
@mock.patch('cinder.scheduler.driver.Scheduler.'
'update_service_capabilities')
def test_update_service_capabilities_empty_dict(self, _mock_update_cap):

View File

@ -290,6 +290,30 @@ class BackupTestCase(BaseBackupTest):
mock_add_threadpool.assert_has_calls(calls, any_order=True)
self.assertEqual(2, mock_add_threadpool.call_count)
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-backup': '1.3',
'cinder-volume': '1.7'})
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-backup': '1.5',
'cinder-volume': '1.4'})
def test_reset(self):
backup_mgr = manager.BackupManager()
backup_rpcapi = backup_mgr.backup_rpcapi
volume_rpcapi = backup_mgr.volume_rpcapi
self.assertEqual('1.3', backup_rpcapi.client.version_cap)
self.assertEqual('1.5',
backup_rpcapi.client.serializer._base.version_cap)
self.assertEqual('1.7', volume_rpcapi.client.version_cap)
self.assertEqual('1.4',
volume_rpcapi.client.serializer._base.version_cap)
backup_mgr.reset()
backup_rpcapi = backup_mgr.backup_rpcapi
volume_rpcapi = backup_mgr.volume_rpcapi
self.assertIsNone(backup_rpcapi.client.version_cap)
self.assertIsNone(backup_rpcapi.client.serializer._base.version_cap)
self.assertIsNone(volume_rpcapi.client.version_cap)
self.assertIsNone(volume_rpcapi.client.serializer._base.version_cap)
def test_is_working(self):
self.assertTrue(self.backup_mgr.is_working())

View File

@ -83,6 +83,18 @@ class ServiceManagerTestCase(test.TestCase):
serv.start()
self.assertEqual('service', serv.test_method())
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'test': '1.5'})
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'test': '1.3'})
def test_reset(self):
serv = service.Service('test',
'test',
'test',
'cinder.tests.unit.test_service.FakeManager')
serv.start()
serv.reset()
self.assertEqual({}, rpc.LAST_OBJ_VERSIONS)
self.assertEqual({}, rpc.LAST_RPC_VERSIONS)
class ServiceFlagsTestCase(test.TestCase):
def test_service_enabled_on_create_based_on_flag(self):

View File

@ -374,6 +374,21 @@ class VolumeTestCase(BaseVolumeTestCase):
manager.init_host()
self.assertEqual(0, mock_add_p_task.call_count)
@mock.patch('cinder.rpc.LAST_RPC_VERSIONS', {'cinder-scheduler': '1.3'})
@mock.patch('cinder.rpc.LAST_OBJ_VERSIONS', {'cinder-scheduler': '1.5'})
def test_reset(self):
vol_mgr = vol_manager.VolumeManager()
scheduler_rpcapi = vol_mgr.scheduler_rpcapi
self.assertEqual('1.3', scheduler_rpcapi.client.version_cap)
self.assertEqual('1.5',
scheduler_rpcapi.client.serializer._base.version_cap)
vol_mgr.reset()
scheduler_rpcapi = vol_mgr.scheduler_rpcapi
self.assertIsNone(scheduler_rpcapi.client.version_cap)
self.assertIsNone(scheduler_rpcapi.client.serializer._base.version_cap)
@mock.patch.object(vol_manager.VolumeManager,
'update_service_capabilities')
def test_report_filter_goodness_function(self, mock_update):

View File

@ -0,0 +1,16 @@
---
features:
- Added RPC backward compatibility layer similar to the
one implemented in Nova. This means that Cinder
services can be upgraded one-by-one without breakage.
After all the services are upgraded SIGHUP signals
should be issued to all the services to signal them
to reload cached minimum RPC versions. Alternative
is of course restart of them. Please note that
cinder-api service doesn't support SIGHUP yet.
Please also take into account that all the rolling
upgrades capabilities are considered tech preview,
as we don't have a CI testing it yet.
upgrade:
- Starting from Mitaka release Cinder is having a tech
preview of rolling upgrades support.