Merge "Replace "phase" with "status" in notification base"

This commit is contained in:
Jenkins 2016-09-16 22:38:07 +00:00 committed by Gerrit Code Review
commit 53f8b173ae
6 changed files with 55 additions and 22 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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