diff --git a/aodh/api/controllers/v2/alarms.py b/aodh/api/controllers/v2/alarms.py index af5ce4f09..0174e59ed 100644 --- a/aodh/api/controllers/v2/alarms.py +++ b/aodh/api/controllers/v2/alarms.py @@ -560,6 +560,26 @@ class AlarmController(rest.RestController): payload['detail'] = scrubbed_data _send_notification(type, payload) + def _record_delete(self, alarm): + if not alarm: + return + type = models.AlarmChange.DELETION + detail = {'state': alarm.state} + user_id = pecan.request.headers.get('X-User-Id') + project_id = pecan.request.headers.get('X-Project-Id') + payload = dict(event_id=str(uuid.uuid4()), + alarm_id=self._id, + type=type, + detail=detail, + user_id=user_id, + project_id=project_id, + on_behalf_of=project_id, + timestamp=timeutils.utcnow(), + severity=alarm.severity) + + pecan.request.storage.delete_alarm(alarm.alarm_id) + _send_notification(type, payload) + @wsme_pecan.wsexpose(Alarm) def get(self): """Return this alarm.""" @@ -621,7 +641,7 @@ class AlarmController(rest.RestController): # ensure alarm exists before deleting alarm = self._enforce_rbac('delete_alarm') - pecan.request.storage.delete_alarm(alarm.alarm_id) + self._record_delete(alarm) alarm_object = Alarm.from_db_model(alarm) alarm_object.delete_actions() diff --git a/aodh/storage/models.py b/aodh/storage/models.py index aa1d75337..becce7634 100644 --- a/aodh/storage/models.py +++ b/aodh/storage/models.py @@ -115,6 +115,7 @@ class AlarmChange(base.Model): CREATION = 'creation' RULE_CHANGE = 'rule change' STATE_TRANSITION = 'state transition' + DELETION = 'deletion' SUPPORT_SORT_KEYS = ( 'event_id', 'alarm_id', 'on_behalf_of', 'project_id', 'user_id', diff --git a/aodh/tests/functional/api/v2/test_alarm_scenarios.py b/aodh/tests/functional/api/v2/test_alarm_scenarios.py index c4189ed29..23e541d2b 100644 --- a/aodh/tests/functional/api/v2/test_alarm_scenarios.py +++ b/aodh/tests/functional/api/v2/test_alarm_scenarios.py @@ -186,8 +186,8 @@ class TestAlarmsBase(v2.FunctionalTest): params=data, headers=auth_headers or self.auth_headers) - def _delete_alarm(self, alarm, auth_headers=None): - self.delete('/alarms/%s' % alarm['alarm_id'], + def _delete_alarm(self, id, auth_headers=None): + self.delete('/alarms/%s' % id, headers=auth_headers or self.auth_headers, status=204) @@ -1755,6 +1755,22 @@ class TestAlarms(TestAlarmsBase): 'project_id', 'timestamp', 'type', 'user_id']).issubset(payload.keys())) + def test_delete_alarm_sends_notification(self): + with mock.patch.object(messaging, 'get_notifier') as get_notifier: + notifier = get_notifier.return_value + self._delete_alarm(default_alarms(self.auth_headers)[1].alarm_id) + get_notifier.assert_called_once_with(mock.ANY, + publisher_id='aodh.api') + calls = notifier.info.call_args_list + self.assertEqual(1, len(calls)) + args, _ = calls[0] + context, event_type, payload = args + self.assertEqual('alarm.deletion', event_type) + self.assertEqual('insufficient data', payload['detail']['state']) + self.assertTrue(set(['alarm_id', 'detail', 'event_id', 'on_behalf_of', + 'project_id', 'timestamp', 'type', 'severity', + 'user_id']).issubset(payload.keys())) + class TestAlarmsLegacy(LegacyPolicyFileMixin, TestAlarms): pass