| 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 | 4af1c1d | 2015-05-18 15:48:58 +0300 | [diff] [blame] | 84 | with sensors_info(sensors_configs, cfg['sensors_remote_path']) as res: | 
|  | 85 | yield res |