| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 1 | #    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 Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 15 | import json | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 16 | import os | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 17 |  | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 18 | from devops.helpers import helpers | 
 | 19 |  | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 20 | from tcp_tests import logger | 
 | 21 | from tcp_tests import settings | 
 | 22 |  | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 23 |  | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 24 | LOG = logger.logger | 
 | 25 |  | 
 | 26 | TEMPEST_CFG_DIR = '/tmp/test' | 
 | 27 |  | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 28 |  | 
 | 29 | class 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 Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 36 |     class_name = "runtest" | 
 | 37 |     run_cmd = '/bin/bash -c "run-tempest"' | 
 | 38 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 39 |     def __init__(self, config, underlay, salt_api, cluster_name, | 
| Oleksii Butenko | 7456610 | 2018-09-11 11:55:13 +0300 | [diff] [blame] | 40 |                  domain_name, tempest_threads, | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 41 |                  tempest_pattern=settings.TEMPEST_PATTERN, | 
| Oleksii Butenko | 25a8f37 | 2019-03-22 17:25:47 +0200 | [diff] [blame] | 42 |                  tempest_extra_args=settings.TEMPEST_EXTRA_ARGS, | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 43 |                  run_cmd=None): | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 44 |         self.__config = config | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 45 |         self.underlay = underlay | 
 | 46 |         self.__salt_api = salt_api | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 47 |         self.cluster_name = cluster_name | 
 | 48 |         self.domain_name = domain_name | 
 | 49 |         self.tempest_threads = tempest_threads | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 50 |         self.tempest_pattern = tempest_pattern | 
| Oleksii Butenko | 25a8f37 | 2019-03-22 17:25:47 +0200 | [diff] [blame] | 51 |         self.tempest_extra_args = tempest_extra_args | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 52 |         self.run_cmd = run_cmd or self.run_cmd | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 53 |         self.master_name = self.underlay.get_target_node_names( | 
 | 54 |             self.master_host)[0] | 
| Dennis Dmitriev | 1566e3f | 2019-01-11 17:35:43 +0200 | [diff] [blame] | 55 |         self.master_minion = self.underlay.get_target_minion_ids( | 
 | 56 |             self.master_host)[0] | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 57 |         self.__target_name = None | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 58 |         self.__target_minion = None | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 59 |  | 
 | 60 |     @property | 
 | 61 |     def salt_api(self): | 
 | 62 |         return self.__salt_api | 
 | 63 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 64 |     @property | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 65 |     def target_name(self): | 
 | 66 |         if not self.__target_name: | 
| obutenko | a1e3cea | 2019-01-12 21:11:55 +0200 | [diff] [blame] | 67 |             target_host = self.__salt_api.get_single_pillar( | 
| Dennis Dmitriev | 1566e3f | 2019-01-11 17:35:43 +0200 | [diff] [blame] | 68 |                 tgt=self.master_minion, | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 69 |                 pillar="runtest:tempest:test_target") | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 70 |             if target_host[-1] == "*": | 
 | 71 |                 target_host = target_host[:-1] | 
 | 72 |             self.__target_name = self.underlay.get_target_node_names( | 
 | 73 |                 target_host)[0] | 
 | 74 |         return self.__target_name | 
| obutenko | 3e44b60 | 2018-11-13 12:50:22 +0200 | [diff] [blame] | 75 |  | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 76 |     @property | 
 | 77 |     def target_minion(self): | 
 | 78 |         if not self.__target_minion: | 
 | 79 |             target_host = self.__salt_api.get_single_pillar( | 
 | 80 |                 tgt=self.master_minion, | 
 | 81 |                 pillar="runtest:tempest:test_target") | 
 | 82 |             if target_host[-1] == "*": | 
 | 83 |                 target_host = target_host[:-1] | 
 | 84 |             self.__target_minion = self.underlay.get_target_minion_ids( | 
 | 85 |                 target_host)[0] | 
 | 86 |         return self.__target_minion | 
 | 87 |  | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 88 |     def fetch_arficats(self, username=None, file_format='xml'): | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 89 |         with self.underlay.remote(node_name=self.target_name, | 
 | 90 |                                   username=None) as tgt: | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 91 |             result = tgt.execute('find {} -name "report_*.{}"'.format( | 
 | 92 |                 TEMPEST_CFG_DIR, file_format)) | 
 | 93 |             LOG.debug("Find result {0}".format(result)) | 
 | 94 |             assert len(result['stdout']) > 0, ('No report found, please check' | 
 | 95 |                                                ' if test run was successful.') | 
 | 96 |             report = result['stdout'][0].rstrip() | 
 | 97 |             LOG.debug("Found files {0}".format(report)) | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 98 |             tgt.download( | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 99 |                 destination=report,  # noqa | 
 | 100 |                 target=os.getcwd()) | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 101 |  | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 102 |     def save_runtime_logs(self, logs=None, inspect=None): | 
 | 103 |         if logs: | 
 | 104 |             with open("{path}/{target}_tempest_run.log".format( | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 105 |                     path=settings.LOGS_DIR, | 
 | 106 |                     target=self.target_name), 'w') as f: | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 107 |                 LOG.info("Save tempest console log") | 
 | 108 |                 container_log = logs | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 109 |                 f.write(container_log.encode('ascii', 'ignore')) | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 110 |  | 
 | 111 |         if inspect: | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 112 |             with open("{path}/{target}_tempest_container_info.json.log".format( | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 113 |                     path=settings.LOGS_DIR, | 
 | 114 |                     target=self.target_name), 'w') as f: | 
| Oleksii Butenko | 71d76f3 | 2018-06-05 17:46:34 +0300 | [diff] [blame] | 115 |                 LOG.info("Save tempest container inspect data") | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 116 |  | 
 | 117 |                 container_inspect = json.dumps(inspect, | 
 | 118 |                                                indent=4, sort_keys=True) | 
 | 119 |                 f.write(container_inspect) | 
 | 120 |  | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 121 |     def prepare(self): | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 122 |         salt_call_cmd = "salt-call -l info --hard-crash --state-output=mixed " | 
| obutenko | a1e3cea | 2019-01-12 21:11:55 +0200 | [diff] [blame] | 123 |         barbican_integration = self.__salt_api.get_single_pillar( | 
| Tatyana Leontovich | 8b1fda0 | 2019-01-23 13:14:33 +0200 | [diff] [blame] | 124 |             tgt="ctl01*", | 
| obutenko | a1e3cea | 2019-01-12 21:11:55 +0200 | [diff] [blame] | 125 |             pillar="_param:barbican_integration_enabled") | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 126 |         if self.__salt_api.local('I@opencontrail:compute:enabled:true', | 
 | 127 |                                  'match.pillar', | 
 | 128 |                                  'opencontrail:compute:enabled:true' | 
 | 129 |                                  ).get('return', [{}]) != [{}]: | 
 | 130 |             contrail_integration = True | 
 | 131 |         else: | 
 | 132 |             contrail_integration = False | 
| Tatyana Leontovich | 8b1fda0 | 2019-01-23 13:14:33 +0200 | [diff] [blame] | 133 |  | 
| obutenko | c48f435 | 2019-01-24 17:03:06 +0200 | [diff] [blame] | 134 |         LOG.info("Barbican integration {0}".format(barbican_integration)) | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 135 |         LOG.info("Opencontrail integration {0}".format(contrail_integration)) | 
 | 136 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 137 |         commands = [ | 
 | 138 |             { | 
| Tatyana Leontovich | eea03e9 | 2018-11-20 12:51:50 +0200 | [diff] [blame] | 139 |                 'description': ("Install docker-ce package and " | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 140 |                                 "enable packets forwarding"), | 
 | 141 |                 'node_name': self.target_name, | 
 | 142 |                 'cmd': ("set -ex;" + | 
| Tatyana Leontovich | eea03e9 | 2018-11-20 12:51:50 +0200 | [diff] [blame] | 143 |                         salt_call_cmd + " pkg.install docker-ce && " + | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 144 |                         " iptables --policy FORWARD ACCEPT")}, | 
 | 145 |             { | 
 | 146 |                 'description': "Install PyPI docker package", | 
 | 147 |                 'node_name': self.target_name, | 
 | 148 |                 'cmd': ("set -ex;" + | 
 | 149 |                         salt_call_cmd + " pip.install setuptools && " + | 
 | 150 |                         salt_call_cmd + " pip.install docker")}, | 
 | 151 |             { | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 152 |                 'description': "Generate config for Tempest", | 
 | 153 |                 'node_name': self.master_name, | 
 | 154 |                 'cmd': ("set -ex;" + | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 155 |                         "salt-run state.orchestrate " + | 
 | 156 |                         "runtest.orchestrate.tempest")}, | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 157 |         ] | 
| obutenko | a1e3cea | 2019-01-12 21:11:55 +0200 | [diff] [blame] | 158 |  | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 159 |         if contrail_integration: | 
 | 160 |             vsrx_router = self.__salt_api.get_single_pillar( | 
 | 161 |                 tgt="I@opencontrail:control:role:primary", | 
| Andrew Baraniuk | 6361cfc | 2019-06-04 12:58:14 +0300 | [diff] [blame] | 162 |                 pillar="_param:opencontrail_router02_address") | 
| Oleksii Butenko | 125dcf4 | 2019-07-23 16:34:40 +0300 | [diff] [blame] | 163 |             target_asn = '["target:64512:10000"]' | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 164 |             public_network = "192.168.200.0" | 
 | 165 |             contrail_commands = [ | 
 | 166 |                 { | 
 | 167 |                     'description': "Iproute to vsrx router", | 
 | 168 |                     'node_name': self.target_name, | 
 | 169 |                     'cmd': ("set -ex; ip route replace " + | 
 | 170 |                             public_network + "/24 via " + vsrx_router)}, | 
 | 171 |                 { | 
| Andrew Baraniuk | 6361cfc | 2019-06-04 12:58:14 +0300 | [diff] [blame] | 172 |                     'description': "Iptables for public", | 
 | 173 |                     'node_name': self.target_name, | 
 | 174 |                     'cmd': ("set -ex; iptables -t nat -A POSTROUTING -s " + | 
 | 175 |                             public_network + "/24 ! -d " + public_network + | 
 | 176 |                             "/24 -j MASQUERADE")}, | 
 | 177 |                 { | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 178 |                     'description': "Align security group: remove all rules", | 
 | 179 |                     'node_name': self.target_name, | 
 | 180 |                     'cmd': ("set -ex;" + | 
 | 181 |                             "salt 'ctl01*' cmd.run '. /root/keystonercv3; " + | 
 | 182 |                             "openstack security group rule list --column ID " + | 
 | 183 |                             "-f value | xargs " + | 
 | 184 |                             "openstack security group rule delete|true';")}, | 
 | 185 |                 { | 
 | 186 |                     'description': "Align security group: remove all default", | 
 | 187 |                     'node_name': self.target_name, | 
 | 188 |                     'cmd': ("set -ex;" + | 
 | 189 |                             " salt ctl01* cmd.run '. /root/keystonercv3; " + | 
 | 190 |                             "openstack security group " + | 
 | 191 |                             "list --column ID --column Name -f value|" + | 
 | 192 |                             "grep default|cut -d \" \" -f 1|" + | 
 | 193 |                             "xargs openstack security group delete|true'")}, | 
 | 194 |                 { | 
 | 195 |                     'description': "Align security group: add rules", | 
 | 196 |                     'node_name': self.target_name, | 
 | 197 |                     'cmd': ("set -ex;" + | 
 | 198 |                             "salt 'ctl01*' cmd.run '. /root/keystonercv3; " + | 
 | 199 |                             "openstack security group rule create default " + | 
 | 200 |                             "--egress --protocol tcp'; " + | 
 | 201 |                             "salt 'ctl01*' cmd.run '. /root/keystonercv3; " + | 
 | 202 |                             "openstack security group rule create default " + | 
 | 203 |                             "--ingress --protocol tcp'; " + | 
 | 204 |                             "salt 'ctl01*' cmd.run '. /root/keystonercv3; " + | 
 | 205 |                             "openstack security group rule create default " + | 
 | 206 |                             "--egress --protocol icmp'; " + | 
 | 207 |                             "salt 'ctl01*' cmd.run '. /root/keystonercv3; " + | 
 | 208 |                             "openstack security group rule create default " + | 
 | 209 |                             "--ingress --protocol icmp'; ")}, | 
 | 210 |                 { | 
| Oleksii Butenko | 125dcf4 | 2019-07-23 16:34:40 +0300 | [diff] [blame] | 211 |                     'description': "Run skipped in pipelines neutron.client", | 
 | 212 |                     'node_name': self.target_name, | 
 | 213 |                     'cmd': ("set -ex;" + | 
 | 214 |                             "salt -C 'I@neutron:client and cfg*' " + | 
 | 215 |                             "state.sls neutron.client|true")}, | 
 | 216 |                 { | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 217 |                     'description': "Create public network with target", | 
 | 218 |                     'node_name': self.target_name, | 
 | 219 |                     'cmd': ("set -ex;" + | 
 | 220 |                             "salt -C 'I@opencontrail:control:role:primary' " + | 
 | 221 |                             "contrail.virtual_network_create public " + | 
| Oleksii Butenko | 125dcf4 | 2019-07-23 16:34:40 +0300 | [diff] [blame] | 222 |                             "route_target_list='" + target_asn + "'")} | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 223 |             ] | 
| Oleksii Butenko | 125dcf4 | 2019-07-23 16:34:40 +0300 | [diff] [blame] | 224 |             commands = contrail_commands + commands | 
| Oleksii Butenko | d4b3dff | 2019-05-10 14:38:14 +0300 | [diff] [blame] | 225 |  | 
| obutenko | c48f435 | 2019-01-24 17:03:06 +0200 | [diff] [blame] | 226 |         if barbican_integration: | 
| obutenko | a1e3cea | 2019-01-12 21:11:55 +0200 | [diff] [blame] | 227 |             commands.append({ | 
 | 228 |                 'description': "Configure barbican", | 
 | 229 |                 'node_name': self.master_name, | 
 | 230 |                 'cmd': ("set -ex;" + | 
 | 231 |                         salt_call_cmd + | 
 | 232 |                         " state.sls barbican.client && " + | 
 | 233 |                         salt_call_cmd + | 
| obutenko | c48f435 | 2019-01-24 17:03:06 +0200 | [diff] [blame] | 234 |                         " state.sls runtest.test_accounts" + | 
| obutenko | a1e3cea | 2019-01-12 21:11:55 +0200 | [diff] [blame] | 235 |                         salt_call_cmd + | 
 | 236 |                         " state.sls runtest.barbican_sign_image")}, | 
 | 237 |             ) | 
 | 238 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 239 |         self.__salt_api.execute_commands(commands=commands, | 
 | 240 |                                          label="Prepare for Tempest") | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 241 |  | 
 | 242 |     def run_tempest(self, timeout=600): | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 243 |         tgt = self.target_minion | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 244 |         image_nameversion = "{}:{}".format(self.image_name, self.image_version) | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 245 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 246 |         docker_args = ( | 
| Oleksii Butenko | 25a8f37 | 2019-03-22 17:25:47 +0200 | [diff] [blame] | 247 |             " -t" | 
 | 248 |             " --net host" | 
 | 249 |             " --name {container_name}" | 
 | 250 |             " -e ARGS=\"-r {tempest_pattern}" | 
 | 251 |             " -w {tempest_threads} {tempest_extra_args}\"" | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 252 |             " -v {cfg_dir}/tempest.conf:/etc/tempest/tempest.conf" | 
 | 253 |             " -v /tmp/:/tmp/" | 
 | 254 |             " -v {cfg_dir}:/root/tempest" | 
 | 255 |             " -v /etc/ssl/certs/:/etc/ssl/certs/" | 
| Oleksii Butenko | 25a8f37 | 2019-03-22 17:25:47 +0200 | [diff] [blame] | 256 |             " -d" | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 257 |             " {image_nameversion} {run_cmd}" | 
 | 258 |             .format( | 
 | 259 |                 container_name=self.container_name, | 
 | 260 |                 image_nameversion=image_nameversion, | 
 | 261 |                 tempest_pattern=self.tempest_pattern, | 
 | 262 |                 tempest_threads=self.tempest_threads, | 
| Oleksii Butenko | 25a8f37 | 2019-03-22 17:25:47 +0200 | [diff] [blame] | 263 |                 tempest_extra_args=self.tempest_extra_args, | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 264 |                 cfg_dir=TEMPEST_CFG_DIR, | 
 | 265 |                 run_cmd=self.run_cmd, | 
 | 266 |             )) | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 267 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 268 |         commands = [ | 
 | 269 |             { | 
 | 270 |                 'description': "Run Tempest tests {0}".format( | 
 | 271 |                     image_nameversion), | 
 | 272 |                 'node_name': self.target_name, | 
 | 273 |                 'cmd': ("set -ex;" + | 
 | 274 |                         " docker rm --force {container_name} || true;" | 
 | 275 |                         " docker run {docker_args}" | 
 | 276 |                         .format(container_name=self.container_name, | 
 | 277 |                                 docker_args=docker_args)), | 
 | 278 |                 'timeout': timeout}, | 
 | 279 |         ] | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 280 |  | 
| Dennis Dmitriev | b6bcc5c | 2018-09-26 11:07:53 +0000 | [diff] [blame] | 281 |         self.__salt_api.execute_commands(commands=commands, | 
 | 282 |                                          label="Run Tempest tests") | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 283 |  | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 284 |         def simplify_salt_api_return(api_return, only_first_match=True): | 
 | 285 |             """ | 
 | 286 |                 Salt API always returns a dict with one key as 'return' | 
 | 287 |                 and value as a list with dict. For example: | 
 | 288 |             For single node: | 
 | 289 |                 api.local('cfg01*', 'test.ping', expr_form='compound') | 
 | 290 |                 {u'return':[{u'cfg01.cookied-cicd-queens-dvr-sl.local':True}]} | 
 | 291 |             For multinode: | 
 | 292 |                 api.local('ctl*', 'test.ping', expr_form='compound') | 
 | 293 |                 {u'return': [{u'ctl01.cookied-cicd-queens-dvr-sl.local': True, | 
 | 294 |                  u'ctl02.cookied-cicd-queens-dvr-sl.local': True, | 
 | 295 |                 u'ctl03.cookied-cicd-queens-dvr-sl.local': True}]} | 
 | 296 |             When wrong function is given: | 
 | 297 |                 api.local('ctl01*', 'wrong_func', expr_form='compound') | 
 | 298 |                 {u'return': [{u'ctl01.cookied-cicd-queens-dvr-sl.local': | 
 | 299 |                  u"'wrong_func' is not available."}]} | 
 | 300 |             Empty return: | 
 | 301 |                 api.local('wrong_target', 'test.ping', expr_form='compound') | 
 | 302 |                 {u'return': [{}]} | 
 | 303 |             """ | 
 | 304 |             if api_return.get('return', [{}]) != [{}]: | 
 | 305 |                 api_return = api_return['return'][0] | 
 | 306 |                 if only_first_match: | 
 | 307 |                     api_return = next(api_return.iteritems())[1] | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 308 |                 return api_return | 
 | 309 |             else: | 
 | 310 |                 LOG.info('''Salt api returns empty result: [{}]''') | 
 | 311 |                 return False | 
 | 312 |  | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 313 |         def wait_status(s): | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 314 |             inspect_res = self.salt_api.local(tgt, 'dockerng.inspect', | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 315 |                                               self.container_name) | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 316 |             inspect = simplify_salt_api_return(inspect_res) | 
 | 317 |             if inspect: | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 318 |                 status = inspect['State']['Status'] | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 319 |                 return status.lower() == s.lower() | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 320 |             return False | 
 | 321 |  | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 322 |         if wait_status('running'): | 
 | 323 |             helpers.wait(lambda: wait_status('exited'), | 
 | 324 |                          timeout=timeout, | 
 | 325 |                          timeout_msg=('Tempest run didnt finished ' | 
 | 326 |                                       'in {}'.format(timeout))) | 
| Oleksii Butenko | b0ca4cc | 2018-10-22 16:29:54 +0300 | [diff] [blame] | 327 |  | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 328 |             inspect_res = self.salt_api.local(tgt, 'dockerng.inspect', | 
 | 329 |                                               self.container_name) | 
 | 330 |             inspect = simplify_salt_api_return(inspect_res) | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 331 |  | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 332 |             logs_res = self.salt_api.local(tgt, 'dockerng.logs', | 
 | 333 |                                            self.container_name) | 
 | 334 |             logs = simplify_salt_api_return(logs_res) | 
| sgudz | 2457db8 | 2019-03-01 16:06:36 +0200 | [diff] [blame] | 335 |             rm_res = self.salt_api.local(tgt, 'dockerng.rm', | 
 | 336 |                                          self.container_name) | 
 | 337 |             LOG.info("Tempest container was removed: {}".format( | 
 | 338 |                 json.dumps(rm_res, indent=4))) | 
| sgudz | 6571a5e | 2019-02-26 15:49:22 +0200 | [diff] [blame] | 339 |         else: | 
 | 340 |             inspect_res = self.salt_api.local(tgt, 'dockerng.inspect', | 
 | 341 |                                               self.container_name) | 
 | 342 |             inspect = simplify_salt_api_return(inspect_res) | 
 | 343 |             if inspect: | 
 | 344 |                 status = inspect['State']['Status'] | 
 | 345 |                 LOG.info("Container is not in RUNNING state. " | 
 | 346 |                          "Current container status is {}".format(status)) | 
 | 347 |                 logs_res = self.salt_api.local(tgt, | 
 | 348 |                                                'dockerng.logs', | 
 | 349 |                                                self.container_name) | 
 | 350 |                 logs = simplify_salt_api_return(logs_res) | 
 | 351 |             else: | 
 | 352 |                 LOG.info("dockerng returns unexpected" | 
 | 353 |                          " result: {}".format(inspect_res)) | 
 | 354 |                 logs = None | 
 | 355 |                 inspect = None | 
| Dmitry Tyzhnenko | c56b77e | 2018-05-21 11:01:43 +0300 | [diff] [blame] | 356 |  | 
 | 357 |         return {'inspect': inspect, | 
 | 358 |                 'logs': logs} | 
| Oleksii Butenko | e82441d | 2018-06-12 16:01:33 +0300 | [diff] [blame] | 359 |  | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 360 |     def prepare_and_run_tempest(self, username='root'): | 
| Oleksii Butenko | e82441d | 2018-06-12 16:01:33 +0300 | [diff] [blame] | 361 |         """ | 
 | 362 |         Run tempest tests | 
 | 363 |         """ | 
 | 364 |         tempest_timeout = settings.TEMPEST_TIMEOUT | 
| obutenko | c431435 | 2018-12-26 16:14:24 +0200 | [diff] [blame] | 365 |         self.prepare() | 
| Oleksii Butenko | e82441d | 2018-06-12 16:01:33 +0300 | [diff] [blame] | 366 |         test_res = self.run_tempest(tempest_timeout) | 
 | 367 |         self.fetch_arficats(username=username) | 
 | 368 |         self.save_runtime_logs(**test_res) |