koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 1 | import time |
| 2 | import json |
| 3 | import os.path |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 4 | import logging |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 5 | |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 6 | from concurrent.futures import ThreadPoolExecutor, wait |
| 7 | |
koder aka kdanilov | e06762a | 2015-03-22 23:32:09 +0200 | [diff] [blame] | 8 | from disk_perf_test_tool.ssh_utils import connect, copy_paths |
| 9 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 10 | logger = logging.getLogger('io-perf-tool') |
| 11 | |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 12 | |
| 13 | def wait_all_ok(futures): |
| 14 | return all(future.result() for future in futures) |
| 15 | |
| 16 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 17 | def deploy_and_start_sensors(monitor_uri, config, |
| 18 | remote_path='/tmp/sensors', |
| 19 | connected_config=None): |
koder aka kdanilov | 12ae063 | 2015-04-15 01:13:43 +0300 | [diff] [blame] | 20 | |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 21 | paths = {os.path.dirname(__file__): remote_path} |
| 22 | with ThreadPoolExecutor(max_workers=32) as executor: |
| 23 | futures = [] |
| 24 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 25 | if connected_config is not None: |
| 26 | assert config is None |
| 27 | node_iter = connected_config |
| 28 | else: |
| 29 | node_iter = config.items() |
| 30 | |
| 31 | for uri_or_conn, config in node_iter: |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 32 | futures.append(executor.submit(deploy_and_start_sensor, |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 33 | paths, uri_or_conn, |
| 34 | monitor_uri, |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 35 | config, remote_path)) |
| 36 | |
| 37 | if not wait_all_ok(futures): |
| 38 | raise RuntimeError("Sensor deployment fails on some nodes") |
| 39 | |
| 40 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 41 | def deploy_and_start_sensor(paths, uri_or_conn, monitor_uri, config, |
| 42 | remote_path): |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 43 | try: |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 44 | if isinstance(uri_or_conn, basestring): |
| 45 | conn = connect(uri_or_conn) |
| 46 | else: |
| 47 | conn = uri_or_conn |
| 48 | |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 49 | copy_paths(conn, paths) |
| 50 | sftp = conn.open_sftp() |
| 51 | |
| 52 | config_remote_path = os.path.join(remote_path, "conf.json") |
| 53 | main_remote_path = os.path.join(remote_path, "main.py") |
| 54 | |
| 55 | with sftp.open(config_remote_path, "w") as fd: |
| 56 | fd.write(json.dumps(config)) |
| 57 | |
| 58 | cmd_templ = "python {0} -d start -u {1} {2}" |
| 59 | cmd = cmd_templ.format(main_remote_path, |
| 60 | monitor_uri, |
| 61 | config_remote_path) |
| 62 | conn.exec_command(cmd) |
| 63 | sftp.close() |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 64 | |
| 65 | if isinstance(uri_or_conn, basestring): |
| 66 | conn.close() |
koder aka kdanilov | e4ade1a | 2015-03-16 20:44:16 +0200 | [diff] [blame] | 67 | except: |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 68 | logger.exception("During deploing sensors in {0}".format(uri_or_conn)) |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 69 | return False |
| 70 | return True |
| 71 | |
| 72 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 73 | def stop_and_remove_sensor(uri_or_conn, remote_path): |
| 74 | if isinstance(uri_or_conn, basestring): |
| 75 | conn = connect(uri_or_conn) |
| 76 | else: |
| 77 | conn = uri_or_conn |
| 78 | |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 79 | main_remote_path = os.path.join(remote_path, "main.py") |
| 80 | |
| 81 | cmd_templ = "python {0} -d stop" |
| 82 | conn.exec_command(cmd_templ.format(main_remote_path)) |
koder aka kdanilov | e4ade1a | 2015-03-16 20:44:16 +0200 | [diff] [blame] | 83 | |
| 84 | # some magic |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 85 | time.sleep(0.3) |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 86 | |
| 87 | conn.exec_command("rm -rf {0}".format(remote_path)) |
| 88 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 89 | if isinstance(uri_or_conn, basestring): |
| 90 | conn.close() |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 91 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 92 | logger.debug("Sensors stopped and removed") |
| 93 | |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 94 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 95 | def stop_and_remove_sensors(config, remote_path='/tmp/sensors', |
| 96 | connected_config=None): |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 97 | with ThreadPoolExecutor(max_workers=32) as executor: |
| 98 | futures = [] |
| 99 | |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 100 | if connected_config is not None: |
| 101 | assert config is None |
| 102 | conf_iter = connected_config |
| 103 | else: |
| 104 | conf_iter = config.items() |
| 105 | |
| 106 | for uri_or_conn, config in conf_iter: |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 107 | futures.append(executor.submit(stop_and_remove_sensor, |
koder aka kdanilov | 2c47309 | 2015-03-29 17:12:13 +0300 | [diff] [blame] | 108 | uri_or_conn, remote_path)) |
koder aka kdanilov | dda86d3 | 2015-03-16 11:20:04 +0200 | [diff] [blame] | 109 | |
| 110 | wait(futures) |