1 ##############################################################################
2 # Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
10 """Heat template and stack management"""
16 from heatclient import client as heatclient
17 import common as op_utils
20 log = logging.getLogger(__name__)
23 class HeatObject(object):
24 ''' base class for template and stack'''
26 self._heat_client = None
29 def _get_heat_client(self):
30 '''returns a heat client instance'''
32 if self._heat_client is None:
33 sess = op_utils.get_session()
34 heat_endpoint = op_utils.get_endpoint(service_type='orchestration')
35 self._heat_client = heatclient.Client(
36 op_utils.get_heat_api_version(),
37 endpoint=heat_endpoint, session=sess)
39 return self._heat_client
42 '''returns stack state as a string'''
43 heat = self._get_heat_client()
44 stack = heat.stacks.get(self.uuid)
45 return getattr(stack, 'stack_status')
48 class HeatStack(HeatObject):
49 ''' Represents a Heat stack (deployed template) '''
52 def __init__(self, name):
53 super(HeatStack, self).__init__()
57 HeatStack.stacks.append(self)
61 '''check if any stack has been deployed'''
62 return len(HeatStack.stacks) > 0
65 '''deletes a stack from the target cloud using heat'''
69 log.info("Deleting stack '%s', uuid:%s", self.name, self.uuid)
70 heat = self._get_heat_client()
71 template = heat.stacks.get(self.uuid)
72 start_time = time.time()
74 status = self.status()
76 while status != u'DELETE_COMPLETE':
77 log.debug("stack state %s", status)
78 if status == u'DELETE_FAILED':
80 heat.stacks.get(self.uuid).stack_status_reason)
83 status = self.status()
85 end_time = time.time()
86 log.info("Deleted stack '%s' in %d secs", self.name,
87 end_time - start_time)
90 def delete(self, block=True, retries=3):
91 '''deletes a stack in the target cloud using heat (with retry)
92 Sometimes delete fail with "InternalServerError" and the next attempt
93 succeeds. So it is worthwhile to test a couple of times.
101 except RuntimeError as err:
103 HeatStack.stacks.remove(self)
111 except RuntimeError as err:
116 if self.uuid is not None:
117 sys.exit("delete stack failed!!!")
119 HeatStack.stacks.remove(self)
123 for stack in HeatStack.stacks[:]:
131 class HeatTemplate(HeatObject):
132 '''Describes a Heat template and a method to deploy template to a stack'''
134 def __init__(self, name, template_file=None, heat_parameters=None):
135 super(HeatTemplate, self).__init__()
137 self.state = "NOT_CREATED"
138 self.keystone_client = None
139 self.heat_client = None
140 self.heat_parameters = {}
142 # heat_parameters is passed to heat in stack create, empty dict when
143 # yardstick creates the template (no get_param in resources part)
145 self.heat_parameters = heat_parameters
148 with open(template_file) as template:
149 print "Parsing external template:", template_file
150 template_str = template.read()
151 self._template = template_str
152 self._parameters = heat_parameters
154 sys.exit("\nno such template file.")
156 # holds results of requested output after deployment
159 log.debug("template object '%s' created", name)
161 def create(self, block=True):
162 '''creates a template in the target cloud using heat
163 returns a dict with the requested output values from the template'''
164 log.info("Creating stack '%s'", self.name)
166 # create stack early to support cleanup, e.g. ctrl-c while waiting
167 stack = HeatStack(self.name)
169 heat = self._get_heat_client()
170 end_time = start_time = time.time()
171 print(self._template)
172 stack.uuid = self.uuid = heat.stacks.create(
173 stack_name=self.name, template=self._template,
174 parameters=self.heat_parameters)['stack']['id']
176 status = self.status()
179 while status != u'CREATE_COMPLETE':
180 log.debug("stack state %s", status)
181 if status == u'CREATE_FAILED':
182 raise RuntimeError(getattr(heat.stacks.get(self.uuid),
183 'stack_status_reason'))
186 status = self.status()
188 end_time = time.time()
189 outputs = getattr(heat.stacks.get(self.uuid), 'outputs')
191 for output in outputs:
192 self.outputs[output["output_key"].encode("ascii")] = \
193 output["output_value"].encode("ascii")
195 log.info("Created stack '%s' in %d secs",
196 self.name, end_time - start_time)
198 stack.outputs = self.outputs