koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 1 | import os |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 2 | import sys |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 3 | import uuid |
koder aka kdanilov | e21d747 | 2015-02-14 19:02:04 -0800 | [diff] [blame] | 4 | import logging |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 5 | import datetime |
koder aka kdanilov | 7acd6bd | 2015-02-12 14:28:30 -0800 | [diff] [blame] | 6 | import contextlib |
koder aka kdanilov | f90de85 | 2017-01-20 18:12:27 +0200 | [diff] [blame] | 7 | |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame^] | 8 | from typing import Any, Tuple, Iterator, Iterable |
koder aka kdanilov | bb5fe07 | 2015-05-21 02:50:23 +0300 | [diff] [blame] | 9 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 10 | try: |
| 11 | from petname import Generate as pet_generate |
| 12 | except ImportError: |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame^] | 13 | def pet_generate(_1: str, _2: str) -> str: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 14 | return str(uuid.uuid4()) |
| 15 | |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame^] | 16 | from cephlib.common import run_locally, sec_to_str |
kdanylov aka koder | 3a9e5db | 2017-05-09 20:00:44 +0300 | [diff] [blame] | 17 | |
| 18 | |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 19 | logger = logging.getLogger("wally") |
koder aka kdanilov | 209e85d | 2015-04-27 23:11:05 +0300 | [diff] [blame] | 20 | |
| 21 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 22 | STORAGE_ROLES = {'ceph-osd'} |
| 23 | |
| 24 | |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 25 | class StopTestError(RuntimeError): |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 26 | pass |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 27 | |
| 28 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 29 | class LogError: |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 30 | def __init__(self, message: str, exc_logger: logging.Logger = None) -> None: |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 31 | self.message = message |
| 32 | self.exc_logger = exc_logger |
| 33 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 34 | def __enter__(self) -> 'LogError': |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 35 | return self |
| 36 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 37 | def __exit__(self, tp: type, value: Exception, traceback: Any) -> bool: |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 38 | if value is None or isinstance(value, StopTestError): |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 39 | return False |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 40 | |
| 41 | if self.exc_logger is None: |
| 42 | exc_logger = sys._getframe(1).f_globals.get('logger', logger) |
| 43 | else: |
| 44 | exc_logger = self.exc_logger |
| 45 | |
| 46 | exc_logger.exception(self.message, exc_info=(tp, value, traceback)) |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 47 | raise StopTestError(self.message) from value |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 48 | |
| 49 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 50 | class TaskFinished(Exception): |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 51 | pass |
koder aka kdanilov | 4643fd6 | 2015-02-10 16:20:13 -0800 | [diff] [blame] | 52 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 53 | |
koder aka kdanilov | ffaf48d | 2016-12-27 02:25:29 +0200 | [diff] [blame] | 54 | def log_block(message: str, exc_logger:logging.Logger = None) -> LogError: |
| 55 | logger.debug("Starts : " + message) |
| 56 | return LogError(message, exc_logger) |
| 57 | |
| 58 | |
| 59 | def check_input_param(is_ok: bool, message: str) -> None: |
| 60 | if not is_ok: |
| 61 | logger.error(message) |
| 62 | raise StopTestError(message) |
| 63 | |
| 64 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 65 | def yamable(data: Any) -> Any: |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 66 | if isinstance(data, (tuple, list)): |
| 67 | return map(yamable, data) |
| 68 | |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 69 | if isinstance(data, dict): |
| 70 | res = {} |
| 71 | for k, v in data.items(): |
| 72 | res[yamable(k)] = yamable(v) |
| 73 | return res |
| 74 | |
| 75 | return data |
koder aka kdanilov | f86d7af | 2015-05-06 04:01:54 +0300 | [diff] [blame] | 76 | |
| 77 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 78 | def get_creds_openrc(path: str) -> Tuple[str, str, str, str, bool]: |
koder aka kdanilov | 89fb610 | 2015-06-13 02:58:08 +0300 | [diff] [blame] | 79 | fc = open(path).read() |
| 80 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 81 | echo = 'echo "$OS_INSECURE:$OS_TENANT_NAME:$OS_USERNAME:$OS_PASSWORD@$OS_AUTH_URL"' |
koder aka kdanilov | 89fb610 | 2015-06-13 02:58:08 +0300 | [diff] [blame] | 82 | |
| 83 | msg = "Failed to get creads from openrc file" |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 84 | with LogError(msg): |
kdanylov aka koder | b083333 | 2017-05-13 20:39:17 +0300 | [diff] [blame^] | 85 | data = run_locally(['/bin/bash'], input_data=(fc + "\n" + echo).encode('utf8')).decode("utf8") |
koder aka kdanilov | 89fb610 | 2015-06-13 02:58:08 +0300 | [diff] [blame] | 86 | |
| 87 | msg = "Failed to get creads from openrc file: " + data |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 88 | with LogError(msg): |
koder aka kdanilov | 89fb610 | 2015-06-13 02:58:08 +0300 | [diff] [blame] | 89 | data = data.strip() |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 90 | insecure_str, user, tenant, passwd_auth_url = data.split(':', 3) |
| 91 | insecure = (insecure_str in ('1', 'True', 'true')) |
koder aka kdanilov | 89fb610 | 2015-06-13 02:58:08 +0300 | [diff] [blame] | 92 | passwd, auth_url = passwd_auth_url.rsplit("@", 1) |
| 93 | assert (auth_url.startswith("https://") or |
| 94 | auth_url.startswith("http://")) |
| 95 | |
koder aka kdanilov | b719743 | 2015-07-15 00:40:43 +0300 | [diff] [blame] | 96 | return user, passwd, tenant, auth_url, insecure |
koder aka kdanilov | 89fb610 | 2015-06-13 02:58:08 +0300 | [diff] [blame] | 97 | |
| 98 | |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 99 | @contextlib.contextmanager |
| 100 | def empty_ctx(val: Any = None) -> Iterator[Any]: |
| 101 | yield val |
| 102 | |
| 103 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 104 | def get_uniq_path_uuid(path: str, max_iter: int = 10) -> Tuple[str, str]: |
| 105 | for i in range(max_iter): |
| 106 | run_uuid = pet_generate(2, "_") |
| 107 | results_dir = os.path.join(path, run_uuid) |
| 108 | if not os.path.exists(results_dir): |
| 109 | break |
| 110 | else: |
| 111 | run_uuid = str(uuid.uuid4()) |
| 112 | results_dir = os.path.join(path, run_uuid) |
| 113 | |
| 114 | return results_dir, run_uuid |
| 115 | |
| 116 | |
koder aka kdanilov | f286517 | 2016-12-30 03:35:11 +0200 | [diff] [blame] | 117 | def get_time_interval_printable_info(seconds: int) -> Tuple[str, str]: |
| 118 | exec_time_s = sec_to_str(seconds) |
| 119 | now_dt = datetime.datetime.now() |
| 120 | end_dt = now_dt + datetime.timedelta(0, seconds) |
| 121 | return exec_time_s, "{:%H:%M:%S}".format(end_dt) |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 122 | |
| 123 | |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 124 | def shape2str(shape: Iterable[int]) -> str: |
| 125 | return "*".join(map(str, shape)) |
| 126 | |
| 127 | |
| 128 | def str2shape(shape: str) -> Tuple[int, ...]: |
| 129 | return tuple(map(int, shape.split('*'))) |