blob: 4390f5ef473d746b00c2b64ecac969b91d7bae98 [file] [log] [blame]
gstepanov023c1e42015-04-08 15:50:19 +03001import os
koder aka kdanilovbc2c8982015-06-13 02:50:43 +03002import re
koder aka kdanilov57ce4db2015-04-25 21:25:51 +03003import time
koder aka kdanilove21d7472015-02-14 19:02:04 -08004import logging
koder aka kdanilov168f6092015-04-19 02:33:38 +03005import functools
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +03006import contextlib
koder aka kdanilov2c473092015-03-29 17:12:13 +03007import collections
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +03008from typing import List, Dict, Optional, Iterable, Any, Generator, Mapping, Callable
koder aka kdanilov88407ff2015-05-26 15:35:57 +03009from yaml import load as _yaml_load
10
11try:
12 from yaml import CLoader
13 yaml_load = functools.partial(_yaml_load, Loader=CLoader)
14except ImportError:
15 yaml_load = _yaml_load
16
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030017from concurrent.futures import ThreadPoolExecutor, wait
koder aka kdanilov6c491062015-04-09 22:33:13 +030018
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030019from .config import Config
20from .config import get_test_files
21from .discover import discover, Node
22from .inode import INode
23from .test_run_class import TestRun
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030024
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030025from . import pretty_yaml, utils, report, ssh_utils, start_vms
26
27from .suits.mysql import MysqlTest
28from .suits.itest import TestConfig
29from .suits.io.fio import IOPerfTest
30from .suits.postgres import PgBenchTest
31from .suits.omgbench import OmgTest
koder aka kdanilovbc2c8982015-06-13 02:50:43 +030032
33
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030034TOOL_TYPE_MAPPER = {
35 "io": IOPerfTest,
36 "pgbench": PgBenchTest,
37 "mysql": MysqlTest,
Yulia Portnovab0c977c2015-12-11 19:23:28 +020038 "omg": OmgTest,
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +030039}
koder aka kdanilov63ad2062015-04-27 13:11:40 +030040
koder aka kdanilov57ce4db2015-04-25 21:25:51 +030041
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030042logger = logging.getLogger("wally")
koder aka kdanilovcee43342015-04-14 22:52:53 +030043
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080044
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030045def connect_all(nodes: Iterable[INode], spawned_node: Optional[bool]=False) -> None:
46 """Connect to all nodes, log errors
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030047 nodes:[Node] - list of nodes
48 spawned_node:bool - whenever nodes is newly spawned VM
49 """
koder aka kdanilove21d7472015-02-14 19:02:04 -080050
koder aka kdanilov2c473092015-03-29 17:12:13 +030051 logger.info("Connecting to nodes")
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030052
53 conn_timeout = 240 if spawned_node else 30
54
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030055 def connect_ext(node: INode) -> bool:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030056 try:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030057 node.connect_ssh(conn_timeout)
58 node.connect_rpc(conn_timeout)
59 return True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030060 except Exception as exc:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030061 logger.error("During connect to {}: {!s}".format(node, exc))
62 return False
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030063
koder aka kdanilov2c473092015-03-29 17:12:13 +030064 with ThreadPoolExecutor(32) as pool:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030065 list(pool.map(connect_ext, nodes))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030066
67 failed_testnodes = []
68 failed_nodes = []
69
70 for node in nodes:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030071 if not node.is_connected():
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030072 if 'testnode' in node.roles:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030073 failed_testnodes.append(node)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030074 else:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030075 failed_nodes.append(node)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030076
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030077 if failed_nodes:
78 msg = "Node(s) {} would be excluded - can't connect"
79 logger.warning(msg.format(",".join(map(str, failed_nodes))))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030080
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030081 if failed_testnodes:
82 msg = "Can't connect to testnode(s) " + \
83 ",".join(map(str, failed_testnodes))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030084 logger.error(msg)
85 raise utils.StopTestError(msg)
86
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030087 if not failed_nodes:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +030088 logger.info("All nodes connected successfully")
koder aka kdanilov2c473092015-03-29 17:12:13 +030089
90
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030091def collect_hw_info_stage(cfg: Config, nodes: Iterable[INode]) -> None:
92 # TODO(koder): rewrite this function, to use other storage type
93 if os.path.exists(cfg.hwreport_fname):
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030094 msg = "{0} already exists. Skip hw info"
95 logger.info(msg.format(cfg['hwreport_fname']))
96 return
97
98 with ThreadPoolExecutor(32) as pool:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +030099 fitures = pool.submit(node.discover_hardware_info
100 for node in nodes)
101 wait(fitures)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300102
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300103 with open(cfg.hwreport_fname, 'w') as hwfd:
104 for node in nodes:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300105 hwfd.write("-" * 60 + "\n")
106 hwfd.write("Roles : " + ", ".join(node.roles) + "\n")
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300107 hwfd.write(str(node.hwinfo) + "\n")
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300108 hwfd.write("-" * 60 + "\n\n")
109
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300110 if node.hwinfo.hostname is not None:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300111 fname = os.path.join(
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300112 cfg.hwinfo_directory,
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300113 node.hwinfo.hostname + "_lshw.xml")
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300114
115 with open(fname, "w") as fd:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300116 fd.write(node.hwinfo.raw)
117
118 logger.info("Hardware report stored in " + cfg.hwreport_fname)
119 logger.debug("Raw hardware info in " + cfg.hwinfo_directory + " folder")
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300120
121
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300122@contextlib.contextmanager
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300123def suspend_vm_nodes_ctx(unused_nodes: Iterable[INode]) -> Generator[List[int]]:
124
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300125 pausable_nodes_ids = [node.os_vm_id for node in unused_nodes
126 if node.os_vm_id is not None]
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300127
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300128 non_pausable = len(unused_nodes) - len(pausable_nodes_ids)
koder aka kdanilov2c473092015-03-29 17:12:13 +0300129
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300130 if 0 != non_pausable:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300131 logger.warning("Can't pause {} nodes".format(
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300132 non_pausable))
133
134 if len(pausable_nodes_ids) != 0:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300135 logger.debug("Try to pause {} unused nodes".format(
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300136 len(pausable_nodes_ids)))
137 start_vms.pause(pausable_nodes_ids)
138
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300139 try:
140 yield pausable_nodes_ids
141 finally:
142 if len(pausable_nodes_ids) != 0:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300143 logger.debug("Unpausing {} nodes".format(
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300144 len(pausable_nodes_ids)))
145 start_vms.unpause(pausable_nodes_ids)
146
147
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300148def generate_result_dir_name(results: str, name: str, params: Dict[str, Any]) -> str:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300149 # make a directory for results
150 all_tests_dirs = os.listdir(results)
151
152 if 'name' in params:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300153 dir_name = "{}_{}".format(name, params['name'])
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300154 else:
155 for idx in range(len(all_tests_dirs) + 1):
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300156 dir_name = "{}_{}".format(name, idx)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300157 if dir_name not in all_tests_dirs:
158 break
159 else:
160 raise utils.StopTestError("Can't select directory for test results")
161
162 return os.path.join(results, dir_name)
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300163
164
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300165@contextlib.contextmanager
166def sensor_monitoring(sensor_cfg: Any, nodes: Iterable[INode]) -> Generator[None]:
167 # TODO(koder): write this function
168 pass
169
170
171def run_tests(cfg: Config, test_block, nodes: Iterable[INode]) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300172 """
173 Run test from test block
174 """
175 test_nodes = [node for node in nodes if 'testnode' in node.roles]
176 not_test_nodes = [node for node in nodes if 'testnode' not in node.roles]
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300177
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300178 if len(test_nodes) == 0:
179 logger.error("No test nodes found")
180 return
181
koder aka kdanilovcee43342015-04-14 22:52:53 +0300182 for name, params in test_block.items():
koder aka kdanilovcee43342015-04-14 22:52:53 +0300183 results = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300184
185 # iterate over all node counts
186 limit = params.get('node_limit', len(test_nodes))
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300187 if isinstance(limit, int):
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300188 vm_limits = [limit]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300189 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300190 list_or_tpl = isinstance(limit, (tuple, list))
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300191 all_ints = list_or_tpl and all(isinstance(climit, int)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300192 for climit in limit)
193 if not all_ints:
194 msg = "'node_limit' parameter ion config should" + \
195 "be either int or list if integers, not {0!r}".format(limit)
196 raise ValueError(msg)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300197 vm_limits = limit
koder aka kdanilov652cd802015-04-13 12:21:07 +0300198
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300199 for vm_count in vm_limits:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300200 # select test nodes
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300201 if vm_count == 'all':
202 curr_test_nodes = test_nodes
203 unused_nodes = []
204 else:
205 curr_test_nodes = test_nodes[:vm_count]
206 unused_nodes = test_nodes[vm_count:]
koder aka kdanilove87ae652015-04-20 02:14:35 +0300207
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300208 if 0 == len(curr_test_nodes):
209 continue
koder aka kdanilov652cd802015-04-13 12:21:07 +0300210
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300211 results_path = generate_result_dir_name(cfg.results_storage, name, params)
212 utils.mkdirs_if_unxists(results_path)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300213
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300214 # suspend all unused virtual nodes
215 if cfg.settings.get('suspend_unused_vms', True):
216 suspend_ctx = suspend_vm_nodes_ctx(unused_nodes)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300217 else:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300218 suspend_ctx = utils.empty_ctx()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300219
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300220 with suspend_ctx:
221 resumable_nodes_ids = [node.os_vm_id for node in curr_test_nodes
222 if node.os_vm_id is not None]
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300223
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300224 if len(resumable_nodes_ids) != 0:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300225 logger.debug("Check and unpause {} nodes".format(
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300226 len(resumable_nodes_ids)))
227 start_vms.unpause(resumable_nodes_ids)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300228
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300229 test_cls = TOOL_TYPE_MAPPER[name]
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300230
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300231 remote_dir = cfg.default_test_local_folder.format(name=name)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300232
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300233 test_cfg = TestConfig(test_cls.__name__,
234 params=params,
235 test_uuid=cfg.run_uuid,
236 nodes=test_nodes,
237 log_directory=results_path,
238 remote_dir=remote_dir)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300239
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300240 t_start = time.time()
241 res = test_cls(test_cfg).run()
242 t_end = time.time()
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300243
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300244 results.append(res)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300245
246 yield name, results
koder aka kdanilov2c473092015-03-29 17:12:13 +0300247
248
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300249def connect_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilovda45e882015-04-06 02:24:42 +0300250 ctx.clear_calls_stack.append(disconnect_stage)
251 connect_all(ctx.nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300252 ctx.nodes = [node for node in ctx.nodes if node.connection is not None]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300253
254
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300255def discover_stage(cfg: Config, ctx: TestRun) -> None:
256 """discover clusters and nodes stage"""
257
koder aka kdanilov652cd802015-04-13 12:21:07 +0300258 if cfg.get('discover') is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300259 discover_objs = [i.strip() for i in cfg.discover.strip().split(",")]
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300260
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300261 nodes = discover(ctx,
262 discover_objs,
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300263 cfg.clouds,
264 cfg.results_storage,
265 not cfg.dont_discover_nodes)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300266
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300267 ctx.nodes.extend(nodes)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300268
269 for url, roles in cfg.get('explicit_nodes', {}).items():
270 ctx.nodes.append(Node(url, roles.split(",")))
271
272
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300273def save_nodes_stage(cfg: Config, ctx: TestRun) -> None:
274 """Save nodes list to file"""
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300275 cluster = {}
276 for node in ctx.nodes:
277 roles = node.roles[:]
278 if 'testnode' in roles:
279 roles.remove('testnode')
280
281 if len(roles) != 0:
282 cluster[node.conn_url] = roles
283
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300284 with open(cfg.nodes_report_file, "w") as fd:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300285 fd.write(pretty_yaml.dumps(cluster))
286
287
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300288def reuse_vms_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300289 vms_patterns = cfg.get('clouds', {}).get('openstack', {}).get('vms', [])
290 private_key_path = get_vm_keypair(cfg)['keypair_file_private']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300291
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300292 for creds in vms_patterns:
293 user_name, vm_name_pattern = creds.split("@", 1)
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300294 msg = "Vm like {} lookup failed".format(vm_name_pattern)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300295
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300296 with utils.LogError(msg):
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300297 msg = "Looking for vm with name like {0}".format(vm_name_pattern)
298 logger.debug(msg)
299
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300300 if not start_vms.is_connected():
301 os_creds = get_OS_credentials(cfg, ctx)
302 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300303 os_creds = None
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300304
koder aka kdanilovb7197432015-07-15 00:40:43 +0300305 conn = start_vms.nova_connect(os_creds)
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300306 for ip, vm_id in start_vms.find_vms(conn, vm_name_pattern):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300307 conn_url = "ssh://{user}@{ip}::{key}".format(user=user_name,
308 ip=ip,
309 key=private_key_path)
310 node = Node(conn_url, ['testnode'])
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300311 node.os_vm_id = vm_id
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300312 ctx.nodes.append(node)
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300313
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300314
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300315def get_OS_credentials(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilovcee43342015-04-14 22:52:53 +0300316 creds = None
koder aka kdanilovb7197432015-07-15 00:40:43 +0300317 os_creds = None
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300318 force_insecure = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300319
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300320 if 'openstack' in cfg.clouds:
321 os_cfg = cfg.clouds['openstack']
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300322 if 'OPENRC' in os_cfg:
323 logger.info("Using OS credentials from " + os_cfg['OPENRC'])
koder aka kdanilovb7197432015-07-15 00:40:43 +0300324 creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC'])
325 os_creds = start_vms.OSCreds(*creds_tuple)
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300326 elif 'ENV' in os_cfg:
327 logger.info("Using OS credentials from shell environment")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300328 os_creds = start_vms.ostack_get_creds()
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300329 elif 'OS_TENANT_NAME' in os_cfg:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300330 logger.info("Using predefined credentials")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300331 os_creds = start_vms.OSCreds(os_cfg['OS_USERNAME'].strip(),
332 os_cfg['OS_PASSWORD'].strip(),
333 os_cfg['OS_TENANT_NAME'].strip(),
334 os_cfg['OS_AUTH_URL'].strip(),
335 os_cfg.get('OS_INSECURE', False))
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300336
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300337 elif 'OS_INSECURE' in os_cfg:
338 force_insecure = os_cfg.get('OS_INSECURE', False)
339
koder aka kdanilovb7197432015-07-15 00:40:43 +0300340 if os_creds is None and 'fuel' in cfg.clouds and \
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300341 'openstack_env' in cfg.clouds['fuel'] and \
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300342 ctx.fuel_openstack_creds is not None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300343 logger.info("Using fuel creds")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300344 creds = start_vms.OSCreds(**ctx.fuel_openstack_creds)
345 elif os_creds is None:
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300346 logger.error("Can't found OS credentials")
347 raise utils.StopTestError("Can't found OS credentials", None)
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300348
koder aka kdanilovcee43342015-04-14 22:52:53 +0300349 if creds is None:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300350 creds = os_creds
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300351
koder aka kdanilov8fbb27f2015-07-17 22:23:31 +0300352 if force_insecure and not creds.insecure:
353 creds = start_vms.OSCreds(creds.name,
354 creds.passwd,
355 creds.tenant,
356 creds.auth_url,
357 True)
358
koder aka kdanilov05e15b92016-02-07 19:32:46 +0200359 logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant} " +
koder aka kdanilovb7197432015-07-15 00:40:43 +0300360 "auth_url={0.auth_url} insecure={0.insecure}").format(creds))
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300361
koder aka kdanilovcee43342015-04-14 22:52:53 +0300362 return creds
koder aka kdanilov4e9f3ed2015-04-14 11:26:12 +0300363
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300364
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300365def get_vm_keypair(cfg: Config) -> Dict[str, str]:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300366 res = {}
367 for field, ext in (('keypair_file_private', 'pem'),
368 ('keypair_file_public', 'pub')):
369 fpath = cfg.vm_configs.get(field)
370
371 if fpath is None:
372 fpath = cfg.vm_configs['keypair_name'] + "." + ext
373
374 if os.path.isabs(fpath):
375 res[field] = fpath
376 else:
377 res[field] = os.path.join(cfg.config_folder, fpath)
378 return res
379
380
koder aka kdanilov168f6092015-04-19 02:33:38 +0300381@contextlib.contextmanager
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300382def create_vms_ctx(ctx: TestRun, cfg: Config, config, already_has_count: int=0) -> Generator[List[INode]]:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300383 if config['count'].startswith('='):
384 count = int(config['count'][1:])
385 if count <= already_has_count:
386 logger.debug("Not need new vms")
387 yield []
388 return
389
390 params = cfg.vm_configs[config['cfg_name']].copy()
koder aka kdanilov168f6092015-04-19 02:33:38 +0300391 os_nodes_ids = []
392
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300393 if not start_vms.is_connected():
394 os_creds = get_OS_credentials(cfg, ctx)
395 else:
koder aka kdanilovb7197432015-07-15 00:40:43 +0300396 os_creds = None
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300397
koder aka kdanilovb7197432015-07-15 00:40:43 +0300398 nova = start_vms.nova_connect(os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300399
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300400 params.update(config)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300401 params.update(get_vm_keypair(cfg))
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300402
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300403 params['group_name'] = cfg.run_uuid
404 params['keypair_name'] = cfg.vm_configs['keypair_name']
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300405
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300406 if not config.get('skip_preparation', False):
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300407 logger.info("Preparing openstack")
koder aka kdanilovb7197432015-07-15 00:40:43 +0300408 start_vms.prepare_os_subpr(nova, params, os_creds)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300409
410 new_nodes = []
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300411 old_nodes = ctx.nodes[:]
koder aka kdanilov168f6092015-04-19 02:33:38 +0300412 try:
koder aka kdanilov10266f42015-09-10 19:26:08 +0300413 for new_node, node_id in start_vms.launch_vms(nova, params, already_has_count):
koder aka kdanilov168f6092015-04-19 02:33:38 +0300414 new_node.roles.append('testnode')
415 ctx.nodes.append(new_node)
416 os_nodes_ids.append(node_id)
417 new_nodes.append(new_node)
418
419 store_nodes_in_log(cfg, os_nodes_ids)
420 ctx.openstack_nodes_ids = os_nodes_ids
421
422 yield new_nodes
423
424 finally:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300425 if not cfg.keep_vm:
koder aka kdanilov168f6092015-04-19 02:33:38 +0300426 shut_down_vms_stage(cfg, ctx)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300427 ctx.nodes = old_nodes
koder aka kdanilov168f6092015-04-19 02:33:38 +0300428
429
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300430def run_tests_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300431 ctx.results = collections.defaultdict(lambda: [])
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300432
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300433 for group in cfg.get('tests', []):
koder aka kdanilovcee43342015-04-14 22:52:53 +0300434
koder aka kdanilov170936a2015-06-27 22:51:17 +0300435 if len(group.items()) != 1:
436 msg = "Items in tests section should have len == 1"
437 logger.error(msg)
438 raise utils.StopTestError(msg)
439
koder aka kdanilovcee43342015-04-14 22:52:53 +0300440 key, config = group.items()[0]
441
442 if 'start_test_nodes' == key:
koder aka kdanilovc368eb62015-04-28 18:22:01 +0300443 if 'openstack' not in config:
444 msg = "No openstack block in config - can't spawn vm's"
445 logger.error(msg)
446 raise utils.StopTestError(msg)
447
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300448 num_test_nodes = 0
449 for node in ctx.nodes:
450 if 'testnode' in node.roles:
451 num_test_nodes += 1
koder aka kdanilovd5ed4da2015-05-07 23:33:23 +0300452
453 vm_ctx = create_vms_ctx(ctx, cfg, config['openstack'],
454 num_test_nodes)
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300455 tests = config.get('tests', [])
456 else:
457 vm_ctx = utils.empty_ctx([])
458 tests = [group]
koder aka kdanilovcee43342015-04-14 22:52:53 +0300459
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300460 if cfg.get('sensors') is None:
461 sensor_ctx = utils.empty_ctx()
462 else:
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300463 sensor_ctx = sensor_monitoring(cfg.get('sensors'), ctx.nodes)
koder aka kdanilovcee43342015-04-14 22:52:53 +0300464
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300465 with vm_ctx as new_nodes:
466 if len(new_nodes) != 0:
467 connect_all(new_nodes, True)
468
469 if not cfg.no_tests:
470 for test_group in tests:
471 with sensor_ctx:
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300472 for tp, res in run_tests(cfg, test_group, ctx.nodes):
473 ctx.results[tp].extend(res)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300474
gstepanov023c1e42015-04-08 15:50:19 +0300475
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300476def shut_down_vms_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300477 vm_ids_fname = cfg.vm_ids_fname
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300478 if ctx.openstack_nodes_ids is None:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300479 nodes_ids = open(vm_ids_fname).read().split()
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300480 else:
481 nodes_ids = ctx.openstack_nodes_ids
482
koder aka kdanilov652cd802015-04-13 12:21:07 +0300483 if len(nodes_ids) != 0:
484 logger.info("Removing nodes")
485 start_vms.clear_nodes(nodes_ids)
486 logger.info("Nodes has been removed")
gstepanov023c1e42015-04-08 15:50:19 +0300487
koder aka kdanilov66839a92015-04-11 13:22:31 +0300488 if os.path.exists(vm_ids_fname):
489 os.remove(vm_ids_fname)
gstepanov023c1e42015-04-08 15:50:19 +0300490
koder aka kdanilov66839a92015-04-11 13:22:31 +0300491
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300492def store_nodes_in_log(cfg: Config, nodes_ids: Iterable[str]):
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300493 with open(cfg.vm_ids_fname, 'w') as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300494 fd.write("\n".join(nodes_ids))
gstepanov023c1e42015-04-08 15:50:19 +0300495
496
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300497def clear_enviroment(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300498 if os.path.exists(cfg.vm_ids_fname):
koder aka kdanilov1c2b5112015-04-10 16:53:51 +0300499 shut_down_vms_stage(cfg, ctx)
gstepanov023c1e42015-04-08 15:50:19 +0300500
501
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300502def disconnect_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov652cd802015-04-13 12:21:07 +0300503 ssh_utils.close_all_sessions()
504
koder aka kdanilovda45e882015-04-06 02:24:42 +0300505 for node in ctx.nodes:
506 if node.connection is not None:
507 node.connection.close()
508
509
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300510def store_raw_results_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300511 if os.path.exists(cfg.raw_results):
512 cont = yaml_load(open(cfg.raw_results).read())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300513 else:
514 cont = []
515
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300516 cont.extend(utils.yamable(ctx.results).items())
koder aka kdanilov66839a92015-04-11 13:22:31 +0300517 raw_data = pretty_yaml.dumps(cont)
518
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300519 with open(cfg.raw_results, "w") as fd:
koder aka kdanilov66839a92015-04-11 13:22:31 +0300520 fd.write(raw_data)
521
522
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300523def console_report_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300524 first_report = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300525 text_rep_fname = cfg.text_report_file
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300526 with open(text_rep_fname, "w") as fd:
527 for tp, data in ctx.results.items():
528 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300529 rep_lst = []
530 for result in data:
531 rep_lst.append(
532 IOPerfTest.format_for_console(list(result)))
533 rep = "\n\n".join(rep_lst)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300534 elif tp in ['mysql', 'pgbench'] and data is not None:
535 rep = MysqlTest.format_for_console(data)
Yulia Portnovab0c977c2015-12-11 19:23:28 +0200536 elif tp == 'omg':
537 rep = OmgTest.format_for_console(data)
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300538 else:
539 logger.warning("Can't generate text report for " + tp)
540 continue
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300541
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300542 fd.write(rep)
543 fd.write("\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300544
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300545 if first_report:
546 logger.info("Text report were stored in " + text_rep_fname)
547 first_report = False
548
koder aka kdanilov4af1c1d2015-05-18 15:48:58 +0300549 print("\n" + rep + "\n")
koder aka kdanilov416b87a2015-05-12 00:26:04 +0300550
koder aka kdanilov66839a92015-04-11 13:22:31 +0300551
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300552def test_load_report_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300553 load_rep_fname = cfg.load_report_file
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300554 found = False
555 for idx, (tp, data) in enumerate(ctx.results.items()):
556 if 'io' == tp and data is not None:
557 if found:
558 logger.error("Making reports for more than one " +
559 "io block isn't supported! All " +
560 "report, except first are skipped")
561 continue
562 found = True
563 report.make_load_report(idx, cfg['results'], load_rep_fname)
564
565
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300566def html_report_stage(cfg: Config, ctx: TestRun) -> None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300567 html_rep_fname = cfg.html_report_file
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300568 found = False
koder aka kdanilovfd2cfa52015-05-20 03:17:42 +0300569 for tp, data in ctx.results.items():
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300570 if 'io' == tp and data is not None:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300571 if found or len(data) > 1:
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300572 logger.error("Making reports for more than one " +
573 "io block isn't supported! All " +
574 "report, except first are skipped")
575 continue
576 found = True
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300577 report.make_io_report(list(data[0]),
koder aka kdanilov88407ff2015-05-26 15:35:57 +0300578 cfg.get('comment', ''),
579 html_rep_fname,
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300580 lab_info=ctx.hw_info)
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300581
koder aka kdanilovda45e882015-04-06 02:24:42 +0300582
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300583def load_data_from_path(test_res_dir: str) -> Mapping[str, List[Any]]:
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300584 files = get_test_files(test_res_dir)
585 raw_res = yaml_load(open(files['raw_results']).read())
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300586 res = collections.defaultdict(list)
koder aka kdanilovda45e882015-04-06 02:24:42 +0300587
koder aka kdanilov0fdaaee2015-06-30 11:10:48 +0300588 for tp, test_lists in raw_res:
589 for tests in test_lists:
590 for suite_name, suite_data in tests.items():
591 result_folder = suite_data[0]
592 res[tp].append(TOOL_TYPE_MAPPER[tp].load(suite_name, result_folder))
koder aka kdanilovda45e882015-04-06 02:24:42 +0300593
koder aka kdanilov6b872662015-06-23 01:58:36 +0300594 return res
595
596
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300597def load_data_from_path_stage(var_dir: str, _, ctx: TestRun) -> None:
koder aka kdanilov6b872662015-06-23 01:58:36 +0300598 for tp, vals in load_data_from_path(var_dir).items():
599 ctx.results.setdefault(tp, []).extend(vals)
koder aka kdanilovbc2c8982015-06-13 02:50:43 +0300600
601
koder aka kdanilov3b4da8b2016-10-17 00:17:53 +0300602def load_data_from(var_dir: str) -> Callable:
koder aka kdanilov6b872662015-06-23 01:58:36 +0300603 return functools.partial(load_data_from_path_stage, var_dir)