Add assert_min_rpc_version decorator
We have multiple places in RPC APIs where we're blocking sending RPC calls if version cap is set to value lower than our minimal version. This commit implements this consistently by adding a reusable decorator that can be used with RPC API methods. Change-Id: I11c0d79c45294bd412feffd4b301359254d2e143
This commit is contained in:
parent
e0bf4ce7af
commit
0b7c4cc54e
@ -31,10 +31,11 @@ from oslo_log import log as logging
|
||||
import oslo_messaging as messaging
|
||||
from oslo_utils import importutils
|
||||
profiler = importutils.try_import('osprofiler.profiler')
|
||||
import six
|
||||
|
||||
import cinder.context
|
||||
import cinder.exception
|
||||
from cinder.i18n import _LE, _LI
|
||||
from cinder.i18n import _, _LE, _LI
|
||||
from cinder import objects
|
||||
from cinder.objects import base
|
||||
|
||||
@ -170,6 +171,28 @@ def get_notifier(service=None, host=None, publisher_id=None):
|
||||
return NOTIFIER.prepare(publisher_id=publisher_id)
|
||||
|
||||
|
||||
def assert_min_rpc_version(min_ver, exc=None):
|
||||
"""Decorator to block RPC calls when version cap is lower than min_ver."""
|
||||
|
||||
if exc is None:
|
||||
exc = cinder.exception.ServiceTooOld
|
||||
|
||||
def decorator(f):
|
||||
@six.wraps(f)
|
||||
def _wrapper(self, *args, **kwargs):
|
||||
if not self.client.can_send_version(min_ver):
|
||||
msg = _('One of %(binary)s services is too old to accept '
|
||||
'%(method)s request. Required RPC API version is '
|
||||
'%(version)s. Are you running mixed versions of '
|
||||
'%(binary)ss?') % {'binary': self.BINARY,
|
||||
'version': min_ver,
|
||||
'method': f.__name__}
|
||||
raise exc(msg)
|
||||
return f(self, *args, **kwargs)
|
||||
return _wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
LAST_RPC_VERSIONS = {}
|
||||
LAST_OBJ_VERSIONS = {}
|
||||
|
||||
|
@ -20,8 +20,6 @@ from oslo_serialization import jsonutils
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from cinder.common import constants
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import rpc
|
||||
|
||||
|
||||
@ -148,13 +146,10 @@ class SchedulerAPI(rpc.RPCAPI):
|
||||
}
|
||||
return cctxt.cast(ctxt, 'manage_existing', **msg_args)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.2')
|
||||
def extend_volume(self, ctxt, volume, new_size, reservations,
|
||||
request_spec, filter_properties=None):
|
||||
cctxt = self._get_cctxt()
|
||||
if not cctxt.can_send_version('3.2'):
|
||||
msg = _('extend_volume requires cinder-scheduler '
|
||||
'RPC API version >= 3.2.')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
request_spec_p = jsonutils.to_primitive(request_spec)
|
||||
msg_args = {
|
||||
@ -194,14 +189,9 @@ class SchedulerAPI(rpc.RPCAPI):
|
||||
cctxt = self._get_cctxt(fanout=True, version=version)
|
||||
cctxt.cast(ctxt, 'update_service_capabilities', **msg_args)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.1')
|
||||
def notify_service_capabilities(self, ctxt, service_name,
|
||||
backend, capabilities, timestamp=None):
|
||||
version = '3.1'
|
||||
if not self.client.can_send_version(version):
|
||||
msg = _('notify_service_capabilities requires cinder-scheduler '
|
||||
'RPC API version >= 3.1.')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
parameters = {'service_name': service_name,
|
||||
'capabilities': capabilities}
|
||||
if self.client.can_send_version('3.5'):
|
||||
@ -209,32 +199,23 @@ class SchedulerAPI(rpc.RPCAPI):
|
||||
parameters.update(backend=backend,
|
||||
timestamp=self.prepare_timestamp(timestamp))
|
||||
else:
|
||||
version = '3.1'
|
||||
parameters['host'] = backend
|
||||
|
||||
cctxt = self._get_cctxt(version=version)
|
||||
cctxt.cast(ctxt, 'notify_service_capabilities', **parameters)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.4')
|
||||
def work_cleanup(self, ctxt, cleanup_request):
|
||||
"""Generate individual service cleanup requests from user request."""
|
||||
if not self.client.can_send_version('3.4'):
|
||||
msg = _('One of cinder-scheduler services is too old to accept '
|
||||
'such request. Are you running mixed Newton-Ocata'
|
||||
'cinder-schedulers?')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
cctxt = self.client.prepare(version='3.4')
|
||||
# Response will have services that are receiving the cleanup request
|
||||
# and services that couldn't receive it since they are down.
|
||||
return cctxt.call(ctxt, 'work_cleanup',
|
||||
cleanup_request=cleanup_request)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.4')
|
||||
def do_cleanup(self, ctxt, cleanup_request):
|
||||
"""Perform this scheduler's resource cleanup as per cleanup_request."""
|
||||
if not self.client.can_send_version('3.4'):
|
||||
msg = _('One of cinder-scheduler services is too old to accept '
|
||||
'such request. Are you running mixed Newton-Ocata'
|
||||
'cinder-schedulers?')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
cctxt = self.client.prepare(version='3.4')
|
||||
cctxt.cast(ctxt, 'do_cleanup', cleanup_request=cleanup_request)
|
||||
|
@ -14,8 +14,6 @@
|
||||
|
||||
|
||||
from cinder.common import constants
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import objects
|
||||
from cinder import quota
|
||||
from cinder import rpc
|
||||
@ -407,13 +405,8 @@ class VolumeAPI(rpc.RPCAPI):
|
||||
cctxt.cast(ctxt, 'delete_group_snapshot',
|
||||
group_snapshot=group_snapshot)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.9')
|
||||
def attachment_update(self, ctxt, vref, connector, attachment_id):
|
||||
if not self.client.can_send_version('3.9'):
|
||||
msg = _('One of cinder-volume services is too old to accept '
|
||||
'such request. Are you running mixed Newton-Ocata'
|
||||
'cinder-schedulers?')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
version = self._compat_ver('3.9')
|
||||
cctxt = self._get_cctxt(vref.host, version=version)
|
||||
return cctxt.call(ctxt,
|
||||
@ -422,13 +415,8 @@ class VolumeAPI(rpc.RPCAPI):
|
||||
connector=connector,
|
||||
attachment_id=attachment_id)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.9')
|
||||
def attachment_delete(self, ctxt, attachment_id, vref):
|
||||
if not self.client.can_send_version('3.9'):
|
||||
msg = _('One of cinder-volume services is too old to accept '
|
||||
'such request. Are you running mixed Newton-Ocata'
|
||||
'cinder-schedulers?')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
version = self._compat_ver('3.9')
|
||||
cctxt = self._get_cctxt(vref.host, version=version)
|
||||
return cctxt.call(ctxt,
|
||||
@ -436,13 +424,9 @@ class VolumeAPI(rpc.RPCAPI):
|
||||
attachment_id=attachment_id,
|
||||
vref=vref)
|
||||
|
||||
@rpc.assert_min_rpc_version('3.7')
|
||||
def do_cleanup(self, ctxt, cleanup_request):
|
||||
"""Perform this service/cluster resource cleanup as requested."""
|
||||
if not self.client.can_send_version('3.7'):
|
||||
msg = _('One of cinder-volume services is too old to accept such '
|
||||
'a request. Are you running mixed Newton-Ocata services?')
|
||||
raise exception.ServiceTooOld(msg)
|
||||
|
||||
destination = cleanup_request.service_topic_queue
|
||||
cctxt = self._get_cctxt(destination, '3.7')
|
||||
# NOTE(geguileo): This call goes to do_cleanup code in
|
||||
|
Loading…
Reference in New Issue
Block a user