Block 3.1 message with c-sch RPCAPI pinned to 3.0

notify_service_capabilities was sent unconditionally, even when we
shouldn't allow it due to RPC version pinning. This commit blocks that
message when RPC API is pinned to anything lower than 3.1.

Change-Id: Ib2e4f65f626cad79773f46077a75813f434cb806
Closes-Bug: 1647789
This commit is contained in:
Michał Dulko 2016-12-06 17:58:50 +01:00
parent 85841a1713
commit 850a197226
3 changed files with 37 additions and 6 deletions

View File

@ -174,11 +174,20 @@ class SchedulerDependentManager(Manager):
self.service_name,
self.host,
self.last_capabilities)
self.scheduler_rpcapi.notify_service_capabilities(
context,
self.service_name,
self.host,
self.last_capabilities)
try:
self.scheduler_rpcapi.notify_service_capabilities(
context,
self.service_name,
self.host,
self.last_capabilities)
except exception.ServiceTooOld as e:
# This means we have Newton's c-sch in the deployment, so
# rpcapi cannot send the message. We can safely ignore the
# error. Log it because it shouldn't happen after upgrade.
msg = _LW("Failed to notify about cinder-volume service "
"capabilities for host %(host)s. This is normal "
"during a live upgrade. Error: %(e)s")
LOG.warning(msg, {'host': self.host, 'e': e})
def _add_to_threadpool(self, func, *args, **kwargs):
self._tp.spawn_n(func, *args, **kwargs)

View File

@ -19,6 +19,8 @@ Client side of the scheduler manager RPC API.
from oslo_serialization import jsonutils
from cinder.common import constants
from cinder import exception
from cinder.i18n import _
from cinder import rpc
@ -144,6 +146,10 @@ class SchedulerAPI(rpc.RPCAPI):
def notify_service_capabilities(self, ctxt, service_name,
host, capabilities):
cctxt = self._get_cctxt(version='3.1')
if not cctxt.can_send_version('3.1'):
msg = _('notify_service_capabilities requires cinder-scheduler '
'RPC API version >= 3.1.')
raise exception.ServiceTooOld(msg)
cctxt.cast(ctxt, 'notify_service_capabilities',
service_name=service_name, host=host,
capabilities=capabilities)

View File

@ -20,6 +20,7 @@ Unit Tests for cinder.scheduler.rpcapi
import mock
from cinder import context
from cinder import exception
from cinder.scheduler import rpcapi as scheduler_rpcapi
from cinder import test
from cinder.tests.unit import fake_constants
@ -96,7 +97,8 @@ class SchedulerRpcAPITestCase(test.TestCase):
version='3.0')
create_worker_mock.assert_called_once()
def test_notify_service_capabilities(self):
@mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
def test_notify_service_capabilities(self, can_send_version_mock):
capabilities = {'host': 'fake_host',
'total': '10.01', }
self._test_scheduler_api('notify_service_capabilities',
@ -106,6 +108,20 @@ class SchedulerRpcAPITestCase(test.TestCase):
capabilities=capabilities,
version='3.1')
@mock.patch('oslo_messaging.RPCClient.can_send_version',
return_value=False)
def test_notify_service_capabilities_capped(self, can_send_version_mock):
capabilities = {'host': 'fake_host',
'total': '10.01', }
self.assertRaises(exception.ServiceTooOld,
self._test_scheduler_api,
'notify_service_capabilities',
rpc_method='cast',
service_name='fake_name',
host='fake_host',
capabilities=capabilities,
version='3.1')
def test_create_volume_serialization(self):
volume = fake_volume.fake_volume_obj(self.context)
create_worker_mock = self.mock_object(volume, 'create_worker')