diff --git a/doc/ext/versioned_notifications.py b/doc/ext/versioned_notifications.py new file mode 100644 index 0000000000..5f7fe5ed18 --- /dev/null +++ b/doc/ext/versioned_notifications.py @@ -0,0 +1,112 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +This provides a sphinx extension able to list the implemented versioned +notifications into the developer documentation. + +It is used via a single directive in the .rst file + + .. versioned_notifications:: + +""" + +from sphinx.util.compat import Directive +from docutils import nodes + +from nova.objects import base +from nova.objects import notification + + +def full_name(cls): + return cls.__module__ + '.' + cls.__name__ + + +class VersionedNotificationDirective(Directive): + + LINK_PREFIX = 'https://git.openstack.org/cgit/openstack/nova/plain/' + SAMPLE_ROOT = 'doc/notification_samples/' + + def run(self): + notifications = self._collect_notifications() + return self._build_markup(notifications) + + def _collect_notifications(self): + notifications = [] + ovos = base.NovaObjectRegistry.obj_classes() + for name, cls in ovos.items(): + cls = cls[0] + if (issubclass(cls, notification.NotificationBase) and + cls != notification.NotificationBase): + + payload_name = cls.fields['payload'].objname + payload_cls = ovos[payload_name][0] + + notifications.append((full_name(cls), full_name(payload_cls), + cls.sample)) + return notifications + + def _build_markup(self, notifications): + content = [] + cols = ['Notification class', 'Payload class', 'Sample file link'] + table = nodes.table() + content.append(table) + group = nodes.tgroup(cols=len(cols)) + table.append(group) + + head = nodes.thead() + group.append(head) + + for i in range(len(cols)): + group.append(nodes.colspec(colwidth=1)) + + body = nodes.tbody() + group.append(body) + + # fill the table header + row = nodes.row() + body.append(row) + for col_name in cols: + col = nodes.entry() + row.append(col) + text = nodes.strong(text=col_name) + col.append(text) + + # fill the table content, one notification per row + for name, payload, sample in notifications: + row = nodes.row() + body.append(row) + col = nodes.entry() + row.append(col) + text = nodes.literal(text=name) + col.append(text) + + col = nodes.entry() + row.append(col) + text = nodes.literal(text=payload) + col.append(text) + + col = nodes.entry() + row.append(col) + ref = nodes.reference(refuri=self.LINK_PREFIX + + self.SAMPLE_ROOT + sample) + txt = nodes.inline() + col.append(txt) + txt.append(ref) + ref.append(nodes.literal(text=sample)) + + return content + + +def setup(app): + app.add_directive('versioned_notifications', + VersionedNotificationDirective) diff --git a/doc/source/conf.py b/doc/source/conf.py index 797b09cbac..af23503ad2 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -35,6 +35,7 @@ extensions = ['sphinx.ext.autodoc', 'oslosphinx', "ext.support_matrix", 'oslo_config.sphinxconfiggen', + 'ext.versioned_notifications' ] config_generator_config_file = '../../etc/nova/nova-config-generator.conf' diff --git a/doc/source/notifications.rst b/doc/source/notifications.rst index 8396e9d8e1..f8d6579783 100644 --- a/doc/source/notifications.rst +++ b/doc/source/notifications.rst @@ -98,6 +98,10 @@ notification payload: * a major version bump indicates a backward incompatible change of the payload which can mean removed fields, type change, etc in the payload. +There is a Nova configuration parameter `notification_format` that can be used +to specify which notifications are emitted by Nova. The possible values are +`unversioned`, `versioned`, `both` and the default value is `both`. + How to add a new versioned notification ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -115,6 +119,7 @@ in [3]_. The following code example defines the necessary model classes for a new notification `myobject.update`:: + @notification.notification_sample('myobject-update.json') @base.NovaObjectRegistry.register class MyObjectNotification(notification.NotificationBase): # Version 1.0: Initial version @@ -172,6 +177,7 @@ between the fields of existing objects and the fields of the new payload 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 class ServiceStatusNotification(notification.NotificationBase): # Version 1.0: Initial version @@ -181,7 +187,6 @@ object. For example the service.status notification reuses the existing 'payload': fields.ObjectField('ServiceStatusPayload') } - @base.NovaObjectRegistry.register class ServiceStatusPayload(notification.NotificationPayloadBase): SCHEMA = { @@ -254,9 +259,18 @@ with a `host` and a `binary` string parameter or it can be generated from a `Service` object by calling `NotificationPublisher.from_service_obj` function. Versioned notifications shall have a sample file stored under -`doc/sample_notifications` directory. For example the `service.update` -notification has a sample file stored in -`doc/sample_notifications/service-update.json`. +`doc/sample_notifications` directory and the notification object shall be +decorated with the `notification_sample` decorator. For example the +`service.update` notification has a sample file stored in +`doc/sample_notifications/service-update.json` and the +ServiceUpdateNotification class is decorated accordingly. + +Existing versioned notifications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versioned_notifications:: + + .. [1] http://docs.openstack.org/developer/oslo.messaging/notifier.html .. [2] http://docs.openstack.org/developer/oslo.versionedobjects diff --git a/nova/objects/notification.py b/nova/objects/notification.py index 79b90c62c2..40533eac33 100644 --- a/nova/objects/notification.py +++ b/nova/objects/notification.py @@ -134,3 +134,17 @@ class NotificationBase(base.NovaObject): (self.publisher.binary, self.publisher.host), payload=self.payload.obj_to_primitive()) + + +def notification_sample(sample): + """Class decorator to attach the notification sample information + to the notification object for documentation generation purposes. + + :param sample: the path of the sample json file relative to the + doc/notification_samples/ directory in the nova repository + root. + """ + def wrap(cls): + cls.sample = sample + return cls + return wrap diff --git a/nova/objects/service.py b/nova/objects/service.py index cf95414d2d..6bbff98914 100644 --- a/nova/objects/service.py +++ b/nova/objects/service.py @@ -393,6 +393,7 @@ class ServiceList(base.ObjectListBase, base.NovaObject): db_services) +@notification.notification_sample('service-update.json') @base.NovaObjectRegistry.register class ServiceStatusNotification(notification.NotificationBase): # Version 1.0: Initial version diff --git a/releasenotes/notes/service-status-notification-e137297f5d5aa45d.yaml b/releasenotes/notes/service-status-notification-e137297f5d5aa45d.yaml index 535492967d..d5a9a31d86 100644 --- a/releasenotes/notes/service-status-notification-e137297f5d5aa45d.yaml +++ b/releasenotes/notes/service-status-notification-e137297f5d5aa45d.yaml @@ -4,4 +4,6 @@ features: When the status of the Service object is changed nova will send a new service.update notification with versioned payload according to bp versioned-notification-api. + The new notification is documented in + http://docs.openstack.org/developer/nova/notifications.html diff --git a/releasenotes/notes/versioned-notifications-423f4d8d2a3992c6.yaml b/releasenotes/notes/versioned-notifications-423f4d8d2a3992c6.yaml index d290494598..413e08930b 100644 --- a/releasenotes/notes/versioned-notifications-423f4d8d2a3992c6.yaml +++ b/releasenotes/notes/versioned-notifications-423f4d8d2a3992c6.yaml @@ -5,3 +5,5 @@ features: which notification format shall be used by nova. The possible values are 'unversioned' (e.g. legacy), 'versioned', 'both'. The default value is 'both'. + The new versioned notifications are documented in + http://docs.openstack.org/developer/nova/notifications.html