blob: d5d6f486cdbe2f378e73f93890006703ca47f113 [file] [log] [blame]
koder aka kdanilov652cd802015-04-13 12:21:07 +03001import re
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +03002import os
koder aka kdanilovafd98742015-04-24 01:27:22 +03003import socket
koder aka kdanilove21d7472015-02-14 19:02:04 -08004import logging
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08005import threading
6import contextlib
koder aka kdanilov652cd802015-04-13 12:21:07 +03007import subprocess
koder aka kdanilov4643fd62015-02-10 16:20:13 -08008
koder aka kdanilove21d7472015-02-14 19:02:04 -08009
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030010logger = logging.getLogger("wally")
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080011
12
koder aka kdanilov209e85d2015-04-27 23:11:05 +030013def is_ip(data):
14 if data.count('.') != 3:
15 return False
16
17 try:
18 for part in map(int, data.split('.')):
19 if part > 255 or part < 0:
20 raise ValueError()
21 except ValueError:
22 return False
23 return True
24
25
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030026class StopTestError(RuntimeError):
27 def __init__(self, reason, orig_exc=None):
28 RuntimeError.__init__(self, reason)
29 self.orig_exc = orig_exc
30
31
32def check_input_param(is_ok, message):
33 if not is_ok:
34 logger.error(message)
35 raise StopTestError(message)
36
37
koder aka kdanilove06762a2015-03-22 23:32:09 +020038def parse_creds(creds):
39 # parse user:passwd@host
40 user, passwd_host = creds.split(":", 1)
41
42 if '@' not in passwd_host:
43 passwd, host = passwd_host, None
44 else:
45 passwd, host = passwd_host.rsplit('@', 1)
46
47 return user, passwd, host
48
49
koder aka kdanilov2c473092015-03-29 17:12:13 +030050class TaksFinished(Exception):
51 pass
koder aka kdanilov4643fd62015-02-10 16:20:13 -080052
koder aka kdanilov2c473092015-03-29 17:12:13 +030053
54class Barrier(object):
55 def __init__(self, count):
56 self.count = count
57 self.curr_count = 0
58 self.cond = threading.Condition()
59 self.exited = False
60
61 def wait(self, timeout=None):
62 with self.cond:
63 if self.exited:
64 raise TaksFinished()
65
66 self.curr_count += 1
67 if self.curr_count == self.count:
68 self.curr_count = 0
69 self.cond.notify_all()
koder aka kdanilov652cd802015-04-13 12:21:07 +030070 return True
koder aka kdanilov4643fd62015-02-10 16:20:13 -080071 else:
koder aka kdanilov2c473092015-03-29 17:12:13 +030072 self.cond.wait(timeout=timeout)
koder aka kdanilov652cd802015-04-13 12:21:07 +030073 return False
koder aka kdanilov4643fd62015-02-10 16:20:13 -080074
koder aka kdanilov2c473092015-03-29 17:12:13 +030075 def exit(self):
76 with self.cond:
77 self.exited = True
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080078
79
80@contextlib.contextmanager
81def log_error(action, types=(Exception,)):
82 if not action.startswith("!"):
koder aka kdanilove21d7472015-02-14 19:02:04 -080083 logger.debug("Starts : " + action)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080084 else:
85 action = action[1:]
86
87 try:
88 yield
89 except Exception as exc:
90 if isinstance(exc, types) and not isinstance(exc, StopIteration):
koder aka kdanilovec1b9732015-04-23 20:43:29 +030091 templ = "Error during {0} stage: {1!s}"
92 logger.debug(templ.format(action, exc))
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080093 raise
94
95
koder aka kdanilov2c473092015-03-29 17:12:13 +030096SMAP = dict(k=1024, m=1024 ** 2, g=1024 ** 3, t=1024 ** 4)
koder aka kdanilov8ad6e812015-03-22 14:42:18 +020097
98
koder aka kdanilovf86d7af2015-05-06 04:01:54 +030099def ssize2b(ssize):
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200100 try:
koder aka kdanilov63e9c5a2015-04-28 23:06:07 +0300101 if isinstance(ssize, (int, long)):
102 return ssize
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200103
koder aka kdanilov63e9c5a2015-04-28 23:06:07 +0300104 ssize = ssize.lower()
koder aka kdanilov2c473092015-03-29 17:12:13 +0300105 if ssize[-1] in SMAP:
106 return int(ssize[:-1]) * SMAP[ssize[-1]]
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200107 return int(ssize)
108 except (ValueError, TypeError, AttributeError):
koder aka kdanilov2e928022015-04-08 13:47:15 +0300109 raise ValueError("Unknow size format {0!r}".format(ssize))
koder aka kdanilov652cd802015-04-13 12:21:07 +0300110
111
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300112RSMAP = [('K', 1024),
113 ('M', 1024 ** 2),
114 ('G', 1024 ** 3),
115 ('T', 1024 ** 4)]
116
117
118def b2ssize(size):
119 if size < 1024:
120 return str(size)
121
122 for name, scale in RSMAP:
123 if size < 1024 * scale:
124 if size % scale == 0:
125 return "{0} {1}i".format(size // scale, name)
126 else:
127 return "{0:.1f} {1}i".format(float(size) / scale, name)
128
129 return "{0}{1}i".format(size // scale, name)
130
131
koder aka kdanilov652cd802015-04-13 12:21:07 +0300132def get_ip_for_target(target_ip):
koder aka kdanilov209e85d2015-04-27 23:11:05 +0300133 if not is_ip(target_ip):
koder aka kdanilovafd98742015-04-24 01:27:22 +0300134 target_ip = socket.gethostbyname(target_ip)
135
koder aka kdanilov209e85d2015-04-27 23:11:05 +0300136 first_dig = map(int, target_ip.split("."))
137 if first_dig == 127:
koder aka kdanilovafd98742015-04-24 01:27:22 +0300138 return '127.0.0.1'
139
koder aka kdanilov652cd802015-04-13 12:21:07 +0300140 cmd = 'ip route get to'.split(" ") + [target_ip]
141 data = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
142
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300143 rr1 = r'{0} via [.0-9]+ dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
144 rr1 = rr1.replace(" ", r'\s+')
145 rr1 = rr1.format(target_ip.replace('.', r'\.'))
146
147 rr2 = r'{0} dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
148 rr2 = rr2.replace(" ", r'\s+')
149 rr2 = rr2.format(target_ip.replace('.', r'\.'))
koder aka kdanilov652cd802015-04-13 12:21:07 +0300150
151 data_line = data.split("\n")[0].strip()
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300152 res1 = re.match(rr1, data_line)
153 res2 = re.match(rr2, data_line)
koder aka kdanilov652cd802015-04-13 12:21:07 +0300154
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300155 if res1 is not None:
156 return res1.group('ip')
koder aka kdanilov652cd802015-04-13 12:21:07 +0300157
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300158 if res2 is not None:
159 return res2.group('ip')
160
161 raise OSError("Can't define interface for {0}".format(target_ip))
162
163
164def open_for_append_or_create(fname):
165 if not os.path.exists(fname):
166 return open(fname, "w")
167
168 fd = open(fname, 'r+')
169 fd.seek(0, os.SEEK_END)
170 return fd
171
172
173def sec_to_str(seconds):
174 h = seconds // 3600
175 m = (seconds % 3600) // 60
176 s = seconds % 60
177 return "{0}:{1:02d}:{2:02d}".format(h, m, s)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300178
179
180def yamable(data):
181 if isinstance(data, (tuple, list)):
182 return map(yamable, data)
183
184 if isinstance(data, unicode):
185 return str(data)
186
187 if isinstance(data, dict):
188 res = {}
189 for k, v in data.items():
190 res[yamable(k)] = yamable(v)
191 return res
192
193 return data
koder aka kdanilovf86d7af2015-05-06 04:01:54 +0300194
195
196CLEANING = []
197
198
199def clean_resource(func, *args, **kwargs):
200 CLEANING.append((func, args, kwargs))
201
202
203def iter_clean_func():
204 while CLEANING != []:
205 yield CLEANING.pop()