From 23e06f66b9e0ccb667c24318764da72aa82d4e18 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Mon, 20 Nov 2017 15:06:13 -0500 Subject: [PATCH] Speed up event listing with nested stacks When handling the command "openstack stack event list --nested-depth=n", we obtain the list of nested stacks by querying the database for all resources that share the root stack ID. However, since all we're getting is the stack IDs, there's no need to query all of the fields and construct a versioned object for each resource. Just get the set of stack IDs. Change-Id: I12155433e2ac1af919aa4b5e780fb965cd5885d8 Related-Bug: #1588561 --- heat/db/sqlalchemy/api.py | 11 +++++++---- heat/engine/service.py | 8 ++++---- heat/objects/resource.py | 14 ++++++++++---- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/heat/db/sqlalchemy/api.py b/heat/db/sqlalchemy/api.py index 0be4b9686b..1da9bb0903 100644 --- a/heat/db/sqlalchemy/api.py +++ b/heat/db/sqlalchemy/api.py @@ -496,15 +496,18 @@ def resource_get_all_active_by_stack(context, stack_id): def resource_get_all_by_root_stack(context, stack_id, filters=None, - eager=True): + stack_id_only=False): query = context.session.query( models.Resource ).filter_by( root_stack_id=stack_id - ).options(orm.joinedload("data")) + ) - if eager: - query = query.options(orm.joinedload("rsrc_prop_data")) + if stack_id_only: + query = query.options(orm.load_only("id", "stack_id")) + else: + query = query.options(orm.joinedload("data")).options( + orm.joinedload("rsrc_prop_data")) query = db_filters.exact_filter(query, models.Resource, filters) results = query.all() diff --git a/heat/engine/service.py b/heat/engine/service.py index e9e054e49d..15f2425838 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -1744,12 +1744,12 @@ class EngineService(service.ServiceBase): if nested_depth: root_stack_identifier = st.identifier() - # find all resources associated with a root stack - all_r = resource_objects.Resource.get_all_by_root_stack( - cnxt, st.id, None, eager=False) + # find all stacks with resources associated with a root stack + ResObj = resource_objects.Resource + stack_ids = ResObj.get_all_stack_ids_by_root_stack(cnxt, + st.id) # find stacks to the requested nested_depth - stack_ids = {r.stack_id for r in six.itervalues(all_r)} stack_filters = { 'id': stack_ids, 'nested_depth': list(range(nested_depth + 1)) diff --git a/heat/objects/resource.py b/heat/objects/resource.py index 2e3e6c31fb..ef4992ac50 100644 --- a/heat/objects/resource.py +++ b/heat/objects/resource.py @@ -264,18 +264,24 @@ class Resource( return dict(resources) @classmethod - def get_all_by_root_stack(cls, context, stack_id, filters, cache=False, - eager=True): + def get_all_by_root_stack(cls, context, stack_id, filters, cache=False): resources_db = db_api.resource_get_all_by_root_stack( context, stack_id, - filters, - eager=eager) + filters) all = cls._resources_to_dict(context, resources_db) if cache: context.cache(ResourceCache).set_by_stack_id(all) return all + @classmethod + def get_all_stack_ids_by_root_stack(cls, context, stack_id): + resources_db = db_api.resource_get_all_by_root_stack( + context, + stack_id, + stack_id_only=True) + return {db_res.stack_id for db_res in six.itervalues(resources_db)} + @classmethod def purge_deleted(cls, context, stack_id): return db_api.resource_purge_deleted(context, stack_id)