oslo_versionedobjects.base

Common internal object model

class oslo_versionedobjects.base.ComparableVersionedObject

Mix-in to provide comparison methods

When objects are to be compared with each other (in tests for example), this mixin can be used.

class oslo_versionedobjects.base.ObjectListBase(*args: Any, **kwargs: Any)

Mixin class for lists of objects.

This mixin class can be added as a base class for an object that is implementing a list of objects. It adds a single field of ‘objects’, which is the list store, and behaves like a list itself. It supports serialization of the list of objects automatically.

class oslo_versionedobjects.base.TimestampedObject

Mixin class for db backed objects with timestamp fields.

Sqlalchemy models that inherit from the oslo_db TimestampMixin will include these fields and the corresponding objects will benefit from this mixin.

class oslo_versionedobjects.base.VersionedObject(context: Any = None, **kwargs: Any)

Base class and object factory.

This forms the base of all objects that can be remoted or instantiated via RPC. Simply defining a class that inherits from this base class will make it remotely instantiatable. Objects should implement the necessary “get” classmethod routines as well as “save” object methods as appropriate.

OBJ_PROJECT_NAMESPACE: str = 'versionedobjects'

Object project namespace for serialization

This is used to disambiguate owners of objects sharing a common RPC medium.

OBJ_SERIAL_NAMESPACE: str = 'versioned_object'

Object namespace for serialization

This should generally not be changed, but is needed for backwards compatibility

VERSION: str = '1.0'

Object version field

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.

This version is allowed to have three parts, X.Y.Z, where the .Z element is reserved for stable branch backports. The .Z is ignored for the purposes of triggering a backport, which means anything changed under a .Z must be additive and non-destructive such that a node that knows about X.Y can consider X.Y.Z equivalent.

fields: MutableMapping[str, Field[Any]] = {}

The fields present in this object as key:field pairs.

For example:

fields = {
    'foo': obj_fields.IntegerField(),
    'bar': obj_fields.StringField(),
}
obj_attr_is_set(attrname: str) bool

Test object to see if attrname is present.

Returns True if the named attribute has a value set, or False if not. Raises AttributeError if attrname is not a valid attribute for this object.

classmethod obj_class_from_name(objname: str, objver: str) type[VersionedObject]

Returns a class from the registry based on a name and version.

obj_clone() Self

Create a copy.

obj_extra_fields: Sequence[str] = []

List of additional object attributes to expose alongside fields.

Names listed here are typically implemented as Python properties and are included in obj_fields and exposed through iteration, but they are not versioned and not serialized during RPC:

class MyObject(VersionedObject):
    fields = {'foo': obj_fields.IntegerField()}
    obj_extra_fields = ['bar']

    @property
    def bar(self):
        return self.foo * 2
classmethod obj_from_primitive(primitive: dict[str, Any], context: Any = None) Self

Object field-by-field hydration.

obj_get_changes() dict[str, Any]

Returns a dict of changed fields and their new values.

obj_load_attr(attrname: str) None

Load an additional attribute from the real object.

This should load self.$attrname and cache any data that might be useful for future load operations.

obj_make_compatible(primitive: dict[str, Any], target_version: str) None

Make an object representation compatible with a target version.

This is responsible for taking the primitive representation of an object and making it suitable for the given target_version. This may mean converting the format of object attributes, removing attributes that have been added since the target version, etc. In general:

  • If a new version of an object adds a field, this routine should remove it for older versions.

  • If a new version changed or restricted the format of a field, this should convert it back to something a client knowing only of the older version will tolerate.

  • If an object that this object depends on is bumped, then this object should also take a version bump. Then, this routine should backlevel the dependent object (by calling its obj_make_compatible()) if the requested version of this object is older than the version where the new dependent object was added.

Parameters:
  • primitive – The result of obj_to_primitive()

  • target_version – The version string requested by the recipient of the object

Raises:

oslo_versionedobjects.exception.UnsupportedObjectError if conversion is not possible for some reason

classmethod obj_name() str

Return the object’s name.

Return a canonical name for this object which will be used over the wire for remote hydration.

obj_relationships: dict[str, list[tuple[str, str]]] = {}

Table of sub-object versioning information

This contains a list of version mappings, by the field name of the subobject. The mappings must be in order of oldest to newest, and are tuples of (my_version, subobject_version). A request to backport this object to my_version will cause the subobject to be backported to subobject_version:

obj_relationships = {
    'subobject1': [('1.2', '1.1'), ('1.4', '1.2')],
    'subobject2': [('1.2', '1.0')],
}

In the above example:

  • If we are asked to backport our object to version 1.3, subobject1 will be backported to version 1.1, since it was bumped to version 1.2 when our version was 1.4.

  • If we are asked to backport our object to version 1.5, no changes will be made to subobject1 or subobject2, since they have not changed since version 1.4.

  • If we are asked to backlevel our object to version 1.1, we will remove both subobject1 and subobject2 from the primitive, since they were not added until version 1.2.

obj_reset_changes(fields: list[str] | None = None, recursive: bool = False) None

Reset the list of fields that have been changed.

Parameters:
  • fields – List of fields to reset, or “all” if None.

  • recursive – Call obj_reset_changes(recursive=True) on any sub-objects within the list of fields being reset.

This is NOT “revert to previous values”.

Specifying fields on recursive resets will only be honored at the top level. Everything below the top will reset all.

obj_to_primitive(target_version: str | None = None, version_manifest: dict[str, str] | None = None) dict[str, Any]

Simple base-case dehydration.

This calls to_primitive() for each item in fields.

obj_what_changed() set[str]

Returns a set of fields that have been modified.

save() None

Save the changed fields back to the store.

This is optional for subclasses, but is presented here in the base class for consistency among those that do.

class oslo_versionedobjects.base.VersionedObjectDictCompat

Mix-in to provide dictionary key access compatibility

If an object needs to support attribute access using dictionary items instead of object attributes, inherit from this class. This should only be used as a temporary measure until all callers are converted to use modern attribute access.

class oslo_versionedobjects.base.VersionedObjectMixin

Marker base class for OVO mixin classes that contribute fields.

Mixin classes that define an OVO fields dict should inherit from this class so that the oslo_versionedobjects.mypy plugin can discover and type-check their fields in the same way it handles registered VersionedObject subclasses.

Example:

class MyFieldsMixin(VersionedObjectMixin):
    fields: MutableMapping[str, fields.Field[Any]] = {
        'name': fields.StringField(),
    }


@base.VersionedObjectRegistry.register
class MyObject(MyFieldsMixin, base.VersionedObject):
    VERSION = '1.0'
    fields = {
        'count': fields.IntegerField(),
    }
class oslo_versionedobjects.base.VersionedObjectSerializer

A VersionedObject-aware Serializer.

This implements the Oslo Serializer interface and provides the ability to serialize and deserialize VersionedObject entities. Any service that needs to accept or return VersionedObjects as arguments or result values should pass this to its RPCClient and RPCServer objects.

OBJ_BASE_CLASS

alias of VersionedObject

deserialize_entity(context: Any, entity: Any) Any

Deserialize something from primitive form.

Parameters:
  • ctxt – Request context, in deserialized form

  • entity – Primitive to be deserialized

Returns:

Deserialized form of entity

serialize_entity(context: Any, entity: Any) Any

Serialize something to primitive form.

Parameters:
  • ctxt – Request context, in deserialized form

  • entity – Entity to be serialized

Returns:

Serialized form of entity

oslo_versionedobjects.base.obj_make_list(context: Any, list_obj: ObjectListBase[_VO], item_cls: type[_VO], db_list: list[dict[str, Any]], **extra_args: Any) ObjectListBase[_VO]

Construct an object list from a list of primitives.

This calls item_cls._from_db_object() on each item of db_list, and adds the resulting object to list_obj.

Param:context:

Request context

Param:list_obj:

An ObjectListBase object

Param:item_cls:

The VersionedObject class of the objects within the list

Param:db_list:

The list of primitives to convert to objects

Param:extra_args:

Extra arguments to pass to _from_db_object()

Returns:

list_obj

oslo_versionedobjects.base.obj_tree_get_versions(objname: str, tree: dict[str, str] | None = None) dict[str, str]

Construct a mapping of dependent object versions.

This method builds a list of dependent object versions given a top- level object with other objects as fields. It walks the tree recursively to determine all the objects (by symbolic name) that could be contained within the top-level object, and the maximum versions of each. The result is a dict like:

{'MyObject': '1.23', ... }
Parameters:
  • objname – The top-level object at which to start

  • tree – Used internally, pass None here.

Returns:

A dictionary of object names and versions

oslo_versionedobjects.base.remotable(fn: Callable[[Concatenate[_VO, P]], R]) Callable[[Concatenate[_VO, P]], R]
oslo_versionedobjects.base.remotable(fn: Callable[[Concatenate[type[_VO], P]], R]) Callable[[Concatenate[type[_VO], P]], R]

Decorator for remotable object methods.

oslo_versionedobjects.base.remotable_classmethod(fn: Callable[Concatenate[type[_VO], P], R]) classmethod[_VO, P, R]

Decorator for remotable classmethods.

Deprecated since version Use: @classmethod combined with @remotable instead::

@classmethod @remotable def my_method(cls, context): …