175 lines
6.4 KiB
Python
175 lines
6.4 KiB
Python
# Copyright 2010 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
"""Super simple fake memcache client."""
|
|
|
|
import copy
|
|
|
|
from oslo_cache import core as cache
|
|
from oslo_config import cfg
|
|
|
|
from nova.i18n import _
|
|
|
|
|
|
# NOTE(dims): There are many copies of memcache_opts with memcached_servers
|
|
# in various projects as this used to be in a copy of memory_cache.py
|
|
# Since we are making a change in just our copy, oslo-config-generator fails
|
|
# with cfg.DuplicateOptError unless we override the comparison check
|
|
class _DeprecatedListOpt(cfg.ListOpt):
|
|
def __ne__(self, another):
|
|
self_dict = copy.deepcopy(vars(self))
|
|
another_dict = copy.deepcopy(vars(another))
|
|
self_dict.pop('help')
|
|
self_dict.pop('deprecated_for_removal')
|
|
another_dict.pop('help')
|
|
another_dict.pop('deprecated_for_removal')
|
|
return self_dict != another_dict
|
|
|
|
|
|
memcache_opts = [
|
|
_DeprecatedListOpt('memcached_servers',
|
|
help='DEPRECATED: Memcached servers or None for in '
|
|
'process cache. "memcached_servers" opt is '
|
|
'deprecated in Mitaka. In Newton release '
|
|
'oslo.cache config options should be used as '
|
|
'this option will be removed. Please add a '
|
|
'[cache] group in your nova.conf file and '
|
|
'add "enable" and "memcache_servers" option in '
|
|
'this section.',
|
|
deprecated_for_removal=True),
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(memcache_opts)
|
|
|
|
WEEK = 604800
|
|
|
|
|
|
def list_opts():
|
|
"""Entry point for oslo-config-generator."""
|
|
return [(None, copy.deepcopy(memcache_opts))]
|
|
|
|
|
|
def get_memcached_client(expiration_time=0):
|
|
"""Used ONLY when memcached is explicitly needed."""
|
|
# If the operator uses the old style [DEFAULT]/memcached_servers
|
|
# then we just respect that setting
|
|
if CONF.memcached_servers:
|
|
return CacheClient(
|
|
_get_custom_cache_region(expiration_time=expiration_time,
|
|
backend='dogpile.cache.memcached',
|
|
url=CONF.memcached_servers))
|
|
# If the operator still uses the new style [cache]/memcache_servers
|
|
# and has [cache]/enabled flag on then we let oslo_cache configure
|
|
# the region from the configuration settings
|
|
elif CONF.cache.enabled and CONF.cache.memcache_servers:
|
|
return CacheClient(
|
|
_get_default_cache_region(expiration_time=expiration_time))
|
|
raise RuntimeError(_('memcached_servers not defined'))
|
|
|
|
|
|
def get_client(expiration_time=0):
|
|
"""Used to get a caching client."""
|
|
# If the operator still uses the old style [DEFAULT]/memcached_servers
|
|
# then we just respect that setting
|
|
if CONF.memcached_servers:
|
|
return CacheClient(
|
|
_get_custom_cache_region(expiration_time=expiration_time,
|
|
backend='dogpile.cache.memcached',
|
|
url=CONF.memcached_servers))
|
|
# If the operator has [cache]/enabled flag on then we let oslo_cache
|
|
# configure the region from configuration settings.
|
|
elif CONF.cache.enabled:
|
|
return CacheClient(
|
|
_get_default_cache_region(expiration_time=expiration_time))
|
|
# If [cache]/enabled flag is off and [DEFAULT]/memcached_servers is
|
|
# absent we use the dictionary backend
|
|
return CacheClient(
|
|
_get_custom_cache_region(expiration_time=expiration_time,
|
|
backend='oslo_cache.dict'))
|
|
|
|
|
|
def _get_default_cache_region(expiration_time):
|
|
region = cache.create_region()
|
|
if expiration_time != 0:
|
|
CONF.cache.expiration_time = expiration_time
|
|
cache.configure_cache_region(CONF, region)
|
|
return region
|
|
|
|
|
|
def _get_custom_cache_region(expiration_time=WEEK,
|
|
backend=None,
|
|
url=None):
|
|
"""Create instance of oslo_cache client.
|
|
|
|
For backends you can pass specific parameters by kwargs.
|
|
For 'dogpile.cache.memcached' backend 'url' parameter must be specified.
|
|
|
|
:param backend: backend name
|
|
:param expiration_time: interval in seconds to indicate maximum
|
|
time-to-live value for each key
|
|
:param url: memcached url(s)
|
|
"""
|
|
|
|
region = cache.create_region()
|
|
region_params = {}
|
|
if expiration_time != 0:
|
|
region_params['expiration_time'] = expiration_time
|
|
|
|
if backend == 'oslo_cache.dict':
|
|
region_params['arguments'] = {'expiration_time': expiration_time}
|
|
elif backend == 'dogpile.cache.memcached':
|
|
region_params['arguments'] = {'url': url}
|
|
else:
|
|
raise RuntimeError(_('old style configuration can use '
|
|
'only dictionary or memcached backends'))
|
|
|
|
region.configure(backend, **region_params)
|
|
return region
|
|
|
|
|
|
class CacheClient(object):
|
|
"""Replicates a tiny subset of memcached client interface."""
|
|
|
|
def __init__(self, region):
|
|
self.region = region
|
|
|
|
def get(self, key):
|
|
value = self.region.get(key)
|
|
if value == cache.NO_VALUE:
|
|
return None
|
|
return value
|
|
|
|
def get_or_create(self, key, creator):
|
|
return self.region.get_or_create(key, creator)
|
|
|
|
def set(self, key, value):
|
|
return self.region.set(key, value)
|
|
|
|
def add(self, key, value):
|
|
return self.region.get_or_create(key, lambda: value)
|
|
|
|
def delete(self, key):
|
|
return self.region.delete(key)
|
|
|
|
def get_multi(self, keys):
|
|
values = self.region.get_multi(keys)
|
|
return [None if value is cache.NO_VALUE else value for value in
|
|
values]
|
|
|
|
def delete_multi(self, keys):
|
|
return self.region.delete_multi(keys)
|