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):
|
class NegativeLimitError(WatcherException):
|
||||||
msg_fmt = _("Limit should be positive")
|
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)
|
aliases=TRANSPORT_ALIASES)
|
||||||
|
|
||||||
serializer = RequestContextSerializer(JsonPayloadSerializer())
|
serializer = RequestContextSerializer(JsonPayloadSerializer())
|
||||||
NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
|
if not conf.notification_level:
|
||||||
serializer=serializer)
|
NOTIFIER = messaging.Notifier(
|
||||||
|
NOTIFICATION_TRANSPORT, serializer=serializer, driver='noop')
|
||||||
|
else:
|
||||||
|
NOTIFIER = messaging.Notifier(NOTIFICATION_TRANSPORT,
|
||||||
|
serializer=serializer)
|
||||||
|
|
||||||
|
|
||||||
def initialized():
|
def initialized():
|
||||||
|
@ -36,6 +36,7 @@ from watcher.common import rpc
|
|||||||
from watcher.common import scheduling
|
from watcher.common import scheduling
|
||||||
from watcher import objects
|
from watcher import objects
|
||||||
from watcher.objects import base
|
from watcher.objects import base
|
||||||
|
from watcher.objects import fields as wfields
|
||||||
from watcher import opts
|
from watcher import opts
|
||||||
from watcher import version
|
from watcher import version
|
||||||
|
|
||||||
@ -64,6 +65,18 @@ service_opts = [
|
|||||||
|
|
||||||
cfg.CONF.register_opts(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
|
CONF = cfg.CONF
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -103,14 +103,13 @@ class BaseWatcherEnum(Enum):
|
|||||||
|
|
||||||
|
|
||||||
class NotificationPriority(BaseWatcherEnum):
|
class NotificationPriority(BaseWatcherEnum):
|
||||||
CRITICAL = 'critical'
|
|
||||||
DEBUG = 'debug'
|
DEBUG = 'debug'
|
||||||
INFO = 'info'
|
INFO = 'info'
|
||||||
|
WARNING = 'warning'
|
||||||
ERROR = 'error'
|
ERROR = 'error'
|
||||||
SAMPLE = 'sample'
|
CRITICAL = 'critical'
|
||||||
WARNING = 'warn'
|
|
||||||
|
|
||||||
ALL = (CRITICAL, DEBUG, INFO, ERROR, SAMPLE, WARNING)
|
ALL = (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||||
|
|
||||||
|
|
||||||
class NotificationPhase(BaseWatcherEnum):
|
class NotificationPhase(BaseWatcherEnum):
|
||||||
|
@ -12,10 +12,24 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from watcher.common import exception
|
||||||
from watcher.common import rpc
|
from watcher.common import rpc
|
||||||
from watcher.objects import base
|
from watcher.objects import base
|
||||||
from watcher.objects import fields as wfields
|
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)
|
@base.WatcherObjectRegistry.register_if(False)
|
||||||
class NotificationObject(base.WatcherObject):
|
class NotificationObject(base.WatcherObject):
|
||||||
@ -125,6 +139,20 @@ class NotificationBase(NotificationObject):
|
|||||||
'publisher': wfields.ObjectField('NotificationPublisher'),
|
'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):
|
def _emit(self, context, event_type, publisher_id, payload):
|
||||||
notifier = rpc.get_notifier(publisher_id)
|
notifier = rpc.get_notifier(publisher_id)
|
||||||
notify = getattr(notifier, self.priority)
|
notify = getattr(notifier, self.priority)
|
||||||
@ -132,8 +160,11 @@ class NotificationBase(NotificationObject):
|
|||||||
|
|
||||||
def emit(self, context):
|
def emit(self, context):
|
||||||
"""Send the notification."""
|
"""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
|
# Note(gibi): notification payload will be a newly populated object
|
||||||
# therefore every field of it will look changed so this does not carry
|
# therefore every field of it will look changed so this does not carry
|
||||||
# any extra information so we drop this from the payload.
|
# any extra information so we drop this from the payload.
|
||||||
|
@ -17,6 +17,7 @@ import collections
|
|||||||
import mock
|
import mock
|
||||||
from oslo_versionedobjects import fixture
|
from oslo_versionedobjects import fixture
|
||||||
|
|
||||||
|
from watcher.common import exception
|
||||||
from watcher.common import rpc
|
from watcher.common import rpc
|
||||||
from watcher.objects import base
|
from watcher.objects import base
|
||||||
from watcher.objects import fields as wfields
|
from watcher.objects import fields as wfields
|
||||||
@ -136,6 +137,46 @@ class TestNotificationBase(testbase.TestCase):
|
|||||||
expected_event_type='test_object.update.start',
|
expected_event_type='test_object.update.start',
|
||||||
expected_payload=self.expected_payload)
|
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')
|
@mock.patch.object(rpc, 'NOTIFIER')
|
||||||
def test_emit_event_type_without_phase(self, mock_notifier):
|
def test_emit_event_type_without_phase(self, mock_notifier):
|
||||||
noti = self.TestNotification(
|
noti = self.TestNotification(
|
||||||
@ -171,7 +212,8 @@ class TestNotificationBase(testbase.TestCase):
|
|||||||
payload=non_populated_payload)
|
payload=non_populated_payload)
|
||||||
|
|
||||||
mock_context = mock.Mock()
|
mock_context = mock.Mock()
|
||||||
self.assertRaises(AssertionError, noti.emit, mock_context)
|
self.assertRaises(exception.NotificationPayloadError,
|
||||||
|
noti.emit, mock_context)
|
||||||
self.assertFalse(mock_notifier.called)
|
self.assertFalse(mock_notifier.called)
|
||||||
|
|
||||||
@mock.patch.object(rpc, 'NOTIFIER')
|
@mock.patch.object(rpc, 'NOTIFIER')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user