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
This commit is contained in:
Zane Bitter 2017-11-20 15:06:13 -05:00
parent dbc852b47a
commit 23e06f66b9
3 changed files with 21 additions and 12 deletions

View File

@ -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()

View File

@ -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))

View File

@ -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)