blob: 9fb2177bfaa5a468eb73a15f4b8a3cf3666d48eb [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
kdanylov aka koderb0833332017-05-13 20:39:17 +03009from cephlib.units import b2ssize
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +030010
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020011from . import utils
koder aka kdanilov70227062016-11-26 23:23:21 +020012from .test_run_class import TestRun
koder aka kdanilova732a602017-02-01 20:29:56 +020013from .result_classes import DataSource
koder aka kdanilov39e449e2016-12-17 15:15:26 +020014from .stage import Stage, StepOrder
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):
kdanylov aka koder736e5c12017-05-07 17:27:14 +030089 total_sz = 0
90
91 logger.info("Start loading sensors")
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020092 for node in ctx.nodes:
koder aka kdanilov108ac362017-01-19 20:17:16 +020093 node_id = node.node_id
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020094 if node_id in ctx.sensors_run_on:
kdanylov aka koder736e5c12017-05-07 17:27:14 +030095 func = node.conn.sensors.stop if stop else node.conn.sensors.get_updates
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020096
kdanylov aka koder736e5c12017-05-07 17:27:14 +030097 # hack to calculate total transferred size
98 offset_map, compressed_blob, compressed_collected_at_b = func()
99 data_tpl = (offset_map, compressed_blob, compressed_collected_at_b)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200100
kdanylov aka koder736e5c12017-05-07 17:27:14 +0300101 total_sz += len(compressed_blob) + len(compressed_collected_at_b) + sum(map(len, offset_map)) + \
102 16 * len(offset_map)
kdanylov aka koder150b2192017-04-01 16:53:01 +0300103
kdanylov aka koder736e5c12017-05-07 17:27:14 +0300104 for path, value, is_array, units in sensors_rpc_plugin.unpack_rpc_updates(data_tpl):
koder aka kdanilova732a602017-02-01 20:29:56 +0200105 if path == 'collected_at':
kdanylov aka koder45183182017-04-30 23:55:40 +0300106 ds = DataSource(node_id=node_id, metric='collected_at', tag='csv')
kdanylov aka koderb0833332017-05-13 20:39:17 +0300107 ctx.rstorage.append_sensor(numpy.array(value), ds, units)
koder aka kdanilova732a602017-02-01 20:29:56 +0200108 else:
109 sensor, dev, metric = path.split(".")
kdanylov aka koder45183182017-04-30 23:55:40 +0300110 ds = DataSource(node_id=node_id, metric=metric, dev=dev, sensor=sensor, tag='csv')
111 if is_array:
kdanylov aka koderb0833332017-05-13 20:39:17 +0300112 ctx.rstorage.append_sensor(numpy.array(value), ds, units)
kdanylov aka koder45183182017-04-30 23:55:40 +0300113 else:
114 if metric == 'historic':
kdanylov aka koderb0833332017-05-13 20:39:17 +0300115 ctx.rstorage.put_sensor_raw(bz2.compress(value), ds(tag='bin'))
kdanylov aka koder45183182017-04-30 23:55:40 +0300116 else:
117 assert metric in ('perf_dump', 'historic_js')
kdanylov aka koderb0833332017-05-13 20:39:17 +0300118 ctx.rstorage.put_sensor_raw(value, ds(tag='js'))
119 logger.info("Download %sB of sensors data", b2ssize(total_sz))
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +0300120
koder aka kdanilov70227062016-11-26 23:23:21 +0200121
122
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200123class CollectSensorsStage(Stage):
124 priority = StepOrder.COLLECT_SENSORS
125 config_block = 'sensors'
koder aka kdanilov70227062016-11-26 23:23:21 +0200126
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200127 def run(self, ctx: TestRun) -> None:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200128 collect_sensors_data(ctx, True)
koder aka kdanilov70227062016-11-26 23:23:21 +0200129