# Copyright 2018 Nokia # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from datetime import datetime from oslo_log import log as logging from testtools import matchers from vitrage_tempest_plugin.tests.api.event.base import BaseTestEvents from vitrage_tempest_plugin.tests.base import IsEmpty from vitrage_tempest_plugin.tests.common.constants import EntityCategory from vitrage_tempest_plugin.tests.common.constants import VertexProperties \ as VProps from vitrage_tempest_plugin.tests.utils import wait_for_answer LOG = logging.getLogger(__name__) FIRING = 'firing' RESOLVED = 'resolved' class TestPrometheus(BaseTestEvents): """Test class for Prometheus datasource""" def test_send_prometheus_alert_without_resource_id(self): """Sending an alert in Prometheus format should result in an alarm""" self._test_send_prometheus_alert( self._create_prometheus_alert_details('host123', FIRING)) def test_send_prometheus_alert_without_resource_id_v2(self): """Sending an alert in Prometheus format should result in an alarm""" self._test_send_prometheus_alert( self._create_prometheus_alert_details('host457', FIRING)) def _test_send_prometheus_alert(self, details): try: # post an event to the message bus event_time = datetime.now() event_type = 'prometheus.alarm' self._post_event(event_time, event_type, details) api_alarms = wait_for_answer(2, 0.5, self._check_alarms) # expect to get a 'prometheus.alarm', generated by Prometheus # datasource self.assertThat(api_alarms, matchers.HasLength(1), 'Expected Prometheus alarm on host') alarm = api_alarms[0] self._check_alarm(alarm, details) event_time = datetime.now() details['status'] = RESOLVED self._post_event(event_time, event_type, details) api_alarms = wait_for_answer(2, 0.5, self._check_alarms) self.assertIsNotNone(api_alarms,) self.assertThat(api_alarms, IsEmpty(), 'Expected no alarms on ' 'host') except Exception as e: LOG.exception(e) raise def _check_alarm(self, alarm, details): self.assertEqual(EntityCategory.ALARM, alarm[VProps.VITRAGE_CATEGORY]) self.assertEqual(details['status'], alarm['status']) self.assertFalse(alarm[VProps.VITRAGE_IS_DELETED]) self.assertFalse(alarm[VProps.VITRAGE_IS_PLACEHOLDER]) @staticmethod def _create_prometheus_alert_details(hostname, status): return { "status": status, "groupLabels": { "alertname": "HighInodeUsage" }, "groupKey": "{}:{alertname=\"HighInodeUsage\"}", "commonAnnotations": { "mount_point": "/%", "description": "\"Consider ssh\"ing into instance \"\n", "title": "High number of inode usage", "value": "96.81%", "device": "/dev/vda1%", "runbook": "troubleshooting/filesystem_alerts_inodes.md" }, "alerts": [ { "status": status, "labels": { "severity": "critical", "fstype": "ext4", "instance": hostname, "job": "node", "alertname": "HighInodeUsage", "device": "/dev/vda1", "mountpoint": "/" }, "endsAt": "0001-01-01T00:00:00Z", "generatorURL": "http://devstack-4:9090/graph?g0.htm1", "startsAt": "2018-05-03T12:25:38.231388525Z", "annotations": { "mount_point": "/%", "description": "\"Consider ssh\"ing into instance\"\n", "title": "High number of inode usage", "value": "96.81%", "device": "/dev/vda1%", "runbook": "filesystem_alerts_inodes.md" } } ], "version": "4", "receiver": "vitrage", "externalURL": "http://devstack-rocky-4:9093", "commonLabels": { "severity": "critical", "fstype": "ext4", "instance": hostname, "job": "node", "alertname": "HighInodeUsage", "device": "/dev/vda1", "mountpoint": "/" } }