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
This commit is contained in:
Balazs Gibizer 2016-04-22 15:31:54 +02:00
parent cdfecc65e7
commit 520ee65a55
6 changed files with 56 additions and 22 deletions

View File

@ -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():

View File

@ -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'),

View File

@ -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.

View File

@ -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'),

View File

@ -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

View File

@ -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())