Added notification_level config option
In this changeset, I implemented the notification_level parameter that allows you to set the level minimum level of notification to be emitted by Watcher. Partially Implements: blueprint watcher-notifications-ovo Change-Id: I78b30ceb3ee7606078a87beb3a4ce5d9568af1e0
This commit is contained in:
parent
cdda06c08c
commit
4bebf882d9
@ -399,3 +399,8 @@ class NotSoftDeletedStateError(WatcherException):
|
||||
|
||||
class NegativeLimitError(WatcherException):
|
||||
msg_fmt = _("Limit should be positive")
|
||||
|
||||
|
||||
class NotificationPayloadError(WatcherException):
|
||||
_msg_fmt = _("Payload not populated when trying to send notification "
|
||||
"\"%(class_name)s\"")
|
||||
|
@ -72,8 +72,12 @@ def init(conf):
|
||||
aliases=TRANSPORT_ALIASES)
|
||||
|
||||
serializer = RequestContextSerializer(JsonPayloadSerializer())
|
||||
NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
|
||||
serializer=serializer)
|
||||
if not conf.notification_level:
|
||||
NOTIFIER = messaging.Notifier(
|
||||
NOTIFICATION_TRANSPORT, serializer=serializer, driver='noop')
|
||||
else:
|
||||
NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
|
||||
serializer=serializer)
|
||||
|
||||
|
||||
def initialized():
|
||||
|
@ -36,6 +36,7 @@ from watcher.common import rpc
|
||||
from watcher.common import scheduling
|
||||
from watcher import objects
|
||||
from watcher.objects import base
|
||||
from watcher.objects import fields as wfields
|
||||
from watcher import opts
|
||||
from watcher import version
|
||||
|
||||
@ -64,6 +65,18 @@ service_opts = [
|
||||
|
||||
cfg.CONF.register_opts(service_opts)
|
||||
|
||||
NOTIFICATION_OPTS = [
|
||||
cfg.StrOpt('notification_level',
|
||||
choices=[''] + list(wfields.NotificationPriority.ALL),
|
||||
default=wfields.NotificationPriority.INFO,
|
||||
help=_('Specifies the minimum level for which to send '
|
||||
'notifications. If not set, no notifications will '
|
||||
'be sent. The default is for this option to be at the '
|
||||
'`INFO` level.'))
|
||||
]
|
||||
cfg.CONF.register_opts(NOTIFICATION_OPTS)
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
@ -103,14 +103,13 @@ class BaseWatcherEnum(Enum):
|
||||
|
||||
|
||||
class NotificationPriority(BaseWatcherEnum):
|
||||
CRITICAL = 'critical'
|
||||
DEBUG = 'debug'
|
||||
INFO = 'info'
|
||||
WARNING = 'warning'
|
||||
ERROR = 'error'
|
||||
SAMPLE = 'sample'
|
||||
WARNING = 'warn'
|
||||
CRITICAL = 'critical'
|
||||
|
||||
ALL = (CRITICAL, DEBUG, INFO, ERROR, SAMPLE, WARNING)
|
||||
ALL = (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
|
||||
|
||||
class NotificationPhase(BaseWatcherEnum):
|
||||
|
@ -12,10 +12,24 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from watcher.common import exception
|
||||
from watcher.common import rpc
|
||||
from watcher.objects import base
|
||||
from watcher.objects import fields as wfields
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
# Definition of notification levels in increasing order of severity
|
||||
NOTIFY_LEVELS = {
|
||||
wfields.NotificationPriority.DEBUG: 0,
|
||||
wfields.NotificationPriority.INFO: 1,
|
||||
wfields.NotificationPriority.WARNING: 2,
|
||||
wfields.NotificationPriority.ERROR: 3,
|
||||
wfields.NotificationPriority.CRITICAL: 4
|
||||
}
|
||||
|
||||
|
||||
@base.WatcherObjectRegistry.register_if(False)
|
||||
class NotificationObject(base.WatcherObject):
|
||||
@ -125,6 +139,20 @@ class NotificationBase(NotificationObject):
|
||||
'publisher': wfields.ObjectField('NotificationPublisher'),
|
||||
}
|
||||
|
||||
def _should_notify(self):
|
||||
"""Determine whether the notification should be sent.
|
||||
|
||||
A notification is sent when the level of the notification is
|
||||
greater than or equal to the level specified in the
|
||||
configuration, in the increasing order of DEBUG, INFO, WARNING,
|
||||
ERROR, CRITICAL.
|
||||
:return: True if notification should be sent, False otherwise.
|
||||
"""
|
||||
if not CONF.notification_level:
|
||||
return False
|
||||
return (NOTIFY_LEVELS[self.priority] >=
|
||||
NOTIFY_LEVELS[CONF.notification_level])
|
||||
|
||||
def _emit(self, context, event_type, publisher_id, payload):
|
||||
notifier = rpc.get_notifier(publisher_id)
|
||||
notify = getattr(notifier, self.priority)
|
||||
@ -132,8 +160,11 @@ class NotificationBase(NotificationObject):
|
||||
|
||||
def emit(self, context):
|
||||
"""Send the notification."""
|
||||
assert self.payload.populated
|
||||
|
||||
if not self._should_notify():
|
||||
return
|
||||
if not self.payload.populated:
|
||||
raise exception.NotificationPayloadError(
|
||||
class_name=self.__class__.__name__)
|
||||
# Note(gibi): notification payload will be a newly populated object
|
||||
# therefore every field of it will look changed so this does not carry
|
||||
# any extra information so we drop this from the payload.
|
||||
|
@ -17,6 +17,7 @@ import collections
|
||||
import mock
|
||||
from oslo_versionedobjects import fixture
|
||||
|
||||
from watcher.common import exception
|
||||
from watcher.common import rpc
|
||||
from watcher.objects import base
|
||||
from watcher.objects import fields as wfields
|
||||
@ -136,6 +137,46 @@ class TestNotificationBase(testbase.TestCase):
|
||||
expected_event_type='test_object.update.start',
|
||||
expected_payload=self.expected_payload)
|
||||
|
||||
@mock.patch.object(rpc, 'NOTIFIER')
|
||||
def test_no_emit_notifs_disabled(self, mock_notifier):
|
||||
# Make sure notifications aren't emitted when notification_level
|
||||
# isn't defined, indicating notifications should be disabled
|
||||
self.config(notification_level=None)
|
||||
notif = self.TestNotification(
|
||||
event_type=notificationbase.EventType(
|
||||
object='test_object',
|
||||
action=wfields.NotificationAction.UPDATE,
|
||||
phase=wfields.NotificationPhase.START),
|
||||
publisher=notificationbase.NotificationPublisher(
|
||||
host='fake-host', binary='watcher-fake'),
|
||||
priority=wfields.NotificationPriority.INFO,
|
||||
payload=self.payload)
|
||||
|
||||
mock_context = mock.Mock()
|
||||
notif.emit(mock_context)
|
||||
|
||||
self.assertFalse(mock_notifier.called)
|
||||
|
||||
@mock.patch.object(rpc, 'NOTIFIER')
|
||||
def test_no_emit_level_too_low(self, mock_notifier):
|
||||
# Make sure notification doesn't emit when set notification
|
||||
# level < config level
|
||||
self.config(notification_level='warning')
|
||||
notif = self.TestNotification(
|
||||
event_type=notificationbase.EventType(
|
||||
object='test_object',
|
||||
action=wfields.NotificationAction.UPDATE,
|
||||
phase=wfields.NotificationPhase.START),
|
||||
publisher=notificationbase.NotificationPublisher(
|
||||
host='fake-host', binary='watcher-fake'),
|
||||
priority=wfields.NotificationPriority.INFO,
|
||||
payload=self.payload)
|
||||
|
||||
mock_context = mock.Mock()
|
||||
notif.emit(mock_context)
|
||||
|
||||
self.assertFalse(mock_notifier.called)
|
||||
|
||||
@mock.patch.object(rpc, 'NOTIFIER')
|
||||
def test_emit_event_type_without_phase(self, mock_notifier):
|
||||
noti = self.TestNotification(
|
||||
@ -171,7 +212,8 @@ class TestNotificationBase(testbase.TestCase):
|
||||
payload=non_populated_payload)
|
||||
|
||||
mock_context = mock.Mock()
|
||||
self.assertRaises(AssertionError, noti.emit, mock_context)
|
||||
self.assertRaises(exception.NotificationPayloadError,
|
||||
noti.emit, mock_context)
|
||||
self.assertFalse(mock_notifier.called)
|
||||
|
||||
@mock.patch.object(rpc, 'NOTIFIER')
|
||||
|
Loading…
x
Reference in New Issue
Block a user