Use user_id/project_id from service_credentials in alarm_change

Like recording alarm history in aodh-api when update alarm. the user_id
and project_id is the operator credential, we need to spedify the user_id
and project from service_credentials when evaluator update alarm.

Change-Id: I8a96ab4f39b522d6ed52a9c6ea095182869775fd
This commit is contained in:
liu-sheng 2015-07-27 12:41:59 +08:00
parent 61717e7a8d
commit 469860fca4
5 changed files with 67 additions and 18 deletions

View File

@ -34,6 +34,7 @@ import uuid
import aodh import aodh
from aodh import coordination from aodh import coordination
from aodh.i18n import _ from aodh.i18n import _
from aodh import keystone_client
from aodh import messaging from aodh import messaging
from aodh import rpc from aodh import rpc
from aodh import storage from aodh import storage
@ -65,6 +66,13 @@ class Evaluator(object):
self.conf = conf self.conf = conf
self.notifier = notifier self.notifier = notifier
self.storage_conn = None self.storage_conn = None
self._ks_client = None
@property
def ks_client(self):
if self._ks_client is None:
self._ks_client = keystone_client.get_client(self.conf)
return self._ks_client
@property @property
def _storage_conn(self): def _storage_conn(self):
@ -77,10 +85,7 @@ class Evaluator(object):
return return
type = models.AlarmChange.STATE_TRANSITION type = models.AlarmChange.STATE_TRANSITION
detail = json.dumps({'state': alarm.state}) detail = json.dumps({'state': alarm.state})
# TODO(liusheng) the user_id and project_id should be user_id, project_id = self.ks_client.user_id, self.ks_client.project_id
# specify than None?
user_id = None
project_id = None
on_behalf_of = alarm.project_id on_behalf_of = alarm.project_id
now = timeutils.utcnow() now = timeutils.utcnow()
payload = dict(event_id=str(uuid.uuid4()), payload = dict(event_id=str(uuid.uuid4()),

View File

@ -20,7 +20,6 @@ import requests
from aodh.evaluator import threshold from aodh.evaluator import threshold
from aodh.i18n import _ from aodh.i18n import _
from aodh import keystone_client
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -39,13 +38,6 @@ class GnocchiThresholdEvaluator(threshold.ThresholdEvaluator):
def __init__(self, conf, notifier): def __init__(self, conf, notifier):
super(threshold.ThresholdEvaluator, self).__init__(conf, notifier) super(threshold.ThresholdEvaluator, self).__init__(conf, notifier)
self.gnocchi_url = cfg.CONF.gnocchi_url self.gnocchi_url = cfg.CONF.gnocchi_url
self._ks_client = None
@property
def ks_client(self):
if self._ks_client is None:
self._ks_client = keystone_client.get_client(cfg.CONF)
return self._ks_client
def _get_headers(self, content_type="application/json"): def _get_headers(self, content_type="application/json"):
return { return {

View File

@ -26,6 +26,9 @@ class TestEvaluatorBase(base.BaseTestCase):
self.evaluator = self.EVALUATOR(self.conf, self.notifier) self.evaluator = self.EVALUATOR(self.conf, self.notifier)
self.storage_conn = mock.MagicMock() self.storage_conn = mock.MagicMock()
self.evaluator.storage_conn = self.storage_conn self.evaluator.storage_conn = self.storage_conn
self.evaluator._ks_client = mock.Mock(user_id='fake_user_id',
project_id='fake_project_id',
auth_token='fake_token')
self.prepare_alarms() self.prepare_alarms()
@staticmethod @staticmethod

View File

@ -45,12 +45,6 @@ class TestGnocchiThresholdEvaluate(base.TestEvaluatorBase):
EVALUATOR = gnocchi.GnocchiThresholdEvaluator EVALUATOR = gnocchi.GnocchiThresholdEvaluator
def setUp(self): def setUp(self):
ks_client = mock.Mock(auth_token='fake_token')
ks_client.users.find.return_value = 'gnocchi'
self.useFixture(mockpatch.Patch(
'keystoneclient.v2_0.client.Client',
return_value=ks_client))
super(TestGnocchiThresholdEvaluate, self).setUp() super(TestGnocchiThresholdEvaluate, self).setUp()
self.useFixture(mockpatch.Patch('ceilometerclient.client.get_client', self.useFixture(mockpatch.Patch('ceilometerclient.client.get_client',

View File

@ -15,6 +15,7 @@
"""Tests for aodh/evaluator/threshold.py """Tests for aodh/evaluator/threshold.py
""" """
import datetime import datetime
import json
import uuid import uuid
from ceilometerclient import exc from ceilometerclient import exc
@ -25,6 +26,7 @@ import pytz
from six import moves from six import moves
from aodh.evaluator import threshold from aodh.evaluator import threshold
from aodh import messaging
from aodh.storage import models from aodh.storage import models
from aodh.tests import constants from aodh.tests import constants
from aodh.tests.evaluator import base from aodh.tests.evaluator import base
@ -223,6 +225,59 @@ class TestEvaluate(base.TestEvaluatorBase):
in zip(self.alarms, reasons, reason_datas)] in zip(self.alarms, reasons, reason_datas)]
self.assertEqual(expected, self.notifier.notify.call_args_list) self.assertEqual(expected, self.notifier.notify.call_args_list)
def _construct_payloads(self):
payloads = []
for alarm in self.alarms:
type = models.AlarmChange.STATE_TRANSITION
detail = json.dumps({'state': alarm.state})
on_behalf_of = alarm.project_id
payload = dict(
event_id='fake_event_id_%s' % self.alarms.index(alarm),
alarm_id=alarm.alarm_id,
type=type,
detail=detail,
user_id='fake_user_id',
project_id='fake_project_id',
on_behalf_of=on_behalf_of,
timestamp=datetime.datetime(2015, 7, 26, 3, 33, 21, 876795))
payloads.append(payload)
return payloads
@mock.patch.object(uuid, 'uuid4')
@mock.patch.object(timeutils, 'utcnow')
@mock.patch.object(messaging, 'get_notifier')
def test_alarm_change_record(self, get_notifier, utcnow, mock_uuid):
# the context.RequestContext() method need to generate uuid,
# so we need to provide 'fake_uuid_0' and 'fake_uuid_1' for that.
mock_uuid.side_effect = ['fake_event_id_0', 'fake_uuid_0',
'fake_event_id_1', 'fake_uuid_1']
change_notifier = mock.MagicMock()
get_notifier.return_value = change_notifier
utcnow.return_value = datetime.datetime(2015, 7, 26, 3, 33, 21, 876795)
self._set_all_alarms('ok')
with mock.patch('ceilometerclient.client.get_client',
return_value=self.api_client):
avgs = [self._get_stat('avg', self.alarms[0].rule['threshold'] + v)
for v in moves.xrange(1, 6)]
maxs = [self._get_stat('max', self.alarms[1].rule['threshold'] - v)
for v in moves.xrange(4)]
self.api_client.statistics.list.side_effect = [avgs, maxs]
self._evaluate_all_alarms()
self._assert_all_alarms('alarm')
expected = [mock.call(alarm) for alarm in self.alarms]
update_calls = self.storage_conn.update_alarm.call_args_list
self.assertEqual(expected, update_calls)
payloads = self._construct_payloads()
expected_payloads = [mock.call(p) for p in payloads]
change_records = \
self.storage_conn.record_alarm_change.call_args_list
self.assertEqual(expected_payloads, change_records)
notify_calls = change_notifier.info.call_args_list
notification = "alarm.state_transition"
expected_payloads = [mock.call(mock.ANY, notification, p)
for p in payloads]
self.assertEqual(expected_payloads, notify_calls)
def test_equivocal_from_known_state(self): def test_equivocal_from_known_state(self):
self._set_all_alarms('ok') self._set_all_alarms('ok')
with mock.patch('ceilometerclient.client.get_client', with mock.patch('ceilometerclient.client.get_client',