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_make_compatible(self, primitive, target_version): LOG.info('%s(): caller(): %s', log_utils.get_fname(1), log_utils.get_fname(2)) _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version < (1, 3): raise exception.IncompatibleObjectVersion( objver=target_version, objtype=self.__class__.__name__)
def obj_make_compatible(self, primitive, target_version): _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version >= (1, 1): if primitive['mtu'] is None: # mtu will not be nullable after raise exception.IncompatibleObjectVersion( objver=target_version, objname=self.__class__.__name__)
def obj_make_compatible(self, primitive, target_version): _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version < (1, 3) and 'direction' in primitive: direction = primitive.pop('direction') if direction == constants.INGRESS_DIRECTION: raise exception.IncompatibleObjectVersion( objver=target_version, objtype="QosBandwidthLimitRule")
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_make_compatible(self, primitive, target_version): def filter_rules(obj_names, rules): return [rule for rule in rules if rule['versioned_object.name'] in obj_names] _target_version = versionutils.convert_version_to_tuple(target_version) names = [] if _target_version >= (1, 0): names.append(rule_obj_impl.QosBandwidthLimitRule.obj_name()) if _target_version >= (1, 1): names.append(rule_obj_impl.QosDscpMarkingRule.obj_name()) if _target_version >= (1, 2): names.append(rule_obj_impl.QosMinimumBandwidthRule.obj_name()) if 'rules' in primitive and names: primitive['rules'] = filter_rules(names, primitive['rules']) if _target_version < (1, 3): standard_fields = ['revision_number', 'created_at', 'updated_at'] for f in standard_fields: primitive.pop(f) if primitive['description'] is None: # description was not nullable before raise exception.IncompatibleObjectVersion( objver=target_version, objname='QoSPolicy') if _target_version < (1, 4): primitive['tenant_id'] = primitive.pop('project_id')
def obj_make_compatible(self, primitive, target_version): LOG.info('%s(): caller(): %s', log_utils.get_fname(1), log_utils.get_fname(2)) _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version >= (1, 1): if primitive['mtu'] is None: # mtu will not be nullable after raise exception.IncompatibleObjectVersion( objver=target_version, objname=self.__class__.__name__)
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 obj_make_compatible(self, primitive, target_version): def filter_rules(obj_names, rules): return [ rule for rule in rules if rule['versioned_object.name'] in obj_names ] def filter_ingress_bandwidth_limit_rules(rules): bwlimit_obj_name = rule_obj_impl.QosBandwidthLimitRule.obj_name() filtered_rules = [] for rule in rules: if rule['versioned_object.name'] == bwlimit_obj_name: direction = rule['versioned_object.data'].get("direction") if direction == n_const.EGRESS_DIRECTION: rule['versioned_object.data'].pop('direction') filtered_rules.append(rule) else: filtered_rules.append(rule) return filtered_rules _target_version = versionutils.convert_version_to_tuple(target_version) names = [] if _target_version >= (1, 0): names.append(rule_obj_impl.QosBandwidthLimitRule.obj_name()) if _target_version >= (1, 1): names.append(rule_obj_impl.QosDscpMarkingRule.obj_name()) if _target_version >= (1, 2): names.append(rule_obj_impl.QosMinimumBandwidthRule.obj_name()) if 'rules' in primitive and names: primitive['rules'] = filter_rules(names, primitive['rules']) if _target_version < (1, 3): standard_fields = ['revision_number', 'created_at', 'updated_at'] for f in standard_fields: primitive.pop(f) if primitive['description'] is None: # description was not nullable before raise exception.IncompatibleObjectVersion( objver=target_version, objname='QoSPolicy') if _target_version < (1, 4): primitive['tenant_id'] = primitive.pop('project_id') if _target_version < (1, 5): if 'rules' in primitive: primitive['rules'] = filter_ingress_bandwidth_limit_rules( primitive['rules']) if _target_version < (1, 6): primitive.pop('is_default', None)
def obj_make_compatible(self, primitive, target_version): def filter_rules(obj_names, rules): return [rule for rule in rules if rule['versioned_object.name'] in obj_names] _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version < (1, 8): raise exception.IncompatibleObjectVersion( objver=target_version, objname=self.__class__.__name__) names = [ rule_obj_impl.QosBandwidthLimitRule.obj_name(), rule_obj_impl.QosDscpMarkingRule.obj_name(), rule_obj_impl.QosMinimumBandwidthRule.obj_name(), ] if _target_version >= (1, 9): names.append(rule_obj_impl.QosPacketRateLimitRule.obj_name()) if 'rules' in primitive and names: primitive['rules'] = filter_rules(names, primitive['rules'])
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 obj_make_compatible(self, primitive, target_version): _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version < (1, 2): raise exception.IncompatibleObjectVersion( objver=target_version, objname="QosMinimumBandwidthRule")
def obj_make_compatible(self, primitive, target_version): _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version < (1, 1): raise exception.IncompatibleObjectVersion( objver=target_version, objname="QosDscpMarkingRule")
def obj_make_compatible(self, primitive, target_version): _target_version = versionutils.convert_version_to_tuple(target_version) if _target_version < (1, 3): raise exception.IncompatibleObjectVersion( objver=target_version, objtype=self.__class__.__name__)
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