Delete its corresponding history data when deleting an alarm
The history data of an alarm will still be stored in storage after the alarm being deleted. that is easy to cause residue issue. Change-Id: I5f6d7a1998104335079b7988e3d0b929b8854b28 Closes-Bug: #1476883
This commit is contained in:
parent
469860fca4
commit
6244caf058
@ -615,10 +615,6 @@ class AlarmController(rest.RestController):
|
|||||||
self.conn.delete_alarm(alarm.alarm_id)
|
self.conn.delete_alarm(alarm.alarm_id)
|
||||||
alarm_object = Alarm.from_db_model(alarm)
|
alarm_object = Alarm.from_db_model(alarm)
|
||||||
alarm_object.delete_actions()
|
alarm_object.delete_actions()
|
||||||
change = alarm_object.as_dict(models.Alarm)
|
|
||||||
self._record_change(change,
|
|
||||||
timeutils.utcnow(),
|
|
||||||
type=models.AlarmChange.DELETION)
|
|
||||||
|
|
||||||
@wsme_pecan.wsexpose([AlarmChange], [base.Query])
|
@wsme_pecan.wsexpose([AlarmChange], [base.Query])
|
||||||
def history(self, q=None):
|
def history(self, q=None):
|
||||||
|
@ -105,7 +105,7 @@ class Connection(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_alarm(alarm_id):
|
def delete_alarm(alarm_id):
|
||||||
"""Delete an alarm."""
|
"""Delete an alarm and its history data."""
|
||||||
raise aodh.NotImplementedError('Alarms not implemented')
|
raise aodh.NotImplementedError('Alarms not implemented')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -112,9 +112,14 @@ class Connection(hbase_base.Connection, base.Connection):
|
|||||||
create_alarm = update_alarm
|
create_alarm = update_alarm
|
||||||
|
|
||||||
def delete_alarm(self, alarm_id):
|
def delete_alarm(self, alarm_id):
|
||||||
|
"""Delete an alarm and its history data."""
|
||||||
with self.conn_pool.connection() as conn:
|
with self.conn_pool.connection() as conn:
|
||||||
alarm_table = conn.table(self.ALARM_TABLE)
|
alarm_table = conn.table(self.ALARM_TABLE)
|
||||||
alarm_table.delete(alarm_id)
|
alarm_table.delete(alarm_id)
|
||||||
|
q = hbase_utils.make_query(alarm_id=alarm_id)
|
||||||
|
alarm_history_table = conn.table(self.ALARM_HISTORY_TABLE)
|
||||||
|
for alarm_id, ignored in alarm_history_table.scan(filter=q):
|
||||||
|
alarm_history_table.delete(alarm_id)
|
||||||
|
|
||||||
def get_alarms(self, name=None, user=None, state=None, meter=None,
|
def get_alarms(self, name=None, user=None, state=None, meter=None,
|
||||||
project=None, enabled=None, alarm_id=None,
|
project=None, enabled=None, alarm_id=None,
|
||||||
|
@ -53,7 +53,7 @@ class Connection(base.Connection):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_alarm(alarm_id):
|
def delete_alarm(alarm_id):
|
||||||
"""Delete an alarm."""
|
"""Delete an alarm and its history data."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clear_expired_alarm_history_data(alarm_history_ttl):
|
def clear_expired_alarm_history_data(alarm_history_ttl):
|
||||||
|
@ -185,7 +185,7 @@ class Connection(base.Connection):
|
|||||||
return self._row_to_alarm_model(alarm_row)
|
return self._row_to_alarm_model(alarm_row)
|
||||||
|
|
||||||
def delete_alarm(self, alarm_id):
|
def delete_alarm(self, alarm_id):
|
||||||
"""Delete an alarm
|
"""Delete an alarm and its history data.
|
||||||
|
|
||||||
:param alarm_id: ID of the alarm to delete
|
:param alarm_id: ID of the alarm to delete
|
||||||
"""
|
"""
|
||||||
@ -193,6 +193,9 @@ class Connection(base.Connection):
|
|||||||
with session.begin():
|
with session.begin():
|
||||||
session.query(models.Alarm).filter(
|
session.query(models.Alarm).filter(
|
||||||
models.Alarm.alarm_id == alarm_id).delete()
|
models.Alarm.alarm_id == alarm_id).delete()
|
||||||
|
# FIXME(liusheng): we should use delete cascade
|
||||||
|
session.query(models.AlarmChange).filter(
|
||||||
|
models.AlarmChange.alarm_id == alarm_id).delete()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _row_to_alarm_change_model(row):
|
def _row_to_alarm_change_model(row):
|
||||||
|
@ -109,7 +109,6 @@ class AlarmChange(base.Model):
|
|||||||
CREATION = 'creation'
|
CREATION = 'creation'
|
||||||
RULE_CHANGE = 'rule change'
|
RULE_CHANGE = 'rule change'
|
||||||
STATE_TRANSITION = 'state transition'
|
STATE_TRANSITION = 'state transition'
|
||||||
DELETION = 'deletion'
|
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
event_id,
|
event_id,
|
||||||
|
@ -77,8 +77,9 @@ class Connection(base.Connection):
|
|||||||
create_alarm = update_alarm
|
create_alarm = update_alarm
|
||||||
|
|
||||||
def delete_alarm(self, alarm_id):
|
def delete_alarm(self, alarm_id):
|
||||||
"""Delete an alarm."""
|
"""Delete an alarm and its history data."""
|
||||||
self.db.alarm.remove({'alarm_id': alarm_id})
|
self.db.alarm.remove({'alarm_id': alarm_id})
|
||||||
|
self.db.alarm_history.remove({'alarm_id': alarm_id})
|
||||||
|
|
||||||
def record_alarm_change(self, alarm_change):
|
def record_alarm_change(self, alarm_change):
|
||||||
"""Record alarm change event."""
|
"""Record alarm change event."""
|
||||||
|
@ -2290,26 +2290,18 @@ class TestAlarms(TestAlarmsBase):
|
|||||||
PayloadMatcher(), mock.ANY)
|
PayloadMatcher(), mock.ANY)
|
||||||
|
|
||||||
def test_alarm_sends_notification(self):
|
def test_alarm_sends_notification(self):
|
||||||
# Hit the AlarmController (with alarm_id supplied) ...
|
alarm = self._get_alarm('a')
|
||||||
data = self.get_json('/alarms')
|
|
||||||
del_alarm_name = "name1"
|
|
||||||
for d in data:
|
|
||||||
if d['name'] == del_alarm_name:
|
|
||||||
del_alarm_id = d['alarm_id']
|
|
||||||
|
|
||||||
with mock.patch.object(messaging, 'get_notifier') as get_notifier:
|
with mock.patch.object(messaging, 'get_notifier') as get_notifier:
|
||||||
notifier = get_notifier.return_value
|
notifier = get_notifier.return_value
|
||||||
|
self._update_alarm(alarm, dict(name='new_name'))
|
||||||
self.delete('/alarms/%s' % del_alarm_id,
|
|
||||||
headers=self.auth_headers, status=204)
|
|
||||||
get_notifier.assert_called_once_with(mock.ANY,
|
get_notifier.assert_called_once_with(mock.ANY,
|
||||||
publisher_id='aodh.api')
|
publisher_id='aodh.api')
|
||||||
calls = notifier.info.call_args_list
|
calls = notifier.info.call_args_list
|
||||||
self.assertEqual(1, len(calls))
|
self.assertEqual(1, len(calls))
|
||||||
args, _ = calls[0]
|
args, _ = calls[0]
|
||||||
context, event_type, payload = args
|
context, event_type, payload = args
|
||||||
self.assertEqual('alarm.deletion', event_type)
|
self.assertEqual('alarm.rule_change', event_type)
|
||||||
self.assertEqual(del_alarm_name, payload['detail']['name'])
|
self.assertEqual('new_name', payload['detail']['name'])
|
||||||
self.assertTrue(set(['alarm_id', 'detail', 'event_id', 'on_behalf_of',
|
self.assertTrue(set(['alarm_id', 'detail', 'event_id', 'on_behalf_of',
|
||||||
'project_id', 'timestamp', 'type',
|
'project_id', 'timestamp', 'type',
|
||||||
'user_id']).issubset(payload.keys()))
|
'user_id']).issubset(payload.keys()))
|
||||||
@ -2710,7 +2702,7 @@ class TestAlarmsHistory(TestAlarmsBase):
|
|||||||
history = self._get_alarm_history(self._get_alarm('a'), auth)
|
history = self._get_alarm_history(self._get_alarm('a'), auth)
|
||||||
self.assertEqual([], history)
|
self.assertEqual([], history)
|
||||||
|
|
||||||
def test_get_recorded_alarm_history_preserved_after_deletion(self):
|
def test_delete_alarm_history_after_deletion(self):
|
||||||
alarm = self._get_alarm('a')
|
alarm = self._get_alarm('a')
|
||||||
history = self._get_alarm_history(alarm)
|
history = self._get_alarm_history(alarm)
|
||||||
self.assertEqual([], history)
|
self.assertEqual([], history)
|
||||||
@ -2722,45 +2714,24 @@ class TestAlarmsHistory(TestAlarmsBase):
|
|||||||
headers=self.auth_headers,
|
headers=self.auth_headers,
|
||||||
status=204)
|
status=204)
|
||||||
history = self._get_alarm_history(alarm)
|
history = self._get_alarm_history(alarm)
|
||||||
self.assertEqual(2, len(history))
|
self.assertEqual(0, len(history))
|
||||||
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
|
||||||
on_behalf_of=alarm['project_id'],
|
|
||||||
project_id=alarm['project_id'],
|
|
||||||
type='deletion',
|
|
||||||
user_id=alarm['user_id']),
|
|
||||||
history[0])
|
|
||||||
alarm['rule'] = alarm['threshold_rule']
|
|
||||||
del alarm['threshold_rule']
|
|
||||||
self._assert_in_json(alarm, history[0]['detail'])
|
|
||||||
detail = '{"name": "renamed"}'
|
|
||||||
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
|
||||||
detail=detail,
|
|
||||||
on_behalf_of=alarm['project_id'],
|
|
||||||
project_id=alarm['project_id'],
|
|
||||||
type='rule change',
|
|
||||||
user_id=alarm['user_id']),
|
|
||||||
history[1])
|
|
||||||
|
|
||||||
def test_get_alarm_history_ordered_by_recentness(self):
|
def test_get_alarm_history_ordered_by_recentness(self):
|
||||||
alarm = self._get_alarm('a')
|
alarm = self._get_alarm('a')
|
||||||
for i in moves.xrange(10):
|
for i in moves.xrange(10):
|
||||||
self._update_alarm(alarm, dict(name='%s' % i))
|
self._update_alarm(alarm, dict(name='%s' % i))
|
||||||
alarm = self._get_alarm('a')
|
alarm = self._get_alarm('a')
|
||||||
self._delete_alarm(alarm)
|
|
||||||
history = self._get_alarm_history(alarm)
|
history = self._get_alarm_history(alarm)
|
||||||
self.assertEqual(11, len(history), 'hist: %s' % history)
|
self.assertEqual(10, len(history), 'hist: %s' % history)
|
||||||
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
||||||
type='deletion'),
|
type='rule change'),
|
||||||
history[0])
|
history[0])
|
||||||
alarm['rule'] = alarm['threshold_rule']
|
for i in moves.xrange(1, 11):
|
||||||
del alarm['threshold_rule']
|
|
||||||
self._assert_in_json(alarm, history[0]['detail'])
|
|
||||||
for i in moves.xrange(1, 10):
|
|
||||||
detail = '{"name": "%s"}' % (10 - i)
|
detail = '{"name": "%s"}' % (10 - i)
|
||||||
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
||||||
detail=detail,
|
detail=detail,
|
||||||
type='rule change'),
|
type='rule change'),
|
||||||
history[i])
|
history[i - 1])
|
||||||
|
|
||||||
def test_get_alarm_history_constrained_by_timestamp(self):
|
def test_get_alarm_history_constrained_by_timestamp(self):
|
||||||
alarm = self._get_alarm('a')
|
alarm = self._get_alarm('a')
|
||||||
@ -2783,19 +2754,18 @@ class TestAlarmsHistory(TestAlarmsBase):
|
|||||||
|
|
||||||
def test_get_alarm_history_constrained_by_type(self):
|
def test_get_alarm_history_constrained_by_type(self):
|
||||||
alarm = self._get_alarm('a')
|
alarm = self._get_alarm('a')
|
||||||
self._delete_alarm(alarm)
|
self._update_alarm(alarm, dict(name='renamed2'))
|
||||||
query = dict(field='type', op='eq', value='deletion')
|
query = dict(field='type', op='eq', value='rule change')
|
||||||
history = self._get_alarm_history(alarm, query=query)
|
history = self._get_alarm_history(alarm, query=query)
|
||||||
self.assertEqual(1, len(history))
|
self.assertEqual(1, len(history))
|
||||||
|
detail = '{"name": "renamed2"}'
|
||||||
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
self._assert_is_subset(dict(alarm_id=alarm['alarm_id'],
|
||||||
|
detail=detail,
|
||||||
on_behalf_of=alarm['project_id'],
|
on_behalf_of=alarm['project_id'],
|
||||||
project_id=alarm['project_id'],
|
project_id=alarm['project_id'],
|
||||||
type='deletion',
|
type='rule change',
|
||||||
user_id=alarm['user_id']),
|
user_id=alarm['user_id']),
|
||||||
history[0])
|
history[0])
|
||||||
alarm['rule'] = alarm['threshold_rule']
|
|
||||||
del alarm['threshold_rule']
|
|
||||||
self._assert_in_json(alarm, history[0]['detail'])
|
|
||||||
|
|
||||||
def test_get_alarm_history_constrained_by_alarm_id_failed(self):
|
def test_get_alarm_history_constrained_by_alarm_id_failed(self):
|
||||||
alarm = self._get_alarm('a')
|
alarm = self._get_alarm('a')
|
||||||
|
@ -288,6 +288,17 @@ class AlarmHistoryTest(AlarmTestBase,
|
|||||||
utcnow = datetime.datetime(2014, 4, 7, 7, 45)
|
utcnow = datetime.datetime(2014, 4, 7, 7, 45)
|
||||||
self._clear_alarm_history(utcnow, 3 * 60, 0)
|
self._clear_alarm_history(utcnow, 3 * 60, 0)
|
||||||
|
|
||||||
|
def test_delete_history_when_delete_alarm(self):
|
||||||
|
alarms = list(self.alarm_conn.get_alarms())
|
||||||
|
self.assertEqual(3, len(alarms))
|
||||||
|
history = list(self.alarm_conn.query_alarm_history())
|
||||||
|
self.assertEqual(3, len(history))
|
||||||
|
for alarm in alarms:
|
||||||
|
self.alarm_conn.delete_alarm(alarm.alarm_id)
|
||||||
|
self.assertEqual(3, len(alarms))
|
||||||
|
history = list(self.alarm_conn.query_alarm_history())
|
||||||
|
self.assertEqual(0, len(history))
|
||||||
|
|
||||||
|
|
||||||
class ComplexAlarmQueryTest(AlarmTestBase,
|
class ComplexAlarmQueryTest(AlarmTestBase,
|
||||||
tests_db.MixinTestsWithBackendScenarios):
|
tests_db.MixinTestsWithBackendScenarios):
|
||||||
@ -416,24 +427,9 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
|
|||||||
|
|
||||||
self.alarm_conn.record_alarm_change(alarm_change=alarm_change3)
|
self.alarm_conn.record_alarm_change(alarm_change=alarm_change3)
|
||||||
|
|
||||||
if alarm.name in ["red-alert", "yellow-alert"]:
|
|
||||||
alarm_change4 = dict(event_id=(
|
|
||||||
"16fd2706-8baf-433b-82eb-8c7fada847f%s"
|
|
||||||
% i),
|
|
||||||
alarm_id=alarm.alarm_id,
|
|
||||||
type=alarm_models.AlarmChange.DELETION,
|
|
||||||
detail="detail %s" % (i + 2),
|
|
||||||
user_id=alarm.user_id,
|
|
||||||
project_id=alarm.project_id,
|
|
||||||
on_behalf_of=alarm.project_id,
|
|
||||||
timestamp=datetime.datetime(2012, 9, 27,
|
|
||||||
10 + i,
|
|
||||||
30 + i))
|
|
||||||
self.alarm_conn.record_alarm_change(alarm_change=alarm_change4)
|
|
||||||
|
|
||||||
def test_alarm_history_with_no_filter(self):
|
def test_alarm_history_with_no_filter(self):
|
||||||
history = list(self.alarm_conn.query_alarm_history())
|
history = list(self.alarm_conn.query_alarm_history())
|
||||||
self.assertEqual(11, len(history))
|
self.assertEqual(9, len(history))
|
||||||
|
|
||||||
def test_alarm_history_with_no_filter_and_limit(self):
|
def test_alarm_history_with_no_filter_and_limit(self):
|
||||||
history = list(self.alarm_conn.query_alarm_history(limit=3))
|
history = list(self.alarm_conn.query_alarm_history(limit=3))
|
||||||
@ -481,9 +477,8 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
|
|||||||
filter_expr = {"=": {"alarm_id": "r3d"}}
|
filter_expr = {"=": {"alarm_id": "r3d"}}
|
||||||
history = list(self.alarm_conn.query_alarm_history(
|
history = list(self.alarm_conn.query_alarm_history(
|
||||||
filter_expr=filter_expr, orderby=[{"timestamp": "asc"}]))
|
filter_expr=filter_expr, orderby=[{"timestamp": "asc"}]))
|
||||||
self.assertEqual(4, len(history))
|
self.assertEqual(3, len(history))
|
||||||
self.assertEqual([alarm_models.AlarmChange.CREATION,
|
self.assertEqual([alarm_models.AlarmChange.CREATION,
|
||||||
alarm_models.AlarmChange.RULE_CHANGE,
|
alarm_models.AlarmChange.RULE_CHANGE,
|
||||||
alarm_models.AlarmChange.STATE_TRANSITION,
|
alarm_models.AlarmChange.STATE_TRANSITION],
|
||||||
alarm_models.AlarmChange.DELETION],
|
|
||||||
[h.type for h in history])
|
[h.type for h in history])
|
||||||
|
Loading…
Reference in New Issue
Block a user