summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYadnesh Kulkarni <ykulkarn@redhat.com>2023-04-04 10:51:06 +0530
committerYadnesh Kulkarni <yadnesh_kulkarni@proton.me>2023-04-24 12:54:54 +0530
commit7dbb69e9e2e0b1d563185d3d43509cd223a781aa (patch)
treec986a4d4e7c17a8981f8b8fa91371bf415083d53
parentb21648d45292fd2e80ba3609c6b7d1265fc2f77d (diff)
downloadceilometer-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.py28
-rw-r--r--ceilometer/meter/notifications.py19
-rw-r--r--ceilometer/polling/manager.py35
-rw-r--r--ceilometer/sample.py7
-rw-r--r--ceilometer/tests/unit/meter/test_notifications.py45
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):