koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 1 | import os.path |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 2 | import logging |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 3 | import contextlib |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 4 | |
koder aka kdanilov | bb5fe07 | 2015-05-21 02:50:23 +0300 | [diff] [blame] | 5 | from concurrent.futures import ThreadPoolExecutor |
| 6 | |
| 7 | from wally import ssh_utils |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 8 | from wally.sensors.api import (with_sensors, sensors_info, SensorConfig) |
| 9 | |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 10 | |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 11 | logger = logging.getLogger("wally.sensors") |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 12 | |
| 13 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 14 | def get_sensors_config_for_nodes(cfg, nodes, remote_path): |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 15 | monitored_nodes = [] |
| 16 | sensors_configs = [] |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 17 | source2roles_map = {} |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 18 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 19 | receiver_url = "csvfile://" + os.path.join(remote_path, "results.csv") |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 20 | |
| 21 | for role, sensors_str in cfg["roles_mapping"].items(): |
| 22 | sensors = [sens.strip() for sens in sensors_str.split(",")] |
| 23 | |
| 24 | collect_cfg = dict((sensor, {}) for sensor in sensors) |
| 25 | |
| 26 | for node in nodes: |
| 27 | if role in node.roles: |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 28 | source2roles_map[node.get_conn_id()] = node.roles |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 29 | monitored_nodes.append(node) |
| 30 | sens_cfg = SensorConfig(node.connection, |
| 31 | node.get_conn_id(), |
| 32 | collect_cfg, |
| 33 | source_id=node.get_conn_id(), |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 34 | monitor_url=receiver_url) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 35 | sensors_configs.append(sens_cfg) |
| 36 | |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 37 | return monitored_nodes, sensors_configs, source2roles_map |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 38 | |
| 39 | |
koder aka kdanilov | bb5fe07 | 2015-05-21 02:50:23 +0300 | [diff] [blame] | 40 | PID_FILE = "/tmp/sensors.pid" |
| 41 | |
| 42 | |
| 43 | def clear_old_sensors(sensors_configs): |
| 44 | def stop_sensors(sens_cfg): |
| 45 | with sens_cfg.conn.open_sftp() as sftp: |
| 46 | try: |
| 47 | pid = ssh_utils.read_from_remote(sftp, PID_FILE) |
| 48 | pid = int(pid.strip()) |
| 49 | ssh_utils.run_over_ssh(sens_cfg.conn, |
| 50 | "kill -9 " + str(pid)) |
| 51 | sftp.remove(PID_FILE) |
| 52 | except: |
| 53 | pass |
| 54 | |
| 55 | with ThreadPoolExecutor(32) as pool: |
| 56 | list(pool.map(stop_sensors, sensors_configs)) |
| 57 | |
| 58 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 59 | @contextlib.contextmanager |
| 60 | def with_sensors_util(cfg, nodes): |
| 61 | if 'sensors' not in cfg: |
| 62 | yield |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 63 | return |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 64 | |
koder aka kdanilov | 57ce4db | 2015-04-25 21:25:51 +0300 | [diff] [blame] | 65 | monitored_nodes, sensors_configs, source2roles_map = \ |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 66 | get_sensors_config_for_nodes(cfg['sensors'], nodes, |
| 67 | cfg['sensors_remote_path']) |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 68 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 69 | with with_sensors(sensors_configs, cfg['sensors_remote_path']): |
| 70 | yield source2roles_map |
| 71 | |
| 72 | |
| 73 | @contextlib.contextmanager |
| 74 | def sensors_info_util(cfg, nodes): |
| 75 | if 'sensors' not in cfg: |
| 76 | yield None |
koder aka kdanilov | 168f609 | 2015-04-19 02:33:38 +0300 | [diff] [blame] | 77 | return |
| 78 | |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 79 | _, sensors_configs, _ = \ |
| 80 | get_sensors_config_for_nodes(cfg['sensors'], nodes, |
| 81 | cfg['sensors_remote_path']) |
koder aka kdanilov | 416b87a | 2015-05-12 00:26:04 +0300 | [diff] [blame] | 82 | |
koder aka kdanilov | bb5fe07 | 2015-05-21 02:50:23 +0300 | [diff] [blame] | 83 | clear_old_sensors(sensors_configs) |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame^] | 84 | ctx = sensors_info(sensors_configs, cfg['sensors_remote_path']) |
| 85 | try: |
| 86 | res = ctx.__enter__() |
koder aka kdanilov | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 87 | yield res |
koder aka kdanilov | 88407ff | 2015-05-26 15:35:57 +0300 | [diff] [blame^] | 88 | except: |
| 89 | ctx.__exit__(None, None, None) |
| 90 | raise |
| 91 | finally: |
| 92 | try: |
| 93 | ctx.__exit__(None, None, None) |
| 94 | except: |
| 95 | logger.exception("During stop/collect sensors") |
| 96 | del res[:] |