blob: 8603f5858347b245b11a8565f2c49dba54b1a188 [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 kdanilove06762a2015-03-22 23:32:09 +020026def parse_creds(creds):
27 # parse user:passwd@host
28 user, passwd_host = creds.split(":", 1)
29
30 if '@' not in passwd_host:
31 passwd, host = passwd_host, None
32 else:
33 passwd, host = passwd_host.rsplit('@', 1)
34
35 return user, passwd, host
36
37
koder aka kdanilov2c473092015-03-29 17:12:13 +030038class TaksFinished(Exception):
39 pass
koder aka kdanilov4643fd62015-02-10 16:20:13 -080040
koder aka kdanilov2c473092015-03-29 17:12:13 +030041
koder aka kdanilove2de58c2015-04-24 22:59:36 +030042class StopTestError(RuntimeError):
43 def __init__(self, reason, orig_exc=None):
44 RuntimeError.__init__(self, reason)
45 self.orig_exc = orig_exc
46
47
koder aka kdanilov2c473092015-03-29 17:12:13 +030048class Barrier(object):
49 def __init__(self, count):
50 self.count = count
51 self.curr_count = 0
52 self.cond = threading.Condition()
53 self.exited = False
54
55 def wait(self, timeout=None):
56 with self.cond:
57 if self.exited:
58 raise TaksFinished()
59
60 self.curr_count += 1
61 if self.curr_count == self.count:
62 self.curr_count = 0
63 self.cond.notify_all()
koder aka kdanilov652cd802015-04-13 12:21:07 +030064 return True
koder aka kdanilov4643fd62015-02-10 16:20:13 -080065 else:
koder aka kdanilov2c473092015-03-29 17:12:13 +030066 self.cond.wait(timeout=timeout)
koder aka kdanilov652cd802015-04-13 12:21:07 +030067 return False
koder aka kdanilov4643fd62015-02-10 16:20:13 -080068
koder aka kdanilov2c473092015-03-29 17:12:13 +030069 def exit(self):
70 with self.cond:
71 self.exited = True
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080072
73
74@contextlib.contextmanager
75def log_error(action, types=(Exception,)):
76 if not action.startswith("!"):
koder aka kdanilove21d7472015-02-14 19:02:04 -080077 logger.debug("Starts : " + action)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080078 else:
79 action = action[1:]
80
81 try:
82 yield
83 except Exception as exc:
84 if isinstance(exc, types) and not isinstance(exc, StopIteration):
koder aka kdanilovec1b9732015-04-23 20:43:29 +030085 templ = "Error during {0} stage: {1!s}"
86 logger.debug(templ.format(action, exc))
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080087 raise
88
89
koder aka kdanilov2c473092015-03-29 17:12:13 +030090SMAP = dict(k=1024, m=1024 ** 2, g=1024 ** 3, t=1024 ** 4)
koder aka kdanilov8ad6e812015-03-22 14:42:18 +020091
92
93def ssize_to_b(ssize):
94 try:
koder aka kdanilov63e9c5a2015-04-28 23:06:07 +030095 if isinstance(ssize, (int, long)):
96 return ssize
koder aka kdanilov8ad6e812015-03-22 14:42:18 +020097
koder aka kdanilov63e9c5a2015-04-28 23:06:07 +030098 ssize = ssize.lower()
koder aka kdanilov2c473092015-03-29 17:12:13 +030099 if ssize[-1] in SMAP:
100 return int(ssize[:-1]) * SMAP[ssize[-1]]
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200101 return int(ssize)
102 except (ValueError, TypeError, AttributeError):
koder aka kdanilov2e928022015-04-08 13:47:15 +0300103 raise ValueError("Unknow size format {0!r}".format(ssize))
koder aka kdanilov652cd802015-04-13 12:21:07 +0300104
105
106def get_ip_for_target(target_ip):
koder aka kdanilov209e85d2015-04-27 23:11:05 +0300107 if not is_ip(target_ip):
koder aka kdanilovafd98742015-04-24 01:27:22 +0300108 target_ip = socket.gethostbyname(target_ip)
109
koder aka kdanilov209e85d2015-04-27 23:11:05 +0300110 first_dig = map(int, target_ip.split("."))
111 if first_dig == 127:
koder aka kdanilovafd98742015-04-24 01:27:22 +0300112 return '127.0.0.1'
113
koder aka kdanilov652cd802015-04-13 12:21:07 +0300114 cmd = 'ip route get to'.split(" ") + [target_ip]
115 data = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
116
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300117 rr1 = r'{0} via [.0-9]+ dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
118 rr1 = rr1.replace(" ", r'\s+')
119 rr1 = rr1.format(target_ip.replace('.', r'\.'))
120
121 rr2 = r'{0} dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
122 rr2 = rr2.replace(" ", r'\s+')
123 rr2 = rr2.format(target_ip.replace('.', r'\.'))
koder aka kdanilov652cd802015-04-13 12:21:07 +0300124
125 data_line = data.split("\n")[0].strip()
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300126 res1 = re.match(rr1, data_line)
127 res2 = re.match(rr2, data_line)
koder aka kdanilov652cd802015-04-13 12:21:07 +0300128
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300129 if res1 is not None:
130 return res1.group('ip')
koder aka kdanilov652cd802015-04-13 12:21:07 +0300131
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300132 if res2 is not None:
133 return res2.group('ip')
134
135 raise OSError("Can't define interface for {0}".format(target_ip))
136
137
138def open_for_append_or_create(fname):
139 if not os.path.exists(fname):
140 return open(fname, "w")
141
142 fd = open(fname, 'r+')
143 fd.seek(0, os.SEEK_END)
144 return fd
145
146
147def sec_to_str(seconds):
148 h = seconds // 3600
149 m = (seconds % 3600) // 60
150 s = seconds % 60
151 return "{0}:{1:02d}:{2:02d}".format(h, m, s)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300152
153
154def yamable(data):
155 if isinstance(data, (tuple, list)):
156 return map(yamable, data)
157
158 if isinstance(data, unicode):
159 return str(data)
160
161 if isinstance(data, dict):
162 res = {}
163 for k, v in data.items():
164 res[yamable(k)] = yamable(v)
165 return res
166
167 return data