Pin RPC and object version to lowest running
This commit adds detection and pinning to lowest RPC API version to all rpcapi modules. The version pin is determined by a DB call done once per service lifetime thanks to caching. Handling the compatibility is guaranteed by oslo.messaging and our shims in rpcapi modules. To achieve o.vo compatibility, a similar approach is implemented. Custom oslo.messaging serializer is implemented that backports objects to the lowest running version on sending. During the process of upgrade it may happen that manager receives an object in the version lower than current one. Handling of such situations is up to the manager and it should do that explicitely by checking obj.VERSION. The patch also adds required methods to db.api and Service object. Co-Authored-By: Thang Pham <thang.g.pham@gmail.com> Change-Id: I649892da64f9734928a6cf0f004a369aa7aa375f Partial-Implements: blueprint rpc-object-compatibility
This commit is contained in:
@@ -27,14 +27,19 @@ __all__ = [
|
||||
]
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import oslo_messaging as messaging
|
||||
from oslo_serialization import jsonutils
|
||||
from osprofiler import profiler
|
||||
|
||||
import cinder.context
|
||||
import cinder.exception
|
||||
from cinder.i18n import _LI
|
||||
from cinder import objects
|
||||
from cinder.objects import base
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
TRANSPORT = None
|
||||
NOTIFIER = None
|
||||
|
||||
@@ -160,3 +165,70 @@ def get_notifier(service=None, host=None, publisher_id=None):
|
||||
if not publisher_id:
|
||||
publisher_id = "%s.%s" % (service, host or CONF.host)
|
||||
return NOTIFIER.prepare(publisher_id=publisher_id)
|
||||
|
||||
|
||||
LAST_RPC_VERSIONS = {}
|
||||
LAST_OBJ_VERSIONS = {}
|
||||
|
||||
|
||||
class RPCAPI(object):
|
||||
"""Mixin class aggregating methods related to RPC API compatibility."""
|
||||
|
||||
RPC_API_VERSION = '1.0'
|
||||
TOPIC = ''
|
||||
BINARY = ''
|
||||
|
||||
def __init__(self):
|
||||
target = messaging.Target(topic=self.TOPIC,
|
||||
version=self.RPC_API_VERSION)
|
||||
obj_version_cap = self._determine_obj_version_cap()
|
||||
serializer = base.CinderObjectSerializer(obj_version_cap)
|
||||
|
||||
rpc_version_cap = self._determine_rpc_version_cap()
|
||||
self.client = get_client(target, version_cap=rpc_version_cap,
|
||||
serializer=serializer)
|
||||
|
||||
def _determine_rpc_version_cap(self):
|
||||
global LAST_RPC_VERSIONS
|
||||
if self.BINARY in LAST_RPC_VERSIONS:
|
||||
return LAST_RPC_VERSIONS[self.BINARY]
|
||||
|
||||
version_cap = objects.Service.get_minimum_rpc_version(
|
||||
cinder.context.get_admin_context(), self.BINARY)
|
||||
if version_cap == 'liberty':
|
||||
# NOTE(dulek): This means that one of the services is Liberty,
|
||||
# we should cap to it's RPC version.
|
||||
version_cap = LIBERTY_RPC_VERSIONS[self.BINARY]
|
||||
LOG.info(_LI('Automatically selected %(binary)s RPC version '
|
||||
'%(version)s as minimum service version.'),
|
||||
{'binary': self.BINARY, 'version': version_cap})
|
||||
LAST_RPC_VERSIONS[self.BINARY] = version_cap
|
||||
return version_cap
|
||||
|
||||
def _determine_obj_version_cap(self):
|
||||
global LAST_OBJ_VERSIONS
|
||||
if self.BINARY in LAST_OBJ_VERSIONS:
|
||||
return LAST_OBJ_VERSIONS[self.BINARY]
|
||||
|
||||
version_cap = objects.Service.get_minimum_obj_version(
|
||||
cinder.context.get_admin_context(), self.BINARY)
|
||||
LOG.info(_LI('Automatically selected %(binary)s objects version '
|
||||
'%(version)s as minimum service version.'),
|
||||
{'binary': self.BINARY, 'version': version_cap})
|
||||
LAST_OBJ_VERSIONS[self.BINARY] = version_cap
|
||||
return version_cap
|
||||
|
||||
|
||||
# FIXME(dulek): Liberty haven't reported its RPC versions, so we need to have
|
||||
# them hardcoded. This dict may go away as soon as we drop compatibility with
|
||||
# L, which should be in early N.
|
||||
#
|
||||
# This is the only time we need to have such dictionary. We don't need to add
|
||||
# similar ones for any release following Liberty.
|
||||
LIBERTY_RPC_VERSIONS = {
|
||||
'cinder-volume': '1.30',
|
||||
'cinder-scheduler': '1.8',
|
||||
# NOTE(dulek) backup.manager had specified version '1.2', but backup.rpcapi
|
||||
# was really only sending messages up to '1.1'.
|
||||
'cinder-backup': '1.1',
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user