very large refactoring
diff --git a/wally/utils.py b/wally/utils.py
new file mode 100644
index 0000000..60645d4
--- /dev/null
+++ b/wally/utils.py
@@ -0,0 +1,124 @@
+import re
+import os
+import logging
+import threading
+import contextlib
+import subprocess
+
+
+logger = logging.getLogger("wally")
+
+
+def parse_creds(creds):
+ # parse user:passwd@host
+ user, passwd_host = creds.split(":", 1)
+
+ if '@' not in passwd_host:
+ passwd, host = passwd_host, None
+ else:
+ passwd, host = passwd_host.rsplit('@', 1)
+
+ return user, passwd, host
+
+
+class TaksFinished(Exception):
+ pass
+
+
+class Barrier(object):
+ def __init__(self, count):
+ self.count = count
+ self.curr_count = 0
+ self.cond = threading.Condition()
+ self.exited = False
+
+ def wait(self, timeout=None):
+ with self.cond:
+ if self.exited:
+ raise TaksFinished()
+
+ self.curr_count += 1
+ if self.curr_count == self.count:
+ self.curr_count = 0
+ self.cond.notify_all()
+ return True
+ else:
+ self.cond.wait(timeout=timeout)
+ return False
+
+ def exit(self):
+ with self.cond:
+ self.exited = True
+
+
+@contextlib.contextmanager
+def log_error(action, types=(Exception,)):
+ if not action.startswith("!"):
+ logger.debug("Starts : " + action)
+ else:
+ action = action[1:]
+
+ try:
+ yield
+ except Exception as exc:
+ if isinstance(exc, types) and not isinstance(exc, StopIteration):
+ templ = "Error during {0} stage: {1}"
+ logger.debug(templ.format(action, exc.message))
+ raise
+
+
+SMAP = dict(k=1024, m=1024 ** 2, g=1024 ** 3, t=1024 ** 4)
+
+
+def ssize_to_b(ssize):
+ try:
+ ssize = ssize.lower()
+
+ if ssize.endswith("b"):
+ ssize = ssize[:-1]
+ if ssize[-1] in SMAP:
+ return int(ssize[:-1]) * SMAP[ssize[-1]]
+ return int(ssize)
+ except (ValueError, TypeError, AttributeError):
+ raise ValueError("Unknow size format {0!r}".format(ssize))
+
+
+def get_ip_for_target(target_ip):
+ cmd = 'ip route get to'.split(" ") + [target_ip]
+ data = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
+
+ rr1 = r'{0} via [.0-9]+ dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
+ rr1 = rr1.replace(" ", r'\s+')
+ rr1 = rr1.format(target_ip.replace('.', r'\.'))
+
+ rr2 = r'{0} dev (?P<dev>.*?) src (?P<ip>[.0-9]+)$'
+ rr2 = rr2.replace(" ", r'\s+')
+ rr2 = rr2.format(target_ip.replace('.', r'\.'))
+
+ data_line = data.split("\n")[0].strip()
+ res1 = re.match(rr1, data_line)
+ res2 = re.match(rr2, data_line)
+
+ if res1 is not None:
+ return res1.group('ip')
+
+ if res2 is not None:
+ return res2.group('ip')
+
+ raise OSError("Can't define interface for {0}".format(target_ip))
+
+
+def open_for_append_or_create(fname):
+ if not os.path.exists(fname):
+ return open(fname, "w")
+
+ fd = open(fname, 'r+')
+ fd.seek(0, os.SEEK_END)
+ return fd
+
+
+def sec_to_str(seconds):
+ h = seconds // 3600
+ m = (seconds % 3600) // 60
+ s = seconds % 60
+ return "{0}:{1:02d}:{2:02d}".format(h, m, s)