def test_same_major_true(self): """Even though the current version is 2.0, since `same_major` defaults to `True`, 1.0 is deemed incompatible. """ self.assertFalse(versionutils.is_compatible('2.0', '1.0')) self.assertTrue(versionutils.is_compatible('1.0', '1.0')) self.assertFalse(versionutils.is_compatible('1.0', '2.0'))
def test_same_major_false(self): """With `same_major` set to False, then major version compatibiity rule is not enforced, so a current version of 2.0 is deemed to satisfy a requirement of 1.0. """ self.assertFalse( versionutils.is_compatible('2.0', '1.0', same_major=False)) self.assertTrue( versionutils.is_compatible('1.0', '1.0', same_major=False)) self.assertTrue( versionutils.is_compatible('1.0', '2.0', same_major=False))
def test_same_major_false(self): """With `same_major` set to False, then major version compatibiity rule is not enforced, so a current version of 2.0 is deemed to satisfy a requirement of 1.0. """ self.assertFalse(versionutils.is_compatible('2.0', '1.0', same_major=False)) self.assertTrue(versionutils.is_compatible('1.0', '1.0', same_major=False)) self.assertTrue(versionutils.is_compatible('1.0', '2.0', same_major=False))
def _from_db_object(context, obj, db_object, fields=None): """Converts a database entity to a formal object. This always converts the database entity to the latest version of the object. Note that the latest version is available at object.__class__.VERSION. object.VERSION is the version of this particular object instance; it is possible that it is not the latest version. :param context: security context :param obj: An object of the class. :param db_object: A DB entity of the object :param fields: list of fields to set on obj from values from db_object. :return: The object of the class with the database entity added :raises: ovo_exception.IncompatibleObjectVersion """ objname = obj.obj_name() db_version = db_object['version'] if db_version is None: # NOTE(rloo): This can only happen after we've updated the DB # tables to include the 'version' column but haven't saved the # object to the DB since the new column was added. This column is # added in the Pike cycle, so if the version isn't set, use the # version associated with the most recent release, i.e. '8.0'. # The objects and RPC versions haven't changed between '8.0' and # Ocata, which is why it is fine to use Ocata. # Furthermore, if this is a new object that did not exist in the # most recent release, we assume it is version 1.0. # TODO(rloo): This entire if clause can be deleted in Queens # since the dbsync online migration populates all the versions # and it must be run to completion before upgrading to Queens. db_version = versions.RELEASE_MAPPING['ocata']['objects'].get( objname, ['1.0'])[0] if not versionutils.is_compatible(db_version, obj.__class__.VERSION): raise ovo_exception.IncompatibleObjectVersion( objname=objname, objver=db_version, supported=obj.__class__.VERSION) obj._set_from_db_object(context, db_object, fields) obj._context = context # NOTE(rloo). We now have obj, a versioned object that corresponds to # its DB representation. A versioned object has an internal attribute # ._changed_fields; this is a list of changed fields -- used, e.g., # when saving the object to the DB (only those changed fields are # saved to the DB). The obj.obj_reset_changes() clears this list # since we didn't actually make any modifications to the object that # we want saved later. obj.obj_reset_changes() if db_version != obj.__class__.VERSION: # convert to the latest version obj.VERSION = db_version obj.convert_to_version(obj.__class__.VERSION, remove_unavailable_fields=False) return obj
def test_send_with_timeout(self, fake_publish): transport = oslo_messaging.get_transport(self.conf, 'kombu+memory:////') with transport._driver._get_connection( driver_common.PURPOSE_SEND) as pool_conn: conn = pool_conn.connection conn._publish(mock.Mock(), 'msg', routing_key='routing_key', timeout=1) # NOTE(gcb) kombu accept TTL as seconds instead of millisecond since # version 3.0.25, so do conversion according to kombu version. # TODO(gcb) remove this workaround when all supported branches # with requirement kombu >=3.0.25 kombu_version = pkg_resources.get_distribution('kombu').version if versionutils.is_compatible('3.0.25', kombu_version): fake_publish.assert_called_with( 'msg', expiration=1, compression=self.conf.oslo_messaging_rabbit.kombu_compression) else: fake_publish.assert_called_with( 'msg', expiration=1000, compression=self.conf.oslo_messaging_rabbit.kombu_compression)
def _use_groups(self): release_ver = versions.RELEASE_MAPPING.get(CONF.pin_release_version) # NOTE(jroll) self.RPC_API_VERSION is actually defined in a subclass, # but we only use this class from there. version_cap = (release_ver['rpc'] if release_ver else self.RPC_API_VERSION) return versionutils.is_compatible('1.47', version_cap)
def test_send_with_timeout(self, fake_publish): transport = oslo_messaging.get_transport(self.conf, 'kombu+memory:////') exchange_mock = mock.Mock() with transport._driver._get_connection( driver_common.PURPOSE_SEND) as pool_conn: conn = pool_conn.connection conn._publish(exchange_mock, 'msg', routing_key='routing_key', timeout=1) # NOTE(gcb) kombu accept TTL as seconds instead of millisecond since # version 3.0.25, so do conversion according to kombu version. # TODO(gcb) remove this workaround when all supported branches # with requirement kombu >=3.0.25 kombu_version = pkg_resources.get_distribution('kombu').version if versionutils.is_compatible('3.0.25', kombu_version): fake_publish.assert_called_with( 'msg', expiration=1, exchange=exchange_mock, compression=self.conf.oslo_messaging_rabbit.kombu_compression, routing_key='routing_key') else: fake_publish.assert_called_with( 'msg', expiration=1000, exchange=exchange_mock, compression=self.conf.oslo_messaging_rabbit.kombu_compression, routing_key='routing_key')
def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" if objname not in cls._obj_classes: LOG.error( _LE('Unable to instantiate unregistered object type ' '%(objtype)s'), dict(objtype=objname)) raise exception.UnsupportedObjectError(objtype=objname) latest = None compatible_match = None for objclass in cls._obj_classes[objname]: if objclass.VERSION == objver: return objclass version_bits = tuple([int(x) for x in objclass.VERSION.split(".")]) if latest is None: latest = version_bits elif latest < version_bits: latest = version_bits if versionutils.is_compatible(objver, objclass.VERSION): compatible_match = objclass if compatible_match: return compatible_match latest_ver = '%i.%i' % latest raise exception.IncompatibleObjectVersion(objname=objname, objver=objver, supported=latest_ver)
def get_target_version(cls): """Returns the target version for this object. This is the version in which the object should be manipulated, e.g. sent over the wire via RPC or saved in the DB. :returns: if pinned, returns the version of this object corresponding to the pin. Otherwise, returns the version of the object. :raises: ovo_exception.IncompatibleObjectVersion """ pin = CONF.pin_release_version if not pin: return cls.VERSION version_manifest = versions.RELEASE_MAPPING[pin]['objects'] pinned_versions = version_manifest.get(cls.obj_name()) if pinned_versions: pinned_version = max_version(pinned_versions) if not versionutils.is_compatible(pinned_version, cls.VERSION): LOG.error( 'For object "%(objname)s", the target version ' '"%(target)s" is not compatible with its supported ' 'version "%(support)s". The value ("%(pin)s") of the ' '"pin_release_version" configuration option may be ' 'incorrect.', {'objname': cls.obj_name(), 'target': pinned_version, 'support': cls.VERSION, 'pin': pin}) raise ovo_exception.IncompatibleObjectVersion( objname=cls.obj_name(), objver=pinned_version, supported=cls.VERSION) return pinned_version return cls.VERSION
def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" if objname not in VersionedObjectRegistry.obj_classes(): LOG.error(_LE('Unable to instantiate unregistered object type ' '%(objtype)s'), dict(objtype=objname)) raise exception.UnsupportedObjectError(objtype=objname) # NOTE(comstud): If there's not an exact match, return the highest # compatible version. The objects stored in the class are sorted # such that highest version is first, so only set compatible_match # once below. compatible_match = None for objclass in VersionedObjectRegistry.obj_classes()[objname]: if objclass.VERSION == objver: return objclass if (not compatible_match and vutils.is_compatible(objver, objclass.VERSION)): compatible_match = objclass if compatible_match: return compatible_match # As mentioned above, latest version is always first in the list. latest_ver = VersionedObjectRegistry.obj_classes()[objname][0].VERSION raise exception.IncompatibleObjectVersion(objname=objname, objver=objver, supported=latest_ver)
def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" if objname not in cls._obj_classes: LOG.error(_LE('Unable to instantiate unregistered object type ' '%(objtype)s'), dict(objtype=objname)) raise exception.UnsupportedObjectError(objtype=objname) latest = None compatible_match = None for objclass in cls._obj_classes[objname]: if objclass.VERSION == objver: return objclass version_bits = tuple([int(x) for x in objclass.VERSION.split(".")]) if latest is None: latest = version_bits elif latest < version_bits: latest = version_bits if versionutils.is_compatible(objver, objclass.VERSION): compatible_match = objclass if compatible_match: return compatible_match latest_ver = '%i.%i' % latest raise exception.IncompatibleObjectVersion(objname=objname, objver=objver, supported=latest_ver)
def get_target_version(cls): """Returns the target version for this object. This is the version in which the object should be manipulated, e.g. sent over the wire via RPC or saved in the DB. :returns: if pinned, returns the version of this object corresponding to the pin. Otherwise, returns the version of the object. :raises: ovo_exception.IncompatibleObjectVersion """ pin = CONF.pin_release_version if not pin: return cls.VERSION version_manifest = versions.RELEASE_MAPPING[pin]['objects'] pinned_version = version_manifest.get(cls.obj_name()) if pinned_version: pinned_version = pinned_version[0] if not versionutils.is_compatible(pinned_version, cls.VERSION): LOG.error( 'For object "%(objname)s", the target version ' '"%(target)s" is not compatible with its supported ' 'version "%(support)s". The value ("%(pin)s") of the ' '"pin_release_version" configuration option may be ' 'incorrect.', {'objname': cls.obj_name(), 'target': pinned_version, 'support': cls.VERSION, 'pin': pin}) raise ovo_exception.IncompatibleObjectVersion( objname=cls.obj_name(), objver=pinned_version, supported=cls.VERSION) return pinned_version return cls.VERSION
def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" if objname not in NovaObjectRegistry.obj_classes(): LOG.error( _LE('Unable to instantiate unregistered object type ' '%(objtype)s'), dict(objtype=objname)) raise exception.UnsupportedObjectError(objtype=objname) # NOTE(comstud): If there's not an exact match, return the highest # compatible version. The objects stored in the class are sorted # such that highest version is first, so only set compatible_match # once below. compatible_match = None obj_classes = NovaObjectRegistry.obj_classes() for objclass in obj_classes[objname]: if objclass.VERSION == objver: return objclass if (not compatible_match and versionutils.is_compatible(objver, objclass.VERSION)): compatible_match = objclass if compatible_match: return compatible_match # As mentioned above, latest version is always first in the list. latest_ver = obj_classes[objname][0].VERSION raise exception.IncompatibleObjectVersion(objname=objname, objver=objver, supported=latest_ver)
def _verify_plugin_version(self): requested_version = self.PLUGIN_REQUIRED_VERSION current_version = self.call_plugin_serialized( 'nova_plugin_version', 'get_version') if not versionutils.is_compatible(requested_version, current_version): raise self.XenAPI.Failure( _("Plugin version mismatch (Expected %(exp)s, got %(got)s)") % {'exp': requested_version, 'got': current_version})
def _from_db_object(context, obj, db_object, fields=None): """Converts a database entity to a formal object. This always converts the database entity to the latest version of the object. Note that the latest version is available at object.__class__.VERSION. object.VERSION is the version of this particular object instance; it is possible that it is not the latest version. :param context: security context :param obj: An object of the class. :param db_object: A DB entity of the object :param fields: list of fields to set on obj from values from db_object. :return: The object of the class with the database entity added :raises: ovo_exception.IncompatibleObjectVersion """ objname = obj.obj_name() db_version = db_object['version'] if db_version is None: # NOTE(rloo): This can only happen if the DB is corrupt or this # is the conductor object. (Because the rest of the objects will # all have their DB version set properly.) # TODO(rloo): This entire if clause can be deleted in Rocky # since the dbsync online migration populates all the conductor # versions and it must be run to completion before upgrading to # Rocky. db_version = versions.RELEASE_MAPPING['pike']['objects'].get( objname, ['1.0'])[0] if not versionutils.is_compatible(db_version, obj.__class__.VERSION): raise ovo_exception.IncompatibleObjectVersion( objname=objname, objver=db_version, supported=obj.__class__.VERSION) obj._set_from_db_object(context, db_object, fields) obj._context = context # NOTE(rloo). We now have obj, a versioned object that corresponds to # its DB representation. A versioned object has an internal attribute # ._changed_fields; this is a list of changed fields -- used, e.g., # when saving the object to the DB (only those changed fields are # saved to the DB). The obj.obj_reset_changes() clears this list # since we didn't actually make any modifications to the object that # we want saved later. obj.obj_reset_changes() if db_version != obj.__class__.VERSION: # convert to the latest version obj.VERSION = db_version obj.convert_to_version(obj.__class__.VERSION, remove_unavailable_fields=False) return obj
def do_setup(self, context): """Any initialization the volume driver needs to do while starting. :param context: The admin context. """ super(VMwareVStorageObjectDriver, self).do_setup(context) self.volumeops.set_vmx_version('vmx-13') vc_67_compatible = versionutils.is_compatible( '6.7.0', self._vc_version, same_major=False) self._use_fcd_snapshot = vc_67_compatible self._storage_policy_enabled = vc_67_compatible
def _verify_plugin_version(self): requested_version = self.PLUGIN_REQUIRED_VERSION current_version = self.call_plugin_serialized( 'nova_plugin_version.py', 'get_version') # v2.0 is the same as v1.8, with no version bumps. Remove this once # Ocata is released if requested_version == '2.0' and current_version == '1.8': return if not versionutils.is_compatible(requested_version, current_version): raise self.XenAPI.Failure( _("Plugin version mismatch (Expected %(exp)s, got %(got)s)") % {'exp': requested_version, 'got': current_version})
def expect_http(self, host=None, is_secure=False, api_version=None): """Returns a new EC2 connection.""" self.ec2 = boto.connect_ec2( aws_access_key_id='fake', aws_secret_access_key='fake', is_secure=False, region=regioninfo.RegionInfo(None, 'test', self.host), port=8773, path='/services/Cloud') if api_version: self.ec2.APIVersion = api_version self.mox.StubOutWithMock(self.ec2, 'new_http_connection') self.http = FakeHttplibConnection( self.app, '%s:8773' % (self.host), False) if versionutils.is_compatible('2.14', boto.Version, same_major=False): self.ec2.new_http_connection(host or self.host, 8773, is_secure).AndReturn(self.http) elif versionutils.is_compatible('2', boto.Version, same_major=False): self.ec2.new_http_connection(host or '%s:8773' % (self.host), is_secure).AndReturn(self.http) else: self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) return self.http
def is_xsm_sr_check_relaxed(self): if self._cached_xsm_sr_relaxed is None: config_value = self.call_plugin('config_file', 'get_val', key='relax-xsm-sr-check') if not config_value: version_str = '.'.join(str(v) for v in self.platform_version) if versionutils.is_compatible('2.1.0', version_str, same_major=False): self._cached_xsm_sr_relaxed = True else: self._cached_xsm_sr_relaxed = False else: self._cached_xsm_sr_relaxed = config_value.lower() == 'true' return self._cached_xsm_sr_relaxed
def is_xsm_sr_check_relaxed(self): if self._cached_xsm_sr_relaxed is None: config_value = self.call_plugin('config_file', 'get_val', dict(key='relax-xsm-sr-check')) if not config_value: version_str = '.'.join(str(v) for v in self.platform_version) if versionutils.is_compatible('2.1.0', version_str, same_major=False): self._cached_xsm_sr_relaxed = True else: self._cached_xsm_sr_relaxed = False else: self._cached_xsm_sr_relaxed = config_value.lower() == 'true' return self._cached_xsm_sr_relaxed
def expect_http(self, host=None, is_secure=False, api_version=None): """Returns a new EC2 connection.""" self.ec2 = boto.connect_ec2(aws_access_key_id='fake', aws_secret_access_key='fake', is_secure=False, region=regioninfo.RegionInfo( None, 'test', self.host), port=8773, path='/services/Cloud') if api_version: self.ec2.APIVersion = api_version self.mox.StubOutWithMock(self.ec2, 'new_http_connection') self.http = FakeHttplibConnection(self.app, '%s:8773' % (self.host), False) if versionutils.is_compatible('2.14', boto.Version, same_major=False): self.ec2.new_http_connection(host or self.host, 8773, is_secure).AndReturn(self.http) elif versionutils.is_compatible('2', boto.Version, same_major=False): self.ec2.new_http_connection(host or '%s:8773' % (self.host), is_secure).AndReturn(self.http) else: self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) return self.http
def _from_db_object(context, obj, db_object, fields=None): """Converts a database entity to a formal object. This always converts the database entity to the latest version of the object. Note that the latest version is available at object.__class__.VERSION. object.VERSION is the version of this particular object instance; it is possible that it is not the latest version. :param context: security context :param obj: An object of the class. :param db_object: A DB entity of the object :param fields: list of fields to set on obj from values from db_object. :return: The object of the class with the database entity added :raises: ovo_exception.IncompatibleObjectVersion """ objname = obj.obj_name() db_version = db_object['version'] if not versionutils.is_compatible(db_version, obj.__class__.VERSION): raise ovo_exception.IncompatibleObjectVersion( objname=objname, objver=db_version, supported=obj.__class__.VERSION) obj._set_from_db_object(context, db_object, fields) obj._context = context # NOTE(rloo). We now have obj, a versioned object that corresponds to # its DB representation. A versioned object has an internal attribute # ._changed_fields; this is a list of changed fields -- used, e.g., # when saving the object to the DB (only those changed fields are # saved to the DB). The obj.obj_reset_changes() clears this list # since we didn't actually make any modifications to the object that # we want saved later. obj.obj_reset_changes() if db_version != obj.__class__.VERSION: # convert to the latest version obj.VERSION = db_version obj.convert_to_version(obj.__class__.VERSION, remove_unavailable_fields=False) return obj
def obj_class_from_name(cls, objname, objver): """Returns a class from the registry based on a name and version.""" # NOTE(slaweq): it is override method # oslo_versionedobjects.base.VersionedObject.obj_class_from_name # We need to override it to use Neutron's objects registry class # (NeutronObjectRegistry) instead of original VersionedObjectRegistry # class from oslo_versionedobjects # This is necessary to avoid clash in naming objects between Neutron # and e.g. os-vif (for example Route or Subnet objects are used in # both) if objname not in NeutronObjectRegistry.obj_classes(): LOG.error('Unable to instantiate unregistered object type ' '%(objtype)s', dict(objtype=objname)) raise obj_exception.UnsupportedObjectError(objtype=objname) # NOTE(comstud): If there's not an exact match, return the highest # compatible version. The objects stored in the class are sorted # such that highest version is first, so only set compatible_match # once below. compatible_match = None for objclass in NeutronObjectRegistry.obj_classes()[objname]: if objclass.VERSION == objver: return objclass if (not compatible_match and versionutils.is_compatible(objver, objclass.VERSION)): compatible_match = objclass if compatible_match: return compatible_match # As mentioned above, latest version is always first in the list. latest_ver = ( NeutronObjectRegistry.obj_classes()[objname][0].VERSION) raise obj_exception.IncompatibleObjectVersion(objname=objname, objver=objver, supported=latest_ver)
def test_requested_minor_less_than(self): self.assertTrue(versionutils.is_compatible('1.0', '1.1'))
def test_same_version(self): self.assertTrue(versionutils.is_compatible('1', '1')) self.assertTrue(versionutils.is_compatible('1.0', '1.0')) self.assertTrue(versionutils.is_compatible('1.0.0', '1.0.0'))
def _requires_backend_kind(version): # Fix for Bug #1502929 version_as_string = '.'.join(str(v) for v in version) return (versionutils.is_compatible('6.5', version_as_string))
def test_current_patch_not_present_same(self): self.assertTrue(versionutils.is_compatible('1.0.0', '1.0'))
def test_current_patch_not_present_less_than(self): self.assertFalse(versionutils.is_compatible('1.0.1', '1.0'))
def test_requested_patch_not_present_less_than(self): self.assertTrue(versionutils.is_compatible('1.0', '1.0.1'))
def test_requested_patch_greater(self): self.assertFalse(versionutils.is_compatible('1.0.1', '1.0.0'))
def _from_db_object(context, obj, db_object, fields=None): """Converts a database entity to a formal object. This always converts the database entity to the latest version of the object. Note that the latest version is available at object.__class__.VERSION. object.VERSION is the version of this particular object instance; it is possible that it is not the latest version. :param context: security context :param obj: An object of the class. :param db_object: A DB entity of the object :param fields: list of fields to set on obj from values from db_object. :return: The object of the class with the database entity added :raises: ovo_exception.IncompatibleObjectVersion """ objname = obj.obj_name() db_version = db_object['version'] if db_version is None: # NOTE(rloo): This can only happen after we've updated the DB # tables to include the 'version' column but haven't saved the # object to the DB since the new column was added. This column is # added in the Pike cycle, so if the version isn't set, use the # version associated with the most recent release, i.e. '8.0'. # The objects and RPC versions haven't changed between '8.0' and # Ocata, which is why it is fine to use Ocata. # Furthermore, if this is a new object that did not exist in the # most recent release, we assume it is version 1.0. # TODO(rloo): This entire if clause can be deleted in Queens # since the dbsync online migration populates all the versions # and it must be run to completion before upgrading to Queens. db_version = versions.RELEASE_MAPPING['ocata']['objects'].get( objname, '1.0') if not versionutils.is_compatible(db_version, obj.__class__.VERSION): raise ovo_exception.IncompatibleObjectVersion( objname=objname, objver=db_version, supported=obj.__class__.VERSION) obj._set_from_db_object(context, db_object, fields) obj._context = context # NOTE(rloo). We now have obj, a versioned object that corresponds to # its DB representation. A versioned object has an internal attribute # ._changed_fields; this is a list of changed fields -- used, e.g., # when saving the object to the DB (only those changed fields are # saved to the DB). The obj.obj_reset_changes() clears this list # since we didn't actually make any modifications to the object that # we want saved later. obj.obj_reset_changes() if db_version != obj.__class__.VERSION: # convert to the latest version obj.convert_to_version(obj.__class__.VERSION) if obj.get_target_version() == db_version: # pinned, so no need to keep these changes (we'll end up # converting back to db_version if obj is saved) obj.obj_reset_changes() else: # keep these changes around because they are needed # when/if saving to the DB in the latest version pass return obj
from oslo_utils import versionutils print(versionutils.convert_version_to_int('9.6.6')) print( versionutils.convert_version_to_str(9007000)) # every 3 bits is a number. print(versionutils.convert_version_to_str(90070000)) print(versionutils.convert_version_to_tuple('9.7.0')) print(versionutils.is_compatible('9.6.6', '9.7.0', same_major=True))