blob: 8c1cd53f90acd4388c7f81ad178bbbcae85547e6 [file] [log] [blame]
Steve Baker10a4bc42015-07-23 10:21:02 +12001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
Thomas Herve2ce4bda2016-01-22 17:55:55 +010013import json
14import os
Steve Baker9d3cd4f2015-08-07 10:45:26 +120015import requests
Thomas Herve2ce4bda2016-01-22 17:55:55 +010016import subprocess
Thomas Herve4d1362b2017-03-24 10:33:01 +010017import sys
Thomas Herve2ce4bda2016-01-22 17:55:55 +010018import tempfile
Steve Baker9d3cd4f2015-08-07 10:45:26 +120019import time
20import yaml
21
Thomas Herve2ce4bda2016-01-22 17:55:55 +010022from oslo_utils import timeutils
23
Steve Baker9d3cd4f2015-08-07 10:45:26 +120024from heat_integrationtests.common import exceptions
rabi6ce8d962017-07-10 16:40:12 +053025from heat_integrationtests.common import test
Rabi Mishra477efc92015-07-31 13:01:45 +053026from heat_integrationtests.functional import functional_base
Steve Baker10a4bc42015-07-23 10:21:02 +120027
28
Rabi Mishra477efc92015-07-31 13:01:45 +053029class ParallelDeploymentsTest(functional_base.FunctionalTestsBase):
Steve Baker9d3cd4f2015-08-07 10:45:26 +120030 server_template = '''
Steve Baker10a4bc42015-07-23 10:21:02 +120031heat_template_version: "2013-05-23"
32parameters:
33 flavor:
34 type: string
35 image:
36 type: string
37 network:
38 type: string
39resources:
40 server:
41 type: OS::Nova::Server
42 properties:
43 image: {get_param: image}
44 flavor: {get_param: flavor}
45 user_data_format: SOFTWARE_CONFIG
Steve Baker9d3cd4f2015-08-07 10:45:26 +120046 networks: [{network: {get_param: network}}]
47outputs:
48 server:
49 value: {get_resource: server}
50'''
51
52 config_template = '''
53heat_template_version: "2013-05-23"
54parameters:
55 server:
56 type: string
57resources:
Steve Baker10a4bc42015-07-23 10:21:02 +120058 config:
59 type: OS::Heat::SoftwareConfig
60 properties:
Steve Baker10a4bc42015-07-23 10:21:02 +120061'''
62
Steve Baker9d3cd4f2015-08-07 10:45:26 +120063 deployment_snippet = '''
64type: OS::Heat::SoftwareDeployments
65properties:
66 config: {get_resource: config}
67 servers: {'0': {get_param: server}}
68'''
Steve Baker10a4bc42015-07-23 10:21:02 +120069
Steve Baker9d3cd4f2015-08-07 10:45:26 +120070 enable_cleanup = True
71
72 def test_deployments_metadata(self):
Steve Baker10a4bc42015-07-23 10:21:02 +120073 parms = {'flavor': self.conf.minimal_instance_type,
74 'network': self.conf.fixed_network_name,
75 'image': self.conf.minimal_image_ref}
76 stack_identifier = self.stack_create(
77 parameters=parms,
Steve Baker9d3cd4f2015-08-07 10:45:26 +120078 template=self.server_template,
79 enable_cleanup=self.enable_cleanup)
80 server_stack = self.client.stacks.get(stack_identifier)
81 server = server_stack.outputs[0]['output_value']
82
83 config_stacks = []
84 # add up to 3 stacks each with up to 3 deployments
85 deploy_count = 0
86 deploy_count = self.deploy_many_configs(
87 stack_identifier,
88 server,
89 config_stacks,
90 2,
91 5,
92 deploy_count)
Oleksii Chuprykova064e282015-08-30 09:05:32 +030093 self.deploy_many_configs(
Steve Baker9d3cd4f2015-08-07 10:45:26 +120094 stack_identifier,
95 server,
96 config_stacks,
97 3,
98 3,
99 deploy_count)
100
101 self.signal_deployments(stack_identifier)
102 for config_stack in config_stacks:
103 self._wait_for_stack_status(config_stack, 'CREATE_COMPLETE')
104
rabi6ce8d962017-07-10 16:40:12 +0530105 def test_deployments_timeout_failed(self):
106 parms = {'flavor': self.conf.minimal_instance_type,
107 'network': self.conf.fixed_network_name,
108 'image': self.conf.minimal_image_ref}
109 stack_identifier = self.stack_create(
110 parameters=parms,
111 template=self.server_template,
112 enable_cleanup=self.enable_cleanup)
113 server_stack = self.client.stacks.get(stack_identifier)
114 server = server_stack.outputs[0]['output_value']
115 config_stack = self.deploy_config(server, 3, 1)
116 self._wait_for_stack_status(config_stack, 'CREATE_FAILED')
117 kwargs = {'server_id': server}
118
119 def check_deployment_status():
120 sd_list = self.client.software_deployments.list(**kwargs)
121 for sd in sd_list:
122 if sd.status != 'FAILED':
123 return False
124 return True
125
126 self.assertTrue(test.call_until_true(
127 20, 0, check_deployment_status))
128
Oleksii Chuprykova064e282015-08-30 09:05:32 +0300129 def deploy_many_configs(self, stack, server, config_stacks,
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200130 stack_count, deploys_per_stack,
131 deploy_count_start):
132 for a in range(stack_count):
133 config_stacks.append(
134 self.deploy_config(server, deploys_per_stack))
135
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200136 new_count = deploy_count_start + stack_count * deploys_per_stack
Oleksii Chuprykova064e282015-08-30 09:05:32 +0300137 self.wait_for_deploy_metadata_set(stack, new_count)
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200138 return new_count
139
rabi6ce8d962017-07-10 16:40:12 +0530140 def deploy_config(self, server, deploy_count, timeout=None):
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200141 parms = {'server': server}
142 template = yaml.safe_load(self.config_template)
143 resources = template['resources']
144 resources['config']['properties'] = {'config': 'x' * 10000}
145 for a in range(deploy_count):
146 resources['dep_%s' % a] = yaml.safe_load(self.deployment_snippet)
147 return self.stack_create(
148 parameters=parms,
149 template=template,
150 enable_cleanup=self.enable_cleanup,
rabi6ce8d962017-07-10 16:40:12 +0530151 expected_status=None,
152 timeout=timeout)
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200153
Oleksii Chuprykova064e282015-08-30 09:05:32 +0300154 def wait_for_deploy_metadata_set(self, stack, deploy_count):
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200155 build_timeout = self.conf.build_timeout
156 build_interval = self.conf.build_interval
157
158 start = timeutils.utcnow()
159 while timeutils.delta_seconds(start,
160 timeutils.utcnow()) < build_timeout:
Oleksii Chuprykova064e282015-08-30 09:05:32 +0300161 server_metadata = self.client.resources.metadata(
162 stack, 'server')
163 if len(server_metadata['deployments']) == deploy_count:
Steve Baker9d3cd4f2015-08-07 10:45:26 +1200164 return
165 time.sleep(build_interval)
166
167 message = ('Deployment resources failed to be created within '
168 'the required time (%s s).' %
169 (build_timeout))
170 raise exceptions.TimeoutException(message)
171
172 def signal_deployments(self, stack_identifier):
173 server_metadata = self.client.resources.metadata(
174 stack_identifier, 'server')
175 for dep in server_metadata['deployments']:
176 iv = dict((i['name'], i['value']) for i in dep['inputs'])
177 sigurl = iv.get('deploy_signal_id')
178 requests.post(sigurl, data='{}',
rabi10a9b102017-01-12 08:09:11 +0530179 headers={'content-type': 'application/json'},
tyagi39aa11a2016-03-07 04:47:00 -0800180 verify=self.verify_cert)
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100181
182
183class ZaqarSignalTransportTest(functional_base.FunctionalTestsBase):
184 server_template = '''
185heat_template_version: "2013-05-23"
186
187parameters:
188 flavor:
189 type: string
190 image:
191 type: string
192 network:
193 type: string
194
195resources:
196 server:
197 type: OS::Nova::Server
198 properties:
199 image: {get_param: image}
200 flavor: {get_param: flavor}
201 user_data_format: SOFTWARE_CONFIG
202 software_config_transport: ZAQAR_MESSAGE
203 networks: [{network: {get_param: network}}]
204 config:
205 type: OS::Heat::SoftwareConfig
206 properties:
207 config: echo 'foo'
208 deployment:
209 type: OS::Heat::SoftwareDeployment
210 properties:
211 config: {get_resource: config}
212 server: {get_resource: server}
213 signal_transport: ZAQAR_SIGNAL
214
215outputs:
216 data:
217 value: {get_attr: [deployment, deploy_stdout]}
218'''
219
220 conf_template = '''
221[zaqar]
222user_id = %(user_id)s
223password = %(password)s
224project_id = %(project_id)s
225auth_url = %(auth_url)s
226queue_id = %(queue_id)s
227 '''
228
229 def test_signal_queues(self):
230 parms = {'flavor': self.conf.minimal_instance_type,
231 'network': self.conf.fixed_network_name,
232 'image': self.conf.minimal_image_ref}
233 stack_identifier = self.stack_create(
234 parameters=parms,
235 template=self.server_template,
236 expected_status=None)
237 metadata = self.wait_for_deploy_metadata_set(stack_identifier)
238 config = metadata['os-collect-config']['zaqar']
239 conf_content = self.conf_template % config
240 fd, temp_path = tempfile.mkstemp()
Thomas Herve4d1362b2017-03-24 10:33:01 +0100241 os.write(fd, conf_content.encode('utf-8'))
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100242 os.close(fd)
243 cmd = ['os-collect-config', '--one-time',
244 '--config-file=%s' % temp_path, 'zaqar']
245 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
246 stdout_value = proc.communicate()[0]
Thomas Herve4d1362b2017-03-24 10:33:01 +0100247 data = json.loads(stdout_value.decode('utf-8'))
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100248 self.assertEqual(config, data['zaqar']['os-collect-config']['zaqar'])
249 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
250 stdout_value = proc.communicate()[0]
Thomas Herve4d1362b2017-03-24 10:33:01 +0100251 data = json.loads(stdout_value.decode('utf-8'))
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100252
253 fd, temp_path = tempfile.mkstemp()
Thomas Herve4d1362b2017-03-24 10:33:01 +0100254 os.write(fd,
255 json.dumps(data['zaqar']['deployments'][0]).encode('utf-8'))
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100256 os.close(fd)
Thomas Herve4d1362b2017-03-24 10:33:01 +0100257 cmd = [sys.executable, self.conf.heat_config_notify_script, temp_path]
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100258 proc = subprocess.Popen(cmd,
259 stderr=subprocess.PIPE,
260 stdin=subprocess.PIPE)
Thomas Herve4d1362b2017-03-24 10:33:01 +0100261 proc.communicate(
262 json.dumps({'deploy_stdout': 'here!'}).encode('utf-8'))
Thomas Herve2ce4bda2016-01-22 17:55:55 +0100263 self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
264 stack = self.client.stacks.get(stack_identifier)
265 self.assertEqual('here!', stack.outputs[0]['output_value'])
266
267 def wait_for_deploy_metadata_set(self, stack):
268 build_timeout = self.conf.build_timeout
269 build_interval = self.conf.build_interval
270
271 start = timeutils.utcnow()
272 while timeutils.delta_seconds(start,
273 timeutils.utcnow()) < build_timeout:
274 server_metadata = self.client.resources.metadata(
275 stack, 'server')
276 if server_metadata.get('deployments'):
277 return server_metadata
278 time.sleep(build_interval)
279
280 message = ('Deployment resources failed to be created within '
281 'the required time (%s s).' %
282 (build_timeout))
283 raise exceptions.TimeoutException(message)