2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
10 # | Copyright Mathias Kettner 2016 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # <<<openhardwaremonitor:sep(44)>>>
28 # Index,Name,Parent,SensorType,Value
29 # 1,Available Memory,/ram,Data,3.009140
30 # 0,CPU Total,/intelcpu/0,Load,1.953125
31 # 0,Used Space,/hdd/0,Load,58.754211
32 # 4,CPU Core #4,/intelcpu/0,Load,0.000000
33 # 2,CPU Graphics,/intelcpu/0,Power,0.000000
34 # 2,CPU Core #2,/intelcpu/0,Load,6.250000
35 # 4,CPU Core #4,/intelcpu/0,Clock,3192.720947
36 # 0,Bus Speed,/intelcpu/0,Clock,99.772530
37 # 3,CPU DRAM,/intelcpu/0,Power,0.000000
38 # 3,CPU Core #3,/intelcpu/0,Load,0.000000
39 # 1,CPU Core #1,/intelcpu/0,Clock,3192.720947
40 # 3,CPU Core #3,/intelcpu/0,Clock,3192.720947
41 # 0,Memory,/ram,Load,24.763321
42 # 0,Used Memory,/ram,Data,0.990425
43 # 2,CPU Core #2,/intelcpu/0,Clock,3192.720947
44 # 0,CPU Package,/intelcpu/0,Power,0.000000
45 # 1,CPU Cores,/intelcpu/0,Power,0.000000
46 # 1,CPU Core #1,/intelcpu/0,Load,1.562500
48 # Newer agent data provide WMIStatus column
49 # Index,Name,Parent,SensorType,Value,WMIStatus
50 # 1,CPU Core #1,/intelcpu/0,Load,1.562500,OK/Timeout
52 # since the temperature sensors could be anything (cpu, gpu, hdd, psu) we need different
53 # default levels per item type
54 factory_settings
['openhardwaremonitor_temperature_default_levels'] = {
66 OpenhardwaremonitorTraits
= {
112 'factor': 1073741824.0
115 OpenhardwaremonitorSensor
= collections
.namedtuple("OpenhardwaremonitorSensor",
116 ("reading", "unit", "perf_var", "WMIstatus"))
119 def parse_openhardwaremonitor(info
):
122 if line
[0] == 'Index':
127 # Old agent output has no WMIStatus column
128 _index
, name
, parent
, sensor_type
, value
= line
131 _index
, name
, parent
, sensor_type
, value
, wmistatus
= line
135 full_name
= _create_openhardwaremonitor_full_name(parent
, name
)
136 traits
= OpenhardwaremonitorTraits
.get(sensor_type
, {})
137 parsed
.setdefault(sensor_type
, {}).setdefault(
139 OpenhardwaremonitorSensor(
140 float(value
) * traits
.get('factor', 1), traits
.get('unit', ''),
141 traits
.get('perf_var'), wmistatus
))
145 def _create_openhardwaremonitor_full_name(parent
, name
):
146 def dict_replace(input_
, replacements
):
147 pattern
= regex(r
'\b(' + '|'.join(replacements
.keys()) + r
')\b')
148 return pattern
.sub(lambda x
: replacements
[x
.group()], input_
)
150 parent
= dict_replace(parent
, {"intelcpu": "cpu", "amdcpu": "cpu", "genericcpu": "cpu"})
151 name
= dict_replace(name
, {"CPU ": "", "Temperature": ""})
152 return (parent
.replace("/", "") + " " + name
).strip()
155 def _openhardwaremonitor_worst_status(*args
):
157 return sorted(args
, key
=lambda x
: order
[x
], reverse
=True)[0]
160 def _openhardwaremonitor_expect_order(*args
):
161 arglist
= [x
for x
in args
if x
is not None]
162 sorted_by_val
= sorted(enumerate(arglist
), key
=lambda x
: x
[1])
163 return max([abs(x
[0] - x
[1][0]) for x
in enumerate(sorted_by_val
)])
166 def inventory_openhardwaremonitor(sensor_type
, parsed
):
167 return [(key
, {}) for key
in parsed
.get(sensor_type
, {}).keys()]
170 def check_openhardwaremonitor(sensor_type
, item
, params
, parsed
):
171 if item
in parsed
.get(sensor_type
, {}):
172 data
= parsed
[sensor_type
][item
]
173 _check_openhardwaremonitor_wmistatus(data
)
174 if 'lower' in params
:
175 status_lower
= _openhardwaremonitor_expect_order(params
['lower'][1], params
['lower'][0],
179 if 'upper' in params
:
180 status_upper
= _openhardwaremonitor_expect_order(data
.reading
, params
['upper'][0],
187 perfdata
= [(data
.perf_var
, data
.reading
)]
189 return (_openhardwaremonitor_worst_status(status_lower
, status_upper
),
190 '%.1f%s' % (data
.reading
, data
.unit
), perfdata
)
193 def _check_openhardwaremonitor_wmistatus(data
):
194 if data
.WMIstatus
.lower() == 'timeout':
195 raise MKCounterWrapped('WMI query timed out')
198 # .--clock---------------------------------------------------------------.
200 # | ___| | ___ ___| | __ |
201 # | / __| |/ _ \ / __| |/ / |
202 # | | (__| | (_) | (__| < |
203 # | \___|_|\___/ \___|_|\_\ |
205 # '----------------------------------------------------------------------'
207 check_info
['openhardwaremonitor'] = {
208 'inventory_function': lambda parsed
: inventory_openhardwaremonitor('Clock', parsed
),
209 'check_function': lambda item
, params
, parsed
: check_openhardwaremonitor(
210 'Clock', item
, params
, parsed
),
211 'parse_function': parse_openhardwaremonitor
,
212 'has_perfdata': True,
213 'service_description': "Clock %s",
217 # .--temp----------------------------------------------------------------.
219 # | | |_ ___ _ __ ___ _ __ |
220 # | | __/ _ \ '_ ` _ \| '_ \ |
221 # | | || __/ | | | | | |_) | |
222 # | \__\___|_| |_| |_| .__/ |
224 # '----------------------------------------------------------------------'
227 def check_openhardwaremonitor_temperature(item
, params
, parsed
):
228 if not 'levels' in params
:
230 for key
in params
.iterkeys():
236 params
= params
["_default"]
238 if item
in parsed
.get('Temperature', {}):
239 data
= parsed
['Temperature'][item
]
240 _check_openhardwaremonitor_wmistatus(data
)
241 return check_temperature(data
.reading
, params
, "openhardwaremonitor_%s" % item
)
244 check_info
['openhardwaremonitor.temperature'] = {
245 'inventory_function': lambda parsed
: inventory_openhardwaremonitor('Temperature', parsed
),
246 'check_function': check_openhardwaremonitor_temperature
,
247 'has_perfdata': True,
248 'service_description': "Temperature %s",
249 'group': 'temperature',
250 'default_levels_variable': 'openhardwaremonitor_temperature_default_levels',
251 'includes': ['temperature.include']
255 # .--power---------------------------------------------------------------.
257 # | _ __ _____ _____ _ __ |
258 # | | '_ \ / _ \ \ /\ / / _ \ '__| |
259 # | | |_) | (_) \ V V / __/ | |
260 # | | .__/ \___/ \_/\_/ \___|_| |
262 # '----------------------------------------------------------------------'
264 check_info
['openhardwaremonitor.power'] = {
265 'inventory_function': lambda parsed
: inventory_openhardwaremonitor('Power', parsed
),
266 'check_function': lambda item
, params
, parsed
: check_openhardwaremonitor(
267 'Power', item
, params
, parsed
),
268 'has_perfdata': True,
269 'service_description': "Power %s",
273 # .--fan-----------------------------------------------------------------.
276 # | | |_ / _` | '_ \ |
277 # | | _| (_| | | | | |
278 # | |_| \__,_|_| |_| |
280 # '----------------------------------------------------------------------'
282 factory_settings
['openhardwaremonitor_fan_default_levels'] = {
283 'lower': (None, None),
284 'upper': (None, None),
288 def check_openhardwaremonitor_fan(item
, params
, parsed
):
289 if item
in parsed
.get("Fan", {}):
290 data
= parsed
["Fan"][item
]
291 _check_openhardwaremonitor_wmistatus(data
)
292 return check_fan(data
.reading
, params
)
295 check_info
['openhardwaremonitor.fan'] = {
296 'inventory_function': lambda parsed
: inventory_openhardwaremonitor('Fan', parsed
),
297 'check_function': check_openhardwaremonitor_fan
,
298 'has_perfdata': True,
299 'service_description': "Fan %s",
300 'default_levels_variable': 'openhardwaremonitor_fan_default_levels',
302 'includes': ['fan.include'],
306 # .--smart---------------------------------------------------------------.
308 # | ___ _ __ ___ __ _ _ __| |_ |
309 # | / __| '_ ` _ \ / _` | '__| __| |
310 # | \__ \ | | | | | (_| | | | |_ |
311 # | |___/_| |_| |_|\__,_|_| \__| |
313 # '----------------------------------------------------------------------'
315 openhardwaremonitor_smart_readings
= {
317 'name': "Remaining Life",
318 'key': 'remaining_life',
323 factory_settings
['openhardwaremonitor_smart_default_levels'] = {
324 'remaining_life': (30, 10), # wild guess
328 def inventory_openhardwaremonitor_smart(parsed
):
330 # find all devices for which at least one known smart reading is available
331 for sensor_type
in openhardwaremonitor_smart_readings
:
332 for key
in parsed
.get(sensor_type
, {}):
334 devices
.add(key
.split(" ")[0])
335 return [(dev
, {}) for dev
in devices
]
338 def check_openhardwaremonitor_smart(item
, params
, parsed
):
339 for sensor_type
, readings
in openhardwaremonitor_smart_readings
.iteritems():
340 for reading
in readings
:
341 reading_name
= "%s %s" % (item
, reading
['name'])
343 if not reading_name
in parsed
[sensor_type
]:
344 # what smart values ohm reports is device dependent
347 warn
, crit
= params
[reading
['key']]
348 data
= parsed
[sensor_type
][reading_name
]
349 _check_openhardwaremonitor_wmistatus(data
)
351 if reading
.get('lower_bounds', False):
352 status
= _openhardwaremonitor_expect_order(crit
, warn
, data
.reading
)
354 status
= _openhardwaremonitor_expect_order(data
.reading
, warn
, crit
)
358 "%s %.1f%s" % (reading
['name'], data
.reading
, data
.unit
),
359 [(reading
['key'], data
.reading
)],
363 # the smart check is different from the others as it has one item per device and
364 # combines different sensors per item (but not all, i.e. hdd temperature is still
365 # reported as a temperature item)
366 check_info
['openhardwaremonitor.smart'] = {
367 'inventory_function': inventory_openhardwaremonitor_smart
,
368 'check_function': check_openhardwaremonitor_smart
,
369 'has_perfdata': True,
370 'service_description': "SMART %s Stats",
371 'default_levels_variable': "openhardwaremonitor_smart_default_levels",
372 'group': "openhardwaremonitor_smart"