blob: 71fbe576bda6c42424c00ec3710f62a346d2967f [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 kdanilove21d7472015-02-14 19:02:04 -08003import logging
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -08004import threading
5import contextlib
koder aka kdanilov652cd802015-04-13 12:21:07 +03006import subprocess
koder aka kdanilov4643fd62015-02-10 16:20:13 -08007
koder aka kdanilove21d7472015-02-14 19:02:04 -08008
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +03009logger = logging.getLogger("wally")
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080010
11
koder aka kdanilove06762a2015-03-22 23:32:09 +020012def parse_creds(creds):
13 # parse user:passwd@host
14 user, passwd_host = creds.split(":", 1)
15
16 if '@' not in passwd_host:
17 passwd, host = passwd_host, None
18 else:
19 passwd, host = passwd_host.rsplit('@', 1)
20
21 return user, passwd, host
22
23
koder aka kdanilov2c473092015-03-29 17:12:13 +030024class TaksFinished(Exception):
25 pass
koder aka kdanilov4643fd62015-02-10 16:20:13 -080026
koder aka kdanilov2c473092015-03-29 17:12:13 +030027
28class Barrier(object):
29 def __init__(self, count):
30 self.count = count
31 self.curr_count = 0
32 self.cond = threading.Condition()
33 self.exited = False
34
35 def wait(self, timeout=None):
36 with self.cond:
37 if self.exited:
38 raise TaksFinished()
39
40 self.curr_count += 1
41 if self.curr_count == self.count:
42 self.curr_count = 0
43 self.cond.notify_all()
koder aka kdanilov652cd802015-04-13 12:21:07 +030044 return True
koder aka kdanilov4643fd62015-02-10 16:20:13 -080045 else:
koder aka kdanilov2c473092015-03-29 17:12:13 +030046 self.cond.wait(timeout=timeout)
koder aka kdanilov652cd802015-04-13 12:21:07 +030047 return False
koder aka kdanilov4643fd62015-02-10 16:20:13 -080048
koder aka kdanilov2c473092015-03-29 17:12:13 +030049 def exit(self):
50 with self.cond:
51 self.exited = True
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080052
53
54@contextlib.contextmanager
55def log_error(action, types=(Exception,)):
56 if not action.startswith("!"):
koder aka kdanilove21d7472015-02-14 19:02:04 -080057 logger.debug("Starts : " + action)
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080058 else:
59 action = action[1:]
60
61 try:
62 yield
63 except Exception as exc:
64 if isinstance(exc, types) and not isinstance(exc, StopIteration):
65 templ = "Error during {0} stage: {1}"
koder aka kdanilove21d7472015-02-14 19:02:04 -080066 logger.debug(templ.format(action, exc.message))
koder aka kdanilov7acd6bd2015-02-12 14:28:30 -080067 raise
68
69
koder aka kdanilov2c473092015-03-29 17:12:13 +030070SMAP = dict(k=1024, m=1024 ** 2, g=1024 ** 3, t=1024 ** 4)
koder aka kdanilov8ad6e812015-03-22 14:42:18 +020071
72
73def ssize_to_b(ssize):
74 try:
koder aka kdanilov2c473092015-03-29 17:12:13 +030075 ssize = ssize.lower()
koder aka kdanilov8ad6e812015-03-22 14:42:18 +020076
koder aka kdanilov2c473092015-03-29 17:12:13 +030077 if ssize.endswith("b"):
78 ssize = ssize[:-1]
79 if ssize[-1] in SMAP:
80 return int(ssize[:-1]) * SMAP[ssize[-1]]
koder aka kdanilov8ad6e812015-03-22 14:42:18 +020081 return int(ssize)
82 except (ValueError, TypeError, AttributeError):
koder aka kdanilov2e928022015-04-08 13:47:15 +030083 raise ValueError("Unknow size format {0!r}".format(ssize))
koder aka kdanilov652cd802015-04-13 12:21:07 +030084
85
86def get_ip_for_target(target_ip):
87 cmd = 'ip route get to'.split(" ") + [target_ip]
88 data = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
89
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030090 rr1 = r'{0} via [.0-9]+ dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
91 rr1 = rr1.replace(" ", r'\s+')
92 rr1 = rr1.format(target_ip.replace('.', r'\.'))
93
94 rr2 = r'{0} dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
95 rr2 = rr2.replace(" ", r'\s+')
96 rr2 = rr2.format(target_ip.replace('.', r'\.'))
koder aka kdanilov652cd802015-04-13 12:21:07 +030097
98 data_line = data.split("\n")[0].strip()
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +030099 res1 = re.match(rr1, data_line)
100 res2 = re.match(rr2, data_line)
koder aka kdanilov652cd802015-04-13 12:21:07 +0300101
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300102 if res1 is not None:
103 return res1.group('ip')
koder aka kdanilov652cd802015-04-13 12:21:07 +0300104
koder aka kdanilovcff7b2e2015-04-18 20:48:15 +0300105 if res2 is not None:
106 return res2.group('ip')
107
108 raise OSError("Can't define interface for {0}".format(target_ip))
109
110
111def open_for_append_or_create(fname):
112 if not os.path.exists(fname):
113 return open(fname, "w")
114
115 fd = open(fname, 'r+')
116 fd.seek(0, os.SEEK_END)
117 return fd
118
119
120def sec_to_str(seconds):
121 h = seconds // 3600
122 m = (seconds % 3600) // 60
123 s = seconds % 60
124 return "{0}:{1:02d}:{2:02d}".format(h, m, s)
koder aka kdanilov168f6092015-04-19 02:33:38 +0300125
126
127def yamable(data):
128 if isinstance(data, (tuple, list)):
129 return map(yamable, data)
130
131 if isinstance(data, unicode):
132 return str(data)
133
134 if isinstance(data, dict):
135 res = {}
136 for k, v in data.items():
137 res[yamable(k)] = yamable(v)
138 return res
139
140 return data