| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 1 | import time | 
| koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 2 | import json | 
| kdanylov aka koder | 736e5c1 | 2017-05-07 17:27:14 +0300 | [diff] [blame] | 3 | import copy | 
| koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 4 | import logging | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 5 | from typing import List, Tuple, Optional, Union, cast | 
| koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 6 |  | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 7 | from cephlib.wally_storage import WallyDB | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 8 | from cephlib.node import NodeInfo, IRPCNode, get_hw_info, get_sw_info, get_hostname | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 9 | from cephlib.ssh import parse_ssh_uri | 
 | 10 | from cephlib.node_impl import setup_rpc, connect | 
 | 11 |  | 
 | 12 | from . import utils | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 13 | from .config import ConfigBlock | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 14 | from .stage import Stage, StepOrder | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 15 | from .sensors import collect_sensors_data | 
| koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 16 | from .suits.all_suits import all_suits | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 17 | from .test_run_class import TestRun | 
| koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 18 | from .result_classes import SuiteConfig | 
| koder aka kdanilov | 63ad206 | 2015-04-27 13:11:40 +0300 | [diff] [blame] | 19 |  | 
| koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 20 |  | 
| koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 21 | logger = logging.getLogger("wally") | 
| koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 22 |  | 
| koder aka kdanilov | 7acd6bd | 2015-02-12 14:28:30 -0800 | [diff] [blame] | 23 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 24 | class ConnectStage(Stage): | 
 | 25 |     """Connect to nodes stage""" | 
| koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 26 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 27 |     priority = StepOrder.CONNECT | 
| koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 28 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 29 |     def run(self, ctx: TestRun) -> None: | 
| koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 30 |         with ctx.get_pool() as pool: | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 31 |             logger.info("Connecting to %s nodes", len(ctx.nodes_info)) | 
| koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 32 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 33 |             def connect_ext(node_info: NodeInfo) -> Tuple[bool, Union[IRPCNode, NodeInfo]]: | 
 | 34 |                 try: | 
 | 35 |                     ssh_node = connect(node_info, conn_timeout=ctx.config.connect_timeout) | 
| koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 36 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 37 |                     return True, setup_rpc(ssh_node, | 
 | 38 |                                            ctx.rpc_code, | 
 | 39 |                                            ctx.default_rpc_plugins, | 
 | 40 |                                            log_level=ctx.config.rpc_log_level) | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 41 |                 except Exception as exc: | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 42 |                     logger.exception("During connect to %s: %s", node_info, exc) | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 43 |                     return False, node_info | 
| koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 44 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 45 |             failed_testnodes = []  # type: List[NodeInfo] | 
 | 46 |             failed_nodes = []  # type: List[NodeInfo] | 
 | 47 |             ctx.nodes = [] | 
| koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 48 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 49 |             for ok, node in pool.map(connect_ext, ctx.nodes_info.values()): | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 50 |                 if not ok: | 
 | 51 |                     node = cast(NodeInfo, node) | 
 | 52 |                     if 'testnode' in node.roles: | 
 | 53 |                         failed_testnodes.append(node) | 
 | 54 |                     else: | 
 | 55 |                         failed_nodes.append(node) | 
 | 56 |                 else: | 
 | 57 |                     ctx.nodes.append(cast(IRPCNode, node)) | 
| koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 58 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 59 |             if failed_nodes: | 
 | 60 |                 msg = "Node(s) {} would be excluded - can't connect" | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 61 |                 logger.warning(msg.format(", ".join(map(str, failed_nodes)))) | 
| koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 62 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 63 |             if failed_testnodes: | 
| koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 64 |                 msg = "Can't start RPC on testnode(s) " + ",".join(map(str, failed_testnodes)) | 
| koder aka kdanilov | c368eb6 | 2015-04-28 18:22:01 +0300 | [diff] [blame] | 65 |                 logger.error(msg) | 
 | 66 |                 raise utils.StopTestError(msg) | 
 | 67 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 68 |             if not failed_nodes: | 
 | 69 |                 logger.info("All nodes connected successfully") | 
| koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 70 |  | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 71 |             def get_time(node): | 
 | 72 |                 return node.conn.sys.time() | 
 | 73 |  | 
 | 74 |             t_start = time.time() | 
 | 75 |             tms = pool.map(get_time, ctx.nodes) | 
 | 76 |             t_end = time.time() | 
 | 77 |  | 
 | 78 |             for node, val in zip(ctx.nodes, tms): | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 79 |                 delta = 0 | 
 | 80 |                 if val > t_end: | 
 | 81 |                     delta = val - t_end | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 82 |                 elif val < t_start: | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 83 |                     delta = t_start - val | 
 | 84 |  | 
 | 85 |                 if delta > ctx.config.max_time_diff_ms: | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 86 |                     msg = ("Too large time shift {}ms on node {}. Stopping test." + | 
 | 87 |                            " Fix time on cluster nodes and restart test, or change " + | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 88 |                            "max_time_diff_ms(={}ms) setting in config").format(delta, | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 89 |                                                                                str(node), | 
 | 90 |                                                                                ctx.config.max_time_diff_ms) | 
 | 91 |                     logger.error(msg) | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 92 |                     raise utils.StopTestError(msg) | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 93 |  | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 94 |                 if delta > 1: | 
 | 95 |                     logger.warning("Node %s has time shift at least %s ms", node, int(delta)) | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 96 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 97 |     def cleanup(self, ctx: TestRun) -> None: | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 98 |         if ctx.config.get("download_rpc_logs", False): | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 99 |             logger.info("Killing all outstanding processes") | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 100 |             for node in ctx.nodes: | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 101 |                 node.conn.cli.killall() | 
 | 102 |  | 
 | 103 |             logger.info("Downloading RPC servers logs") | 
 | 104 |             for node in ctx.nodes: | 
 | 105 |                 node.conn.cli.killall() | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 106 |                 if node.rpc_log_file is not None: | 
| koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 107 |                     nid = node.node_id | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 108 |                     path = WallyDB.rpc_logs.format(node_id=nid) | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 109 |                     node.conn.server.flush_logs() | 
 | 110 |                     log = node.get_file_content(node.rpc_log_file) | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 111 |                     if path in ctx.storage: | 
| koder aka kdanilov | ffaf48d | 2016-12-27 02:25:29 +0200 | [diff] [blame] | 112 |                         ctx.storage.append_raw(log, path) | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 113 |                     else: | 
| koder aka kdanilov | ffaf48d | 2016-12-27 02:25:29 +0200 | [diff] [blame] | 114 |                         ctx.storage.put_raw(log, path) | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 115 |                     logger.debug("RPC log from node {} stored into storage::{}".format(nid, path)) | 
 | 116 |  | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 117 |         logger.info("Disconnecting") | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 118 |         with ctx.get_pool() as pool: | 
 | 119 |             list(pool.map(lambda node: node.disconnect(stop=True), ctx.nodes)) | 
| koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 120 |  | 
| koder aka kdanilov | 0fdaaee | 2015-06-30 11:10:48 +0300 | [diff] [blame] | 121 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 122 | class CollectInfoStage(Stage): | 
 | 123 |     """Collect node info""" | 
| koder aka kdanilov | 3d2bc4f | 2016-11-12 18:31:18 +0200 | [diff] [blame] | 124 |  | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 125 |     priority = StepOrder.UPDATE_NODES_INFO | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 126 |     config_block = 'collect_info' | 
 | 127 |  | 
 | 128 |     def run(self, ctx: TestRun) -> None: | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 129 |         with ctx.get_pool() as pool: | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 130 |             try: | 
 | 131 |                 # can't make next RPC request until finish with previous for same node | 
 | 132 |                 for node, hw_info in zip(ctx.nodes, pool.map(get_hw_info, ctx.nodes)): | 
 | 133 |                     node.info.hw_info = hw_info | 
 | 134 |                 for node, sw_info in zip(ctx.nodes, pool.map(get_sw_info, ctx.nodes)): | 
 | 135 |                     node.info.sw_info = sw_info | 
 | 136 |             except Exception as exc: | 
 | 137 |                 logger.exception("During collecting cluster info") | 
 | 138 |                 raise utils.StopTestError() from exc | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 139 |  | 
| kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 140 |             logger.debug("Collecting hostnames") | 
 | 141 |             hostnames = pool.map(get_hostname, ctx.nodes) | 
 | 142 |             for node, hostname in zip(ctx.nodes, hostnames): | 
 | 143 |                 node.info.hostname = hostname | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 144 |  | 
 | 145 |  | 
 | 146 | class ExplicitNodesStage(Stage): | 
 | 147 |     """add explicit nodes""" | 
 | 148 |  | 
 | 149 |     priority = StepOrder.DISCOVER | 
 | 150 |     config_block = 'nodes' | 
 | 151 |  | 
 | 152 |     def run(self, ctx: TestRun) -> None: | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 153 |         if WallyDB.all_nodes in ctx.storage: | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 154 |             logger.info("Skip explicid nodes filling, as all_nodes all ready in storage") | 
 | 155 |             return | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 156 |  | 
| koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 157 |         for url, roles in ctx.config.get('nodes', {}).raw().items(): | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 158 |             ctx.merge_node(parse_ssh_uri(url), set(role.strip() for role in roles.split(","))) | 
| koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 159 |             logger.debug("Add node %s with roles %s", url, roles) | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 160 |  | 
 | 161 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 162 | class SleepStage(Stage): | 
 | 163 |     """Save nodes list to file""" | 
 | 164 |  | 
 | 165 |     priority = StepOrder.TEST | 
 | 166 |     config_block = 'sleep' | 
 | 167 |  | 
 | 168 |     def run(self, ctx: TestRun) -> None: | 
 | 169 |         logger.debug("Will sleep for %r seconds", ctx.config.sleep) | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 170 |         stime = time.time() | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 171 |         time.sleep(ctx.config.sleep) | 
| kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 172 |         ctx.storage.put([int(stime), int(time.time())], 'idle') | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 173 |  | 
 | 174 |  | 
| koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 175 | class PrepareNodes(Stage): | 
 | 176 |     priority = StepOrder.START_SENSORS - 1 | 
 | 177 |  | 
 | 178 |     def __init__(self): | 
 | 179 |         Stage.__init__(self) | 
 | 180 |         self.nodeepscrub_updated = False | 
 | 181 |         self.noscrub_updated = False | 
 | 182 |  | 
 | 183 |     def run(self, ctx: TestRun) -> None: | 
 | 184 |         ceph_sett = ctx.config.get('ceph_settings', "").split() | 
 | 185 |         if ceph_sett: | 
 | 186 |             for node in ctx.nodes: | 
 | 187 |                 if "ceph-mon" in node.info.roles or "ceph-osd" in node.info.roles: | 
 | 188 |                     state = json.loads(node.run("ceph health --format json"))["summary"]["summary"] | 
 | 189 |                     if 'noscrub' in ceph_sett: | 
 | 190 |                         if 'noscrub' in state: | 
 | 191 |                             logger.debug("noscrub already set on cluster") | 
 | 192 |                         else: | 
 | 193 |                             logger.info("Applying noscrub settings to ceph cluster") | 
 | 194 |                             node.run("ceph osd set noscrub") | 
 | 195 |                             self.noscrub_updated = True | 
 | 196 |  | 
 | 197 |                     if 'nodeepscrub' in ceph_sett: | 
 | 198 |                         if 'nodeepscrub' in state: | 
 | 199 |                             logger.debug("noscrub already set on cluster") | 
 | 200 |                         else: | 
 | 201 |                             logger.info("Applying noscrub settings to ceph cluster") | 
 | 202 |                             node.run("ceph osd set noscrub") | 
 | 203 |                             self.nodeepscrub_updated = True | 
 | 204 |                     break | 
 | 205 |  | 
 | 206 |     def cleanup(self, ctx: TestRun) -> None: | 
 | 207 |         if self.nodeepscrub_updated or self.noscrub_updated: | 
 | 208 |             for node in ctx.nodes: | 
 | 209 |                 if "ceph-mon" in node.info.roles or "ceph-osd" in node.info.roles : | 
 | 210 |                     if self.noscrub_updated: | 
 | 211 |                         logger.info("Reverting noscrub setting for ceph cluster") | 
 | 212 |                         node.run("ceph osd unset noscrub") | 
 | 213 |                         self.noscrub_updated = False | 
 | 214 |  | 
 | 215 |                     if self.nodeepscrub_updated: | 
 | 216 |                         logger.info("Reverting noscrub setting for ceph cluster") | 
 | 217 |                         node.run("ceph osd unset nodeepscrub") | 
 | 218 |                         self.nodeepscrub_updated = False | 
 | 219 |  | 
 | 220 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 221 | class RunTestsStage(Stage): | 
 | 222 |  | 
 | 223 |     priority = StepOrder.TEST | 
 | 224 |     config_block = 'tests' | 
 | 225 |  | 
 | 226 |     def run(self, ctx: TestRun) -> None: | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 227 |         if ctx.config.no_tests: | 
 | 228 |             logger.info("Skiping tests, as 'no_tests' config settings is True") | 
 | 229 |             return | 
| koder aka kdanilov | 3d2bc4f | 2016-11-12 18:31:18 +0200 | [diff] [blame] | 230 |  | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 231 |         for suite_idx, test_suite in enumerate(ctx.config.get('tests', [])): | 
 | 232 |             test_nodes = [node for node in ctx.nodes if 'testnode' in node.info.roles] | 
| koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 233 |  | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 234 |             if not test_nodes: | 
 | 235 |                 logger.error("No test nodes found") | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 236 |                 raise utils.StopTestError() | 
| gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 237 |  | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 238 |             if len(test_suite) != 1: | 
 | 239 |                 logger.error("Test suite %s contain more than one test. Put each test in separated group", suite_idx) | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 240 |                 raise utils.StopTestError() | 
| koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 241 |  | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 242 |             name, params = list(test_suite.items())[0] | 
 | 243 |             vm_count = params.get('node_limit', None)  # type: Optional[int] | 
| koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 244 |  | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 245 |             # select test nodes | 
 | 246 |             if vm_count is None: | 
 | 247 |                 curr_test_nodes = test_nodes | 
 | 248 |             else: | 
 | 249 |                 curr_test_nodes = test_nodes[:vm_count] | 
| koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 250 |  | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 251 |             if not curr_test_nodes: | 
 | 252 |                 logger.error("No nodes found for test, skipping it.") | 
 | 253 |                 continue | 
 | 254 |  | 
| kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 255 |             if name not in all_suits: | 
 | 256 |                 logger.error("Test suite %r not found. Only suits [%s] available", name, ", ".join(all_suits)) | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 257 |                 raise utils.StopTestError() | 
| kdanylov aka koder | 150b219 | 2017-04-01 16:53:01 +0300 | [diff] [blame] | 258 |  | 
| koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 259 |             test_cls = all_suits[name] | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 260 |             remote_dir = ctx.config.default_test_local_folder.format(name=name, uuid=ctx.config.run_uuid) | 
| koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 261 |             suite = SuiteConfig(test_cls.name, | 
 | 262 |                                 params=params, | 
 | 263 |                                 run_uuid=ctx.config.run_uuid, | 
 | 264 |                                 nodes=test_nodes, | 
 | 265 |                                 remote_dir=remote_dir, | 
 | 266 |                                 idx=suite_idx, | 
 | 267 |                                 keep_raw_files=ctx.config.keep_raw_files) | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 268 |  | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 269 |             test_cls(storage=ctx.rstorage, | 
| koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 270 |                      suite=suite, | 
| koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 271 |                      on_idle=lambda: collect_sensors_data(ctx, False)).run() | 
| gstepanov | 023c1e4 | 2015-04-08 15:50:19 +0300 | [diff] [blame] | 272 |  | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 273 |     @classmethod | 
 | 274 |     def validate_config(cls, cfg: ConfigBlock) -> None: | 
 | 275 |         pass | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 276 |  | 
 | 277 |  | 
| kdanylov aka koder | 736e5c1 | 2017-05-07 17:27:14 +0300 | [diff] [blame] | 278 | class SaveNodesStage(Stage): | 
 | 279 |     """Save nodes list to file""" | 
| kdanylov aka koder | 736e5c1 | 2017-05-07 17:27:14 +0300 | [diff] [blame] | 280 |     priority = StepOrder.UPDATE_NODES_INFO + 1 | 
 | 281 |  | 
 | 282 |     def run(self, ctx: TestRun) -> None: | 
 | 283 |         infos = list(ctx.nodes_info.values()) | 
 | 284 |         params = {node.node_id: node.params for node in infos} | 
 | 285 |         ninfos = [copy.copy(node) for node in infos] | 
 | 286 |         for node in ninfos: | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 287 |             node.params = {"in file": WallyDB.nodes_params} | 
 | 288 |         ctx.storage.put_list(ninfos, WallyDB.all_nodes) | 
 | 289 |         ctx.storage.put_raw(json.dumps(params).encode('utf8'), WallyDB.nodes_params) | 
| kdanylov aka koder | 736e5c1 | 2017-05-07 17:27:14 +0300 | [diff] [blame] | 290 |  | 
 | 291 |  | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 292 | class LoadStoredNodesStage(Stage): | 
 | 293 |     priority = StepOrder.DISCOVER | 
 | 294 |  | 
 | 295 |     def run(self, ctx: TestRun) -> None: | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 296 |         if WallyDB.all_nodes in ctx.storage: | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 297 |             if ctx.nodes_info: | 
 | 298 |                 logger.error("Internal error: Some nodes already stored in " + | 
 | 299 |                              "nodes_info before LoadStoredNodesStage stage") | 
| kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame] | 300 |                 raise utils.StopTestError() | 
| kdanylov aka koder | 736e5c1 | 2017-05-07 17:27:14 +0300 | [diff] [blame] | 301 |  | 
| kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 302 |             ctx.nodes_info = {node.node_id: node for node in ctx.rstorage.load_nodes()} | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 303 |             logger.info("%s nodes loaded from database", len(ctx.nodes_info)) |