syncloud-lib 333__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ from syncloudlib.integration.ssh import run_ssh
2
+ import re
3
+
4
+
5
+ class LosetupEntry:
6
+ def __init__(self, device, file):
7
+ self.file = file
8
+ self.device = device
9
+
10
+ def is_deleted(self):
11
+ return '(deleted)' in self.file
12
+
13
+
14
+ class MountEntry:
15
+ def __init__(self, device):
16
+ self.device = device
17
+
18
+
19
+ def loop_device_cleanup(host, dev_file, password):
20
+ print('cleanup')
21
+ for mount in parse_mount(run_ssh(host, 'mount', password=password)):
22
+ if dev_file == mount.device:
23
+ run_ssh(host, 'umount {0}'.format(mount.device), throw=False, password=password)
24
+
25
+ for loop in parse_losetup(run_ssh(host, 'losetup', password=password)):
26
+ if loop.file == dev_file or loop.is_deleted():
27
+ run_ssh(host, 'losetup -d {0}'.format(loop.device), throw=False, password=password)
28
+
29
+ run_ssh(host, 'losetup', password=password)
30
+
31
+ for loop in run_ssh(host, 'dmsetup ls', password=password).splitlines():
32
+ if 'loop0p1' in loop:
33
+ run_ssh(host, 'sudo dmsetup remove loop0p1', password=password)
34
+ if 'loop0p2' in loop:
35
+ run_ssh(host, 'sudo dmsetup remove loop0p2', password=password)
36
+
37
+ run_ssh(host, 'rm -rf {0}'.format(dev_file), throw=False, password=password)
38
+
39
+
40
+ def parse_losetup(output):
41
+ entries = []
42
+ for line in output.splitlines():
43
+ match = re.match(r'(.*[0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*)\s+([0-9]+)\s+([0-9]+)', line.strip())
44
+ if match:
45
+ entry = LosetupEntry(match.group(1).strip(), match.group(6).strip())
46
+ entries.append(entry)
47
+ return entries
48
+
49
+
50
+ def parse_mount(output):
51
+ entries = []
52
+ for line in output.splitlines():
53
+ match = re.match(r'(.*)\son\s.*', line.strip())
54
+ if match:
55
+ entry = MountEntry(match.group(1).strip())
56
+ entries.append(entry)
57
+ return entries
58
+
59
+
60
+ def loop_device_add(host, fs, dev_file, password):
61
+ print('adding loop device')
62
+ run_ssh(host, 'dd if=/dev/zero bs=1M count=10 of={0}'.format(dev_file), password=password)
63
+ loop = run_ssh(host, 'losetup -f --show {0}'.format(dev_file), password=password)
64
+ run_ssh(host, 'mkfs.{0} {1}'.format(fs, loop), password=password)
65
+ return loop
@@ -0,0 +1,7 @@
1
+ from os.path import join
2
+
3
+
4
+ def screenshots(driver, screenshot_dir, name):
5
+ driver.get_screenshot_as_file(join(screenshot_dir, '{0}.png'.format(name)))
6
+ with open(join(screenshot_dir, '{0}.html.log'.format(name)), "w") as f:
7
+ f.write(str(driver.page_source.encode("utf-8")))
@@ -0,0 +1,127 @@
1
+ import time
2
+
3
+ from retry import retry
4
+
5
+ from syncloudlib.integration.screenshots import screenshots
6
+ from selenium.webdriver.support.ui import WebDriverWait
7
+ from selenium.webdriver.common.by import By
8
+ from selenium.webdriver.support import expected_conditions
9
+
10
+
11
+ class SeleniumWrapper:
12
+ def __init__(self, driver, ui_mode, screenshot_dir, app_domain, timeout, browser):
13
+ self.app_domain = app_domain
14
+ self.screenshot_dir = screenshot_dir
15
+ self.ui_mode = ui_mode
16
+ self.driver = driver
17
+ self.browser = browser
18
+ self.wait_driver = WebDriverWait(self.driver, timeout)
19
+
20
+ def find_by_xpath(self, xpath):
21
+ return self.find_by(By.XPATH, xpath)
22
+
23
+ def find_by_name(self, name):
24
+ return self.find_by(By.NAME, name)
25
+
26
+ def find_by_id(self, field_id):
27
+ return self.find_by(By.ID, field_id)
28
+
29
+ def find_by_css(self, css):
30
+ return self.find_by(By.CSS_SELECTOR, css)
31
+
32
+ def find_by(self, by, value, parent=None):
33
+ if not parent:
34
+ parent = self.driver
35
+ #self.wait_or_screenshot(expected_conditions.visibility_of_element_located((by, value)))
36
+ self.wait_or_screenshot(expected_conditions.presence_of_element_located((by, value)))
37
+ try:
38
+ return parent.find_element(by, value)
39
+ except Exception as e:
40
+ self.screenshot('exception', True)
41
+
42
+ def invisible_by(self, by, value):
43
+ self.wait_or_screenshot(expected_conditions.invisibility_of_element_located((by, value)))
44
+
45
+ def click_by(self, by, value):
46
+ #self.wait_or_screenshot(expected_conditions.element_to_be_clickable((by, value)))
47
+ self.wait_or_screenshot(expected_conditions.presence_of_element_located((by, value)))
48
+ try:
49
+ self.driver.find_element(by, value).click()
50
+ except Exception as e:
51
+ self.screenshot('exception', True)
52
+
53
+ def clickable_by(self, by, value):
54
+ self.wait_or_screenshot(expected_conditions.element_to_be_clickable((by, value)))
55
+ try:
56
+ return self.driver.find_element(by, value)
57
+ except Exception as e:
58
+ self.screenshot('exception', True)
59
+
60
+ def present_by(self, by, value):
61
+ self.wait_or_screenshot(expected_conditions.presence_of_element_located((by, value)))
62
+ try:
63
+ return self.driver.find_element(by, value)
64
+ except Exception as e:
65
+ self.screenshot('exception', True)
66
+
67
+ def exists_by(self, by, value, timeout=10):
68
+ driver = WebDriverWait(self.driver, timeout)
69
+ cond = expected_conditions.visibility_of_element_located((by, value))
70
+ try:
71
+ driver.until(cond)
72
+ return True
73
+ except Exception as _:
74
+ self.screenshot('exception', False)
75
+ return False
76
+
77
+ @retry(exceptions=Exception, tries=3, delay=1, backoff=2)
78
+ def wait_or_screenshot(self, method, throw=True):
79
+ try:
80
+ self.wait_driver.until(method)
81
+ return True
82
+ except Exception as e:
83
+ self.screenshot('exception', throw)
84
+ if throw:
85
+ raise e
86
+ else:
87
+ return False
88
+
89
+ def screenshot(self, name, throw=True):
90
+ retries = 5
91
+ retry = 0
92
+ while True:
93
+ try:
94
+ screenshots(self.driver, self.screenshot_dir, '{}-{}'.format(name, self.ui_mode))
95
+ break
96
+ except Exception as e:
97
+ if retry >= retries:
98
+ if throw:
99
+ raise
100
+ else:
101
+ return
102
+ retry += 1
103
+ time.sleep(1)
104
+ print('retrying screenshot {0}'.format(retry))
105
+
106
+ def open_app(self, path=''):
107
+ self.driver.get("https://{0}{1}".format(self.app_domain, path))
108
+
109
+ def log(self):
110
+ if self.browser != "chrome":
111
+ print("browser logs are only supported in chrome")
112
+ return
113
+
114
+ print("browser log")
115
+ for entry in self.driver.get_log('browser'):
116
+ print(entry)
117
+
118
+ @retry(exceptions=Exception, tries=10, delay=1, backoff=2)
119
+ def element_by_js(self, js):
120
+ try:
121
+ elem = self.driver.execute_script('return ' + js)
122
+ self.driver.execute_script("arguments[0].scrollIntoView();", elem)
123
+ return elem
124
+ except Exception:
125
+ self.screenshot('exception')
126
+ raise
127
+
@@ -0,0 +1,51 @@
1
+ from subprocess import check_output, STDOUT, CalledProcessError
2
+
3
+ import time
4
+
5
+
6
+ def run_scp(command, throw=True, debug=True, password='syncloud', retries=0, sleep=1, port=22):
7
+ retry = 0
8
+ while True:
9
+ try:
10
+ return _run_command('scp -P {0} -o StrictHostKeyChecking=no {1}'.format(port, command), throw, debug, password)
11
+ except Exception as e:
12
+ if retry >= retries:
13
+ raise
14
+ retry += 1
15
+ time.sleep(sleep)
16
+ sleep = sleep * 2
17
+ print('retrying {0}'.format(retry))
18
+
19
+
20
+ def run_ssh(host, command, throw=True, debug=True, password='syncloud', retries=0, sleep=1, env_vars='', port=22):
21
+ ssh_command='{0} {1}'.format(env_vars, command)
22
+ retry = 0
23
+ while True:
24
+ try:
25
+ return _run_command('ssh -p {0} -o StrictHostKeyChecking=no root@{1} "{2}"'.format(port, host, ssh_command), throw, debug, password)
26
+ except Exception as e:
27
+ if retry >= retries:
28
+ raise
29
+ retry += 1
30
+ time.sleep(sleep)
31
+ sleep = sleep * 2
32
+ print('retrying {0}'.format(retry))
33
+
34
+
35
+ def ssh_command(password, command):
36
+ return 'sshpass -p {0} {1}'.format(password, command)
37
+
38
+
39
+ def _run_command(command, throw, debug, password):
40
+ try:
41
+ print('ssh command: {0}'.format(command))
42
+ output = str(check_output(ssh_command(password, command), shell=True, stderr=STDOUT, encoding='UTF-8')).strip()
43
+ if debug:
44
+ print("ssh output: " + output)
45
+ print
46
+ return output
47
+ except CalledProcessError as e:
48
+ print("ssh error: " + str(e.output))
49
+ if throw:
50
+ raise
51
+ return str(e.output)
File without changes
@@ -0,0 +1,114 @@
1
+ import sys
2
+
3
+ import jsonpickle
4
+ import os
5
+ import datetime
6
+ import inspect
7
+
8
+ jsonpickle.set_preferred_backend('json')
9
+ if sys.version_info.major < 3:
10
+ types = (bool, str, unicode, int, long, float, datetime.datetime)
11
+ else:
12
+ types = (bool, str, int, float, datetime.datetime)
13
+
14
+
15
+ def pretty_print():
16
+ jsonpickle.set_encoder_options('json', indent=2)
17
+
18
+ def ugly_print():
19
+ jsonpickle.set_encoder_options('json', indent=None)
20
+
21
+ class List:
22
+ def __init__(self, item_type):
23
+ self.item_type = item_type
24
+
25
+ class Field:
26
+ def __init__(self, field_type=None, default=None):
27
+ self.field_type = field_type
28
+ self.default = default
29
+
30
+ class Struct(object):
31
+ def __init__(self, adict):
32
+ self.__dict__.update(adict)
33
+ for k, v in adict.items():
34
+ if isinstance(v, (dict, list)):
35
+ self.__dict__[k] = to_object(v)
36
+
37
+
38
+ def get_field_value(field, field_meta, structure):
39
+ if field in structure.keys():
40
+ value = structure[field]
41
+ if field_meta.field_type:
42
+ return to_object(value, field_meta.field_type)
43
+ return value
44
+ else:
45
+ if field_meta.default is not None:
46
+ return field_meta.default
47
+ return None
48
+
49
+
50
+ def to_object(structure, obj_type=None):
51
+ if obj_type:
52
+ if isinstance(obj_type, List):
53
+ return [to_object(item, obj_type.item_type) for item in structure]
54
+ else:
55
+ obj = obj_type()
56
+ for field, field_meta in inspect.getmembers(obj):
57
+ if isinstance(field_meta, Field):
58
+ value = get_field_value(field, field_meta, structure)
59
+ setattr(obj, field, value)
60
+ return obj
61
+ else:
62
+ if structure is None or isinstance(structure, types):
63
+ return structure
64
+ if isinstance(structure, list):
65
+ return [to_object(item) for item in structure]
66
+ return Struct(structure)
67
+
68
+ def limit(dictionary, keys):
69
+ filtered = [key for key in dictionary.keys() if key not in keys]
70
+ for key in filtered:
71
+ dictionary.pop(key, None)
72
+
73
+ def to_dict(value):
74
+ if isinstance(value, list):
75
+ return [to_dict(item) for item in value]
76
+ if isinstance(value, dict):
77
+ cloned = value.copy()
78
+ for key, value in cloned.items():
79
+ cloned[key] = to_dict(value)
80
+ return cloned
81
+ if value is None or isinstance(value, types):
82
+ return value
83
+ result = value.__dict__.copy()
84
+ if hasattr(value, '__public__'):
85
+ limit(result, value.__public__)
86
+ for member, mvalue in result.items():
87
+ result[member] = to_dict(mvalue)
88
+ return result
89
+
90
+ def from_json(json_text, obj_type=None):
91
+ return to_object(jsonpickle.decode(json_text), obj_type)
92
+
93
+ def to_json(value):
94
+ return jsonpickle.encode(value, unpicklable=False)
95
+
96
+ def reformat(json_text):
97
+ return to_json(from_json(json_text))
98
+
99
+ def read_json(filename, obj_type=None):
100
+ if not os.path.isfile(filename):
101
+ return None
102
+ with open(filename, 'r') as f:
103
+ json = f.read()
104
+ if json.strip(' \t\n\r') == '':
105
+ return None
106
+ return from_json(json, obj_type)
107
+
108
+ def write_json(filename, obj):
109
+ if not obj:
110
+ json = ''
111
+ else:
112
+ json = to_json(obj)
113
+ with open(filename, 'w') as file:
114
+ file.write(json)
syncloudlib/linux.py ADDED
@@ -0,0 +1,15 @@
1
+ from subprocess import check_output
2
+ import pwd
3
+
4
+
5
+ def useradd(user, home_folder=None, shell='/bin/false'):
6
+ try:
7
+ pwd.getpwnam(user)
8
+ return 'user {0} exists'.format(user)
9
+ except KeyError:
10
+ options = '-r -s {0}'.format(shell)
11
+ if home_folder:
12
+ home_folder_options = '-m -d {0}'.format(home_folder)
13
+ options = home_folder_options + ' ' + options
14
+ command_line = '/usr/sbin/useradd {0} {1}'.format(options, user)
15
+ return check_output(command_line, shell=True).decode()
syncloudlib/logger.py ADDED
@@ -0,0 +1,54 @@
1
+ import logging
2
+ import logging.handlers
3
+ import sys
4
+
5
+ factory_instance = None
6
+
7
+
8
+ class WhitespaceRemovingFormatter(logging.Formatter):
9
+ def format(self, record):
10
+ record.msg = clean(record.msg)
11
+ return super(WhitespaceRemovingFormatter, self).format(record)
12
+
13
+
14
+ def clean(message):
15
+ return str(message).strip()
16
+
17
+
18
+ class LoggerFactory:
19
+ def __init__(self, level, console, filename, line_format):
20
+ self.level = level
21
+ self.console = console
22
+ self.filename = filename
23
+ self.formatter = WhitespaceRemovingFormatter(line_format)
24
+ if filename:
25
+ self.file_handler = logging.handlers.RotatingFileHandler(self.filename, maxBytes=1000000, backupCount=5)
26
+ self.file_handler.setFormatter(self.formatter)
27
+ if console:
28
+ self.console_handler = logging.StreamHandler(sys.stdout)
29
+ self.console_handler.setFormatter(self.formatter)
30
+
31
+ def get_logger(self, name):
32
+ logger = logging.getLogger(name)
33
+ logger.setLevel(self.level)
34
+ if self.filename:
35
+ if self.file_handler not in logger.handlers:
36
+ logger.addHandler(self.file_handler)
37
+ if self.console:
38
+ if self.console_handler not in logger.handlers:
39
+ logger.addHandler(self.console_handler)
40
+ return logger
41
+
42
+ default_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
43
+
44
+
45
+ def init(level=logging.INFO, console=False, filename=None, line_format=default_format):
46
+ global factory_instance
47
+ factory_instance = LoggerFactory(level, console, filename, line_format)
48
+
49
+
50
+ def get_logger(name):
51
+ global factory_instance
52
+ if not factory_instance:
53
+ raise Exception('Logging is not initialized')
54
+ return factory_instance.get_logger(name)