From: Steve Baker Date: Thu, 8 Nov 2012 19:43:23 +0000 (+1300) Subject: Add a list_stacks RPC call. X-Git-Tag: 2014.1~1230 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=e848c080790996e85fbbe0080e50b51d9deab46c;p=openstack-build%2Fheat-build.git Add a list_stacks RPC call. 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 --- diff --git a/heat/api/cfn/v1/stacks.py b/heat/api/cfn/v1/stacks.py index 7c18f541..42f33173 100644 --- a/heat/api/cfn/v1/stacks.py +++ b/heat/api/cfn/v1/stacks.py @@ -125,9 +125,7 @@ class StackController(object): 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) diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py index d32ccf83..7091a6d7 100644 --- a/heat/api/openstack/v1/stacks.py +++ b/heat/api/openstack/v1/stacks.py @@ -229,9 +229,7 @@ class StackController(object): """ 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) diff --git a/heat/engine/parser.py b/heat/engine/parser.py index fc40a032..c0ea0008 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -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 @@ -73,7 +73,10 @@ class Stack(object): 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, @@ -92,7 +95,7 @@ class Stack(object): 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: @@ -102,7 +105,8 @@ class Stack(object): 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 diff --git a/heat/engine/rpcapi.py b/heat/engine/rpcapi.py index ce409f4c..873aef81 100644 --- a/heat/engine/rpcapi.py +++ b/heat/engine/rpcapi.py @@ -70,6 +70,15 @@ class EngineAPI(heat.openstack.common.rpc.proxy.RpcProxy): 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. @@ -77,7 +86,6 @@ class EngineAPI(heat.openstack.common.rpc.proxy.RpcProxy): :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), diff --git a/heat/engine/service.py b/heat/engine/service.py index 36872edb..b7d75460 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -94,12 +94,12 @@ class EngineService(service.Service): """ 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) @@ -107,6 +107,19 @@ class EngineService(service.Service): 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