d5e24cf6f8
Fix "properties" field in the examples and add small note. Change-Id: Id63e8d95fc7f2ba1cf956eff657b3a2d902d9f93
318 lines
13 KiB
ReStructuredText
318 lines
13 KiB
ReStructuredText
.. _notifications:
|
|
|
|
=============
|
|
Notifications
|
|
=============
|
|
|
|
Ironic notifications are events intended for consumption by external services
|
|
like a billing or usage system, a monitoring data store, or other OpenStack
|
|
services. Notifications are sent to these services over a message bus by
|
|
oslo.messaging's Notifier class [1]_. The consumer sees the notification as a
|
|
JSON object structured in the following way as defined by oslo.messaging::
|
|
|
|
{
|
|
"priority": <string, defined by the sender>,
|
|
"event_type": <string, defined by the sender>,
|
|
"timestamp": <string, the isotime of when the notification emitted>,
|
|
"publisher_id": <string, defined by the sender>,
|
|
"message_id": <uuid, generated by oslo>,
|
|
"payload": <json serialized dict, defined by the sender>
|
|
}
|
|
|
|
Versioned notifications in ironic
|
|
=================================
|
|
To make it easier for consumers of ironic's notifications to use predictably,
|
|
ironic defines each notification and its payload as oslo versioned objects
|
|
[2]_.
|
|
|
|
An increase in the minor version of the payload will indicate that only
|
|
new fields have been added since the last version, so the consumer can still
|
|
use the notification as it did previously. An increase in the major version of
|
|
the payload indicates that the consumer can no longer parse the notification as
|
|
it did previously, indicating that a field was removed or the type of the
|
|
payload field changed.
|
|
|
|
Ironic exposes a configuration option in the ``DEFAULT`` section called
|
|
``notification_level`` that indicates the minimum level for which
|
|
notifications will be emitted. This option is not defined by default, which
|
|
indicates that no notifications will be sent by ironic. Notification levels
|
|
may be "debug", "info", "warning", "error", or "critical", and each
|
|
level follows the OpenStack logging guidelines [3]_. If it's desired that
|
|
ironic emit all notifications, the config option should be set to "debug", for
|
|
example. If only "warning", "error", and "critical" notifications are needed,
|
|
the config option should be set to "warning". This level gets exposed in the
|
|
notification on the wire as the "priority" field.
|
|
|
|
All ironic versioned notifications will be sent on the message bus via the
|
|
``ironic_versioned_notifications`` topic.
|
|
|
|
Ironic also has a set of base classes that assist in clearly defining the
|
|
notification itself, the payload, and the other fields not auto-generated by
|
|
oslo (level, event_type and publisher_id). Below describes how to use these
|
|
base classes to add a new notification to ironic.
|
|
|
|
Adding a new notification to ironic
|
|
===================================
|
|
To add a new notification to ironic, a new versioned notification class should
|
|
be created by subclassing the NotificationBase class to define the notification
|
|
itself and the NotificationPayloadBase class to define which fields the new
|
|
notification will contain inside its payload. You may also define a schema to
|
|
allow the payload to be automatically populated by the fields of an ironic
|
|
object. Here's an example::
|
|
|
|
# The ironic object whose fields you want to use in your schema
|
|
@base.IronicObjectRegistry.register
|
|
class ExampleObject(base.IronicObject):
|
|
# Version 1.0: Initial version
|
|
VERSION = '1.0'
|
|
fields = {
|
|
'id': fields.IntegerField(),
|
|
'uuid': fields.UUIDField(),
|
|
'a_useful_field': fields.StringField(),
|
|
'not_useful_field': fields.StringField()
|
|
}
|
|
|
|
# A class for your new notification
|
|
@base.IronicObjectRegistry.register
|
|
class ExampleNotification(notification.NotificationBase):
|
|
# Version 1.0: Initial version
|
|
VERSION = '1.0'
|
|
fields = {
|
|
'payload': fields.ObjectField('ExampleNotifPayload')
|
|
}
|
|
|
|
# A class for your notification's payload
|
|
@base.IronicObjectRegistry.register
|
|
class ExampleNotifPayload(notification.NotificationPayloadBase):
|
|
# Schemas are optional. They just allow you to reuse other objects'
|
|
# fields by passing in that object and calling populate_schema with
|
|
# a kwarg set to the other object.
|
|
SCHEMA = {
|
|
'a_useful_field': ('example_obj', 'a_useful_field')
|
|
}
|
|
|
|
# Version 1.0: Initial version
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'a_useful_field': fields.StringField(),
|
|
'an_extra_field': fields.StringField(nullable=True)
|
|
}
|
|
|
|
SCHEMA defines how to populate the payload fields. It's an optional
|
|
attribute that subclasses may use to easily populate notifications with
|
|
data from other objects.
|
|
|
|
It is a dictionary where every key value pair has the following format::
|
|
|
|
<payload_field_name>: (<data_source_name>,
|
|
<field_of_the_data_source>)
|
|
|
|
The ``<payload_field_name>`` is the name where the data will be stored in the
|
|
payload object; this field has to be defined as a field of the payload.
|
|
The ``<data_source_name>`` shall refer to name of the parameter passed as
|
|
kwarg to the payload's ``populate_schema()`` call and this object will be
|
|
used as the source of the data. The ``<field_of_the_data_source>`` shall be
|
|
a valid field of the passed argument.
|
|
|
|
The SCHEMA needs to be applied with the ``populate_schema()`` call before the
|
|
notification can be emitted.
|
|
|
|
The value of the ``payload.<payload_field_name>`` field will be set by the
|
|
``<data_source_name>.<field_of_the_data_source>`` field. The
|
|
``<data_source_name>`` will not be part of the payload object internal or
|
|
external representation.
|
|
|
|
Payload fields that are not set by the SCHEMA can be filled in the same
|
|
way as in any versioned object.
|
|
|
|
Then, to create a payload, you would do something like the following. Note
|
|
that if you choose to define a schema in the SCHEMA class variable, you must
|
|
populate the schema by calling ``populate_schema(example_obj=my_example_obj)``
|
|
before emitting the notification is allowed::
|
|
|
|
my_example_obj = ExampleObject(id=1,
|
|
a_useful_field='important',
|
|
not_useful_field='blah')
|
|
|
|
# an_extra_field is optional since it's not a part of the SCHEMA and is a
|
|
# nullable field in the class fields
|
|
my_notify_payload = ExampleNotifyPayload(an_extra_field='hello')
|
|
# populate the schema with the ExampleObject fields
|
|
my_notify_payload.populate_schema(example_obj=my_example_obj)
|
|
|
|
You then create the notification with the oslo required fields (event_type,
|
|
publisher_id, and level, all sender fields needed by oslo that are defined
|
|
in the ironic notification base classes) and emit it::
|
|
|
|
notify = ExampleNotification(
|
|
event_type=notification.EventType(object='example_obj',
|
|
action='do_something', status=fields.NotificationStatus.START),
|
|
publisher=notification.NotificationPublisher(
|
|
service='ironic-conductor',
|
|
host='hostname01'),
|
|
level=fields.NotificationLevel.DEBUG,
|
|
payload=my_notify_payload)
|
|
notify.emit(context)
|
|
|
|
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", "error", 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. "error" 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",
|
|
"payload":{
|
|
"ironic_object.namespace":"ironic",
|
|
"ironic_object.name":"ExampleNotifyPayload",
|
|
"ironic_object.version":"1.0",
|
|
"ironic_object.data":{
|
|
"a_useful_field":"important",
|
|
"an_extra_field":"hello"
|
|
}
|
|
},
|
|
"event_type":"baremetal.example_obj.do_something.start",
|
|
"publisher_id":"ironic-conductor.hostname01"
|
|
}
|
|
|
|
|
|
Available notifications
|
|
=======================
|
|
.. TODO(mariojv) Move the below to deployer documentation.
|
|
.. TODO(mariojv) Match Nova's tabular formatting below.
|
|
|
|
|
|
The notifications that ironic emits are described here. They are listed
|
|
(alphabetically) by service first, then by event_type. All examples below
|
|
show payloads before serialization to JSON.
|
|
|
|
------------------------------
|
|
ironic-conductor notifications
|
|
------------------------------
|
|
|
|
|
|
baremetal.node.power_set
|
|
------------------------
|
|
|
|
* ``baremetal.node.power_set.start`` is emitted by the ironic-conductor service
|
|
when it begins a power state change. It has notification level INFO.
|
|
|
|
* ``baremetal.node.power_set.end`` is emitted when ironic-conductor
|
|
successfully completes a power state change task. It has notification level
|
|
INFO.
|
|
|
|
* ``baremetal.node.power_set.error`` is emitted by ironic-conductor when it
|
|
fails to set a node's power state. It has notification level ERROR. This can
|
|
occur when ironic fails to retrieve the old power state prior to setting the
|
|
new one on the node, or when it fails to set the power state if a change is
|
|
requested.
|
|
|
|
Here is an example payload for a notification with this event type. The
|
|
"to_power" payload field indicates the power state to which the
|
|
ironic-conductor is attempting to change the node::
|
|
|
|
{
|
|
"priority": "info",
|
|
"payload":{
|
|
"ironic_object.namespace":"ironic",
|
|
"ironic_object.name":"NodeSetPowerStatePayload",
|
|
"ironic_object.version":"1.0",
|
|
"ironic_object.data":{
|
|
"clean_step": None,
|
|
"console_enabled": False,
|
|
"created_at": "2016-01-26T20:41:03+00:00",
|
|
"driver": "fake",
|
|
"extra": {},
|
|
"inspection_finished_at": None,
|
|
"inspection_started_at": None,
|
|
"instance_uuid": "d6ea00c1-1f94-4e95-90b3-3462d7031678",
|
|
"last_error": None,
|
|
"maintenance": False,
|
|
"maintenance_reason": None,
|
|
"network_interface": "flat",
|
|
"name": None,
|
|
"power_state": "power off",
|
|
"properties": {
|
|
"memory_mb": 4096,
|
|
"cpu_arch": "x86_64",
|
|
"local_gb": 10,
|
|
"cpus": 8},
|
|
"provision_state": "available",
|
|
"provision_updated_at": "2016-01-27T20:41:03+00:00",
|
|
"resource_class": None,
|
|
"target_power_state": None,
|
|
"target_provision_state": None,
|
|
"updated_at": "2016-01-27T20:41:03+00:00",
|
|
"uuid": "1be26c0b-03f2-4d2e-ae87-c02d7f33c123",
|
|
"to_power": "power on"
|
|
}
|
|
},
|
|
"event_type":"baremetal.node.power_set.start",
|
|
"publisher_id":"ironic-conductor.hostname01"
|
|
}
|
|
|
|
|
|
|
|
baremetal.node.power_state_corrected
|
|
------------------------------------
|
|
|
|
* ``baremetal.node.power_state_corrected.success`` is emitted by
|
|
ironic-conductor when the power state on the baremetal hardware is different
|
|
from the previous known power state of the node and the database is corrected
|
|
to reflect this new power state. It has notification level INFO.
|
|
|
|
Here is an example payload for a notification with this event_type. The
|
|
"from_power" payload field indicates the previous power state on the node,
|
|
prior to the correction::
|
|
|
|
{
|
|
"priority": "info",
|
|
"payload":{
|
|
"ironic_object.namespace":"ironic",
|
|
"ironic_object.name":"NodeCorrectedPowerStatePayload",
|
|
"ironic_object.version":"1.0",
|
|
"ironic_object.data":{
|
|
"clean_step": None,
|
|
"console_enabled": False,
|
|
"created_at": "2016-01-26T20:41:03+00:00",
|
|
"driver": "fake",
|
|
"extra": {},
|
|
"inspection_finished_at": None,
|
|
"inspection_started_at": None,
|
|
"instance_uuid": "d6ea00c1-1f94-4e95-90b3-3462d7031678",
|
|
"last_error": None,
|
|
"maintenance": False,
|
|
"maintenance_reason": None,
|
|
"network_interface": "flat",
|
|
"name": None,
|
|
"power_state": "power off",
|
|
"properties": {
|
|
"memory_mb": 4096,
|
|
"cpu_arch": "x86_64",
|
|
"local_gb": 10,
|
|
"cpus": 8},
|
|
"provision_state": "available",
|
|
"provision_updated_at": "2016-01-27T20:41:03+00:00",
|
|
"resource_class": None,
|
|
"target_power_state": None,
|
|
"target_provision_state": None,
|
|
"updated_at": "2016-01-27T20:41:03+00:00",
|
|
"uuid": "1be26c0b-03f2-4d2e-ae87-c02d7f33c123",
|
|
"from_power": "power on"
|
|
}
|
|
},
|
|
"event_type":"baremetal.node.power_state_corrected.success",
|
|
"publisher_id":"ironic-conductor.cond-hostname02"
|
|
}
|
|
|
|
.. [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
|