From 3ab91c47708ec6158a7319b9c3a7e357b756df44 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 8 Oct 2013 21:08:23 +0000 Subject: [PATCH] Use `versionutils.is_compatible` for Nova Objects Oslo's check is designed to support version checking for a number of different existing use-cases, including this one. Related-Oslo-Commit: d7d74a752e34d5249fa47c8e8252da491d46012a Change-Id: I8e03c7781330b02deb7af815d68538b5c0245c4d --- nova/objects/base.py | 38 ++++++---------------- nova/openstack/common/versionutils.py | 45 +++++++++++++++++++++++++++ openstack-common.conf | 1 + 3 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 nova/openstack/common/versionutils.py diff --git a/nova/objects/base.py b/nova/objects/base.py index aafe386375ac..24df30f93782 100644 --- a/nova/objects/base.py +++ b/nova/objects/base.py @@ -25,6 +25,7 @@ from nova.openstack.common.gettextutils import _ from nova.openstack.common import log as logging from nova.openstack.common.rpc import common as rpc_common import nova.openstack.common.rpc.serializer +from nova.openstack.common import versionutils LOG = logging.getLogger('object') @@ -149,30 +150,6 @@ def remotable(fn): return wrapper -# Object versioning rules -# -# Each service has its set of objects, each with a version attached. When -# a client attempts to call an object method, the server checks to see if -# the version of that object matches (in a compatible way) its object -# implementation. If so, cool, and if not, fail. -def check_object_version(server, client): - try: - client_major, _client_minor = client.split('.') - server_major, _server_minor = server.split('.') - client_minor = int(_client_minor) - server_minor = int(_server_minor) - except ValueError: - raise exception.IncompatibleObjectVersion( - _('Invalid version string')) - - if client_major != server_major: - raise exception.IncompatibleObjectVersion( - dict(client=client_major, server=server_major)) - if client_minor > server_minor: - raise exception.IncompatibleObjectVersion( - dict(client=client_minor, server=server_minor)) - - class NovaObject(object): """Base class and object factory. @@ -184,7 +161,12 @@ class NovaObject(object): """ __metaclass__ = NovaObjectMetaclass - # Version of this object (see rules above check_object_version()) + # Object versioning rules + # + # Each service has its set of objects, each with a version attached. When + # a client attempts to call an object method, the server checks to see if + # the version of that object matches (in a compatible way) its object + # implementation. If so, cool, and if not, fail. VERSION = '1.0' # The fields present in this object as key:field pairs. For example: @@ -218,11 +200,9 @@ class NovaObject(object): for objclass in cls._obj_classes[objname]: if objclass.VERSION == objver: return objclass - try: - check_object_version(objclass.VERSION, objver) + + if versionutils.is_compatible(objver, objclass.VERSION): compatible_match = objclass - except exception.IncompatibleObjectVersion: - pass if compatible_match: return compatible_match diff --git a/nova/openstack/common/versionutils.py b/nova/openstack/common/versionutils.py new file mode 100644 index 000000000000..f7b1f8a822aa --- /dev/null +++ b/nova/openstack/common/versionutils.py @@ -0,0 +1,45 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2013 OpenStack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Helpers for comparing version strings. +""" + +import pkg_resources + + +def is_compatible(requested_version, current_version, same_major=True): + """Determine whether `requested_version` is satisfied by + `current_version`; in other words, `current_version` is >= + `requested_version`. + + :param requested_version: version to check for compatibility + :param current_version: version to check against + :param same_major: if True, the major version must be identical between + `requested_version` and `current_version`. This is used when a + major-version difference indicates incompatibility between the two + versions. Since this is the common-case in practice, the default is + True. + :returns: True if compatible, False if not + """ + requested_parts = pkg_resources.parse_version(requested_version) + current_parts = pkg_resources.parse_version(current_version) + + if same_major and (requested_parts[0] != current_parts[0]): + return False + + return current_parts >= requested_parts diff --git a/openstack-common.conf b/openstack-common.conf index 151526b95b49..3c05fd65c301 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -33,6 +33,7 @@ module=strutils module=threadgroup module=timeutils module=uuidutils +module=versionutils module=xmlutils # The base module to hold the copy of openstack.common