diff options
author | Yadnesh Kulkarni <ykulkarn@redhat.com> | 2023-04-04 10:51:06 +0530 |
---|---|---|
committer | Yadnesh Kulkarni <yadnesh_kulkarni@proton.me> | 2023-04-24 12:54:54 +0530 |
commit | 7dbb69e9e2e0b1d563185d3d43509cd223a781aa (patch) | |
tree | c986a4d4e7c17a8981f8b8fa91371bf415083d53 | |
parent | b21648d45292fd2e80ba3609c6b7d1265fc2f77d (diff) | |
download | ceilometer-stable/wallaby.tar.gz |
Add vanity names to notification samplesstable/wallaby
This change adds "project_name" and "user_name" fields to the
polling samples created from notifications of "event_type".
Also move caching helper functions into "ceilometer/cache_utils.py"
to make them accessible throughout the project.
Conflicts:
ceilometer/tests/unit/meter/test_notifications.py
Change-Id: I68bd4ee096b28a2fd952e749d56a6b3eed9bfb94
(cherry picked from commit 6e339d3e74df5460d372b3e2abce27664ddb1100)
(cherry picked from commit d9a61da15033a55b5730974a9c6a4868c1d98d0f)
(cherry picked from commit 600dbfab1e227efc16b03b693d08354eaf1d0f98)
(cherry picked from commit 5191f9466a7a36e3b9c2cc48227cfe40d234bd9f)
(cherry picked from commit 3d03c31ae69b65033da653c6a8b205d54737fa08)
-rw-r--r-- | ceilometer/cache_utils.py | 28 | ||||
-rw-r--r-- | ceilometer/meter/notifications.py | 19 | ||||
-rw-r--r-- | ceilometer/polling/manager.py | 35 | ||||
-rw-r--r-- | ceilometer/sample.py | 7 | ||||
-rw-r--r-- | ceilometer/tests/unit/meter/test_notifications.py | 45 |
5 files changed, 88 insertions, 46 deletions
diff --git a/ceilometer/cache_utils.py b/ceilometer/cache_utils.py index 31c1c0e9..f3fbd187 100644 --- a/ceilometer/cache_utils.py +++ b/ceilometer/cache_utils.py @@ -16,6 +16,8 @@ """Simple wrapper for oslo_cache.""" import uuid +from ceilometer import keystone_client +from keystoneauth1 import exceptions as ka_exceptions from oslo_cache import core as cache from oslo_cache import exception from oslo_log import log @@ -76,3 +78,29 @@ def cache_key_mangler(key): """Construct an opaque cache key.""" return uuid.uuid5(CACHE_NAMESPACE, key).hex + + +def resolve_uuid_from_cache(conf, attr, uuid): + # empty cache_client means either caching is not enabled or + # there was an error configuring cache + cache_client = get_client(conf) + if cache_client: + resource_name = cache_client.get(uuid) + if resource_name: + return resource_name + + # Retrieve project and user names from Keystone only + # if ceilometer doesn't have a caching backend + resource_name = resolve_uuid_from_keystone(conf, attr, uuid) + if cache_client: + cache_client.set(uuid, resource_name) + return resource_name + + +def resolve_uuid_from_keystone(conf, attr, uuid): + try: + return getattr(keystone_client.get_client(conf), attr).get(uuid).name + except AttributeError as e: + LOG.warning("Found '%s' while resolving uuid %s to name", e, uuid) + except ka_exceptions.NotFound as e: + LOG.warning(e.message) diff --git a/ceilometer/meter/notifications.py b/ceilometer/meter/notifications.py index 72fb7a1f..6dc0e209 100644 --- a/ceilometer/meter/notifications.py +++ b/ceilometer/meter/notifications.py @@ -15,6 +15,7 @@ import itertools import os import re +from ceilometer import cache_utils from oslo_config import cfg from oslo_log import log from stevedore import extension @@ -165,8 +166,22 @@ class MeterDefinition(object): # NOTE(sileht): Transform the sample with multiple values per # attribute into multiple samples with one value per attribute. for values in zip(*samples_values): - yield dict((attributes[idx], value) - for idx, value in enumerate(values)) + sample = dict((attributes[idx], value) + for idx, value in enumerate(values)) + + # populate user_name and project_name fields in the sample + # created from notifications + if sample['user_id']: + sample['user_name'] = \ + cache_utils.resolve_uuid_from_cache( + self.conf, 'users', sample['user_id'] + ) + if sample['project_id']: + sample['project_name'] = \ + cache_utils.resolve_uuid_from_cache( + self.conf, 'projects', sample['project_id'] + ) + yield sample else: yield sample diff --git a/ceilometer/polling/manager.py b/ceilometer/polling/manager.py index 10d1cd91..323cd411 100644 --- a/ceilometer/polling/manager.py +++ b/ceilometer/polling/manager.py @@ -159,29 +159,6 @@ class PollingTask(object): key = Resources.key(source.name, pollster) self.resources[key].setup(source) - def resolve_uuid_from_cache(self, attr, uuid): - if self.cache_client: - name = self.cache_client.get(uuid) - if name: - return name - # empty cache_client means either caching is not enabled or - # there was an error configuring cache - name = self.resolve_uuid_from_keystone(attr, uuid) - self.cache_client.set(uuid, name) - return name - - # Retrieve project and user names from Keystone only - # if ceilometer doesn't have a caching backend - return self.resolve_uuid_from_keystone(attr, uuid) - - def resolve_uuid_from_keystone(self, attr, uuid): - try: - return getattr(self.ks_client, attr).get(uuid).name - except AttributeError as e: - LOG.warning("Found '%s' while resolving uuid %s to name", e, uuid) - except ka_exceptions.NotFound as e: - LOG.warning(e.message) - def poll_and_notify(self): """Polling sample and notify.""" cache = {} @@ -240,16 +217,20 @@ class PollingTask(object): # and then keystone if sample.project_id: sample.project_name = \ - self.resolve_uuid_from_cache( - "projects", sample.project_id + cache_utils.resolve_uuid_from_cache( + self.manager.conf, + "projects", + sample.project_id ) # Try to resolve user UUIDs from cache first, # and then keystone if sample.user_id: sample.user_name = \ - self.resolve_uuid_from_cache( - "users", sample.user_id + cache_utils.resolve_uuid_from_cache( + self.manager.conf, + "users", + sample.user_id ) sample_dict = ( diff --git a/ceilometer/sample.py b/ceilometer/sample.py index 536b561d..91059176 100644 --- a/ceilometer/sample.py +++ b/ceilometer/sample.py @@ -121,7 +121,8 @@ class Sample(object): @classmethod def from_notification(cls, name, type, volume, unit, user_id, project_id, resource_id, - message, timestamp=None, metadata=None, source=None): + message, timestamp=None, metadata=None, source=None, + user_name=None, project_name=None): if not metadata: metadata = (copy.copy(message['payload']) if isinstance(message['payload'], dict) else {}) @@ -138,7 +139,9 @@ class Sample(object): resource_id=resource_id, timestamp=ts, resource_metadata=metadata, - source=source) + source=source, + user_name=user_name, + project_name=project_name) def set_timestamp(self, timestamp): self.timestamp = timestamp diff --git a/ceilometer/tests/unit/meter/test_notifications.py b/ceilometer/tests/unit/meter/test_notifications.py index ea3299c3..1435fb3e 100644 --- a/ceilometer/tests/unit/meter/test_notifications.py +++ b/ceilometer/tests/unit/meter/test_notifications.py @@ -139,22 +139,26 @@ MIDDLEWARE_EVENT = { FULL_MULTI_MSG = { 'event_type': u'full.sample', 'payload': [{ - u'counter_name': u'instance1', - u'user_id': u'user1', - u'resource_id': u'res1', - u'counter_unit': u'ns', - u'counter_volume': 28.0, - u'project_id': u'proj1', - u'counter_type': u'gauge' + 'counter_name': 'instance1', + 'user_id': 'user1', + 'user_name': 'test-resource', + 'resource_id': 'res1', + 'counter_unit': 'ns', + 'counter_volume': 28.0, + 'project_id': 'proj1', + 'project_name': 'test-resource', + 'counter_type': 'gauge' }, { - u'counter_name': u'instance2', - u'user_id': u'user2', - u'resource_id': u'res2', - u'counter_unit': u'%', - u'counter_volume': 1.0, - u'project_id': u'proj2', - u'counter_type': u'delta' + 'counter_name': 'instance2', + 'user_id': 'user2', + 'user_name': 'test-resource', + 'resource_id': 'res2', + 'counter_unit': '%', + 'counter_volume': 1.0, + 'project_id': 'proj2', + 'project_name': 'test-resource', + 'counter_type': 'delta' }], u'ctxt': {u'domain': None, u'request_id': u'req-da91b4bf-d2b5-43ae-8b66-c7752e72726d', @@ -615,7 +619,16 @@ class TestMeterProcessing(test.BaseTestCase): c = list(self.handler.build_sample(event)) self.assertEqual(0, len(c)) - def test_multi_meter_payload_all_multi(self): + @mock.patch('ceilometer.cache_utils.resolve_uuid_from_cache') + def test_multi_meter_payload_all_multi(self, fake_cached_resource_name): + + # return "test-resource" as the name of the user and project from cache + fake_cached_resource_name.return_value = "test-resource" + + # expect user_name and project_name values to be set to "test-resource" + fake_user_name = "test-resource" + fake_project_name = "test-resource" + cfg = yaml.dump( {'metric': [dict(name="$.payload.[*].counter_name", event_type="full.sample", @@ -640,6 +653,8 @@ class TestMeterProcessing(test.BaseTestCase): self.assertEqual(msg[idx]['resource_id'], s1['resource_id']) self.assertEqual(msg[idx]['project_id'], s1['project_id']) self.assertEqual(msg[idx]['user_id'], s1['user_id']) + self.assertEqual(fake_user_name, s1['user_name']) + self.assertEqual(fake_project_name, s1['project_name']) @mock.patch('ceilometer.meter.notifications.LOG') def test_multi_meter_payload_invalid_missing(self, LOG): |