Add trust+zaqar:// action
Allow Zaqar messages to be posted to a queue under the user's own tenant by using a Keystone trust. Change-Id: Ia9e200ecef13ba46479a155fee064d6dded08917
This commit is contained in:
parent
b9242bf984
commit
ef08bc2e6a
@ -384,7 +384,7 @@ class Alarm(base.Base):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_trust_url(url):
|
def _is_trust_url(url):
|
||||||
return url.scheme in ('trust+http', 'trust+https')
|
return url.scheme.startswith('trust+')
|
||||||
|
|
||||||
def update_actions(self, old_alarm=None):
|
def update_actions(self, old_alarm=None):
|
||||||
trustor_user_id = pecan.request.headers.get('X-User-Id')
|
trustor_user_id = pecan.request.headers.get('X-User-Id')
|
||||||
|
@ -20,14 +20,12 @@ from aodh import keystone_client
|
|||||||
from aodh.notifier import rest
|
from aodh.notifier import rest
|
||||||
|
|
||||||
|
|
||||||
class TrustRestAlarmNotifier(rest.RestAlarmNotifier):
|
class TrustAlarmNotifierMixin(object):
|
||||||
"""Notifier supporting keystone trust authentication.
|
"""Mixin class to add Keystone trust support to an AlarmNotifier.
|
||||||
|
|
||||||
This alarm notifier is intended to be used to call an endpoint using
|
Provides a notify() method that interprets the trust ID and then calls
|
||||||
keystone authentication. It uses the aodh service user to
|
the parent class's notify(), passing the necessary authentication data in
|
||||||
authenticate using the trust ID provided.
|
the headers.
|
||||||
|
|
||||||
The URL must be in the form trust+http://trust-id@host/action.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def notify(self, action, alarm_id, alarm_name, severity, previous, current,
|
def notify(self, action, alarm_id, alarm_name, severity, previous, current,
|
||||||
@ -45,6 +43,17 @@ class TrustRestAlarmNotifier(rest.RestAlarmNotifier):
|
|||||||
action.fragment)
|
action.fragment)
|
||||||
|
|
||||||
headers = {'X-Auth-Token': keystone_client.get_auth_token(client)}
|
headers = {'X-Auth-Token': keystone_client.get_auth_token(client)}
|
||||||
super(TrustRestAlarmNotifier, self).notify(
|
super(TrustAlarmNotifierMixin, self).notify(
|
||||||
action, alarm_id, alarm_name, severity, previous, current, reason,
|
action, alarm_id, alarm_name, severity, previous, current, reason,
|
||||||
reason_data, headers)
|
reason_data, headers)
|
||||||
|
|
||||||
|
|
||||||
|
class TrustRestAlarmNotifier(TrustAlarmNotifierMixin, rest.RestAlarmNotifier):
|
||||||
|
"""Notifier supporting keystone trust authentication.
|
||||||
|
|
||||||
|
This alarm notifier is intended to be used to call an endpoint using
|
||||||
|
keystone authentication. It uses the aodh service user to
|
||||||
|
authenticate using the trust ID provided.
|
||||||
|
|
||||||
|
The URL must be in the form ``trust+http://trust-id@host/action``.
|
||||||
|
"""
|
||||||
|
@ -22,6 +22,7 @@ import six.moves.urllib.parse as urlparse
|
|||||||
from aodh.i18n import _LE, _LI
|
from aodh.i18n import _LE, _LI
|
||||||
from aodh import keystone_client
|
from aodh import keystone_client
|
||||||
from aodh import notifier
|
from aodh import notifier
|
||||||
|
from aodh.notifier import trust
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -144,7 +145,7 @@ class ZaqarAlarmNotifier(notifier.AlarmNotifier):
|
|||||||
'current': current, 'reason': reason,
|
'current': current, 'reason': reason,
|
||||||
'reason_data': reason_data}
|
'reason_data': reason_data}
|
||||||
message = dict(body=body)
|
message = dict(body=body)
|
||||||
self.notify_zaqar(action, message)
|
self.notify_zaqar(action, message, headers)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def client(self):
|
def client(self):
|
||||||
@ -152,7 +153,7 @@ class ZaqarAlarmNotifier(notifier.AlarmNotifier):
|
|||||||
self._zclient = self.get_zaqar_client(self._get_client_conf())
|
self._zclient = self.get_zaqar_client(self._get_client_conf())
|
||||||
return self._zclient
|
return self._zclient
|
||||||
|
|
||||||
def notify_zaqar(self, action, message):
|
def notify_zaqar(self, action, message, headers=None):
|
||||||
queue_info = urlparse.parse_qs(action.query)
|
queue_info = urlparse.parse_qs(action.query)
|
||||||
try:
|
try:
|
||||||
# NOTE(flwang): Try to get build a pre-signed client if user has
|
# NOTE(flwang): Try to get build a pre-signed client if user has
|
||||||
@ -187,3 +188,41 @@ class ZaqarAlarmNotifier(notifier.AlarmNotifier):
|
|||||||
LOG.error(_LE("Unknown error occurred; Failed to post message to"
|
LOG.error(_LE("Unknown error occurred; Failed to post message to"
|
||||||
" Zaqar queue"),
|
" Zaqar queue"),
|
||||||
exc_info=True)
|
exc_info=True)
|
||||||
|
|
||||||
|
|
||||||
|
class TrustZaqarAlarmNotifier(trust.TrustAlarmNotifierMixin,
|
||||||
|
ZaqarAlarmNotifier):
|
||||||
|
"""Zaqar notifier using a Keystone trust to post to user-defined queues.
|
||||||
|
|
||||||
|
The URL must be in the form ``trust+zaqar://trust_id@?queue_name=example``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _get_client_conf(self, auth_token):
|
||||||
|
return {
|
||||||
|
'auth_opts': {
|
||||||
|
'backend': 'keystone',
|
||||||
|
'options': {
|
||||||
|
'os_auth_token': auth_token,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def notify_zaqar(self, action, message, headers):
|
||||||
|
queue_info = urlparse.parse_qs(action.query)
|
||||||
|
try:
|
||||||
|
queue_name = queue_info.get('queue_name')[-1]
|
||||||
|
except IndexError:
|
||||||
|
LOG.error(_LE("Required 'queue_name' query option missing in"
|
||||||
|
" action %s"),
|
||||||
|
action)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
conf = self._get_client_conf(headers['X-Auth-Token'])
|
||||||
|
client = self.get_zaqar_client(conf)
|
||||||
|
queue = client.queue(queue_name)
|
||||||
|
queue.post(message)
|
||||||
|
except Exception:
|
||||||
|
LOG.error(_LE("Unknown error occurred; Failed to post message to"
|
||||||
|
" Zaqar queue"),
|
||||||
|
exc_info=True)
|
||||||
|
@ -405,6 +405,21 @@ class TestAlarmNotifier(tests_base.BaseTestCase):
|
|||||||
self.assertEqual(1, self.zaqar.subscriptions)
|
self.assertEqual(1, self.zaqar.subscriptions)
|
||||||
self.assertEqual(1, self.zaqar.posts)
|
self.assertEqual(1, self.zaqar.posts)
|
||||||
|
|
||||||
|
def test_trust_zaqar_notifier_action(self):
|
||||||
|
client = mock.MagicMock()
|
||||||
|
client.session.auth.get_access.return_value.auth_token = 'token_1234'
|
||||||
|
|
||||||
|
self.useFixture(
|
||||||
|
mockpatch.Patch('aodh.keystone_client.get_trusted_client',
|
||||||
|
lambda *args: client))
|
||||||
|
|
||||||
|
action = 'trust+zaqar://trust-1234:delete@?queue_name=foobar-critical'
|
||||||
|
self._msg_notifier.sample({}, 'alarm.update',
|
||||||
|
self._notification(action))
|
||||||
|
time.sleep(1)
|
||||||
|
self.assertEqual(0, self.zaqar.subscriptions)
|
||||||
|
self.assertEqual(1, self.zaqar.posts)
|
||||||
|
|
||||||
|
|
||||||
class FakeZaqarClient(object):
|
class FakeZaqarClient(object):
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ aodh.notifier =
|
|||||||
trust+http = aodh.notifier.trust:TrustRestAlarmNotifier
|
trust+http = aodh.notifier.trust:TrustRestAlarmNotifier
|
||||||
trust+https = aodh.notifier.trust:TrustRestAlarmNotifier
|
trust+https = aodh.notifier.trust:TrustRestAlarmNotifier
|
||||||
zaqar = aodh.notifier.zaqar:ZaqarAlarmNotifier
|
zaqar = aodh.notifier.zaqar:ZaqarAlarmNotifier
|
||||||
|
trust+zaqar = aodh.notifier.zaqar:TrustZaqarAlarmNotifier
|
||||||
|
|
||||||
wsgi_scripts =
|
wsgi_scripts =
|
||||||
aodh-api = aodh.api.app:build_wsgi_app
|
aodh-api = aodh.api.app:build_wsgi_app
|
||||||
|
Loading…
Reference in New Issue
Block a user