From 520ee65a55bf9894d5915d3cebc892439d703312 Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Fri, 22 Apr 2016 15:31:54 +0200 Subject: [PATCH] Do not register notification objects Only registering the notification objects during unit test. Notification objects are never used in the Nova RPC interface and shall not be mixed with such objects. Change-Id: Iba9079bb204e6ef1302529ac159199ab9fa6272b --- doc/ext/versioned_notifications.py | 1 + doc/source/notifications.rst | 21 +++++++++++++-------- nova/notifications/objects/base.py | 24 +++++++++++++----------- nova/notifications/objects/service.py | 6 +++--- nova/objects/base.py | 21 +++++++++++++++++++++ nova/tests/unit/objects/test_objects.py | 5 +++++ 6 files changed, 56 insertions(+), 22 deletions(-) diff --git a/doc/ext/versioned_notifications.py b/doc/ext/versioned_notifications.py index 795ed59d141d..38e0e4875e6f 100644 --- a/doc/ext/versioned_notifications.py +++ b/doc/ext/versioned_notifications.py @@ -41,6 +41,7 @@ class VersionedNotificationDirective(Directive): return self._build_markup(notifications) def _collect_notifications(self): + base.NovaObjectRegistry.register_notification_objects() notifications = [] ovos = base.NovaObjectRegistry.obj_classes() for name, cls in ovos.items(): diff --git a/doc/source/notifications.rst b/doc/source/notifications.rst index 5d362dfb31a0..d9d6aae4527c 100644 --- a/doc/source/notifications.rst +++ b/doc/source/notifications.rst @@ -106,20 +106,25 @@ How to add a new versioned notification To support the above contract from the Nova code every versioned notification is modeled with oslo versionedobjects. Every versioned notification class -shall inherit from the `nova.objects.notification.NotificationBase` which +shall inherit from the `nova.notifications.objects.base.NotificationBase` which already defines three mandatory fields of the notification `event_type`, `publisher_id` and `priority`. The new notification class shall add a new field `payload` with an appropriate payload type. The payload object of the notifications shall inherit from the -`nova.objects.notification.NotificationPayloadBase` class and shall define the -fields of the payload as versionedobject fields. The base classes are described -in [3]_. +`nova.objects.notifications.base.NotificationPayloadBase` class and shall +define the fields of the payload as versionedobject fields. The base classes +are described in [3]_. + +Please note that the notification objects shall not be registered to the +NovaObjectRegistry to avoid mixing nova internal objects with the notification +objects. Instead of that use the register_notification decorator on every +concrete notification object. The following code example defines the necessary model classes for a new notification `myobject.update`:: @notification.notification_sample('myobject-update.json') - @base.NovaObjectRegistry.register + @object_base.NovaObjectRegistry.register.register_notification class MyObjectNotification(notification.NotificationBase): # Version 1.0: Initial version VERSION = '1.0' @@ -129,7 +134,7 @@ notification `myobject.update`:: } - @base.NovaObjectRegistry.register + @object_base.NovaObjectRegistry.register.register_notification class MyObjectUpdatePayload(notification.NotificationPayloadBase): # Version 1.0: Initial version VERSION = '1.0' @@ -177,7 +182,7 @@ object. For example the service.status notification reuses the existing `nova.objects.service.Service` object when defines the notification's payload:: @notification.notification_sample('service-update.json') - @base.NovaObjectRegistry.register + @object_base.NovaObjectRegistry.register.register_notification class ServiceStatusNotification(notification.NotificationBase): # Version 1.0: Initial version VERSION = '1.0' @@ -186,7 +191,7 @@ object. For example the service.status notification reuses the existing 'payload': fields.ObjectField('ServiceStatusPayload') } - @base.NovaObjectRegistry.register + @object_base.NovaObjectRegistry.register.register_notification class ServiceStatusPayload(notification.NotificationPayloadBase): SCHEMA = { 'host': ('service', 'host'), diff --git a/nova/notifications/objects/base.py b/nova/notifications/objects/base.py index 40533eac3334..6cd8b6cbfc92 100644 --- a/nova/notifications/objects/base.py +++ b/nova/notifications/objects/base.py @@ -12,14 +12,20 @@ # License for the specific language governing permissions and limitations # under the License. - from nova.objects import base from nova.objects import fields from nova import rpc -@base.NovaObjectRegistry.register -class EventType(base.NovaObject): +@base.NovaObjectRegistry.register_if(False) +class NotificationObject(base.NovaObject): + """Base class for every notification related versioned object.""" + # Version 1.0: Initial version + VERSION = '1.0' + + +@base.NovaObjectRegistry.register_notification +class EventType(NotificationObject): # Version 1.0: Initial version VERSION = '1.0' @@ -37,10 +43,8 @@ class EventType(base.NovaObject): return s -# Note(gibi): It is explicitly not registered as this class shall not be used -# directly, it is just a base class for notification payloads. @base.NovaObjectRegistry.register_if(False) -class NotificationPayloadBase(base.NovaObject): +class NotificationPayloadBase(NotificationObject): """Base class for the payload of versioned notifications.""" # SCHEMA defines how to populate the payload fields. It is a dictionary # where every key value pair has the following format: @@ -81,8 +85,8 @@ class NotificationPayloadBase(base.NovaObject): self.populated = True -@base.NovaObjectRegistry.register -class NotificationPublisher(base.NovaObject): +@base.NovaObjectRegistry.register_notification +class NotificationPublisher(NotificationObject): # Version 1.0: Initial version VERSION = '1.0' @@ -96,10 +100,8 @@ class NotificationPublisher(base.NovaObject): return cls(host=service.host, binary=service.binary) -# Note(gibi): It is explicitly not registered as this class shall not be used -# directly, it is just a base class for notification. @base.NovaObjectRegistry.register_if(False) -class NotificationBase(base.NovaObject): +class NotificationBase(NotificationObject): """Base class for versioned notifications. Every subclass shall define a 'payload' field. diff --git a/nova/notifications/objects/service.py b/nova/notifications/objects/service.py index 887dc139e247..61480e1aa086 100644 --- a/nova/notifications/objects/service.py +++ b/nova/notifications/objects/service.py @@ -14,12 +14,12 @@ # under the License. from nova.notifications.objects import base -from nova.objects import base as object_base +from nova.objects import base as nova_base from nova.objects import fields @base.notification_sample('service-update.json') -@object_base.NovaObjectRegistry.register +@nova_base.NovaObjectRegistry.register_notification class ServiceStatusNotification(base.NotificationBase): # Version 1.0: Initial version VERSION = '1.0' @@ -29,7 +29,7 @@ class ServiceStatusNotification(base.NotificationBase): } -@object_base.NovaObjectRegistry.register +@nova_base.NovaObjectRegistry.register_notification class ServiceStatusPayload(base.NotificationPayloadBase): SCHEMA = { 'host': ('service', 'host'), diff --git a/nova/objects/base.py b/nova/objects/base.py index cf938ab24ef5..1cf1693c666c 100644 --- a/nova/objects/base.py +++ b/nova/objects/base.py @@ -40,6 +40,8 @@ def get_attrname(name): class NovaObjectRegistry(ovoo_base.VersionedObjectRegistry): + notification_classes = [] + def registration_hook(self, cls, index): # NOTE(danms): This is called when an object is registered, # and is responsible for maintaining nova.objects.$OBJECT @@ -53,6 +55,25 @@ class NovaObjectRegistry(ovoo_base.VersionedObjectRegistry): if version >= cur_version: setattr(objects, cls.obj_name(), cls) + @classmethod + def register_notification(cls, notification_cls): + """Register a class as notification. + Use only to register concrete notification or payload classes, + do not register base classes intended for inheritance only. + """ + cls.register_if(False)(notification_cls) + cls.notification_classes.append(notification_cls) + return notification_cls + + @classmethod + def register_notification_objects(cls): + """Register previously decorated notification as normal ovos. + This is not intended for production use but only for testing and + document generation purposes. + """ + for notification_cls in cls.notification_classes: + cls.register(notification_cls) + remotable_classmethod = ovoo_base.remotable_classmethod remotable = ovoo_base.remotable diff --git a/nova/tests/unit/objects/test_objects.py b/nova/tests/unit/objects/test_objects.py index 17aee10ccf32..f97a1aa06819 100644 --- a/nova/tests/unit/objects/test_objects.py +++ b/nova/tests/unit/objects/test_objects.py @@ -1209,6 +1209,11 @@ object_data = { class TestObjectVersions(test.NoDBTestCase): + + def setUp(self): + super(test.NoDBTestCase, self).setUp() + base.NovaObjectRegistry.register_notification_objects() + def test_versions(self): checker = fixture.ObjectVersionChecker( base.NovaObjectRegistry.obj_classes())