From 3cd84afcfc71ad41dceb15619a3c89ce21db605c Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Thu, 11 Jan 2018 20:11:04 -0500 Subject: [PATCH] Cache the TemplateResource reference ID like an attribute TemplateResources can have their reference ID defined by an OS::stack_id output in the template. However getting it - or just checking that it even exists - is very expensive, and it happens virtually every time we load the stack in memory for any reason. Since when the output is present the reference ID is also available as an attribute, simply cache it in the database as if it were an attribute regardless of whether the output exists. Once it is in the cache, subsequent accesses will be cheap just like they are for attributes. Keep previous performance optimisations in place as well, since attributes are not stored in the database in the legacy path (so legacy stacks don't benefit from this change), and since the cache does get invalidated e.g. on every stack update. Change-Id: Ib9cd0aa40d377ec227754e386e02f185fd871909 Closes-Bug: #1742847 Related-Bug: #1719333 --- heat/engine/resources/template_resource.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/heat/engine/resources/template_resource.py b/heat/engine/resources/template_resource.py index 3435c44ba5..7abf6d2876 100644 --- a/heat/engine/resources/template_resource.py +++ b/heat/engine/resources/template_resource.py @@ -60,8 +60,6 @@ class TemplateResource(stack_resource.StackResource): self.stack = stack self.validation_exception = None - self._reference_id = None - tri = self._get_resource_info(json_snippet) self.properties_schema = {} @@ -308,14 +306,15 @@ class TemplateResource(stack_resource.StackResource): if self.resource_id is None: return six.text_type(self.name) - if self._reference_id is not None: - return self._reference_id + if STACK_ID_OUTPUT in self.attributes.cached_attrs: + return self.attributes.cached_attrs[STACK_ID_OUTPUT] stack_identity = self.nested_identifier() + reference_id = stack_identity.arn() try: if self._outputs is not None: - self._reference_id = self.get_output(STACK_ID_OUTPUT) + reference_id = self.get_output(STACK_ID_OUTPUT) elif STACK_ID_OUTPUT in self.attributes: output = self.rpc_client().show_output(self.context, dict(stack_identity), @@ -325,15 +324,14 @@ class TemplateResource(stack_resource.StackResource): resource=self.name, attribute=STACK_ID_OUTPUT, message=output[rpc_api.OUTPUT_ERROR]) - self._reference_id = output[rpc_api.OUTPUT_VALUE] + reference_id = output[rpc_api.OUTPUT_VALUE] except exception.TemplateOutputError as err: LOG.info('%s', err) except exception.NotFound: pass - else: - return self._reference_id - return stack_identity.arn() + self.attributes.set_cached_attr(STACK_ID_OUTPUT, reference_id) + return reference_id def get_attribute(self, key, *path): if self.resource_id is None: