koder aka kdanilov | 4643fd6 | 2015-02-10 16:20:13 -0800 | [diff] [blame] | 1 | import abc |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 2 | import time |
| 3 | import logging |
koder aka kdanilov | 4643fd6 | 2015-02-10 16:20:13 -0800 | [diff] [blame] | 4 | import os.path |
kdanylov aka koder | 2e5fce1 | 2017-05-23 01:47:36 +0300 | [diff] [blame] | 5 | from typing import Any, List, Optional, Callable, Iterable, cast |
koder aka kdanilov | 652cd80 | 2015-04-13 12:21:07 +0300 | [diff] [blame] | 6 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 7 | from concurrent.futures import ThreadPoolExecutor, wait |
koder aka kdanilov | 4643fd6 | 2015-02-10 16:20:13 -0800 | [diff] [blame] | 8 | |
kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 9 | from cephlib.node import IRPCNode |
kdanylov aka koder | 2e5fce1 | 2017-05-23 01:47:36 +0300 | [diff] [blame] | 10 | from cephlib.units import unit_conversion_coef_f |
kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 11 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 12 | from ..utils import StopTestError, get_time_interval_printable_info |
kdanylov aka koder | 026e5f2 | 2017-05-15 01:04:39 +0300 | [diff] [blame] | 13 | from ..result_classes import SuiteConfig, JobConfig, TimeSeries, IWallyStorage |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 14 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 15 | |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 16 | logger = logging.getLogger("wally") |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame] | 17 | |
| 18 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 19 | __doc__ = "Contains base classes for performance tests" |
| 20 | |
| 21 | |
koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 22 | class PerfTest(metaclass=abc.ABCMeta): |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 23 | """Base class for all tests""" |
| 24 | name = None # type: str |
| 25 | max_retry = 3 |
| 26 | retry_time = 30 |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 27 | job_config_cls = None # type: type |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 28 | |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 29 | def __init__(self, storage: IWallyStorage, suite: SuiteConfig, |
| 30 | on_tests_boundry: Callable[[bool], None] = None) -> None: |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 31 | self.suite = suite |
koder aka kdanilov | e2de58c | 2015-04-24 22:59:36 +0300 | [diff] [blame] | 32 | self.stop_requested = False |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 33 | self.sorted_nodes_ids = sorted(node.node_id for node in self.suite.nodes) |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 34 | self.on_tests_boundry = on_tests_boundry |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 35 | self.storage = storage |
koder aka kdanilov | e2de58c | 2015-04-24 22:59:36 +0300 | [diff] [blame] | 36 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 37 | def request_stop(self) -> None: |
koder aka kdanilov | e2de58c | 2015-04-24 22:59:36 +0300 | [diff] [blame] | 38 | self.stop_requested = True |
koder aka kdanilov | 2066daf | 2015-04-23 21:05:41 +0300 | [diff] [blame] | 39 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 40 | def join_remote(self, path: str) -> str: |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 41 | return os.path.join(self.suite.remote_dir, path) |
koder aka kdanilov | 4500a5f | 2015-04-17 16:55:17 +0300 | [diff] [blame] | 42 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 43 | @abc.abstractmethod |
koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 44 | def run(self) -> None: |
koder aka kdanilov | 4643fd6 | 2015-02-10 16:20:13 -0800 | [diff] [blame] | 45 | pass |
| 46 | |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 47 | @abc.abstractmethod |
koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 48 | def format_for_console(self, data: Any) -> str: |
koder aka kdanilov | ec1b973 | 2015-04-23 20:43:29 +0300 | [diff] [blame] | 49 | pass |
| 50 | |
koder aka kdanilov | 4643fd6 | 2015-02-10 16:20:13 -0800 | [diff] [blame] | 51 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 52 | class ThreadedTest(PerfTest, metaclass=abc.ABCMeta): |
| 53 | """Base class for tests, which spawn separated thread for each node""" |
| 54 | |
| 55 | # max allowed time difference between starts and stops of run of the same test on different test nodes |
| 56 | # used_max_diff = max((min_run_time * max_rel_time_diff), max_time_diff) |
| 57 | max_time_diff = 5 |
| 58 | max_rel_time_diff = 0.05 |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 59 | load_profile_name: str = None # type: ignore |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 60 | |
koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 61 | def __init__(self, *args, **kwargs) -> None: |
| 62 | PerfTest.__init__(self, *args, **kwargs) |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 63 | self.job_configs: List[JobConfig] = None # type: ignore |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 64 | |
| 65 | @abc.abstractmethod |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 66 | def get_expected_runtime(self, iter_cfg: JobConfig) -> Optional[int]: |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 67 | pass |
| 68 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 69 | def get_not_done_jobs(self) -> Iterable[JobConfig]: |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 70 | jobs_map = {job.storage_id: job for job in self.job_configs} |
| 71 | already_in_storage = set() |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 72 | for db_config in cast(List[JobConfig], self.storage.iter_job(self.suite)): |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 73 | if db_config.storage_id in jobs_map: |
| 74 | job = jobs_map[db_config.storage_id] |
| 75 | if job != db_config: |
| 76 | logger.error("Test info at '%s.%s' is not equal to expected config for iteration %s.%s." + |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 77 | " Maybe configuration was changed before test was restarted. " + |
| 78 | "DB cfg is:\n %s\nExpected cfg is:\n %s\nFix DB or rerun test from beginning", |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 79 | self.suite.storage_id, job.storage_id, self.name, job.summary, |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 80 | str(db_config).replace("\n", "\n "), |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 81 | str(job).replace("\n", "\n ")) |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 82 | raise StopTestError() |
koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 83 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 84 | logger.info("Test iteration %s.%s found in storage and will be skipped", self.name, job.summary) |
| 85 | already_in_storage.add(db_config.storage_id) |
| 86 | |
| 87 | return [job for job in self.job_configs if job.storage_id not in already_in_storage] |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 88 | |
koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 89 | def run(self) -> None: |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 90 | self.storage.put_or_check_suite(self.suite) |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 91 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 92 | not_in_storage = list(self.get_not_done_jobs()) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 93 | if not not_in_storage: |
| 94 | logger.info("All test iteration in storage already. Skip test") |
| 95 | return |
| 96 | |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 97 | logger.debug("Run test %s with profile %r on nodes %s.", self.name, |
| 98 | self.load_profile_name, |
| 99 | ",".join(self.sorted_nodes_ids)) |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 100 | logger.debug("Prepare nodes") |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 101 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 102 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 103 | with ThreadPoolExecutor(len(self.suite.nodes)) as pool: |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 104 | # config nodes |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 105 | list(pool.map(self.config_node, self.suite.nodes)) |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 106 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 107 | run_times = list(map(self.get_expected_runtime, not_in_storage)) |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 108 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 109 | if None not in run_times: |
kdanylov aka koder | 84de1e4 | 2017-05-22 14:00:07 +0300 | [diff] [blame] | 110 | # +10s - is a rough estimation for additional operations per iteration |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 111 | expected_run_time: int = int(sum(run_times) + 10 * len(not_in_storage)) # type: ignore |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 112 | exec_time_s, end_dt_s = get_time_interval_printable_info(expected_run_time) |
kdanylov aka koder | 736e5c1 | 2017-05-07 17:27:14 +0300 | [diff] [blame] | 113 | logger.info("Entire test should takes around %s and finish at %s", exec_time_s, end_dt_s) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 114 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 115 | for job in not_in_storage: |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 116 | results: List[TimeSeries] = [] |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 117 | for retry_idx in range(self.max_retry): |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 118 | logger.info("Preparing job %s", job.params.summary) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 119 | |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 120 | # prepare nodes for new iterations |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 121 | wait([pool.submit(self.prepare_iteration, node, job) for node in self.suite.nodes]) |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 122 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 123 | expected_job_time = self.get_expected_runtime(job) |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 124 | if expected_job_time is None: |
| 125 | logger.info("Job execution time is unknown") |
| 126 | else: |
| 127 | exec_time_s, end_dt_s = get_time_interval_printable_info(expected_job_time) |
| 128 | logger.info("Job should takes around %s and finish at %s", exec_time_s, end_dt_s) |
| 129 | |
| 130 | if self.on_tests_boundry is not None: |
| 131 | self.on_tests_boundry(True) |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 132 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 133 | jfutures = [pool.submit(self.run_iteration, node, job) for node in self.suite.nodes] |
| 134 | failed = False |
| 135 | for future in jfutures: |
| 136 | try: |
| 137 | results.extend(future.result()) |
| 138 | except EnvironmentError: |
| 139 | failed = True |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 140 | |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 141 | if self.on_tests_boundry is not None: |
| 142 | self.on_tests_boundry(False) |
| 143 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 144 | if not failed: |
| 145 | break |
| 146 | |
| 147 | if self.max_retry - 1 == retry_idx: |
| 148 | logger.exception("Fio failed") |
| 149 | raise StopTestError() |
| 150 | |
| 151 | logger.exception("During fio run") |
| 152 | logger.info("Sleeping %ss and retrying job", self.retry_time) |
| 153 | time.sleep(self.retry_time) |
| 154 | results = [] |
| 155 | |
| 156 | # per node jobs start and stop times |
kdanylov aka koder | 13e5845 | 2018-07-15 02:51:51 +0300 | [diff] [blame] | 157 | start_times: List[int] = [] |
| 158 | stop_times: List[int] = [] |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 159 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 160 | for ts in results: |
| 161 | self.storage.put_ts(ts) |
| 162 | if len(ts.times) >= 2: # type: ignore |
| 163 | start_times.append(ts.times[0]) |
| 164 | stop_times.append(ts.times[-1]) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 165 | |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 166 | if len(start_times) > 0: |
| 167 | min_start_time = min(start_times) |
| 168 | max_start_time = max(start_times) |
| 169 | min_stop_time = min(stop_times) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 170 | |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 171 | max_allowed_time_diff = int((min_stop_time - max_start_time) * self.max_rel_time_diff) |
| 172 | max_allowed_time_diff = max(max_allowed_time_diff, self.max_time_diff) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 173 | |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 174 | if min_start_time + self.max_time_diff < max_allowed_time_diff: |
| 175 | logger.warning("Too large difference in %s:%s start time - %s. " + |
| 176 | "Max recommended difference is %s", |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 177 | self.name, job.summary, |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 178 | max_start_time - min_start_time, self.max_time_diff) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 179 | |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 180 | if min_stop_time + self.max_time_diff < max_allowed_time_diff: |
| 181 | logger.warning("Too large difference in %s:%s stop time - %s. " + |
| 182 | "Max recommended difference is %s", |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 183 | self.name, job.summary, |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 184 | max_start_time - min_start_time, self.max_time_diff) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 185 | |
kdanylov aka koder | 2e5fce1 | 2017-05-23 01:47:36 +0300 | [diff] [blame] | 186 | one_s = int(unit_conversion_coef_f('s', results[0].time_units)) |
| 187 | job.reliable_info_range = (int(max_start_time) + one_s, int(min_stop_time) - one_s) |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 188 | |
| 189 | self.storage.put_job(self.suite, job) |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 190 | self.storage.sync() |
koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 191 | |
koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame] | 192 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 193 | @abc.abstractmethod |
| 194 | def config_node(self, node: IRPCNode) -> None: |
| 195 | pass |
| 196 | |
| 197 | @abc.abstractmethod |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 198 | def prepare_iteration(self, node: IRPCNode, job: JobConfig) -> None: |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 199 | pass |
| 200 | |
| 201 | @abc.abstractmethod |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 202 | def run_iteration(self, node: IRPCNode, job: JobConfig) -> List[TimeSeries]: |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 203 | pass |
| 204 | |
| 205 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 206 | class TwoScriptTest(ThreadedTest, metaclass=abc.ABCMeta): |
| 207 | def __init__(self, *dt, **mp) -> None: |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 208 | ThreadedTest.__init__(self, *dt, **mp) |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 209 | self.prerun_script = self.suite.params['prerun_script'] |
| 210 | self.run_script = self.suite.params['run_script'] |
| 211 | self.prerun_tout = self.suite.params.get('prerun_tout', 3600) |
| 212 | self.run_tout = self.suite.params.get('run_tout', 3600) |
| 213 | # TODO: fix job_configs field |
| 214 | raise NotImplementedError("Fix job configs") |
Yulia Portnova | 7ddfa73 | 2015-02-24 17:32:58 +0200 | [diff] [blame] | 215 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 216 | def get_expected_runtime(self, job: JobConfig) -> Optional[int]: |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 217 | return None |
Yulia Portnova | 7ddfa73 | 2015-02-24 17:32:58 +0200 | [diff] [blame] | 218 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 219 | def config_node(self, node: IRPCNode) -> None: |
| 220 | node.copy_file(self.run_script, self.join_remote(self.run_script)) |
| 221 | node.copy_file(self.prerun_script, self.join_remote(self.prerun_script)) |
koder aka kdanilov | bc2c898 | 2015-06-13 02:50:43 +0300 | [diff] [blame] | 222 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 223 | cmd = self.join_remote(self.prerun_script) |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 224 | cmd += ' ' + self.suite.params.get('prerun_opts', '') |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 225 | node.run(cmd, timeout=self.prerun_tout) |
Yulia Portnova | 7ddfa73 | 2015-02-24 17:32:58 +0200 | [diff] [blame] | 226 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 227 | def prepare_iteration(self, node: IRPCNode, job: JobConfig) -> None: |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 228 | pass |
| 229 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 230 | def run_iteration(self, node: IRPCNode, job: JobConfig) -> List[TimeSeries]: |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 231 | # TODO: have to store logs |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 232 | cmd = self.join_remote(self.run_script) |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 233 | cmd += ' ' + self.suite.params.get('run_opts', '') |
koder aka kdanilov | 23e6bdf | 2016-12-24 02:18:54 +0200 | [diff] [blame] | 234 | return self.parse_results(node.run(cmd, timeout=self.run_tout)) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 235 | |
| 236 | @abc.abstractmethod |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 237 | def parse_results(self, data: str) -> List[TimeSeries]: |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 238 | pass |
| 239 | |