blob: 3723fb6c917d075060e325c98d702f2a8050822a [file] [log] [blame]
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +03001# Copyright 2018 Mirantis, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030015import json
Oleksii Butenko71d76f32018-06-05 17:46:34 +030016import os
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030017
Oleksii Butenkob0ca4cc2018-10-22 16:29:54 +030018from devops.helpers import helpers
19
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030020from tcp_tests import logger
21from tcp_tests import settings
22
Oleksii Butenkob0ca4cc2018-10-22 16:29:54 +030023
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030024LOG = logger.logger
25
26TEMPEST_CFG_DIR = '/tmp/test'
27
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030028
29class RuntestManager(object):
30 """Helper manager for execution tempest via runtest-formula"""
31
32 image_name = settings.TEMPEST_IMAGE
33 image_version = settings.TEMPEST_IMAGE_VERSION
34 container_name = 'run-tempest-ci'
35 master_host = "cfg01"
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030036 class_name = "runtest"
37 run_cmd = '/bin/bash -c "run-tempest"'
38
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000039 def __init__(self, config, underlay, salt_api, cluster_name,
Oleksii Butenko74566102018-09-11 11:55:13 +030040 domain_name, tempest_threads,
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030041 tempest_pattern=settings.TEMPEST_PATTERN,
obutenkoc4314352018-12-26 16:14:24 +020042 run_cmd=None):
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000043 self.__config = config
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030044 self.underlay = underlay
45 self.__salt_api = salt_api
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030046 self.cluster_name = cluster_name
47 self.domain_name = domain_name
48 self.tempest_threads = tempest_threads
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030049 self.tempest_pattern = tempest_pattern
50 self.run_cmd = run_cmd or self.run_cmd
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000051 self.master_name = self.underlay.get_target_node_names(
52 self.master_host)[0]
obutenkoc4314352018-12-26 16:14:24 +020053 self.__target_name = None
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030054
55 @property
56 def salt_api(self):
57 return self.__salt_api
58
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000059 @property
obutenkoc4314352018-12-26 16:14:24 +020060 def target_name(self):
61 if not self.__target_name:
obutenkoa1e3cea2019-01-12 21:11:55 +020062 target_host = self.__salt_api.get_single_pillar(
obutenkoc4314352018-12-26 16:14:24 +020063 tgt=self.master_name,
64 pillar="runtest:tempest:test_target")
obutenkoc4314352018-12-26 16:14:24 +020065 if target_host[-1] == "*":
66 target_host = target_host[:-1]
67 self.__target_name = self.underlay.get_target_node_names(
68 target_host)[0]
69 return self.__target_name
obutenko3e44b602018-11-13 12:50:22 +020070
Oleksii Butenko71d76f32018-06-05 17:46:34 +030071 def fetch_arficats(self, username=None, file_format='xml'):
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000072 with self.underlay.remote(node_name=self.target_name,
73 username=None) as tgt:
Oleksii Butenko71d76f32018-06-05 17:46:34 +030074 result = tgt.execute('find {} -name "report_*.{}"'.format(
75 TEMPEST_CFG_DIR, file_format))
76 LOG.debug("Find result {0}".format(result))
77 assert len(result['stdout']) > 0, ('No report found, please check'
78 ' if test run was successful.')
79 report = result['stdout'][0].rstrip()
80 LOG.debug("Found files {0}".format(report))
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030081 tgt.download(
Oleksii Butenko71d76f32018-06-05 17:46:34 +030082 destination=report, # noqa
83 target=os.getcwd())
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030084
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030085 def save_runtime_logs(self, logs=None, inspect=None):
86 if logs:
87 with open("{path}/{target}_tempest_run.log".format(
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000088 path=settings.LOGS_DIR,
89 target=self.target_name), 'w') as f:
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030090 LOG.info("Save tempest console log")
91 container_log = logs
Oleksii Butenko71d76f32018-06-05 17:46:34 +030092 f.write(container_log.encode('ascii', 'ignore'))
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030093
94 if inspect:
Oleksii Butenko71d76f32018-06-05 17:46:34 +030095 with open("{path}/{target}_tempest_container_info.json.log".format(
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +000096 path=settings.LOGS_DIR,
97 target=self.target_name), 'w') as f:
Oleksii Butenko71d76f32018-06-05 17:46:34 +030098 LOG.info("Save tempest container inspect data")
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +030099
100 container_inspect = json.dumps(inspect,
101 indent=4, sort_keys=True)
102 f.write(container_inspect)
103
obutenkoc4314352018-12-26 16:14:24 +0200104 def prepare(self):
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000105 salt_call_cmd = "salt-call -l info --hard-crash --state-output=mixed "
Tatyana Leontovich8b1fda02019-01-23 13:14:33 +0200106 barbican_enabled = self.__salt_api.get_single_pillar(
107 tgt='ctl01*', pillar='_param:barbican_enabled')
obutenkoa1e3cea2019-01-12 21:11:55 +0200108 barbican_integration = self.__salt_api.get_single_pillar(
Tatyana Leontovich8b1fda02019-01-23 13:14:33 +0200109 tgt="ctl01*",
obutenkoa1e3cea2019-01-12 21:11:55 +0200110 pillar="_param:barbican_integration_enabled")
Tatyana Leontovich8b1fda02019-01-23 13:14:33 +0200111
112 LOG.info("Barbican enabled {0}: Barbican integration {1}".format(
113 barbican_enabled, barbican_integration))
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000114 commands = [
115 {
Tatyana Leontovicheea03e92018-11-20 12:51:50 +0200116 'description': ("Install docker-ce package and "
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000117 "enable packets forwarding"),
118 'node_name': self.target_name,
119 'cmd': ("set -ex;" +
Tatyana Leontovicheea03e92018-11-20 12:51:50 +0200120 salt_call_cmd + " pkg.install docker-ce && " +
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000121 " iptables --policy FORWARD ACCEPT")},
122 {
123 'description': "Install PyPI docker package",
124 'node_name': self.target_name,
125 'cmd': ("set -ex;" +
126 salt_call_cmd + " pip.install setuptools && " +
127 salt_call_cmd + " pip.install docker")},
128 {
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000129 'description': "Generate config for Tempest",
130 'node_name': self.master_name,
131 'cmd': ("set -ex;" +
obutenkoc4314352018-12-26 16:14:24 +0200132 "salt-run state.orchestrate " +
133 "runtest.orchestrate.tempest")},
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000134 ]
obutenkoa1e3cea2019-01-12 21:11:55 +0200135
Tatyana Leontovich8b1fda02019-01-23 13:14:33 +0200136 if barbican_enabled:
obutenkoa1e3cea2019-01-12 21:11:55 +0200137 commands.append({
138 'description': "Configure barbican",
139 'node_name': self.master_name,
140 'cmd': ("set -ex;" +
141 salt_call_cmd +
142 " state.sls barbican.client && " +
143 salt_call_cmd +
Tatyana Leontovich8b1fda02019-01-23 13:14:33 +0200144 " state.sls runtest.test_accounts")},
145 )
146 if barbican_integration:
147 commands.append({
148 'description': "Configure barbican",
149 'node_name': self.master_name,
150 'cmd': ("set -ex;" +
obutenkoa1e3cea2019-01-12 21:11:55 +0200151 salt_call_cmd +
152 " state.sls runtest.barbican_sign_image")},
153 )
154
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000155 self.__salt_api.execute_commands(commands=commands,
156 label="Prepare for Tempest")
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300157
158 def run_tempest(self, timeout=600):
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000159 tgt = self.target_name
160 image_nameversion = "{}:{}".format(self.image_name, self.image_version)
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300161
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000162 docker_args = (
Oleksii Butenkob0ca4cc2018-10-22 16:29:54 +0300163 " -t "
obutenkoa1e3cea2019-01-12 21:11:55 +0200164 " --net host "
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000165 " --name {container_name} "
166 " -e ARGS=\"-r {tempest_pattern} -w {tempest_threads}\""
167 " -v {cfg_dir}/tempest.conf:/etc/tempest/tempest.conf"
168 " -v /tmp/:/tmp/"
169 " -v {cfg_dir}:/root/tempest"
170 " -v /etc/ssl/certs/:/etc/ssl/certs/"
Oleksii Butenkob0ca4cc2018-10-22 16:29:54 +0300171 " -d "
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000172 " {image_nameversion} {run_cmd}"
173 .format(
174 container_name=self.container_name,
175 image_nameversion=image_nameversion,
176 tempest_pattern=self.tempest_pattern,
177 tempest_threads=self.tempest_threads,
178 cfg_dir=TEMPEST_CFG_DIR,
179 run_cmd=self.run_cmd,
180 ))
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300181
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000182 commands = [
183 {
184 'description': "Run Tempest tests {0}".format(
185 image_nameversion),
186 'node_name': self.target_name,
187 'cmd': ("set -ex;" +
188 " docker rm --force {container_name} || true;"
189 " docker run {docker_args}"
190 .format(container_name=self.container_name,
191 docker_args=docker_args)),
192 'timeout': timeout},
193 ]
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300194
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000195 self.__salt_api.execute_commands(commands=commands,
196 label="Run Tempest tests")
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300197
Oleksii Butenkob0ca4cc2018-10-22 16:29:54 +0300198 def wait_status(s):
199 inspect_res = self.salt_api.local(tgt,
200 'dockerng.inspect',
201 self.container_name)
202 if 'return' in inspect_res:
203 inspect = inspect_res['return']
204 inspect = inspect[0]
205 inspect = next(inspect.iteritems())[1]
206 status = inspect['State']['Status']
207
208 return status.lower() == s.lower()
209
210 return False
211
212 helpers.wait(lambda: wait_status('exited'),
213 timeout=timeout,
214 timeout_msg=('Tempest run didnt finished '
215 'in {}'.format(timeout)))
216
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300217 inspect_res = self.salt_api.local(tgt,
218 'dockerng.inspect',
219 self.container_name)
220 inspect = inspect_res['return'][0]
221 inspect = next(inspect.iteritems())[1]
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300222 logs_res = self.salt_api.local(tgt,
223 'dockerng.logs',
224 self.container_name)
225 logs = logs_res['return'][0]
226 logs = next(logs.iteritems())[1]
Dmitry Tyzhnenkoc56b77e2018-05-21 11:01:43 +0300227
228 res = self.salt_api.local(tgt, 'dockerng.rm', self.container_name)
229 LOG.info("Tempest container was removed".format(
230 json.dumps(res, indent=4)))
231
232 return {'inspect': inspect,
233 'logs': logs}
Oleksii Butenkoe82441d2018-06-12 16:01:33 +0300234
obutenkoc4314352018-12-26 16:14:24 +0200235 def prepare_and_run_tempest(self, username='root'):
Oleksii Butenkoe82441d2018-06-12 16:01:33 +0300236 """
237 Run tempest tests
238 """
239 tempest_timeout = settings.TEMPEST_TIMEOUT
obutenkoc4314352018-12-26 16:14:24 +0200240 self.prepare()
Oleksii Butenkoe82441d2018-06-12 16:01:33 +0300241 test_res = self.run_tempest(tempest_timeout)
242 self.fetch_arficats(username=username)
243 self.save_runtime_logs(**test_res)