diff options
-rw-r--r-- | doc/source/dev/notifications.rst | 20 | ||||
-rw-r--r-- | ironic/common/exception.py | 5 | ||||
-rw-r--r-- | ironic/objects/fields.py | 4 | ||||
-rw-r--r-- | ironic/objects/notification.py | 17 | ||||
-rw-r--r-- | ironic/tests/unit/objects/test_notification.py | 29 | ||||
-rw-r--r-- | ironic/tests/unit/objects/test_objects.py | 2 |
6 files changed, 55 insertions, 22 deletions
diff --git a/doc/source/dev/notifications.rst b/doc/source/dev/notifications.rst index 9cc249be9..aee82e5bf 100644 --- a/doc/source/dev/notifications.rst +++ b/doc/source/dev/notifications.rst @@ -147,14 +147,24 @@ in the ironic notification base classes) and emit it:: notify = ExampleNotification( event_type=notification.EventType(object='example_obj', - action='do_something', phase='start'), + action='do_something', status='start'), publisher=notification.NotificationPublisher(service='conductor', host='cond-hostname01'), level=fields.NotificationLevel.DEBUG, payload=my_notify_payload) notify.emit(context) -This will send the following notification over the message bus:: +When specifying the event_type, ``object`` will specify the object being acted +on, ``action`` will be a string describing what action is being performed on +that object, and ``status`` will be one of "start", "end", "fail", or +"success". "start" and "end" are used to indicate when actions that are not +immediate begin and succeed. "success" is used to indicate when actions that +are immediate succeed. "fail" is used to indicate when any type of action +fails, regardless of whether it's immediate or not. As a result of specifying +these parameters, event_type will be formatted as +``baremetal.<object>.<action>.<status>`` on the message bus. + +This example will send the following notification over the message bus:: { "priority": "debug", @@ -171,6 +181,12 @@ This will send the following notification over the message bus:: "publisher_id":"conductor.cond-hostname01" } +Existing notifications +---------------------- + +Descriptions of notifications emitted by ironic will be documented here when +they are added. + .. [1] http://docs.openstack.org/developer/oslo.messaging/notifier.html .. [2] http://docs.openstack.org/developer/oslo.versionedobjects .. [3] https://wiki.openstack.org/wiki/LoggingStandards#Log_level_definitions diff --git a/ironic/common/exception.py b/ironic/common/exception.py index 4352ee8bc..ce3654de8 100644 --- a/ironic/common/exception.py +++ b/ironic/common/exception.py @@ -611,6 +611,11 @@ class IncompleteLookup(Invalid): "is required") +class NotificationEventTypeError(IronicException): + _msg_fmt = _('Expected "status" to be one of "start", "end", ' + '"error", or "success", but got "%(status)s"') + + class NotificationSchemaObjectError(IronicException): _msg_fmt = _("Expected object %(obj)s when populating notification payload" " but got object %(source)s") diff --git a/ironic/objects/fields.py b/ironic/objects/fields.py index a61ccff7d..f3ce4a303 100644 --- a/ironic/objects/fields.py +++ b/ironic/objects/fields.py @@ -102,6 +102,10 @@ class FlexibleDictField(object_fields.AutoTypedField): super(FlexibleDictField, self)._null(obj, attr) +class EnumField(object_fields.EnumField): + pass + + class NotificationLevel(object_fields.Enum): DEBUG = 'debug' INFO = 'info' diff --git a/ironic/objects/notification.py b/ironic/objects/notification.py index 5dcb009bb..730d2d02b 100644 --- a/ironic/objects/notification.py +++ b/ironic/objects/notification.py @@ -35,22 +35,25 @@ class EventType(base.IronicObject): """Defines the event_type to be sent on the wire. An EventType must specify the object being acted on, a string describing - the action being taken on the notification, and the phase of the action, - if applicable. + the action being taken on the notification, and the status of the action. """ # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: "phase" field was renamed to "status" and only accepts + # "start", "end", "error", or "success" as valid + VERSION = '1.1' fields = { 'object': fields.StringField(nullable=False), 'action': fields.StringField(nullable=False), - 'phase': fields.StringField(nullable=True) + 'status': fields.EnumField(valid_values=['start', 'end', 'error', + 'success'], + nullable=False) } def to_event_type_field(self): - parts = ['baremetal', self.object, self.action] - if self.obj_attr_is_set('phase') and self.phase is not None: - parts.append(self.phase) + if self.status not in ['start', 'end', 'error', 'success']: + raise exception.NotificationEventTypeError(status=self.status) + parts = ['baremetal', self.object, self.action, self.status] return '.'.join(parts) diff --git a/ironic/tests/unit/objects/test_notification.py b/ironic/tests/unit/objects/test_notification.py index 75808a9ed..6483bfb85 100644 --- a/ironic/tests/unit/objects/test_notification.py +++ b/ironic/tests/unit/objects/test_notification.py @@ -95,7 +95,7 @@ class TestNotificationBase(test_base.TestCase): payload.populate_schema(test_obj=self.fake_obj) notif = self.TestNotification( event_type=notification.EventType( - object='test_object', action='test', phase='start'), + object='test_object', action='test', status='start'), level=fields.NotificationLevel.DEBUG, publisher=notification.NotificationPublisher( service='ironic-conductor', @@ -132,7 +132,7 @@ class TestNotificationBase(test_base.TestCase): payload.populate_schema(test_obj=self.fake_obj) notif = self.TestNotification( event_type=notification.EventType( - object='test_object', action='test', phase='start'), + object='test_object', action='test', status='start'), level=fields.NotificationLevel.DEBUG, publisher=notification.NotificationPublisher( service='ironic-conductor', @@ -153,7 +153,7 @@ class TestNotificationBase(test_base.TestCase): payload.populate_schema(test_obj=self.fake_obj) notif = self.TestNotification( event_type=notification.EventType( - object='test_object', action='test', phase='start'), + object='test_object', action='test', status='start'), level=fields.NotificationLevel.DEBUG, publisher=notification.NotificationPublisher( service='ironic-conductor', @@ -172,7 +172,7 @@ class TestNotificationBase(test_base.TestCase): an_optional_field=1) notif = self.TestNotification( event_type=notification.EventType( - object='test_object', action='test', phase='start'), + object='test_object', action='test', status='start'), level=fields.NotificationLevel.DEBUG, publisher=notification.NotificationPublisher( service='ironic-conductor', @@ -190,7 +190,7 @@ class TestNotificationBase(test_base.TestCase): payload = self.TestNotificationPayloadEmptySchema(fake_field='123') notif = self.TestNotificationEmptySchema( event_type=notification.EventType( - object='test_object', action='test', phase='fail'), + object='test_object', action='test', status='error'), level=fields.NotificationLevel.ERROR, publisher=notification.NotificationPublisher( service='ironic-conductor', @@ -203,7 +203,7 @@ class TestNotificationBase(test_base.TestCase): self._verify_notification( mock_notifier, mock_context, - expected_event_type='baremetal.test_object.test.fail', + expected_event_type='baremetal.test_object.test.error', expected_payload={ 'ironic_object.name': 'TestNotificationPayloadEmptySchema', 'ironic_object.data': { @@ -230,14 +230,19 @@ class TestNotificationBase(test_base.TestCase): payload.populate_schema, test_obj=test_obj) - def test_event_type_with_phase(self): + def test_event_type_with_status(self): event_type = notification.EventType( - object="some_obj", action="some_action", phase="some_phase") - self.assertEqual("baremetal.some_obj.some_action.some_phase", + object="some_obj", action="some_action", status="success") + self.assertEqual("baremetal.some_obj.some_action.success", event_type.to_event_type_field()) - def test_event_type_without_phase(self): + def test_event_type_without_status_fails(self): event_type = notification.EventType( object="some_obj", action="some_action") - self.assertEqual("baremetal.some_obj.some_action", - event_type.to_event_type_field()) + self.assertRaises(NotImplementedError, + event_type.to_event_type_field) + + def test_event_type_invalid_status_fails(self): + self.assertRaises(ValueError, + notification.EventType, object="some_obj", + action="some_action", status="invalid") diff --git a/ironic/tests/unit/objects/test_objects.py b/ironic/tests/unit/objects/test_objects.py index efbd3b667..54ea4e448 100644 --- a/ironic/tests/unit/objects/test_objects.py +++ b/ironic/tests/unit/objects/test_objects.py @@ -410,7 +410,7 @@ expected_object_fingerprints = { 'Port': '1.6-609504503d68982a10f495659990084b', 'Portgroup': '1.2-37b374b19bfd25db7e86aebc364e611e', 'Conductor': '1.1-5091f249719d4a465062a1b3dc7f860d', - 'EventType': '1.0-3daeec50c6deb956990255f92b863333', + 'EventType': '1.1-5d44b591d93189b2ea91a1af9b082df6', 'NotificationPublisher': '1.0-51a09397d6c0687771fb5be9a999605d', } |