Merge "Do not register notification objects"

This commit is contained in:
Jenkins
2016-06-10 10:49:07 +00:00
committed by Gerrit Code Review
6 changed files with 56 additions and 22 deletions

View File

@@ -41,6 +41,7 @@ class VersionedNotificationDirective(Directive):
return self._build_markup(notifications) return self._build_markup(notifications)
def _collect_notifications(self): def _collect_notifications(self):
base.NovaObjectRegistry.register_notification_objects()
notifications = [] notifications = []
ovos = base.NovaObjectRegistry.obj_classes() ovos = base.NovaObjectRegistry.obj_classes()
for name, cls in ovos.items(): 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 To support the above contract from the Nova code every versioned notification
is modeled with oslo versionedobjects. Every versioned notification class 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`, already defines three mandatory fields of the notification `event_type`,
`publisher_id` and `priority`. The new notification class shall add a new field `publisher_id` and `priority`. The new notification class shall add a new field
`payload` with an appropriate payload type. The payload object of the `payload` with an appropriate payload type. The payload object of the
notifications shall inherit from the notifications shall inherit from the
`nova.objects.notification.NotificationPayloadBase` class and shall define the `nova.objects.notifications.base.NotificationPayloadBase` class and shall
fields of the payload as versionedobject fields. The base classes are described define the fields of the payload as versionedobject fields. The base classes
in [3]_. 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 The following code example defines the necessary model classes for a new
notification `myobject.update`:: notification `myobject.update`::
@notification.notification_sample('myobject-update.json') @notification.notification_sample('myobject-update.json')
@base.NovaObjectRegistry.register @object_base.NovaObjectRegistry.register.register_notification
class MyObjectNotification(notification.NotificationBase): class MyObjectNotification(notification.NotificationBase):
# Version 1.0: Initial version # Version 1.0: Initial version
VERSION = '1.0' VERSION = '1.0'
@@ -129,7 +134,7 @@ notification `myobject.update`::
} }
@base.NovaObjectRegistry.register @object_base.NovaObjectRegistry.register.register_notification
class MyObjectUpdatePayload(notification.NotificationPayloadBase): class MyObjectUpdatePayload(notification.NotificationPayloadBase):
# Version 1.0: Initial version # Version 1.0: Initial version
VERSION = '1.0' 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:: `nova.objects.service.Service` object when defines the notification's payload::
@notification.notification_sample('service-update.json') @notification.notification_sample('service-update.json')
@base.NovaObjectRegistry.register @object_base.NovaObjectRegistry.register.register_notification
class ServiceStatusNotification(notification.NotificationBase): class ServiceStatusNotification(notification.NotificationBase):
# Version 1.0: Initial version # Version 1.0: Initial version
VERSION = '1.0' VERSION = '1.0'
@@ -186,7 +191,7 @@ object. For example the service.status notification reuses the existing
'payload': fields.ObjectField('ServiceStatusPayload') 'payload': fields.ObjectField('ServiceStatusPayload')
} }
@base.NovaObjectRegistry.register @object_base.NovaObjectRegistry.register.register_notification
class ServiceStatusPayload(notification.NotificationPayloadBase): class ServiceStatusPayload(notification.NotificationPayloadBase):
SCHEMA = { SCHEMA = {
'host': ('service', 'host'), 'host': ('service', 'host'),

View File

@@ -12,14 +12,20 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from nova.objects import base from nova.objects import base
from nova.objects import fields from nova.objects import fields
from nova import rpc from nova import rpc
@base.NovaObjectRegistry.register @base.NovaObjectRegistry.register_if(False)
class EventType(base.NovaObject): 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: Initial version
VERSION = '1.0' VERSION = '1.0'
@@ -37,10 +43,8 @@ class EventType(base.NovaObject):
return s 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) @base.NovaObjectRegistry.register_if(False)
class NotificationPayloadBase(base.NovaObject): class NotificationPayloadBase(NotificationObject):
"""Base class for the payload of versioned notifications.""" """Base class for the payload of versioned notifications."""
# SCHEMA defines how to populate the payload fields. It is a dictionary # SCHEMA defines how to populate the payload fields. It is a dictionary
# where every key value pair has the following format: # where every key value pair has the following format:
@@ -81,8 +85,8 @@ class NotificationPayloadBase(base.NovaObject):
self.populated = True self.populated = True
@base.NovaObjectRegistry.register @base.NovaObjectRegistry.register_notification
class NotificationPublisher(base.NovaObject): class NotificationPublisher(NotificationObject):
# Version 1.0: Initial version # Version 1.0: Initial version
VERSION = '1.0' VERSION = '1.0'
@@ -96,10 +100,8 @@ class NotificationPublisher(base.NovaObject):
return cls(host=service.host, binary=service.binary) 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) @base.NovaObjectRegistry.register_if(False)
class NotificationBase(base.NovaObject): class NotificationBase(NotificationObject):
"""Base class for versioned notifications. """Base class for versioned notifications.
Every subclass shall define a 'payload' field. Every subclass shall define a 'payload' field.

View File

@@ -14,12 +14,12 @@
# under the License. # under the License.
from nova.notifications.objects import base 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 from nova.objects import fields
@base.notification_sample('service-update.json') @base.notification_sample('service-update.json')
@object_base.NovaObjectRegistry.register @nova_base.NovaObjectRegistry.register_notification
class ServiceStatusNotification(base.NotificationBase): class ServiceStatusNotification(base.NotificationBase):
# Version 1.0: Initial version # Version 1.0: Initial version
VERSION = '1.0' VERSION = '1.0'
@@ -29,7 +29,7 @@ class ServiceStatusNotification(base.NotificationBase):
} }
@object_base.NovaObjectRegistry.register @nova_base.NovaObjectRegistry.register_notification
class ServiceStatusPayload(base.NotificationPayloadBase): class ServiceStatusPayload(base.NotificationPayloadBase):
SCHEMA = { SCHEMA = {
'host': ('service', 'host'), 'host': ('service', 'host'),

View File

@@ -40,6 +40,8 @@ def get_attrname(name):
class NovaObjectRegistry(ovoo_base.VersionedObjectRegistry): class NovaObjectRegistry(ovoo_base.VersionedObjectRegistry):
notification_classes = []
def registration_hook(self, cls, index): def registration_hook(self, cls, index):
# NOTE(danms): This is called when an object is registered, # NOTE(danms): This is called when an object is registered,
# and is responsible for maintaining nova.objects.$OBJECT # and is responsible for maintaining nova.objects.$OBJECT
@@ -53,6 +55,25 @@ class NovaObjectRegistry(ovoo_base.VersionedObjectRegistry):
if version >= cur_version: if version >= cur_version:
setattr(objects, cls.obj_name(), cls) 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_classmethod = ovoo_base.remotable_classmethod
remotable = ovoo_base.remotable remotable = ovoo_base.remotable

View File

@@ -1209,6 +1209,11 @@ object_data = {
class TestObjectVersions(test.NoDBTestCase): class TestObjectVersions(test.NoDBTestCase):
def setUp(self):
super(test.NoDBTestCase, self).setUp()
base.NovaObjectRegistry.register_notification_objects()
def test_versions(self): def test_versions(self):
checker = fixture.ObjectVersionChecker( checker = fixture.ObjectVersionChecker(
base.NovaObjectRegistry.obj_classes()) base.NovaObjectRegistry.obj_classes())