From cd0db8b76661507dd99d7bdbbdc1bbed03fd802d Mon Sep 17 00:00:00 2001 From: Jaromir Wysoglad Date: Tue, 21 Jan 2025 15:12:04 -0500 Subject: [PATCH] Poll for evaluation metrics from aodh Change-Id: I584c3859d8c214100c7077dc6fec665a0e93b898 --- ceilometer/alarm/__init__.py | 0 ceilometer/alarm/aodh.py | 57 +++++++++++++++++ ceilometer/alarm/discovery.py | 40 ++++++++++++ ceilometer/opts.py | 4 +- ceilometer/polling/prom_exporter.py | 3 + ceilometer/tests/unit/alarm/__init__.py | 0 ceilometer/tests/unit/alarm/test_aodh.py | 64 +++++++++++++++++++ doc/source/admin/telemetry-measurements.rst | 16 +++++ .../add-aodh-metrics-afbe9b780fd137d6.yaml | 5 ++ requirements.txt | 1 + setup.cfg | 2 + 11 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 ceilometer/alarm/__init__.py create mode 100644 ceilometer/alarm/aodh.py create mode 100644 ceilometer/alarm/discovery.py create mode 100644 ceilometer/tests/unit/alarm/__init__.py create mode 100644 ceilometer/tests/unit/alarm/test_aodh.py create mode 100644 releasenotes/notes/add-aodh-metrics-afbe9b780fd137d6.yaml diff --git a/ceilometer/alarm/__init__.py b/ceilometer/alarm/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ceilometer/alarm/aodh.py b/ceilometer/alarm/aodh.py new file mode 100644 index 0000000000..c1391c3a7e --- /dev/null +++ b/ceilometer/alarm/aodh.py @@ -0,0 +1,57 @@ +# +# Copyright 2025 Red Hat, Inc +# +# 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. +"""Common code for working with alarm metrics +""" +from ceilometer.polling import plugin_base +from ceilometer import sample + +DEFAULT_GROUP = "service_credentials" + + +class _Base(plugin_base.PollsterBase): + @property + def default_discovery(self): + return 'alarm' + + +class EvaluationResultPollster(_Base): + @staticmethod + def get_evaluation_results_metrics(metrics): + evaluation_metrics = [] + if "evaluation_results" in metrics: + for metric in metrics["evaluation_results"]: + for state, count in metric["state_counters"].items(): + evaluation_metrics.append({ + "name": "evaluation_result", + "state": state, + "count": count, + "project_id": metric['project_id'], + "alarm_id": metric['alarm_id'] + }) + return evaluation_metrics + + def get_samples(self, manager, cache, resources): + metrics = self.get_evaluation_results_metrics(resources[0]) + for metric in metrics: + yield sample.Sample( + name='alarm.' + metric['name'], + type=sample.TYPE_GAUGE, + volume=int(metric['count']), + unit='evaluation_result_count', + user_id=None, + project_id=metric['project_id'], + resource_id=metric['alarm_id'], + resource_metadata={"alarm_state": metric['state']}, + ) diff --git a/ceilometer/alarm/discovery.py b/ceilometer/alarm/discovery.py new file mode 100644 index 0000000000..85d854cf0c --- /dev/null +++ b/ceilometer/alarm/discovery.py @@ -0,0 +1,40 @@ +# +# 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 aodhclient import client as aodh_client +from oslo_config import cfg + +from ceilometer import keystone_client +from ceilometer.polling import plugin_base + +SERVICE_OPTS = [ + cfg.StrOpt('aodh', + default='alarming', + help='Aodh service type.'), +] + + +class AlarmDiscovery(plugin_base.DiscoveryBase): + def __init__(self, conf): + super().__init__(conf) + creds = conf.service_credentials + self.aodh_client = aodh_client.Client( + version='2', + session=keystone_client.get_session(conf), + region_name=creds.region_name, + interface=creds.interface, + service_type=conf.service_types.aodh) + + def discover(self, manager, param=None): + """Discover resources to monitor.""" + return [self.aodh_client.metrics.get(all_projects=True)] diff --git a/ceilometer/opts.py b/ceilometer/opts.py index cd540b1d64..a8b2398bee 100644 --- a/ceilometer/opts.py +++ b/ceilometer/opts.py @@ -17,6 +17,7 @@ import socket from keystoneauth1 import loading from oslo_config import cfg +import ceilometer.alarm.discovery import ceilometer.cmd.polling import ceilometer.compute.discovery import ceilometer.compute.virt.inspector @@ -100,7 +101,8 @@ def list_opts(): ('rgw_admin_credentials', ceilometer.objectstore.rgw.CREDENTIAL_OPTS), ('rgw_client', ceilometer.objectstore.rgw.CLIENT_OPTS), ('service_types', - itertools.chain(ceilometer.image.discovery.SERVICE_OPTS, + itertools.chain(ceilometer.alarm.discovery.SERVICE_OPTS, + ceilometer.image.discovery.SERVICE_OPTS, ceilometer.neutron_client.SERVICE_OPTS, ceilometer.nova_client.SERVICE_OPTS, ceilometer.objectstore.rgw.SERVICE_OPTS, diff --git a/ceilometer/polling/prom_exporter.py b/ceilometer/polling/prom_exporter.py index 9e42456efa..cf266ca921 100644 --- a/ceilometer/polling/prom_exporter.py +++ b/ceilometer/polling/prom_exporter.py @@ -136,5 +136,8 @@ def _gen_labels(sample): else: labels['keys'].append('server_group') labels['values'].append('none') + if resource_metadata.get('alarm_state', '') != '': + labels['keys'].append('state') + labels['values'].append(resource_metadata['alarm_state']) return labels diff --git a/ceilometer/tests/unit/alarm/__init__.py b/ceilometer/tests/unit/alarm/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ceilometer/tests/unit/alarm/test_aodh.py b/ceilometer/tests/unit/alarm/test_aodh.py new file mode 100644 index 0000000000..ae3ca3eaad --- /dev/null +++ b/ceilometer/tests/unit/alarm/test_aodh.py @@ -0,0 +1,64 @@ +# +# Copyright 2012 New Dream Network, LLC (DreamHost) +# +# 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 ceilometer.alarm import aodh +from ceilometer.polling import manager +from ceilometer import service +import ceilometer.tests.base as base + +ALARM_METRIC_LIST = [ + { + 'evaluation_results': [{ + 'alarm_id': 'b8e17f58-089a-43fc-a96b-e9bcac4d4b53', + 'project_id': '2dd8edd6c8c24f49bf04670534f6b357', + 'state_counters': { + 'ok': 2, + 'alarm': 5, + 'insufficient data': 0, + } + }, { + 'alarm_id': 'fa386719-67e3-42ff-aec8-17e547dac77a', + 'project_id': 'd45b070bcce04ca99546128a40854e7c', + 'state_counters': { + 'ok': 50, + 'alarm': 3, + 'insufficient data': 10, + } + }], + }, +] + + +class TestAlarmEvaluationResultPollster(base.BaseTestCase): + def setUp(self): + super().setUp() + conf = service.prepare_service([], []) + self.manager = manager.AgentManager(0, conf) + self.pollster = aodh.EvaluationResultPollster(conf) + + def test_alarm_pollster(self): + alarm_samples = list( + self.pollster.get_samples(self.manager, + {}, + resources=ALARM_METRIC_LIST)) + self.assertEqual(6, len(alarm_samples)) + self.assertEqual('alarm.evaluation_result', alarm_samples[0].name) + self.assertEqual(2, alarm_samples[0].volume) + self.assertEqual('2dd8edd6c8c24f49bf04670534f6b357', + alarm_samples[0].project_id) + self.assertEqual('b8e17f58-089a-43fc-a96b-e9bcac4d4b53', + alarm_samples[0].resource_id) + self.assertEqual('ok', + alarm_samples[0].resource_metadata['alarm_state']) diff --git a/doc/source/admin/telemetry-measurements.rst b/doc/source/admin/telemetry-measurements.rst index 3bda071092..2a63236f80 100644 --- a/doc/source/admin/telemetry-measurements.rst +++ b/doc/source/admin/telemetry-measurements.rst @@ -634,3 +634,19 @@ The following meters are collected for FWaaS: | ices.firewal\ | | ll_pol\ | | | firewall policy | | l.policy | | icy | | | | +---------------+-------+---------+------------+-----------+------------------+ + +Openstack alarming +~~~~~~~~~~~~~~~~~~ + +The following meters are collected for Aodh: + ++---------------+-------+---------+------------+-----------+------------------+ +| Name | Type | Unit | Resource | Origin | Note | ++===============+=======+=========+============+===========+==================+ +| **Meters added in the Flamingo release** | ++---------------+-------+---------+------------+-----------+------------------+ +| alarm.evalua\ | Gauge | evalua\ | alarm ID | Pollster | Total count of | +| tion_result | | tion_r\ | | | evaluation | +| | | esult\_\| | | results for each | +| | | count | | | alarm | ++---------------+-------+---------+------------+-----------+------------------+ diff --git a/releasenotes/notes/add-aodh-metrics-afbe9b780fd137d6.yaml b/releasenotes/notes/add-aodh-metrics-afbe9b780fd137d6.yaml new file mode 100644 index 0000000000..e6021692e8 --- /dev/null +++ b/releasenotes/notes/add-aodh-metrics-afbe9b780fd137d6.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Ceilometer is now able to poll the /metrics endpoint in Aodh to get + evaluation results metrics. diff --git a/requirements.txt b/requirements.txt index aff1c869e3..dc4aba795e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,3 +37,4 @@ gnocchiclient>=7.0.0 # Apache-2.0 python-zaqarclient>=1.3.0 # Apache-2.0 prometheus_client>=0.20.0 # Apache-2.0 requests-aws>=0.1.4 # BSD License (3 clause) +aodhclient>=3.8.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg index 8f598bbc3c..252c12669f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,6 +63,7 @@ ceilometer.discover.central = volume_pools = ceilometer.volume.discovery:VolumePoolsDiscovery volume_snapshots = ceilometer.volume.discovery:VolumeSnapshotsDiscovery volume_backups = ceilometer.volume.discovery:VolumeBackupsDiscovery + alarm = ceilometer.alarm.discovery:AlarmDiscovery ceilometer.discover.ipmi = local_node = ceilometer.polling.discovery.localnode:LocalNodeDiscovery @@ -118,6 +119,7 @@ ceilometer.poll.ipmi = hardware.ipmi.power = ceilometer.ipmi.pollsters.sensor:PowerSensorPollster ceilometer.poll.central = + alarm.evaluation_result = ceilometer.alarm.aodh:EvaluationResultPollster ip.floating = ceilometer.network.floatingip:FloatingIPPollster image.size = ceilometer.image.glance:ImageSizePollster radosgw.containers.objects = ceilometer.objectstore.rgw:ContainersObjectsPollster