From 3ab0ede98c6dc0c0327977be994c139113fc0489 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Fri, 27 May 2016 17:07:03 +1200 Subject: [PATCH] Always eager load the raw_template for a stack The vast majority of stack fetches are immediately followed by a raw_template fetch, so this change always eagerly fetches the raw_template for every stack fetch. During stack versioned object creation the stack's raw_template object is used to construct the versioned raw template object. Change-Id: I1a6fb8fb7d069b50dd5d623c989acd5582818ae1 Related-Bug: #1479723 Related-Bug: #1523748 --- heat/db/api.py | 6 ++---- heat/db/sqlalchemy/api.py | 25 ++++++++++++------------- heat/engine/service.py | 6 ++---- heat/engine/service_stack_watch.py | 3 +-- heat/engine/stack.py | 3 +-- heat/engine/watchrule.py | 3 +-- heat/objects/raw_template.py | 10 +++++----- heat/objects/stack.py | 6 ++++-- heat/tests/test_engine_service.py | 4 ++-- 9 files changed, 30 insertions(+), 36 deletions(-) diff --git a/heat/db/api.py b/heat/db/api.py index d9fdd1b074..3956c5ea28 100644 --- a/heat/db/api.py +++ b/heat/db/api.py @@ -156,11 +156,9 @@ def resource_get_by_physical_resource_id(context, physical_resource_id): physical_resource_id) -def stack_get(context, stack_id, show_deleted=False, tenant_safe=True, - eager_load=False): +def stack_get(context, stack_id, show_deleted=False, tenant_safe=True): return IMPL.stack_get(context, stack_id, show_deleted=show_deleted, - tenant_safe=tenant_safe, - eager_load=eager_load) + tenant_safe=tenant_safe) def stack_get_status(context, stack_id): diff --git a/heat/db/sqlalchemy/api.py b/heat/db/sqlalchemy/api.py index 254f4b5b11..a506d952e4 100644 --- a/heat/db/sqlalchemy/api.py +++ b/heat/db/sqlalchemy/api.py @@ -415,28 +415,26 @@ def resource_get_all_by_root_stack(context, stack_id, filters=None): def stack_get_by_name_and_owner_id(context, stack_name, owner_id): query = soft_delete_aware_query( context, models.Stack - ).filter(sqlalchemy.or_( - models.Stack.tenant == context.tenant_id, - models.Stack.stack_user_project_id == context.tenant_id) - ).filter_by(name=stack_name).filter_by(owner_id=owner_id) + ).options(orm.joinedload("raw_template")).filter(sqlalchemy.or_( + models.Stack.tenant == context.tenant_id, + models.Stack.stack_user_project_id == context.tenant_id) + ).filter_by(name=stack_name).filter_by(owner_id=owner_id) return query.first() def stack_get_by_name(context, stack_name): query = soft_delete_aware_query( context, models.Stack - ).filter(sqlalchemy.or_( - models.Stack.tenant == context.tenant_id, - models.Stack.stack_user_project_id == context.tenant_id) - ).filter_by(name=stack_name) + ).options(orm.joinedload("raw_template")).filter(sqlalchemy.or_( + models.Stack.tenant == context.tenant_id, + models.Stack.stack_user_project_id == context.tenant_id) + ).filter_by(name=stack_name) return query.first() -def stack_get(context, stack_id, show_deleted=False, tenant_safe=True, - eager_load=False): - query = context.session.query(models.Stack) - if eager_load: - query = query.options(orm.joinedload("raw_template")) +def stack_get(context, stack_id, show_deleted=False, tenant_safe=True): + query = context.session.query(models.Stack).options( + orm.joinedload("raw_template")) result = query.get(stack_id) deleted_ok = show_deleted or context.show_deleted @@ -569,6 +567,7 @@ def stack_get_all(context, limit=None, sort_keys=None, marker=None, show_hidden=show_hidden, tags=tags, tags_any=tags_any, not_tags=not_tags, not_tags_any=not_tags_any) + query = query.options(orm.joinedload("raw_template")) return _filter_and_page_query(context, query, limit, sort_keys, marker, sort_dir, filters).all() diff --git a/heat/engine/service.py b/heat/engine/service.py index d15c03ee97..29dbd5ae31 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -481,8 +481,7 @@ class EngineService(service.Service): s = stack_object.Stack.get_by_id( cnxt, identity.stack_id, - show_deleted=show_deleted, - eager_load=True) + show_deleted=show_deleted) if s is None: raise exception.EntityNotFound(entity='Stack', @@ -2292,8 +2291,7 @@ class EngineService(service.Service): s = stack_object.Stack.get_by_id( cnxt, stack_id, - tenant_safe=False, - eager_load=True) + tenant_safe=False) if s.status != parser.Stack.IN_PROGRESS: lock.release() continue diff --git a/heat/engine/service_stack_watch.py b/heat/engine/service_stack_watch.py index dc947c7ed2..5d209882e9 100644 --- a/heat/engine/service_stack_watch.py +++ b/heat/engine/service_stack_watch.py @@ -69,8 +69,7 @@ class StackWatch(object): admin_context = context.get_admin_context() db_stack = stack_object.Stack.get_by_id(admin_context, sid, - tenant_safe=False, - eager_load=True) + tenant_safe=False) if not db_stack: LOG.error(_LE("Unable to retrieve stack %s for periodic task"), sid) diff --git a/heat/engine/stack.py b/heat/engine/stack.py index f9542bad8a..d1f62a6e32 100644 --- a/heat/engine/stack.py +++ b/heat/engine/stack.py @@ -487,8 +487,7 @@ class Stack(collections.Mapping): stack = stack_object.Stack.get_by_id( context, stack_id, - show_deleted=show_deleted, - eager_load=True) + show_deleted=show_deleted) if stack is None: message = _('No stack exists with id "%s"') % str(stack_id) raise exception.NotFound(message) diff --git a/heat/engine/watchrule.py b/heat/engine/watchrule.py index 05bc36d011..ec45fad8fb 100644 --- a/heat/engine/watchrule.py +++ b/heat/engine/watchrule.py @@ -265,8 +265,7 @@ class WatchRule(object): else: s = stack_object.Stack.get_by_id( self.context, - self.stack_id, - eager_load=True) + self.stack_id) stk = stack.Stack.load(self.context, stack=s) if (stk.action != stk.DELETE and stk.status == stk.COMPLETE): diff --git a/heat/objects/raw_template.py b/heat/objects/raw_template.py index fee1813788..de1fb48211 100644 --- a/heat/objects/raw_template.py +++ b/heat/objects/raw_template.py @@ -52,7 +52,7 @@ class RawTemplate( } @staticmethod - def _from_db_object(context, tpl, db_tpl): + def from_db_object(context, tpl, db_tpl): for field in tpl.fields: tpl[field] = db_tpl[field] @@ -85,7 +85,7 @@ class RawTemplate( @classmethod def get_by_id(cls, context, template_id): raw_template_db = db_api.raw_template_get(context, template_id) - return cls._from_db_object(context, cls(), raw_template_db) + return cls.from_db_object(context, cls(), raw_template_db) @classmethod def encrypt_hidden_parameters(cls, tmpl): @@ -100,8 +100,8 @@ class RawTemplate( @classmethod def create(cls, context, values): - return cls._from_db_object(context, cls(), - db_api.raw_template_create(context, values)) + return cls.from_db_object(context, cls(), + db_api.raw_template_create(context, values)) @classmethod def update_by_id(cls, context, template_id, values): @@ -109,7 +109,7 @@ class RawTemplate( # table, not in the old location of raw_template.files if 'files_id' in values and values['files_id']: values['files'] = None - return cls._from_db_object( + return cls.from_db_object( context, cls(), db_api.raw_template_update(context, template_id, values)) diff --git a/heat/objects/stack.py b/heat/objects/stack.py index 769dccdcf2..1eeffd5830 100644 --- a/heat/objects/stack.py +++ b/heat/objects/stack.py @@ -68,8 +68,10 @@ class Stack( for field in stack.fields: if field == 'raw_template': stack['raw_template'] = ( - raw_template.RawTemplate.get_by_id( - context, db_stack['raw_template_id'])) + raw_template.RawTemplate.from_db_object( + context, + raw_template.RawTemplate(), + db_stack['raw_template'])) else: stack[field] = db_stack.__dict__.get(field) stack._context = context diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index d45c383b36..0db02a095a 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -1385,8 +1385,8 @@ class StackServiceTest(common.HeatTestCase): tenant_safe=False, show_nested=True) mock_get_by_id.assert_has_calls([ - mock.call(self.ctx, 'foo', tenant_safe=False, eager_load=True), - mock.call(self.ctx, 'bar', tenant_safe=False, eager_load=True), + mock.call(self.ctx, 'foo', tenant_safe=False), + mock.call(self.ctx, 'bar', tenant_safe=False), ]) mock_stack_load.assert_called_once_with(self.ctx, stack=db_stack,