blob: 89bc22419910b7a0067a18e7ebe352c33f081a5a [file] [log] [blame]
kdanylov aka koder45183182017-04-30 23:55:40 +03001import bz2
koder aka kdanilov962ee5f2016-12-19 02:40:08 +02002import array
3import logging
kdanylov aka koder736e5c12017-05-07 17:27:14 +03004from typing import Dict
koder aka kdanilov39e449e2016-12-17 15:15:26 +02005
koder aka kdanilova732a602017-02-01 20:29:56 +02006import numpy
7
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +03008from cephlib import sensors_rpc_plugin
9
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020010from . import utils
koder aka kdanilov70227062016-11-26 23:23:21 +020011from .test_run_class import TestRun
koder aka kdanilova732a602017-02-01 20:29:56 +020012from .result_classes import DataSource
koder aka kdanilov39e449e2016-12-17 15:15:26 +020013from .stage import Stage, StepOrder
koder aka kdanilova732a602017-02-01 20:29:56 +020014from .hlstorage import ResultStorage
koder aka kdanilov70227062016-11-26 23:23:21 +020015
kdanylov aka koder150b2192017-04-01 16:53:01 +030016
koder aka kdanilov70227062016-11-26 23:23:21 +020017plugin_fname = sensors_rpc_plugin.__file__.rsplit(".", 1)[0] + ".py"
koder aka kdanilov23e6bdf2016-12-24 02:18:54 +020018SENSORS_PLUGIN_CODE = open(plugin_fname, "rb").read() # type: bytes
koder aka kdanilov70227062016-11-26 23:23:21 +020019
20
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020021logger = logging.getLogger("wally")
koder aka kdanilov70227062016-11-26 23:23:21 +020022
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020023
24# TODO(koder): in case if node has more than one role sensor settings might be incorrect
koder aka kdanilov39e449e2016-12-17 15:15:26 +020025class StartSensorsStage(Stage):
26 priority = StepOrder.START_SENSORS
27 config_block = 'sensors'
koder aka kdanilov70227062016-11-26 23:23:21 +020028
koder aka kdanilov39e449e2016-12-17 15:15:26 +020029 def run(self, ctx: TestRun) -> None:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020030 if array.array('L').itemsize != 8:
31 message = "Python array.array('L') items should be 8 bytes in size, not {}." + \
32 " Can't provide sensors on this platform. Disable sensors in config and retry"
33 logger.critical(message.format(array.array('L').itemsize))
34 raise utils.StopTestError()
koder aka kdanilov39e449e2016-12-17 15:15:26 +020035
koder aka kdanilov23e6bdf2016-12-24 02:18:54 +020036 # TODO: need carefully fix this
37 # sensors config is:
38 # role:
39 # sensor: [str]
40 # or
41 # role:
42 # sensor:
43 # allowed: [str]
44 # dissallowed: [str]
45 # params: Any
koder aka kdanilov39e449e2016-12-17 15:15:26 +020046 per_role_config = {} # type: Dict[str, Dict[str, str]]
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020047
48 for name, val in ctx.config.sensors.roles_mapping.raw().items():
koder aka kdanilov39e449e2016-12-17 15:15:26 +020049 if isinstance(val, str):
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +030050 val = {vl.strip(): (".*" if vl.strip() != 'ceph' else {}) for vl in val.split(",")}
koder aka kdanilov39e449e2016-12-17 15:15:26 +020051 elif isinstance(val, list):
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +030052 val = {vl: (".*" if vl != 'ceph' else {}) for vl in val}
koder aka kdanilov39e449e2016-12-17 15:15:26 +020053 per_role_config[name] = val
54
55 if 'all' in per_role_config:
56 all_vl = per_role_config.pop('all')
57 all_roles = set(per_role_config)
58
59 for node in ctx.nodes:
koder aka kdanilov23e6bdf2016-12-24 02:18:54 +020060 all_roles.update(node.info.roles) # type: ignore
koder aka kdanilov39e449e2016-12-17 15:15:26 +020061
62 for name, vals in list(per_role_config.items()):
63 new_vals = all_vl.copy()
64 new_vals.update(vals)
65 per_role_config[name] = new_vals
koder aka kdanilov70227062016-11-26 23:23:21 +020066
67 for node in ctx.nodes:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020068 node_cfg = {} # type: Dict[str, Dict[str, str]]
koder aka kdanilov39e449e2016-12-17 15:15:26 +020069 for role in node.info.roles:
koder aka kdanilov23e6bdf2016-12-24 02:18:54 +020070 node_cfg.update(per_role_config.get(role, {})) # type: ignore
koder aka kdanilov70227062016-11-26 23:23:21 +020071
koder aka kdanilov108ac362017-01-19 20:17:16 +020072 nid = node.node_id
koder aka kdanilov39e449e2016-12-17 15:15:26 +020073 if node_cfg:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020074 # ceph requires additional settings
75 if 'ceph' in node_cfg:
76 node_cfg['ceph'].update(node.info.params['ceph'])
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +030077 node_cfg['ceph']['osds'] = [osd['id'] for osd in node.info.params['ceph-osds']] # type: ignore
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020078
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030079 logger.debug("Setting up sensors RPC plugin for node %s", nid)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020080 node.upload_plugin("sensors", SENSORS_PLUGIN_CODE)
81 ctx.sensors_run_on.add(nid)
82 logger.debug("Start monitoring node %s", nid)
83 node.conn.sensors.start(node_cfg)
84 else:
85 logger.debug("Skip monitoring node %s, as no sensors selected", nid)
86
87
88def collect_sensors_data(ctx: TestRun, stop: bool = False):
koder aka kdanilova732a602017-02-01 20:29:56 +020089 rstorage = ResultStorage(ctx.storage)
kdanylov aka koder736e5c12017-05-07 17:27:14 +030090 total_sz = 0
91
92 logger.info("Start loading sensors")
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020093 for node in ctx.nodes:
koder aka kdanilov108ac362017-01-19 20:17:16 +020094 node_id = node.node_id
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020095 if node_id in ctx.sensors_run_on:
kdanylov aka koder736e5c12017-05-07 17:27:14 +030096 func = node.conn.sensors.stop if stop else node.conn.sensors.get_updates
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020097
kdanylov aka koder736e5c12017-05-07 17:27:14 +030098 # hack to calculate total transferred size
99 offset_map, compressed_blob, compressed_collected_at_b = func()
100 data_tpl = (offset_map, compressed_blob, compressed_collected_at_b)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200101
kdanylov aka koder736e5c12017-05-07 17:27:14 +0300102 total_sz += len(compressed_blob) + len(compressed_collected_at_b) + sum(map(len, offset_map)) + \
103 16 * len(offset_map)
kdanylov aka koder150b2192017-04-01 16:53:01 +0300104
kdanylov aka koder736e5c12017-05-07 17:27:14 +0300105 for path, value, is_array, units in sensors_rpc_plugin.unpack_rpc_updates(data_tpl):
koder aka kdanilova732a602017-02-01 20:29:56 +0200106 if path == 'collected_at':
kdanylov aka koder45183182017-04-30 23:55:40 +0300107 ds = DataSource(node_id=node_id, metric='collected_at', tag='csv')
kdanylov aka koder736e5c12017-05-07 17:27:14 +0300108 rstorage.append_sensor(numpy.array(value), ds, units)
koder aka kdanilova732a602017-02-01 20:29:56 +0200109 else:
110 sensor, dev, metric = path.split(".")
kdanylov aka koder45183182017-04-30 23:55:40 +0300111 ds = DataSource(node_id=node_id, metric=metric, dev=dev, sensor=sensor, tag='csv')
112 if is_array:
kdanylov aka koder45183182017-04-30 23:55:40 +0300113 rstorage.append_sensor(numpy.array(value), ds, units)
114 else:
115 if metric == 'historic':
116 rstorage.put_sensor_raw(bz2.compress(value), ds(tag='bin'))
117 else:
118 assert metric in ('perf_dump', 'historic_js')
119 rstorage.put_sensor_raw(value, ds(tag='js'))
kdanylov aka koder736e5c12017-05-07 17:27:14 +0300120 logger.info("Download %sB of sensors data", utils.b2ssize(total_sz))
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +0300121
koder aka kdanilov70227062016-11-26 23:23:21 +0200122
123
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200124class CollectSensorsStage(Stage):
125 priority = StepOrder.COLLECT_SENSORS
126 config_block = 'sensors'
koder aka kdanilov70227062016-11-26 23:23:21 +0200127
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200128 def run(self, ctx: TestRun) -> None:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200129 collect_sensors_data(ctx, True)
koder aka kdanilov70227062016-11-26 23:23:21 +0200130