gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 1 | import os |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 2 | import time |
koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 3 | import logging |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 4 | import functools |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 5 | import contextlib |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 6 | import collections |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 7 | from typing import List, Dict, Iterable, Any, Iterator, Mapping, Callable, Tuple, Optional |
| 8 | from concurrent.futures import ThreadPoolExecutor, Future |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 9 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 10 | from .inode import INode |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 11 | from .discover import discover |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 12 | from .test_run_class import TestRun |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 13 | from . import pretty_yaml, utils, report, ssh_utils, start_vms, hw_info |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 14 | |
| 15 | from .suits.mysql import MysqlTest |
| 16 | from .suits.itest import TestConfig |
| 17 | from .suits.io.fio import IOPerfTest |
| 18 | from .suits.postgres import PgBenchTest |
| 19 | from .suits.omgbench import OmgTest |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 20 | |
| 21 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 22 | TOOL_TYPE_MAPPER = { |
| 23 | "io": IOPerfTest, |
| 24 | "pgbench": PgBenchTest, |
| 25 | "mysql": MysqlTest, |
Yulia Portnova | b0c977c | 2015-12-11 19:23:28 +0200 | [diff] [blame] | 26 | "omg": OmgTest, |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 27 | } |
koder aka kdanilov | 63ad206 | 2015-04-27 13:11:40 +0300 | [diff] [blame] | 28 | |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 29 | |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 30 | logger = logging.getLogger("wally") |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 31 | |
koder aka kdanilov | 7acd6bd | 2015-02-12 14:28:30 -0800 | [diff] [blame] | 32 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 33 | |
| 34 | def connect_all(nodes: Iterable[INode], |
| 35 | pool: ThreadPoolExecutor, |
| 36 | conn_timeout: int = 30, |
| 37 | rpc_conn_callback: ssh_utils.RPCBeforeConnCallback = None) -> None: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 38 | """Connect to all nodes, log errors |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 39 | nodes - list of nodes |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 40 | """ |
koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 41 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 42 | logger.info("Connecting to %s nodes", len(nodes)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 43 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 44 | def connect_ext(node: INode) -> bool: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 45 | try: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 46 | node.connect_ssh(conn_timeout) |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 47 | node.rpc, node.rpc_params = ssh_utils.setup_rpc(node, rpc_conn_callback=rpc_conn_callback) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 48 | return True |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 49 | except Exception as exc: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 50 | logger.error("During connect to {}: {!s}".format(node, exc)) |
| 51 | return False |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 52 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 53 | list(pool.map(connect_ext, nodes)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 54 | |
| 55 | failed_testnodes = [] |
| 56 | failed_nodes = [] |
| 57 | |
| 58 | for node in nodes: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 59 | if not node.is_connected(): |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 60 | if 'testnode' in node.roles: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 61 | failed_testnodes.append(node) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 62 | else: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 63 | failed_nodes.append(node) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 64 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 65 | if failed_nodes: |
| 66 | msg = "Node(s) {} would be excluded - can't connect" |
| 67 | logger.warning(msg.format(",".join(map(str, failed_nodes)))) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 68 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 69 | if failed_testnodes: |
| 70 | msg = "Can't connect to testnode(s) " + \ |
| 71 | ",".join(map(str, failed_testnodes)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 72 | logger.error(msg) |
| 73 | raise utils.StopTestError(msg) |
| 74 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 75 | if not failed_nodes: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 76 | logger.info("All nodes connected successfully") |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 77 | |
| 78 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 79 | def collect_info_stage(ctx: TestRun, nodes: Iterable[INode]) -> None: |
| 80 | futures = {} # type: Dict[str, Future] |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 81 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 82 | with ctx.get_pool() as pool: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 83 | for node in nodes: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 84 | hw_info_path = "hw_info/{}".format(node.node_id()) |
| 85 | if hw_info_path not in ctx.storage: |
| 86 | futures[hw_info_path] = pool.submit(hw_info.get_hw_info, node) |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 87 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 88 | sw_info_path = "sw_info/{}".format(node.node_id()) |
| 89 | if sw_info_path not in ctx.storage: |
| 90 | futures[sw_info_path] = pool.submit(hw_info.get_sw_info, node) |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 91 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 92 | for path, future in futures.items(): |
| 93 | ctx.storage[path] = future.result() |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 94 | |
| 95 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 96 | @contextlib.contextmanager |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 97 | def suspend_vm_nodes_ctx(unused_nodes: List[INode]) -> Iterator[List[int]]: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 98 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 99 | pausable_nodes_ids = [node.os_vm_id for node in unused_nodes |
| 100 | if node.os_vm_id is not None] |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 101 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 102 | non_pausable = len(unused_nodes) - len(pausable_nodes_ids) |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 103 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 104 | if 0 != non_pausable: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 105 | logger.warning("Can't pause {} nodes".format( |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 106 | non_pausable)) |
| 107 | |
| 108 | if len(pausable_nodes_ids) != 0: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 109 | logger.debug("Try to pause {} unused nodes".format( |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 110 | len(pausable_nodes_ids))) |
| 111 | start_vms.pause(pausable_nodes_ids) |
| 112 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 113 | try: |
| 114 | yield pausable_nodes_ids |
| 115 | finally: |
| 116 | if len(pausable_nodes_ids) != 0: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 117 | logger.debug("Unpausing {} nodes".format( |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 118 | len(pausable_nodes_ids))) |
| 119 | start_vms.unpause(pausable_nodes_ids) |
| 120 | |
| 121 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 122 | def generate_result_dir_name(results: str, name: str, params: Dict[str, Any]) -> str: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 123 | # make a directory for results |
| 124 | all_tests_dirs = os.listdir(results) |
| 125 | |
| 126 | if 'name' in params: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 127 | dir_name = "{}_{}".format(name, params['name']) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 128 | else: |
| 129 | for idx in range(len(all_tests_dirs) + 1): |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 130 | dir_name = "{}_{}".format(name, idx) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 131 | if dir_name not in all_tests_dirs: |
| 132 | break |
| 133 | else: |
| 134 | raise utils.StopTestError("Can't select directory for test results") |
| 135 | |
| 136 | return os.path.join(results, dir_name) |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 137 | |
| 138 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 139 | @contextlib.contextmanager |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 140 | def sensor_monitoring(sensor_cfg: Any, nodes: Iterable[INode]) -> Iterator[None]: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 141 | # TODO(koder): write this function |
| 142 | pass |
| 143 | |
| 144 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 145 | def run_tests(cfg: Config, |
| 146 | test_block: Dict[str, Dict[str, Any]], |
| 147 | nodes: Iterable[INode]) -> Iterator[Tuple[str, List[Any]]]: |
| 148 | """Run test from test block""" |
| 149 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 150 | test_nodes = [node for node in nodes if 'testnode' in node.roles] |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 151 | |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 152 | if len(test_nodes) == 0: |
| 153 | logger.error("No test nodes found") |
| 154 | return |
| 155 | |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 156 | for name, params in test_block.items(): |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 157 | results = [] |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 158 | |
| 159 | # iterate over all node counts |
| 160 | limit = params.get('node_limit', len(test_nodes)) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 161 | if isinstance(limit, int): |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 162 | vm_limits = [limit] # type: List[int] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 163 | else: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 164 | list_or_tpl = isinstance(limit, (tuple, list)) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 165 | all_ints = list_or_tpl and all(isinstance(climit, int) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 166 | for climit in limit) |
| 167 | if not all_ints: |
| 168 | msg = "'node_limit' parameter ion config should" + \ |
| 169 | "be either int or list if integers, not {0!r}".format(limit) |
| 170 | raise ValueError(msg) |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 171 | vm_limits = limit # type: List[int] |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 172 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 173 | for vm_count in vm_limits: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 174 | # select test nodes |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 175 | if vm_count == 'all': |
| 176 | curr_test_nodes = test_nodes |
| 177 | unused_nodes = [] |
| 178 | else: |
| 179 | curr_test_nodes = test_nodes[:vm_count] |
| 180 | unused_nodes = test_nodes[vm_count:] |
koder aka kdanilov | e87ae65 | 2015-04-20 02:14:35 +0300 | [diff] [blame] | 181 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 182 | if 0 == len(curr_test_nodes): |
| 183 | continue |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 184 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 185 | results_path = generate_result_dir_name(cfg.results_storage, name, params) |
| 186 | utils.mkdirs_if_unxists(results_path) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 187 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 188 | # suspend all unused virtual nodes |
| 189 | if cfg.settings.get('suspend_unused_vms', True): |
| 190 | suspend_ctx = suspend_vm_nodes_ctx(unused_nodes) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 191 | else: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 192 | suspend_ctx = utils.empty_ctx() |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 193 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 194 | with suspend_ctx: |
| 195 | resumable_nodes_ids = [node.os_vm_id for node in curr_test_nodes |
| 196 | if node.os_vm_id is not None] |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 197 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 198 | if len(resumable_nodes_ids) != 0: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 199 | logger.debug("Check and unpause {} nodes".format( |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 200 | len(resumable_nodes_ids))) |
| 201 | start_vms.unpause(resumable_nodes_ids) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 202 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 203 | test_cls = TOOL_TYPE_MAPPER[name] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 204 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 205 | remote_dir = cfg.default_test_local_folder.format(name=name) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 206 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 207 | test_cfg = TestConfig(test_cls.__name__, |
| 208 | params=params, |
| 209 | test_uuid=cfg.run_uuid, |
| 210 | nodes=test_nodes, |
| 211 | log_directory=results_path, |
| 212 | remote_dir=remote_dir) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 213 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 214 | t_start = time.time() |
| 215 | res = test_cls(test_cfg).run() |
| 216 | t_end = time.time() |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 217 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 218 | results.append(res) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 219 | |
| 220 | yield name, results |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 221 | |
| 222 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 223 | def connect_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 224 | ctx.clear_calls_stack.append(disconnect_stage) |
| 225 | connect_all(ctx.nodes) |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 226 | ctx.nodes = [node for node in ctx.nodes if node.is_connected()] |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 227 | |
| 228 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 229 | def discover_stage(cfg: Config, ctx: TestRun) -> None: |
| 230 | """discover clusters and nodes stage""" |
| 231 | |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 232 | if cfg.get('discover') is not None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 233 | discover_objs = [i.strip() for i in cfg.discover.strip().split(",")] |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 234 | |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 235 | nodes = discover(ctx, |
| 236 | discover_objs, |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 237 | cfg.clouds, |
| 238 | cfg.results_storage, |
| 239 | not cfg.dont_discover_nodes) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 240 | |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 241 | ctx.nodes.extend(nodes) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 242 | |
| 243 | for url, roles in cfg.get('explicit_nodes', {}).items(): |
| 244 | ctx.nodes.append(Node(url, roles.split(","))) |
| 245 | |
| 246 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 247 | def save_nodes_stage(cfg: Config, ctx: TestRun) -> None: |
| 248 | """Save nodes list to file""" |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 249 | cluster = {} |
| 250 | for node in ctx.nodes: |
| 251 | roles = node.roles[:] |
| 252 | if 'testnode' in roles: |
| 253 | roles.remove('testnode') |
| 254 | |
| 255 | if len(roles) != 0: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 256 | cluster[node.ssh_conn_url] = roles |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 257 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 258 | with open(cfg.nodes_report_file, "w") as fd: |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 259 | fd.write(pretty_yaml.dumps(cluster)) |
| 260 | |
| 261 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 262 | def reuse_vms_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 263 | vms_patterns = cfg.get('clouds', {}).get('openstack', {}).get('vms', []) |
| 264 | private_key_path = get_vm_keypair(cfg)['keypair_file_private'] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 265 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 266 | for creds in vms_patterns: |
| 267 | user_name, vm_name_pattern = creds.split("@", 1) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 268 | msg = "Vm like {} lookup failed".format(vm_name_pattern) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 269 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 270 | with utils.LogError(msg): |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 271 | msg = "Looking for vm with name like {0}".format(vm_name_pattern) |
| 272 | logger.debug(msg) |
| 273 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 274 | if not start_vms.is_connected(): |
| 275 | os_creds = get_OS_credentials(cfg, ctx) |
| 276 | else: |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 277 | os_creds = None |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 278 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 279 | conn = start_vms.nova_connect(os_creds) |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 280 | for ip, vm_id in start_vms.find_vms(conn, vm_name_pattern): |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 281 | conn_url = "ssh://{user}@{ip}::{key}".format(user=user_name, |
| 282 | ip=ip, |
| 283 | key=private_key_path) |
| 284 | node = Node(conn_url, ['testnode']) |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 285 | node.os_vm_id = vm_id |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 286 | ctx.nodes.append(node) |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 287 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 288 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 289 | def get_OS_credentials(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 290 | creds = None |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 291 | os_creds = None |
koder aka kdanilov | 8fbb27f | 2015-07-17 22:23:31 +0300 | [diff] [blame] | 292 | force_insecure = False |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 293 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 294 | if 'openstack' in cfg.clouds: |
| 295 | os_cfg = cfg.clouds['openstack'] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 296 | if 'OPENRC' in os_cfg: |
| 297 | logger.info("Using OS credentials from " + os_cfg['OPENRC']) |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 298 | creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC']) |
| 299 | os_creds = start_vms.OSCreds(*creds_tuple) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 300 | elif 'ENV' in os_cfg: |
| 301 | logger.info("Using OS credentials from shell environment") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 302 | os_creds = start_vms.ostack_get_creds() |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 303 | elif 'OS_TENANT_NAME' in os_cfg: |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 304 | logger.info("Using predefined credentials") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 305 | os_creds = start_vms.OSCreds(os_cfg['OS_USERNAME'].strip(), |
| 306 | os_cfg['OS_PASSWORD'].strip(), |
| 307 | os_cfg['OS_TENANT_NAME'].strip(), |
| 308 | os_cfg['OS_AUTH_URL'].strip(), |
| 309 | os_cfg.get('OS_INSECURE', False)) |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 310 | |
koder aka kdanilov | 8fbb27f | 2015-07-17 22:23:31 +0300 | [diff] [blame] | 311 | elif 'OS_INSECURE' in os_cfg: |
| 312 | force_insecure = os_cfg.get('OS_INSECURE', False) |
| 313 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 314 | if os_creds is None and 'fuel' in cfg.clouds and \ |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 315 | 'openstack_env' in cfg.clouds['fuel'] and \ |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 316 | ctx.fuel_openstack_creds is not None: |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 317 | logger.info("Using fuel creds") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 318 | creds = start_vms.OSCreds(**ctx.fuel_openstack_creds) |
| 319 | elif os_creds is None: |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 320 | logger.error("Can't found OS credentials") |
| 321 | raise utils.StopTestError("Can't found OS credentials", None) |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 322 | |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 323 | if creds is None: |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 324 | creds = os_creds |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 325 | |
koder aka kdanilov | 8fbb27f | 2015-07-17 22:23:31 +0300 | [diff] [blame] | 326 | if force_insecure and not creds.insecure: |
| 327 | creds = start_vms.OSCreds(creds.name, |
| 328 | creds.passwd, |
| 329 | creds.tenant, |
| 330 | creds.auth_url, |
| 331 | True) |
| 332 | |
koder aka kdanilov | 05e15b9 | 2016-02-07 19:32:46 +0200 | [diff] [blame] | 333 | logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant} " + |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 334 | "auth_url={0.auth_url} insecure={0.insecure}").format(creds)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 335 | |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 336 | return creds |
koder aka kdanilov | 4e9f3ed | 2015-04-14 11:26:12 +0300 | [diff] [blame] | 337 | |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 338 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 339 | def get_vm_keypair(cfg: Config) -> Dict[str, str]: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 340 | res = {} # type: Dict[str, str] |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 341 | for field, ext in (('keypair_file_private', 'pem'), |
| 342 | ('keypair_file_public', 'pub')): |
| 343 | fpath = cfg.vm_configs.get(field) |
| 344 | |
| 345 | if fpath is None: |
| 346 | fpath = cfg.vm_configs['keypair_name'] + "." + ext |
| 347 | |
| 348 | if os.path.isabs(fpath): |
| 349 | res[field] = fpath |
| 350 | else: |
| 351 | res[field] = os.path.join(cfg.config_folder, fpath) |
| 352 | return res |
| 353 | |
| 354 | |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 355 | @contextlib.contextmanager |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 356 | def create_vms_ctx(ctx: TestRun, cfg: Config, config, already_has_count: int=0) -> Iterator[List[INode]]: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 357 | if config['count'].startswith('='): |
| 358 | count = int(config['count'][1:]) |
| 359 | if count <= already_has_count: |
| 360 | logger.debug("Not need new vms") |
| 361 | yield [] |
| 362 | return |
| 363 | |
| 364 | params = cfg.vm_configs[config['cfg_name']].copy() |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 365 | os_nodes_ids = [] |
| 366 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 367 | if not start_vms.is_connected(): |
| 368 | os_creds = get_OS_credentials(cfg, ctx) |
| 369 | else: |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 370 | os_creds = None |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 371 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 372 | nova = start_vms.nova_connect(os_creds) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 373 | |
koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 374 | params.update(config) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 375 | params.update(get_vm_keypair(cfg)) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 376 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 377 | params['group_name'] = cfg.run_uuid |
| 378 | params['keypair_name'] = cfg.vm_configs['keypair_name'] |
koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 379 | |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 380 | if not config.get('skip_preparation', False): |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 381 | logger.info("Preparing openstack") |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 382 | start_vms.prepare_os(nova, params, os_creds) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 383 | |
| 384 | new_nodes = [] |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 385 | old_nodes = ctx.nodes[:] |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 386 | try: |
koder aka kdanilov | 10266f4 | 2015-09-10 19:26:08 +0300 | [diff] [blame] | 387 | for new_node, node_id in start_vms.launch_vms(nova, params, already_has_count): |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 388 | new_node.roles.append('testnode') |
| 389 | ctx.nodes.append(new_node) |
| 390 | os_nodes_ids.append(node_id) |
| 391 | new_nodes.append(new_node) |
| 392 | |
| 393 | store_nodes_in_log(cfg, os_nodes_ids) |
| 394 | ctx.openstack_nodes_ids = os_nodes_ids |
| 395 | |
| 396 | yield new_nodes |
| 397 | |
| 398 | finally: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 399 | if not cfg.keep_vm: |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 400 | shut_down_vms_stage(cfg, ctx) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 401 | ctx.nodes = old_nodes |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 402 | |
| 403 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 404 | def run_tests_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 405 | ctx.results = collections.defaultdict(lambda: []) |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 406 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 407 | for group in cfg.get('tests', []): |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 408 | gitems = list(group.items()) |
| 409 | if len(gitems) != 1: |
koder aka kdanilov | 170936a | 2015-06-27 22:51:17 +0300 | [diff] [blame] | 410 | msg = "Items in tests section should have len == 1" |
| 411 | logger.error(msg) |
| 412 | raise utils.StopTestError(msg) |
| 413 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 414 | key, config = gitems[0] |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 415 | |
| 416 | if 'start_test_nodes' == key: |
koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 417 | if 'openstack' not in config: |
| 418 | msg = "No openstack block in config - can't spawn vm's" |
| 419 | logger.error(msg) |
| 420 | raise utils.StopTestError(msg) |
| 421 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 422 | num_test_nodes = 0 |
| 423 | for node in ctx.nodes: |
| 424 | if 'testnode' in node.roles: |
| 425 | num_test_nodes += 1 |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 426 | |
| 427 | vm_ctx = create_vms_ctx(ctx, cfg, config['openstack'], |
| 428 | num_test_nodes) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 429 | tests = config.get('tests', []) |
| 430 | else: |
| 431 | vm_ctx = utils.empty_ctx([]) |
| 432 | tests = [group] |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 433 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 434 | if cfg.get('sensors') is None: |
| 435 | sensor_ctx = utils.empty_ctx() |
| 436 | else: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 437 | sensor_ctx = sensor_monitoring(cfg.get('sensors'), ctx.nodes) |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 438 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 439 | with vm_ctx as new_nodes: |
| 440 | if len(new_nodes) != 0: |
| 441 | connect_all(new_nodes, True) |
| 442 | |
| 443 | if not cfg.no_tests: |
| 444 | for test_group in tests: |
| 445 | with sensor_ctx: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 446 | it = run_tests(cfg, test_group, ctx.nodes) |
| 447 | for tp, res in it: |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 448 | ctx.results[tp].extend(res) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 449 | |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 450 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 451 | def shut_down_vms_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 452 | vm_ids_fname = cfg.vm_ids_fname |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 453 | if ctx.openstack_nodes_ids is None: |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 454 | nodes_ids = open(vm_ids_fname).read().split() |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 455 | else: |
| 456 | nodes_ids = ctx.openstack_nodes_ids |
| 457 | |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 458 | if len(nodes_ids) != 0: |
| 459 | logger.info("Removing nodes") |
| 460 | start_vms.clear_nodes(nodes_ids) |
| 461 | logger.info("Nodes has been removed") |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 462 | |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 463 | if os.path.exists(vm_ids_fname): |
| 464 | os.remove(vm_ids_fname) |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 465 | |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 466 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 467 | def store_nodes_in_log(cfg: Config, nodes_ids: Iterable[str]) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 468 | with open(cfg.vm_ids_fname, 'w') as fd: |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 469 | fd.write("\n".join(nodes_ids)) |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 470 | |
| 471 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 472 | def clear_enviroment(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 473 | if os.path.exists(cfg.vm_ids_fname): |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 474 | shut_down_vms_stage(cfg, ctx) |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 475 | |
| 476 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 477 | def disconnect_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 478 | ssh_utils.close_all_sessions() |
| 479 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 480 | for node in ctx.nodes: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 481 | node.disconnect() |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 482 | |
| 483 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 484 | def store_raw_results_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 485 | if os.path.exists(cfg.raw_results): |
| 486 | cont = yaml_load(open(cfg.raw_results).read()) |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 487 | else: |
| 488 | cont = [] |
| 489 | |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 490 | cont.extend(utils.yamable(ctx.results).items()) |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 491 | raw_data = pretty_yaml.dumps(cont) |
| 492 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 493 | with open(cfg.raw_results, "w") as fd: |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 494 | fd.write(raw_data) |
| 495 | |
| 496 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 497 | def console_report_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 498 | first_report = True |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 499 | text_rep_fname = cfg.text_report_file |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 500 | with open(text_rep_fname, "w") as fd: |
| 501 | for tp, data in ctx.results.items(): |
| 502 | if 'io' == tp and data is not None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 503 | rep_lst = [] |
| 504 | for result in data: |
| 505 | rep_lst.append( |
| 506 | IOPerfTest.format_for_console(list(result))) |
| 507 | rep = "\n\n".join(rep_lst) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 508 | elif tp in ['mysql', 'pgbench'] and data is not None: |
| 509 | rep = MysqlTest.format_for_console(data) |
Yulia Portnova | b0c977c | 2015-12-11 19:23:28 +0200 | [diff] [blame] | 510 | elif tp == 'omg': |
| 511 | rep = OmgTest.format_for_console(data) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 512 | else: |
| 513 | logger.warning("Can't generate text report for " + tp) |
| 514 | continue |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 515 | |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 516 | fd.write(rep) |
| 517 | fd.write("\n") |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 518 | |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 519 | if first_report: |
| 520 | logger.info("Text report were stored in " + text_rep_fname) |
| 521 | first_report = False |
| 522 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 523 | print("\n" + rep + "\n") |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 524 | |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 525 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 526 | def test_load_report_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 527 | load_rep_fname = cfg.load_report_file |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 528 | found = False |
| 529 | for idx, (tp, data) in enumerate(ctx.results.items()): |
| 530 | if 'io' == tp and data is not None: |
| 531 | if found: |
| 532 | logger.error("Making reports for more than one " + |
| 533 | "io block isn't supported! All " + |
| 534 | "report, except first are skipped") |
| 535 | continue |
| 536 | found = True |
| 537 | report.make_load_report(idx, cfg['results'], load_rep_fname) |
| 538 | |
| 539 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 540 | def html_report_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 541 | html_rep_fname = cfg.html_report_file |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 542 | found = False |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 543 | for tp, data in ctx.results.items(): |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 544 | if 'io' == tp and data is not None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 545 | if found or len(data) > 1: |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 546 | logger.error("Making reports for more than one " + |
| 547 | "io block isn't supported! All " + |
| 548 | "report, except first are skipped") |
| 549 | continue |
| 550 | found = True |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 551 | report.make_io_report(list(data[0]), |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 552 | cfg.get('comment', ''), |
| 553 | html_rep_fname, |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 554 | lab_info=ctx.nodes) |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 555 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 556 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 557 | def load_data_from_path(test_res_dir: str) -> Mapping[str, List[Any]]: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 558 | files = get_test_files(test_res_dir) |
| 559 | raw_res = yaml_load(open(files['raw_results']).read()) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 560 | res = collections.defaultdict(list) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 561 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 562 | for tp, test_lists in raw_res: |
| 563 | for tests in test_lists: |
| 564 | for suite_name, suite_data in tests.items(): |
| 565 | result_folder = suite_data[0] |
| 566 | res[tp].append(TOOL_TYPE_MAPPER[tp].load(suite_name, result_folder)) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 567 | |
koder aka kdanilov | 6b87266 | 2015-06-23 01:58:36 +0300 | [diff] [blame] | 568 | return res |
| 569 | |
| 570 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 571 | def load_data_from_path_stage(var_dir: str, _, ctx: TestRun) -> None: |
koder aka kdanilov | 6b87266 | 2015-06-23 01:58:36 +0300 | [diff] [blame] | 572 | for tp, vals in load_data_from_path(var_dir).items(): |
| 573 | ctx.results.setdefault(tp, []).extend(vals) |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 574 | |
| 575 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame^] | 576 | def load_data_from(var_dir: str) -> Callable[[TestRun], None]: |
koder aka kdanilov | 6b87266 | 2015-06-23 01:58:36 +0300 | [diff] [blame] | 577 | return functools.partial(load_data_from_path_stage, var_dir) |