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,
11 This file could manage stack include the function:
12 create stack delete stack and so on"""
18 from heatclient import client as heatclient
19 import common as op_utils
22 log = logging.getLogger(__name__)
25 class HeatObject(object):
26 ''' base class for template and stack'''
28 self._heat_client = None
31 def _get_heat_client(self):
32 '''returns a heat client instance'''
34 if self._heat_client is None:
35 sess = op_utils.get_session()
36 heat_endpoint = op_utils.get_endpoint(service_type='orchestration')
37 self._heat_client = heatclient.Client(
38 op_utils.get_heat_api_version(),
39 endpoint=heat_endpoint, session=sess)
41 return self._heat_client
44 '''returns stack state as a string'''
45 heat = self._get_heat_client()
46 stack = heat.stacks.get(self.uuid)
47 return getattr(stack, 'stack_status')
50 class HeatStack(HeatObject):
51 ''' Represents a Heat stack (deployed template) '''
54 def __init__(self, name):
55 super(HeatStack, self).__init__()
59 HeatStack.stacks.append(self)
63 '''check if any stack has been deployed'''
64 return len(HeatStack.stacks) > 0
67 '''deletes a stack from the target cloud using heat'''
71 log.info("Deleting stack '%s', uuid:%s", self.name, self.uuid)
72 heat = self._get_heat_client()
73 template = heat.stacks.get(self.uuid)
74 start_time = time.time()
76 status = self.status()
78 while status != u'DELETE_COMPLETE':
79 log.debug("stack state %s", status)
80 if status == u'DELETE_FAILED':
82 heat.stacks.get(self.uuid).stack_status_reason)
85 status = self.status()
87 end_time = time.time()
88 log.info("Deleted stack '%s' in %d secs", self.name,
89 end_time - start_time)
92 def delete(self, block=True, retries=3):
93 '''deletes a stack in the target cloud using heat (with retry)
94 Sometimes delete fail with "InternalServerError" and the next attempt
95 succeeds. So it is worthwhile to test a couple of times.
103 except RuntimeError as err:
105 HeatStack.stacks.remove(self)
113 except RuntimeError as err:
118 if self.uuid is not None:
119 sys.exit("delete stack failed!!!")
121 HeatStack.stacks.remove(self)
125 for stack in HeatStack.stacks[:]:
133 class HeatTemplate(HeatObject):
134 '''Describes a Heat template and a method to deploy template to a stack'''
139 heat_parameters=None,
141 super(HeatTemplate, self).__init__()
143 self.state = "NOT_CREATED"
144 self.keystone_client = None
145 self.heat_client = None
146 self.heat_parameters = {}
148 # heat_parameters is passed to heat in stack create, empty dict when
149 # yardstick creates the template (no get_param in resources part)
151 self.heat_parameters = heat_parameters
154 with open(template_file) as template:
155 print "Parsing external template:", template_file
156 template_str = template.read()
157 self._template = template_str
158 self._parameters = heat_parameters
161 self._template = heat_template
163 sys.exit("can't init template file!")
165 # holds results of requested output after deployment
168 log.debug("template object '%s' created", name)
170 def create(self, block=True):
171 '''creates a template in the target cloud using heat
172 returns a dict with the requested output values from the template'''
173 log.info("Creating stack '%s'", self.name)
175 # create stack early to support cleanup, e.g. ctrl-c while waiting
176 stack = HeatStack(self.name)
178 heat = self._get_heat_client()
179 end_time = start_time = time.time()
180 print(self._template)
181 stack.uuid = self.uuid = heat.stacks.create(
182 stack_name=self.name, template=self._template,
183 parameters=self.heat_parameters)['stack']['id']
185 status = self.status()
188 while status != u'CREATE_COMPLETE':
189 log.debug("stack state %s", status)
190 if status == u'CREATE_FAILED':
191 raise RuntimeError(getattr(heat.stacks.get(self.uuid),
192 'stack_status_reason'))
195 status = self.status()
197 end_time = time.time()
198 outputs = getattr(heat.stacks.get(self.uuid), 'outputs')
200 for output in outputs:
201 self.outputs[output["output_key"].encode("ascii")] = \
202 output["output_value"].encode("ascii")
204 log.info("Created stack '%s' in %d secs",
205 self.name, end_time - start_time)
207 stack.outputs = self.outputs