Cache service availability results per request
Retrieving the list of available resource types seems to be inordinately slow on at least some clouds (though not in our gate tests). It appears that checking service availability is the main culprit. These service availability checks are also performed during validation of a template, so they should be as fast as possible. Previously, we never cached the availability of a service, probably on the assumption that checking the catalog, once retrieved, would be quick. It's not clear that we even need to use the user's token to retrieve the catalog on each request, since all users should see the same catalog. However, at a minimum we can cache the results for the request so that we don't need to do multiple lookups of the same service when validating a single stack or listing the available resource types. This patch does that, and also caches the results of extension lookups in Neutron and Cinder for the duration of the request, independently of the global oslo.cache settings (which, if enabled, can cache the results across requests). Change-Id: I0618dc2a35f7323abedccb13ef3d6537eef1d24c Task: 37974
This commit is contained in:
parent
5e5d97c2b3
commit
758866d890
|
@ -49,6 +49,7 @@ class ClientPlugin(object):
|
|||
self._context = weakref.ref(context)
|
||||
self._clients = weakref.ref(context.clients)
|
||||
self._client_instances = {}
|
||||
self._endpoint_existence = {}
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
|
@ -163,14 +164,18 @@ class ClientPlugin(object):
|
|||
def does_endpoint_exist(self,
|
||||
service_type,
|
||||
service_name):
|
||||
endpoint_type = self._get_client_option(service_name,
|
||||
'endpoint_type')
|
||||
try:
|
||||
self.url_for(service_type=service_type,
|
||||
endpoint_type=endpoint_type)
|
||||
return True
|
||||
except exceptions.EndpointNotFound:
|
||||
return False
|
||||
endpoint_key = (service_type, service_name)
|
||||
if endpoint_key not in self._endpoint_existence:
|
||||
endpoint_type = self._get_client_option(service_name,
|
||||
'endpoint_type')
|
||||
try:
|
||||
self.url_for(service_type=service_type,
|
||||
endpoint_type=endpoint_type)
|
||||
self._endpoint_existence[endpoint_key] = True
|
||||
except exceptions.EndpointNotFound:
|
||||
self._endpoint_existence[endpoint_key] = False
|
||||
|
||||
return self._endpoint_existence[endpoint_key]
|
||||
|
||||
|
||||
def retry_if_connection_err(exception):
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
|
||||
import six
|
||||
|
||||
from oslo_cache import core
|
||||
from oslo_config import cfg
|
||||
|
||||
|
@ -25,3 +29,20 @@ MEMOIZE_FINDER = core.get_memoization_decorator(
|
|||
conf=cfg.CONF,
|
||||
region=cache.get_cache_region(),
|
||||
group="resource_finder_cache")
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ExtensionMixin(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ExtensionMixin, self).__init__(*args, **kwargs)
|
||||
self._extensions = None
|
||||
|
||||
@abc.abstractmethod
|
||||
def _list_extensions(self):
|
||||
return []
|
||||
|
||||
def has_extension(self, alias):
|
||||
"""Check if specific extension is present."""
|
||||
if self._extensions is None:
|
||||
self._extensions = set(self._list_extensions())
|
||||
return alias in self._extensions
|
||||
|
|
|
@ -29,7 +29,8 @@ LOG = logging.getLogger(__name__)
|
|||
CLIENT_NAME = 'cinder'
|
||||
|
||||
|
||||
class CinderClientPlugin(client_plugin.ClientPlugin):
|
||||
class CinderClientPlugin(os_client.ExtensionMixin,
|
||||
client_plugin.ClientPlugin):
|
||||
|
||||
exceptions_module = exceptions
|
||||
|
||||
|
@ -76,10 +77,6 @@ class CinderClientPlugin(client_plugin.ClientPlugin):
|
|||
extensions = self.client().list_extensions.show_all()
|
||||
return set(extension.alias for extension in extensions)
|
||||
|
||||
def has_extension(self, alias):
|
||||
"""Check if specific extension is present."""
|
||||
return alias in self._list_extensions()
|
||||
|
||||
def get_volume(self, volume):
|
||||
try:
|
||||
return self.client().volumes.get(volume)
|
||||
|
|
|
@ -23,7 +23,8 @@ from heat.engine.clients import client_plugin
|
|||
from heat.engine.clients import os as os_client
|
||||
|
||||
|
||||
class NeutronClientPlugin(client_plugin.ClientPlugin):
|
||||
class NeutronClientPlugin(os_client.ExtensionMixin,
|
||||
client_plugin.ClientPlugin):
|
||||
|
||||
exceptions_module = exceptions
|
||||
|
||||
|
@ -117,10 +118,6 @@ class NeutronClientPlugin(client_plugin.ClientPlugin):
|
|||
extensions = self.client().list_extensions().get('extensions')
|
||||
return set(extension.get('alias') for extension in extensions)
|
||||
|
||||
def has_extension(self, alias):
|
||||
"""Check if specific extension is present."""
|
||||
return alias in self._list_extensions()
|
||||
|
||||
def _resolve(self, props, key, id_key, key_type):
|
||||
if props.get(key):
|
||||
props[id_key] = self.find_resourceid_by_name_or_id(key_type,
|
||||
|
|
Loading…
Reference in New Issue