Skip to content

Commit

Permalink
Add a list_stacks RPC call.
Browse files Browse the repository at this point in the history
This differs from the old show_stack(None) by not resolving stack data.

heat list does not display any of the resolved stack data. Resolving outputs
can be especially slow since FnGetAtt may block while it calls out
to another service (such as with the quantum resources).

Without this change, running heat list on a single Quantum.template takes 1.8s
vs 0.7s.

In the future, list_stacks can be made to support paging of results.

Change-Id: Iae30338b66912d660f1cf48119893b1ab593b67a
  • Loading branch information
steveb committed Nov 8, 2012
1 parent a09a9a2 commit e848c08
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 16 deletions.
4 changes: 1 addition & 3 deletions heat/api/cfn/v1/stacks.py
Expand Up @@ -125,9 +125,7 @@ def format_stack_summary(s):
parms = dict(req.params)

try:
# Note show_stack returns details for all stacks when called with
# no stack_name, we only use a subset of the result here though
stack_list = self.engine_rpcapi.show_stack(con, None)
stack_list = self.engine_rpcapi.list_stacks(con)
except rpc_common.RemoteError as ex:
return exception.map_remote_error(ex)

Expand Down
4 changes: 1 addition & 3 deletions heat/api/openstack/v1/stacks.py
Expand Up @@ -229,9 +229,7 @@ def index(self, req):
"""

try:
# Note show_stack returns details for all stacks when called with
# no stack_name, we only use a subset of the result here though
stack_list = self.engine_rpcapi.show_stack(req.context, None)
stack_list = self.engine_rpcapi.list_stacks(req.context)
except rpc_common.RemoteError as ex:
return self._remote_error(ex, True)

Expand Down
12 changes: 8 additions & 4 deletions heat/engine/parser.py
Expand Up @@ -54,7 +54,7 @@ class Stack(object):

def __init__(self, context, stack_name, tmpl, parameters=None,
stack_id=None, state=None, state_description='',
timeout_mins=60):
timeout_mins=60, resolve_data=True):
'''
Initialise from a context, name, Template object and (optionally)
Parameters object. The database ID may also be initialised, if the
Expand All @@ -73,7 +73,10 @@ def __init__(self, context, stack_name, tmpl, parameters=None,
parameters = Parameters(self.name, self.t)
self.parameters = parameters

self.outputs = self.resolve_static_data(self.t[template.OUTPUTS])
if resolve_data:
self.outputs = self.resolve_static_data(self.t[template.OUTPUTS])
else:
self.outputs = {}

template_resources = self.t[template.RESOURCES]
self.resources = dict((name,
Expand All @@ -92,7 +95,7 @@ def _get_dependencies(resources):
return deps

@classmethod
def load(cls, context, stack_id):
def load(cls, context, stack_id, resolve_data=True):
'''Retrieve a Stack from the database'''
s = db_api.stack_get(context, stack_id)
if s is None:
Expand All @@ -102,7 +105,8 @@ def load(cls, context, stack_id):
template = Template.load(context, s.raw_template_id)
params = Parameters(s.name, template, s.parameters)
stack = cls(context, s.name, template, params,
stack_id, s.status, s.status_reason, s.timeout)
stack_id, s.status, s.status_reason, s.timeout,
resolve_data)

return stack

Expand Down
10 changes: 9 additions & 1 deletion heat/engine/rpcapi.py
Expand Up @@ -70,14 +70,22 @@ def identify_stack(self, ctxt, stack_name):
stack_name=stack_name),
topic=_engine_topic(self.topic, ctxt, None))

def list_stacks(self, ctxt):
"""
The list_stacks method returns the attributes of all stacks.
:param ctxt: RPC context.
"""
return self.call(ctxt, self.make_msg('list_stacks'),
topic=_engine_topic(self.topic, ctxt, None))

def show_stack(self, ctxt, stack_identity):
"""
The show_stack method returns the attributes of one stack.
:param ctxt: RPC context.
:param stack_identity: Name of the stack you want to see,
or None to see all
:param params: Dict of http request parameters passed in from API side.
"""
return self.call(ctxt, self.make_msg('show_stack',
stack_identity=stack_identity),
Expand Down
23 changes: 18 additions & 5 deletions heat/engine/service.py
Expand Up @@ -94,19 +94,32 @@ def show_stack(self, context, stack_identity):
"""
The show_stack method returns the attributes of one stack.
arg1 -> RPC context.
arg2 -> Name of the stack you want to see, or None to see all
arg2 -> Name of the stack you want to see
"""
if stack_identity is not None:
stacks = [self._get_stack(context, stack_identity)]
else:
stacks = db_api.stack_get_by_tenant(context) or []
if stack_identity is None:
raise AttributeError('No stack_identity provided')

stacks = [self._get_stack(context, stack_identity)]

def format_stack_detail(s):
stack = parser.Stack.load(context, s.id)
return api.format_stack(stack)

return {'stacks': [format_stack_detail(s) for s in stacks]}

def list_stacks(self, context):
"""
The list_stacks method returns attributes of all stacks.
arg1 -> RPC context.
"""
stacks = db_api.stack_get_by_tenant(context) or []

def format_stack_detail(s):
stack = parser.Stack.load(context, s.id, resolve_data=False)
return api.format_stack(stack)

return {'stacks': [format_stack_detail(s) for s in stacks]}

def create_stack(self, context, stack_name, template, params, args):
"""
The create_stack method creates a new stack using the template
Expand Down

0 comments on commit e848c08

Please sign in to comment.