gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 1 | import os |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 2 | import re |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 3 | import time |
koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 4 | import logging |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 5 | import functools |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 6 | import contextlib |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 7 | import collections |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 8 | from typing import List, Dict, Optional, Iterable, Any, Generator, Mapping, Callable |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 9 | from yaml import load as _yaml_load |
| 10 | |
| 11 | try: |
| 12 | from yaml import CLoader |
| 13 | yaml_load = functools.partial(_yaml_load, Loader=CLoader) |
| 14 | except ImportError: |
| 15 | yaml_load = _yaml_load |
| 16 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 17 | from concurrent.futures import ThreadPoolExecutor, wait |
koder aka kdanilov | 6c49106 | 2015-04-09 22:33:13 +0300 | [diff] [blame] | 18 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 19 | from .config import Config |
| 20 | from .config import get_test_files |
| 21 | from .discover import discover, Node |
| 22 | from .inode import INode |
| 23 | from .test_run_class import TestRun |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 24 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 25 | from . import pretty_yaml, utils, report, ssh_utils, start_vms |
| 26 | |
| 27 | from .suits.mysql import MysqlTest |
| 28 | from .suits.itest import TestConfig |
| 29 | from .suits.io.fio import IOPerfTest |
| 30 | from .suits.postgres import PgBenchTest |
| 31 | from .suits.omgbench import OmgTest |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 32 | |
| 33 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 34 | TOOL_TYPE_MAPPER = { |
| 35 | "io": IOPerfTest, |
| 36 | "pgbench": PgBenchTest, |
| 37 | "mysql": MysqlTest, |
Yulia Portnova | b0c977c | 2015-12-11 19:23:28 +0200 | [diff] [blame] | 38 | "omg": OmgTest, |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 39 | } |
koder aka kdanilov | 63ad206 | 2015-04-27 13:11:40 +0300 | [diff] [blame] | 40 | |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 41 | |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 42 | logger = logging.getLogger("wally") |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 43 | |
koder aka kdanilov | 7acd6bd | 2015-02-12 14:28:30 -0800 | [diff] [blame] | 44 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 45 | def connect_all(nodes: Iterable[INode], spawned_node: Optional[bool]=False) -> None: |
| 46 | """Connect to all nodes, log errors |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 47 | nodes:[Node] - list of nodes |
| 48 | spawned_node:bool - whenever nodes is newly spawned VM |
| 49 | """ |
koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 50 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 51 | logger.info("Connecting to nodes") |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 52 | |
| 53 | conn_timeout = 240 if spawned_node else 30 |
| 54 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 55 | def connect_ext(node: INode) -> bool: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 56 | try: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 57 | node.connect_ssh(conn_timeout) |
| 58 | node.connect_rpc(conn_timeout) |
| 59 | return True |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 60 | except Exception as exc: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 61 | logger.error("During connect to {}: {!s}".format(node, exc)) |
| 62 | return False |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 63 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 64 | with ThreadPoolExecutor(32) as pool: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 65 | list(pool.map(connect_ext, nodes)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 66 | |
| 67 | failed_testnodes = [] |
| 68 | failed_nodes = [] |
| 69 | |
| 70 | for node in nodes: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 71 | if not node.is_connected(): |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 72 | if 'testnode' in node.roles: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 73 | failed_testnodes.append(node) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 74 | else: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 75 | failed_nodes.append(node) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 76 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 77 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 80 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 81 | if failed_testnodes: |
| 82 | msg = "Can't connect to testnode(s) " + \ |
| 83 | ",".join(map(str, failed_testnodes)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 84 | logger.error(msg) |
| 85 | raise utils.StopTestError(msg) |
| 86 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 87 | if not failed_nodes: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 88 | logger.info("All nodes connected successfully") |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 89 | |
| 90 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 91 | def 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 kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 94 | 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 kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 99 | fitures = pool.submit(node.discover_hardware_info |
| 100 | for node in nodes) |
| 101 | wait(fitures) |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 102 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 103 | with open(cfg.hwreport_fname, 'w') as hwfd: |
| 104 | for node in nodes: |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 105 | hwfd.write("-" * 60 + "\n") |
| 106 | hwfd.write("Roles : " + ", ".join(node.roles) + "\n") |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 107 | hwfd.write(str(node.hwinfo) + "\n") |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 108 | hwfd.write("-" * 60 + "\n\n") |
| 109 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 110 | if node.hwinfo.hostname is not None: |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 111 | fname = os.path.join( |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 112 | cfg.hwinfo_directory, |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 113 | node.hwinfo.hostname + "_lshw.xml") |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 114 | |
| 115 | with open(fname, "w") as fd: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 116 | 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 kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 120 | |
| 121 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 122 | @contextlib.contextmanager |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 123 | def suspend_vm_nodes_ctx(unused_nodes: Iterable[INode]) -> Generator[List[int]]: |
| 124 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 125 | pausable_nodes_ids = [node.os_vm_id for node in unused_nodes |
| 126 | if node.os_vm_id is not None] |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 127 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 128 | non_pausable = len(unused_nodes) - len(pausable_nodes_ids) |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 129 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 130 | if 0 != non_pausable: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 131 | logger.warning("Can't pause {} nodes".format( |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 132 | non_pausable)) |
| 133 | |
| 134 | if len(pausable_nodes_ids) != 0: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 135 | logger.debug("Try to pause {} unused nodes".format( |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 136 | len(pausable_nodes_ids))) |
| 137 | start_vms.pause(pausable_nodes_ids) |
| 138 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 139 | try: |
| 140 | yield pausable_nodes_ids |
| 141 | finally: |
| 142 | if len(pausable_nodes_ids) != 0: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 143 | logger.debug("Unpausing {} nodes".format( |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 144 | len(pausable_nodes_ids))) |
| 145 | start_vms.unpause(pausable_nodes_ids) |
| 146 | |
| 147 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 148 | 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] | 149 | # make a directory for results |
| 150 | all_tests_dirs = os.listdir(results) |
| 151 | |
| 152 | if 'name' in params: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 153 | dir_name = "{}_{}".format(name, params['name']) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 154 | else: |
| 155 | for idx in range(len(all_tests_dirs) + 1): |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 156 | dir_name = "{}_{}".format(name, idx) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 157 | 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 kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 163 | |
| 164 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 165 | @contextlib.contextmanager |
| 166 | def sensor_monitoring(sensor_cfg: Any, nodes: Iterable[INode]) -> Generator[None]: |
| 167 | # TODO(koder): write this function |
| 168 | pass |
| 169 | |
| 170 | |
| 171 | def run_tests(cfg: Config, test_block, nodes: Iterable[INode]) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 172 | """ |
| 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 kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 177 | |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 178 | if len(test_nodes) == 0: |
| 179 | logger.error("No test nodes found") |
| 180 | return |
| 181 | |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 182 | for name, params in test_block.items(): |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 183 | results = [] |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 184 | |
| 185 | # iterate over all node counts |
| 186 | limit = params.get('node_limit', len(test_nodes)) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 187 | if isinstance(limit, int): |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 188 | vm_limits = [limit] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 189 | else: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 190 | list_or_tpl = isinstance(limit, (tuple, list)) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 191 | all_ints = list_or_tpl and all(isinstance(climit, int) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 192 | 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 kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 197 | vm_limits = limit |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 198 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 199 | for vm_count in vm_limits: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 200 | # select test nodes |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 201 | 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 kdanilov | e87ae65 | 2015-04-20 02:14:35 +0300 | [diff] [blame] | 207 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 208 | if 0 == len(curr_test_nodes): |
| 209 | continue |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 210 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 211 | results_path = generate_result_dir_name(cfg.results_storage, name, params) |
| 212 | utils.mkdirs_if_unxists(results_path) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 213 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 214 | # 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 kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 217 | else: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 218 | suspend_ctx = utils.empty_ctx() |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 219 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 220 | 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 kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 223 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 224 | if len(resumable_nodes_ids) != 0: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 225 | logger.debug("Check and unpause {} nodes".format( |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 226 | len(resumable_nodes_ids))) |
| 227 | start_vms.unpause(resumable_nodes_ids) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 228 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 229 | test_cls = TOOL_TYPE_MAPPER[name] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 230 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 231 | remote_dir = cfg.default_test_local_folder.format(name=name) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 232 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 233 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 239 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 240 | t_start = time.time() |
| 241 | res = test_cls(test_cfg).run() |
| 242 | t_end = time.time() |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 243 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 244 | results.append(res) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 245 | |
| 246 | yield name, results |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 247 | |
| 248 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 249 | def connect_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 250 | ctx.clear_calls_stack.append(disconnect_stage) |
| 251 | connect_all(ctx.nodes) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 252 | ctx.nodes = [node for node in ctx.nodes if node.connection is not None] |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 253 | |
| 254 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 255 | def discover_stage(cfg: Config, ctx: TestRun) -> None: |
| 256 | """discover clusters and nodes stage""" |
| 257 | |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 258 | if cfg.get('discover') is not None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 259 | discover_objs = [i.strip() for i in cfg.discover.strip().split(",")] |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 260 | |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 261 | nodes = discover(ctx, |
| 262 | discover_objs, |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 263 | cfg.clouds, |
| 264 | cfg.results_storage, |
| 265 | not cfg.dont_discover_nodes) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 266 | |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 267 | ctx.nodes.extend(nodes) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 268 | |
| 269 | for url, roles in cfg.get('explicit_nodes', {}).items(): |
| 270 | ctx.nodes.append(Node(url, roles.split(","))) |
| 271 | |
| 272 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 273 | def save_nodes_stage(cfg: Config, ctx: TestRun) -> None: |
| 274 | """Save nodes list to file""" |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 275 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 284 | with open(cfg.nodes_report_file, "w") as fd: |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 285 | fd.write(pretty_yaml.dumps(cluster)) |
| 286 | |
| 287 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 288 | def reuse_vms_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 289 | vms_patterns = cfg.get('clouds', {}).get('openstack', {}).get('vms', []) |
| 290 | private_key_path = get_vm_keypair(cfg)['keypair_file_private'] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 291 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 292 | for creds in vms_patterns: |
| 293 | user_name, vm_name_pattern = creds.split("@", 1) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 294 | msg = "Vm like {} lookup failed".format(vm_name_pattern) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 295 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 296 | with utils.LogError(msg): |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 297 | msg = "Looking for vm with name like {0}".format(vm_name_pattern) |
| 298 | logger.debug(msg) |
| 299 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 300 | if not start_vms.is_connected(): |
| 301 | os_creds = get_OS_credentials(cfg, ctx) |
| 302 | else: |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 303 | os_creds = None |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 304 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 305 | conn = start_vms.nova_connect(os_creds) |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 306 | 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] | 307 | 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 kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 311 | node.os_vm_id = vm_id |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 312 | ctx.nodes.append(node) |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 313 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 314 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 315 | def get_OS_credentials(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 316 | creds = None |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 317 | os_creds = None |
koder aka kdanilov | 8fbb27f | 2015-07-17 22:23:31 +0300 | [diff] [blame] | 318 | force_insecure = False |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 319 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 320 | if 'openstack' in cfg.clouds: |
| 321 | os_cfg = cfg.clouds['openstack'] |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 322 | if 'OPENRC' in os_cfg: |
| 323 | logger.info("Using OS credentials from " + os_cfg['OPENRC']) |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 324 | creds_tuple = utils.get_creds_openrc(os_cfg['OPENRC']) |
| 325 | os_creds = start_vms.OSCreds(*creds_tuple) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 326 | elif 'ENV' in os_cfg: |
| 327 | logger.info("Using OS credentials from shell environment") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 328 | os_creds = start_vms.ostack_get_creds() |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 329 | elif 'OS_TENANT_NAME' in os_cfg: |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 330 | logger.info("Using predefined credentials") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 331 | 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 kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 336 | |
koder aka kdanilov | 8fbb27f | 2015-07-17 22:23:31 +0300 | [diff] [blame] | 337 | elif 'OS_INSECURE' in os_cfg: |
| 338 | force_insecure = os_cfg.get('OS_INSECURE', False) |
| 339 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 340 | if os_creds is None and 'fuel' in cfg.clouds and \ |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 341 | 'openstack_env' in cfg.clouds['fuel'] and \ |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 342 | ctx.fuel_openstack_creds is not None: |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 343 | logger.info("Using fuel creds") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 344 | creds = start_vms.OSCreds(**ctx.fuel_openstack_creds) |
| 345 | elif os_creds is None: |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 346 | logger.error("Can't found OS credentials") |
| 347 | raise utils.StopTestError("Can't found OS credentials", None) |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 348 | |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 349 | if creds is None: |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 350 | creds = os_creds |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 351 | |
koder aka kdanilov | 8fbb27f | 2015-07-17 22:23:31 +0300 | [diff] [blame] | 352 | 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 kdanilov | 05e15b9 | 2016-02-07 19:32:46 +0200 | [diff] [blame] | 359 | logger.debug(("OS_CREDS: user={0.name} tenant={0.tenant} " + |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 360 | "auth_url={0.auth_url} insecure={0.insecure}").format(creds)) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 361 | |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 362 | return creds |
koder aka kdanilov | 4e9f3ed | 2015-04-14 11:26:12 +0300 | [diff] [blame] | 363 | |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 364 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 365 | def get_vm_keypair(cfg: Config) -> Dict[str, str]: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 366 | 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 kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 381 | @contextlib.contextmanager |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 382 | def create_vms_ctx(ctx: TestRun, cfg: Config, config, already_has_count: int=0) -> Generator[List[INode]]: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 383 | 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 kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 391 | os_nodes_ids = [] |
| 392 | |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 393 | if not start_vms.is_connected(): |
| 394 | os_creds = get_OS_credentials(cfg, ctx) |
| 395 | else: |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 396 | os_creds = None |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 397 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 398 | nova = start_vms.nova_connect(os_creds) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 399 | |
koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 400 | params.update(config) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 401 | params.update(get_vm_keypair(cfg)) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 402 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 403 | params['group_name'] = cfg.run_uuid |
| 404 | params['keypair_name'] = cfg.vm_configs['keypair_name'] |
koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 405 | |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 406 | if not config.get('skip_preparation', False): |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 407 | logger.info("Preparing openstack") |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 408 | start_vms.prepare_os_subpr(nova, params, os_creds) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 409 | |
| 410 | new_nodes = [] |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 411 | old_nodes = ctx.nodes[:] |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 412 | try: |
koder aka kdanilov | 10266f4 | 2015-09-10 19:26:08 +0300 | [diff] [blame] | 413 | 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] | 414 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 425 | if not cfg.keep_vm: |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 426 | shut_down_vms_stage(cfg, ctx) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 427 | ctx.nodes = old_nodes |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 428 | |
| 429 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 430 | def run_tests_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 431 | ctx.results = collections.defaultdict(lambda: []) |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 432 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 433 | for group in cfg.get('tests', []): |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 434 | |
koder aka kdanilov | 170936a | 2015-06-27 22:51:17 +0300 | [diff] [blame] | 435 | 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 kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 440 | key, config = group.items()[0] |
| 441 | |
| 442 | if 'start_test_nodes' == key: |
koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 443 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 448 | num_test_nodes = 0 |
| 449 | for node in ctx.nodes: |
| 450 | if 'testnode' in node.roles: |
| 451 | num_test_nodes += 1 |
koder aka kdanilov | d5ed4da | 2015-05-07 23:33:23 +0300 | [diff] [blame] | 452 | |
| 453 | vm_ctx = create_vms_ctx(ctx, cfg, config['openstack'], |
| 454 | num_test_nodes) |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 455 | tests = config.get('tests', []) |
| 456 | else: |
| 457 | vm_ctx = utils.empty_ctx([]) |
| 458 | tests = [group] |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 459 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 460 | if cfg.get('sensors') is None: |
| 461 | sensor_ctx = utils.empty_ctx() |
| 462 | else: |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 463 | sensor_ctx = sensor_monitoring(cfg.get('sensors'), ctx.nodes) |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 464 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 465 | 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 kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 472 | for tp, res in run_tests(cfg, test_group, ctx.nodes): |
| 473 | ctx.results[tp].extend(res) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 474 | |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 475 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 476 | def shut_down_vms_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 477 | vm_ids_fname = cfg.vm_ids_fname |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 478 | if ctx.openstack_nodes_ids is None: |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 479 | nodes_ids = open(vm_ids_fname).read().split() |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 480 | else: |
| 481 | nodes_ids = ctx.openstack_nodes_ids |
| 482 | |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 483 | if len(nodes_ids) != 0: |
| 484 | logger.info("Removing nodes") |
| 485 | start_vms.clear_nodes(nodes_ids) |
| 486 | logger.info("Nodes has been removed") |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 487 | |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 488 | if os.path.exists(vm_ids_fname): |
| 489 | os.remove(vm_ids_fname) |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 490 | |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 491 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 492 | def store_nodes_in_log(cfg: Config, nodes_ids: Iterable[str]): |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 493 | with open(cfg.vm_ids_fname, 'w') as fd: |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 494 | fd.write("\n".join(nodes_ids)) |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 495 | |
| 496 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 497 | def clear_enviroment(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 498 | if os.path.exists(cfg.vm_ids_fname): |
koder aka kdanilov | 1c2b511 | 2015-04-10 16:53:51 +0300 | [diff] [blame] | 499 | shut_down_vms_stage(cfg, ctx) |
gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 500 | |
| 501 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 502 | def disconnect_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 503 | ssh_utils.close_all_sessions() |
| 504 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 505 | for node in ctx.nodes: |
| 506 | if node.connection is not None: |
| 507 | node.connection.close() |
| 508 | |
| 509 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 510 | def store_raw_results_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 511 | if os.path.exists(cfg.raw_results): |
| 512 | cont = yaml_load(open(cfg.raw_results).read()) |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 513 | else: |
| 514 | cont = [] |
| 515 | |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 516 | cont.extend(utils.yamable(ctx.results).items()) |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 517 | raw_data = pretty_yaml.dumps(cont) |
| 518 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 519 | with open(cfg.raw_results, "w") as fd: |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 520 | fd.write(raw_data) |
| 521 | |
| 522 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 523 | def console_report_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 524 | first_report = True |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 525 | text_rep_fname = cfg.text_report_file |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 526 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 529 | 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 kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 534 | elif tp in ['mysql', 'pgbench'] and data is not None: |
| 535 | rep = MysqlTest.format_for_console(data) |
Yulia Portnova | b0c977c | 2015-12-11 19:23:28 +0200 | [diff] [blame] | 536 | elif tp == 'omg': |
| 537 | rep = OmgTest.format_for_console(data) |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 538 | else: |
| 539 | logger.warning("Can't generate text report for " + tp) |
| 540 | continue |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 541 | |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 542 | fd.write(rep) |
| 543 | fd.write("\n") |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 544 | |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 545 | if first_report: |
| 546 | logger.info("Text report were stored in " + text_rep_fname) |
| 547 | first_report = False |
| 548 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 549 | print("\n" + rep + "\n") |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 550 | |
koder aka kdanilov | 66839a9 | 2015-04-11 13:22:31 +0300 | [diff] [blame] | 551 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 552 | def test_load_report_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 553 | load_rep_fname = cfg.load_report_file |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 554 | 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 kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 566 | def html_report_stage(cfg: Config, ctx: TestRun) -> None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 567 | html_rep_fname = cfg.html_report_file |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 568 | found = False |
koder aka kdanilov | fd2cfa5 | 2015-05-20 03:17:42 +0300 | [diff] [blame] | 569 | for tp, data in ctx.results.items(): |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 570 | if 'io' == tp and data is not None: |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 571 | if found or len(data) > 1: |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 572 | 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 kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 577 | report.make_io_report(list(data[0]), |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 578 | cfg.get('comment', ''), |
| 579 | html_rep_fname, |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 580 | lab_info=ctx.hw_info) |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 581 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 582 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 583 | 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] | 584 | files = get_test_files(test_res_dir) |
| 585 | raw_res = yaml_load(open(files['raw_results']).read()) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 586 | res = collections.defaultdict(list) |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 587 | |
koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 588 | 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 kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 593 | |
koder aka kdanilov | 6b87266 | 2015-06-23 01:58:36 +0300 | [diff] [blame] | 594 | return res |
| 595 | |
| 596 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 597 | 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] | 598 | for tp, vals in load_data_from_path(var_dir).items(): |
| 599 | ctx.results.setdefault(tp, []).extend(vals) |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 600 | |
| 601 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame^] | 602 | def load_data_from(var_dir: str) -> Callable: |
koder aka kdanilov | 6b87266 | 2015-06-23 01:58:36 +0300 | [diff] [blame] | 603 | return functools.partial(load_data_from_path_stage, var_dir) |