From bcadd55a277b8b8170078f3eca7cfe471456e70b Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Thu, 12 May 2016 16:20:20 -0400 Subject: [PATCH] Lazy-load context information requiring Keystone calls When we load a stored context, don't retrieve additional data from keystone unless and until it is needed. This makes stacks that don't require the full data more efficient, and may help prevent an inability to contact keystone at startup blocking the process of resetting stuck stacks. Change-Id: Ifa8f5f22686a2ee5c30b8cdb42d921163467b64a Co-Authored-By: Thomas Herve Partial-Bug: #1570569 --- heat/common/context.py | 40 ++++++++++++++++++++++++++++++++++++++++ heat/engine/stack.py | 8 +------- heat/tests/test_stack.py | 2 ++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/heat/common/context.py b/heat/common/context.py index a6cca61d5..65e8da2a2 100644 --- a/heat/common/context.py +++ b/heat/common/context.py @@ -238,6 +238,46 @@ class RequestContext(context.RequestContext): return self._auth_plugin +class StoredContext(RequestContext): + def _load_keystone_data(self): + self._keystone_loaded = True + auth_ref = self.clients.client('keystone').auth_ref + + self.roles = auth_ref.role_names + self.user_domain = auth_ref.user_domain_id + self.project_domain = auth_ref.project_domain_id + + @property + def roles(self): + if not getattr(self, '_keystone_loaded', False): + self._load_keystone_data() + return self._roles + + @roles.setter + def roles(self, roles): + self._roles = roles + + @property + def user_domain(self): + if not getattr(self, '_keystone_loaded', False): + self._load_keystone_data() + return self._user_domain + + @user_domain.setter + def user_domain(self, user_domain): + self._user_domain = user_domain + + @property + def project_domain(self): + if not getattr(self, '_keystone_loaded', False): + self._load_keystone_data() + return self._project_domain + + @project_domain.setter + def project_domain(self, project_domain): + self._project_domain = project_domain + + def get_admin_context(show_deleted=False): return RequestContext(is_admin=True, show_deleted=show_deleted) diff --git a/heat/engine/stack.py b/heat/engine/stack.py index 59494a057..537b4bb2a 100644 --- a/heat/engine/stack.py +++ b/heat/engine/stack.py @@ -209,12 +209,6 @@ class Stack(collections.Mapping): if use_stored_context: self.context = self.stored_context() - self.context.roles = self.context.clients.client( - 'keystone').auth_ref.role_names - self.context.user_domain = self.context.clients.client( - 'keystone').auth_ref.user_domain_id - self.context.project_domain = self.context.clients.client( - 'keystone').auth_ref.project_domain_id self.clients = self.context.clients @@ -283,7 +277,7 @@ class Stack(collections.Mapping): creds['is_admin'] = False creds['overwrite'] = False - return common_context.RequestContext.from_dict(creds) + return common_context.StoredContext.from_dict(creds) else: msg = _("Attempt to use stored_context with no user_creds") raise exception.Error(msg) diff --git a/heat/tests/test_stack.py b/heat/tests/test_stack.py index 5c5481a23..cc887c69f 100644 --- a/heat/tests/test_stack.py +++ b/heat/tests/test_stack.py @@ -1337,6 +1337,8 @@ class StackTest(common.HeatTestCase): enforce_type=True) self.m.StubOutWithMock(keystone.KeystoneClientPlugin, '_create') + keystone.KeystoneClientPlugin._create().AndReturn( + fakes.FakeKeystoneClient(user_id='auser123')) keystone.KeystoneClientPlugin._create().AndReturn( fakes.FakeKeystoneClient(user_id='auser123')) self.m.ReplayAll()