From 2d157539244193ab7cedd890460689ccb170df55 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Tue, 20 Dec 2016 19:24:34 -0500 Subject: [PATCH] Don't create multiple trust IDs per alarm Previously, if an alarm had multiple trust+ actions then we would create a new trust ID for each one. We would also create new trusts for them all each time the alarm was updated (even for actions that hadn't changed). With this change, we will only use a single trust ID for each alarm that contains one or more trust+ actions. Change-Id: Ib556ed3248221d6efb36f2117991c47e665ce336 Partial-Bug: #1575113 --- aodh/api/controllers/v2/alarms.py | 62 ++++++++++++++++++------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/aodh/api/controllers/v2/alarms.py b/aodh/api/controllers/v2/alarms.py index c9466605..b3fe1e3b 100644 --- a/aodh/api/controllers/v2/alarms.py +++ b/aodh/api/controllers/v2/alarms.py @@ -386,6 +386,16 @@ class Alarm(base.Base): def _is_trust_url(url): return url.scheme.startswith('trust+') + def _get_existing_trust_ids(self): + for action in itertools.chain(self.ok_actions or [], + self.alarm_actions or [], + self.insufficient_data_actions or []): + url = netutils.urlsplit(action) + if self._is_trust_url(url): + trust_id = url.username + if trust_id and url.password == 'delete': + yield trust_id + def update_actions(self, old_alarm=None): trustor_user_id = pecan.request.headers.get('X-User-Id') trustor_project_id = pecan.request.headers.get('X-Project-Id') @@ -395,46 +405,48 @@ class Alarm(base.Base): else: roles = [] auth_plugin = pecan.request.environ.get('keystone.token_auth') + + if old_alarm: + prev_trust_ids = set(old_alarm._get_existing_trust_ids()) + else: + prev_trust_ids = set() + trust_id = prev_trust_ids.pop() if prev_trust_ids else None + trust_id_used = False + for actions in (self.ok_actions, self.alarm_actions, self.insufficient_data_actions): if actions is not None: for index, action in enumerate(actions[:]): url = netutils.urlsplit(action) if self._is_trust_url(url): - if '@' not in url.netloc: + if '@' in url.netloc: + continue + if trust_id is None: # We have a trust action without a trust ID, # create it trust_id = keystone_client.create_trust_id( pecan.request.cfg, trustor_user_id, trustor_project_id, roles, auth_plugin) - netloc = '%s:delete@%s' % (trust_id, url.netloc) - url = list(url) - url[1] = netloc - actions[index] = urlparse.urlunsplit(url) - if old_alarm: - new_actions = list(itertools.chain( - self.ok_actions or [], - self.alarm_actions or [], - self.insufficient_data_actions or [])) - for action in itertools.chain( - old_alarm.ok_actions or [], - old_alarm.alarm_actions or [], - old_alarm.insufficient_data_actions or []): - if action not in new_actions: - self.delete_trust(action) + if trust_id_used: + pw = '' + else: + pw = ':delete' + trust_id_used = True + netloc = '%s%s@%s' % (trust_id, pw, url.netloc) + url = urlparse.SplitResult(url.scheme, netloc, + url.path, url.query, + url.fragment) + actions[index] = url.geturl() + if trust_id is not None and not trust_id_used: + prev_trust_ids.add(trust_id) + for old_trust_id in prev_trust_ids: + keystone_client.delete_trust_id(old_trust_id, auth_plugin) def delete_actions(self): - for action in itertools.chain(self.ok_actions or [], - self.alarm_actions or [], - self.insufficient_data_actions or []): - self.delete_trust(action) - - def delete_trust(self, action): auth_plugin = pecan.request.environ.get('keystone.token_auth') - url = netutils.urlsplit(action) - if self._is_trust_url(url) and url.password: - keystone_client.delete_trust_id(url.username, auth_plugin) + for trust_id in self._get_existing_trust_ids(): + keystone_client.delete_trust_id(trust_id, auth_plugin) Alarm.add_attributes(**{"%s_rule" % ext.name: ext.plugin