summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYadnesh Kulkarni <ykulkarn@redhat.com>2022-11-08 03:01:11 -0500
committerYadnesh Kulkarni <ykulkarn@redhat.com>2022-11-21 09:17:08 -0500
commitb4a2801ec6a99df400d353d27a11de9be879c2a3 (patch)
treeb80e121031f6968850dbebc4a62dc0bf82861171
parent9fe3674e4705837ef4dbe1a4cd433e6bfd5f9fbd (diff)
downloadceilometer-b4a2801ec6a99df400d353d27a11de9be879c2a3.tar.gz
Change oslo_cache implementation
As of now to leverage caching, oslo_cache library has to be imported and configured everytime it's needed. This change migrates such implementatio to use `cache_utils.py` which returns a cache client to perform caching operations. This eliminates the purpose of importing oslo_cache everytime when needed. To get a cache client: ``` from ceilometer import cache_utils . cache_client = cache_utils.get_client(conf) ``` Signed-off-by: Yadnesh Kulkarni <ykulkarn@redhat.com> Change-Id: I14f9e1cbe84a953b092c3a88345d5faa9bcc9fb2
-rw-r--r--ceilometer/cache_utils.py55
-rw-r--r--ceilometer/polling/manager.py15
-rw-r--r--ceilometer/publisher/gnocchi.py31
-rw-r--r--ceilometer/tests/unit/test_cache_utils.py65
4 files changed, 117 insertions, 49 deletions
diff --git a/ceilometer/cache_utils.py b/ceilometer/cache_utils.py
index 55a9e263..31c1c0e9 100644
--- a/ceilometer/cache_utils.py
+++ b/ceilometer/cache_utils.py
@@ -14,9 +14,22 @@
# under the License.
"""Simple wrapper for oslo_cache."""
-
+import uuid
from oslo_cache import core as cache
+from oslo_cache import exception
+from oslo_log import log
+from oslo_utils.secretutils import md5
+
+# Default cache expiration period
+CACHE_DURATION = 86400
+
+NAME_ENCODED = __name__.encode('utf-8')
+CACHE_NAMESPACE = uuid.UUID(
+ bytes=md5(NAME_ENCODED, usedforsecurity=False).digest()
+)
+
+LOG = log.getLogger(__name__)
class CacheClient(object):
@@ -36,18 +49,30 @@ class CacheClient(object):
return self.region.delete(key)
-def get_client(conf, expiration_time=0):
+def get_client(conf):
cache.configure(conf)
- if conf.cache.enabled:
- return CacheClient(_get_default_cache_region(
- conf,
- expiration_time=expiration_time
- ))
-
-
-def _get_default_cache_region(conf, expiration_time):
- region = cache.create_region()
- if expiration_time != 0:
- conf.cache.expiration_time = expiration_time
- cache.configure_cache_region(conf, region)
- return region
+ if 'cache' in conf.keys() and conf.cache.enabled:
+ region = get_cache_region(conf)
+ if region:
+ return CacheClient(region)
+
+
+def get_cache_region(conf):
+ # Set expiration time to default CACHE_DURATION if missing in conf
+ if not conf.cache.expiration_time:
+ conf.cache.expiration_time = CACHE_DURATION
+
+ try:
+ region = cache.create_region()
+ cache.configure_cache_region(conf, region)
+ cache.key_mangler = cache_key_mangler
+ return region
+ except exception.ConfigurationError as e:
+ LOG.error("failed to configure oslo_cache. %s", str(e))
+ LOG.warning("using keystone to identify names from polled samples")
+
+
+def cache_key_mangler(key):
+ """Construct an opaque cache key."""
+
+ return uuid.uuid5(CACHE_NAMESPACE, key).hex
diff --git a/ceilometer/polling/manager.py b/ceilometer/polling/manager.py
index 3545801f..5835fe25 100644
--- a/ceilometer/polling/manager.py
+++ b/ceilometer/polling/manager.py
@@ -46,8 +46,6 @@ from ceilometer import utils
LOG = log.getLogger(__name__)
-CACHE_DURATION = 3600
-
POLLING_OPTS = [
cfg.StrOpt('cfg_file',
default="polling.yaml",
@@ -154,10 +152,7 @@ class PollingTask(object):
self.ks_client = self.manager.keystone
- self.cache_client = cache_utils.get_client(
- self.manager.conf,
- expiration_time=CACHE_DURATION
- )
+ self.cache_client = cache_utils.get_client(self.manager.conf)
def add(self, pollster, source):
self.pollster_matches[source.name].add(pollster)
@@ -169,9 +164,11 @@ class PollingTask(object):
name = self.cache_client.get(uuid)
if name:
return name
- name = self.resolve_uuid_from_keystone(attr, uuid)
- self.cache_client.set(uuid, 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
diff --git a/ceilometer/publisher/gnocchi.py b/ceilometer/publisher/gnocchi.py
index 2741ba00..355f5320 100644
--- a/ceilometer/publisher/gnocchi.py
+++ b/ceilometer/publisher/gnocchi.py
@@ -14,39 +14,29 @@
# under the License.
from collections import defaultdict
import fnmatch
-import hashlib
import itertools
import json
import operator
import pkg_resources
import threading
-import uuid
from gnocchiclient import exceptions as gnocchi_exc
from keystoneauth1 import exceptions as ka_exceptions
-import oslo_cache
from oslo_log import log
from oslo_utils import timeutils
from stevedore import extension
from urllib import parse as urlparse
+from ceilometer import cache_utils
from ceilometer import declarative
from ceilometer import gnocchi_client
from ceilometer.i18n import _
from ceilometer import keystone_client
from ceilometer import publisher
-NAME_ENCODED = __name__.encode('utf-8')
-CACHE_NAMESPACE = uuid.UUID(bytes=hashlib.md5(NAME_ENCODED).digest())
LOG = log.getLogger(__name__)
-def cache_key_mangler(key):
- """Construct an opaque cache key."""
-
- return uuid.uuid5(CACHE_NAMESPACE, key).hex
-
-
EVENT_CREATE, EVENT_UPDATE, EVENT_DELETE = ("create", "update", "delete")
@@ -213,20 +203,11 @@ class GnocchiPublisher(publisher.ConfigPublisherBase):
timeout = options.get('timeout', [6.05])[-1]
self._ks_client = keystone_client.get_client(conf)
- self.cache = None
- try:
- oslo_cache.configure(conf)
- # NOTE(cdent): The default cache backend is a real but
- # noop backend. We don't want to use that here because
- # we want to avoid the cache pathways entirely if the
- # cache has not been configured explicitly.
- if conf.cache.enabled:
- cache_region = oslo_cache.create_region()
- self.cache = oslo_cache.configure_cache_region(
- conf, cache_region)
- self.cache.key_mangler = cache_key_mangler
- except oslo_cache.exception.ConfigurationError as exc:
- LOG.warning('unable to configure oslo_cache: %s', exc)
+ # NOTE(cdent): The default cache backend is a real but
+ # noop backend. We don't want to use that here because
+ # we want to avoid the cache pathways entirely if the
+ # cache has not been configured explicitly.
+ self.cache = cache_utils.get_client(conf)
self._gnocchi_project_id = None
self._gnocchi_project_id_lock = threading.Lock()
diff --git a/ceilometer/tests/unit/test_cache_utils.py b/ceilometer/tests/unit/test_cache_utils.py
new file mode 100644
index 00000000..245eaa34
--- /dev/null
+++ b/ceilometer/tests/unit/test_cache_utils.py
@@ -0,0 +1,65 @@
+#
+# Copyright 2022 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.
+
+from ceilometer import cache_utils
+from ceilometer import service as ceilometer_service
+from oslo_cache import core as cache
+from oslo_config import fixture as config_fixture
+from oslotest import base
+
+
+class CacheConfFixture(config_fixture.Config):
+ def setUp(self):
+ super(CacheConfFixture, self).setUp()
+ self.conf = ceilometer_service.\
+ prepare_service(argv=[], config_files=[])
+ cache.configure(self.conf)
+ self.config(enabled=True, group='cache')
+
+
+class TestOsloCache(base.BaseTestCase):
+ def setUp(self):
+ super(TestOsloCache, self).setUp()
+
+ conf = ceilometer_service.prepare_service(argv=[], config_files=[])
+
+ dict_conf_fixture = CacheConfFixture(conf)
+ self.useFixture(dict_conf_fixture)
+ dict_conf_fixture.config(expiration_time=600,
+ backend='oslo_cache.dict',
+ group='cache')
+ self.dict_conf = dict_conf_fixture.conf
+
+ # enable_retry_client is only supported by
+ # 'dogpile.cache.pymemcache' backend which makes this
+ # incorrect config
+ faulty_conf_fixture = CacheConfFixture(conf)
+ self.useFixture(faulty_conf_fixture)
+ faulty_conf_fixture.config(expiration_time=600,
+ backend='dogpile.cache.memcached',
+ group='cache',
+ enable_retry_client='true')
+ self.faulty_cache_conf = faulty_conf_fixture.conf
+
+ self.no_cache_conf = ceilometer_service.\
+ prepare_service(argv=[], config_files=[])
+
+ def test_get_cache_region(self):
+ self.assertIsNotNone(cache_utils.get_cache_region(self.dict_conf))
+
+ def test_get_client(self):
+ self.assertIsNotNone(cache_utils.get_client(self.dict_conf))
+ self.assertIsNone(cache_utils.get_client(self.no_cache_conf))
+ self.assertIsNone(cache_utils.get_client(self.faulty_cache_conf))