summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario Villaplana <mario.villaplana@gmail.com>2016-09-01 20:44:49 +0000
committerMario Villaplana <mario.villaplana@gmail.com>2016-09-15 22:53:12 +0000
commit77c7a710fc0eb1f419db650e3aa958c31b3bd74f (patch)
treea72a7fc9abd71172b0c68a7466b182b90686dfc1
parent047fc52a99e99bddc89f9b83759bc2f84d98f48c (diff)
downloadironic-77c7a710fc0eb1f419db650e3aa958c31b3bd74f.tar.gz
Replace "phase" with "status" in notification base
The notification spec is being updated to rename "phase" to "status" and make it a required field. This updates the notification base code and docs to reflect this modification. Version for the notification EventType base class is also bumped. Change-Id: I11b6ea44a01d2a830b592784ccc63a1de9bf2ec1 Depends-On: Ib25bd5a3a600c13f7b265d86ad253af3dfa5552f
-rw-r--r--doc/source/dev/notifications.rst20
-rw-r--r--ironic/common/exception.py5
-rw-r--r--ironic/objects/fields.py4
-rw-r--r--ironic/objects/notification.py17
-rw-r--r--ironic/tests/unit/objects/test_notification.py29
-rw-r--r--ironic/tests/unit/objects/test_objects.py2
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',
}