Refactoring: Moved check parameters from unsorted.py to dedicated modules (CMK-1393)
[check_mk.git] / checks / cmciii
bloba9557807931f46abd18921b01b93fe604d5a8269
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 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 # In order to stay compatible we have to build the items
28 # this complicated way :(
31 def cmciii_temp_get_item(container, device):
32 device = device.replace("Liquid_Cooling_Package", "LCP")
33 itemname = container[1].replace("Temperature", "")
34 if itemname == "":
35 itemname = "Ambient"
36 if device is not None:
37 itemname += " %s" % device
38 if container[-1].startswith("In-") or container[-1].startswith("Out-"):
39 itemname += " %s" % container[-1].split("-")[0]
40 return itemname
43 def cmciii_phase_get_item_and_key(container, device, var_type):
44 itemname = [device]
45 if container[1]:
46 itemname.append(container[1])
47 itemname += [ "Phase", container[2].replace("Phase", "")\
48 .replace("L", "").strip() ]
49 itemname = " ".join(itemname)
50 if var_type == "2":
51 key = "_".join(container[3:]).lower()
52 if key == "power_apparent":
53 key = "appower"
54 elif key.endswith("_active"):
55 key = key.replace("_active", "")
56 else:
57 key = " ".join(container[3:])
58 return itemname, key
61 def parse_cmciii(info):
62 devices = {}
63 parsed = {
64 "state": {},
65 "psm_current": {},
66 "psm_plugs": {},
67 "io": {},
68 "access": {},
69 "temp": {},
70 "temp_in_out": {},
71 "can_current": {},
72 "humidity": {},
73 "phase": {},
76 dev_table, var_table = info
78 num = 0
79 for endoid, name, alias, status in dev_table:
80 # no blanks in names since we use blanks in items
81 # later to split between unit_name and item_name
82 dev_name = alias.replace(" ", "_")
83 num += 1
84 if not dev_name:
85 dev_name = name + "-" + str(num)
87 if dev_name in parsed["state"]:
88 dev_name = "%s %s" % (alias, endoid)
90 devices.setdefault(endoid, dev_name)
92 if dev_name in parsed["state"] and \
93 parsed["state"][dev_name]["_location_"] != endoid:
94 dev_name += " %s" % endoid
96 parsed["state"].setdefault(dev_name, {
97 "status": status,
98 "_location_": endoid,
101 for oidend, variable, var_type, var_unit, scale, value_str, value_int in var_table:
102 location, _index = oidend.split(".")
103 variable_splitted = variable.split(".")
104 device = devices.get(location)
105 container = [location] + variable_splitted[:-1]
106 if len(container) == 2:
107 container += [""]
109 key = variable_splitted[-1]
110 if container[1].startswith("PSM_") and "Unit" in container:
111 this_table = "psm_current"
112 itemname = "%s %s" % (device, container[1])
114 elif container[1].startswith("PSM_") and container[2].startswith("Plug"):
115 this_table = "psm_plugs"
116 itemname = "%s %s" % (device, ".".join(container[1:]))
118 elif container[1].startswith("Input") or container[1].startswith("Output"):
119 this_table = "io"
120 itemname = "%s %s" % (device, container[1])
122 elif "Access" in container:
123 this_table = "access"
124 itemname = "%s %s" % (device, container[1])
126 elif "Humidity" in container:
127 this_table = "humidity"
128 itemname = "%s %s" % (device, container[1])
130 elif "Temperature" in container or "Dew Point" in container or \
131 container[2].endswith("Temperature"):
132 this_table = "temp"
133 itemname = cmciii_temp_get_item(container, device)
135 elif container[2].startswith("CAN") and container[2].endswith("Current"):
136 this_table = "can_current"
137 itemname = "%s %s" % (device, ".".join(container[1:]))
139 elif container[1].startswith("Phase"):
140 this_table = "phase"
141 container = [container[0], ""] + container[1:]
142 itemname, key = cmciii_phase_get_item_and_key(container, device, var_type)
144 elif container[2].startswith("Phase"):
145 this_table = "phase"
146 itemname, key = cmciii_phase_get_item_and_key(container, device, var_type)
148 else:
149 this_table = None
151 if this_table is None:
152 continue
154 if var_type in ["1", "7", "15", "20", "21", "90", "92", "93"]:
155 value = value_str
157 else:
158 # neg. scale: "-X" => "/ X"
159 # pos. scale: "X" => "* X"
160 # else: => "* 1"
161 if int(scale) < 0:
162 value = float(value_int) * (-1.0 / float(scale))
163 elif int(scale) > 0:
164 value = float(value_int) * float(scale)
165 else:
166 value = int(value_int)
168 if "Power" in container or "Energy" in container:
169 if var_unit == "kW" or var_unit == "KWh" or var_unit == "kVA":
170 value = value * 1000 # Convert from kW, kWh, kVA to W, Wh, VA
172 if itemname in parsed[this_table] and \
173 parsed[this_table][itemname]["_location_"] != location:
174 itemname += " %s" % location
176 parsed[this_table].setdefault(itemname, {"_device_": device, "_location_": location})
177 parsed[this_table][itemname].setdefault(key, value)
179 for entry, attrs in parsed.get("temp", {}).items():
180 found_temp_in_out = False
181 for attr, val in attrs.items():
182 if attr.startswith("In-") or attr.startswith("Out-"):
183 parsed["temp_in_out"].setdefault("%s %s" % \
184 (entry, attr.replace("-", " ")\
185 .replace("Bot", "Bottom")\
186 .replace("Mid", "Middle")), {
187 "Value" : val,
188 "_device_" : device,
189 "_location_" : location})
190 found_temp_in_out = True
191 if found_temp_in_out:
192 del parsed["temp"][entry]
194 return parsed
197 # .--state---------------------------------------------------------------.
198 # | _ _ |
199 # | ___| |_ __ _| |_ ___ |
200 # | / __| __/ _` | __/ _ \ |
201 # | \__ \ || (_| | || __/ |
202 # | |___/\__\__,_|\__\___| |
203 # | |
204 # +----------------------------------------------------------------------+
205 # | main check |
206 # '----------------------------------------------------------------------'
209 def inventory_cmciii_state(parsed):
210 for entry in parsed["state"]:
211 yield entry, None
214 def check_cmciii_state(item, params, parsed):
215 map_states = {
216 '1': (3, "not available"),
217 '2': (0, "OK"),
218 '3': (1, "detect"),
219 '4': (2, "lost"),
220 '5': (1, "changed"),
221 '6': (2, "error"),
224 if item in parsed["state"]:
225 state, state_readable = map_states[parsed["state"][item]["status"]]
226 return state, "Status: %s" % state_readable
229 check_info['cmciii'] = {
230 "parse_function": parse_cmciii,
231 "inventory_function": inventory_cmciii_state,
232 "check_function": check_cmciii_state,
233 "service_description": "State %s",
234 "snmp_scan_function": lambda oid: ".1.3.6.1.4.1.2606.7" in oid(".1.3.6.1.2.1.1.2.0"),
235 "includes": ["cmciii.include"],
236 "snmp_info": [
238 ".1.3.6.1.4.1.2606.7.4.1.2.1",
240 OID_END,
241 "2", # RITTAL-CMC-III-MIB::cmcIIIDevName
242 "3", # RITTAL-CMC-III-MIB::cmcIIIDevAlias
243 "6", # RITTAL-CMC-III-MIB::cmcIIIDevStatus
246 ".1.3.6.1.4.1.2606.7.4.2.2.1",
248 OID_END,
249 "3", # RITTAL-CMC-III-MIB::cmcIIIVarName
250 "4", # RITTAL-CMC-III-MIB::cmcIIIVarType
251 "5", # RITTAL-CMC-III-MIB::cmcIIIVarUnit
252 "7", # RITTAL-CMC-III-MIB::cmcIIIVarScale
253 "10", # RITTAL-CMC-III-MIB::cmcIIIVarValueStr
254 "11", # RITTAL-CMC-III-MIB::cmcIIIVarValueInt
260 # .--sensors-------------------------------------------------------------.
261 # | |
262 # | ___ ___ _ __ ___ ___ _ __ ___ |
263 # | / __|/ _ \ '_ \/ __|/ _ \| '__/ __| |
264 # | \__ \ __/ | | \__ \ (_) | | \__ \ |
265 # | |___/\___|_| |_|___/\___/|_| |___/ |
266 # | |
267 # '----------------------------------------------------------------------'
270 def inventory_cmciii_sensor(parsed):
271 return []
274 def check_cmciii_sensor(item, params, parsed):
275 # Older check plugin versions worked as follows:
276 # We've generated items out of device table for the service
277 # cmciii and if device name starts with "CMCIII-SEN", we added
278 # an additional service cmciii.sensor. Then we connected these
279 # names with data from the first variables table (by OID) and took
280 # the status from there. We got:
281 # 1 service cmciii: 'State Zugang_Rack_1_LCP_1_hinten' (OK)
282 # 1 service cmciii.sensor: 'Zugang_Rack_1_LCP_1_hinten Sensor' (Open)
283 # But device table sends already its status, thus we had one service
284 # overmuch (with different readable status).
285 return 1, "This check is deprecated. Please rediscover the services of that host."
288 check_info['cmciii.sensor'] = {
289 "inventory_function": inventory_cmciii_sensor,
290 "check_function": check_cmciii_sensor,
291 "service_description": "%s",
295 # .--PSM current---------------------------------------------------------.
296 # | ____ ____ __ __ _ |
297 # | | _ \/ ___|| \/ | ___ _ _ _ __ _ __ ___ _ __ | |_ |
298 # | | |_) \___ \| |\/| | / __| | | | '__| '__/ _ \ '_ \| __| |
299 # | | __/ ___) | | | | | (__| |_| | | | | | __/ | | | |_ |
300 # | |_| |____/|_| |_| \___|\__,_|_| |_| \___|_| |_|\__| |
301 # | |
302 # '----------------------------------------------------------------------'
305 def inventory_cmciii_psm_current(parsed):
306 for entry in parsed.get("psm_current", {}):
307 yield entry, {}
310 def check_cmciii_psm_current(item, params, parsed):
311 if item in parsed.get("psm_current", {}):
312 attrs = parsed["psm_current"][item]
313 current = attrs["Value"]
314 min_current = attrs["SetPtHighAlarm"]
315 max_current = attrs["SetPtLowAlarm"]
317 if attrs["Status"] == "OK":
318 state = 0
319 else:
320 state = 2
322 return state, "Current: %s (%s/%s), Type: %s, Serial: %s, Position: %s" % \
323 (current, min_current, max_current, attrs["Unit Type"], \
324 attrs["Serial Number"], attrs["Mounting Position"]), \
325 [( "current", current, 0, 0, min_current, max_current)]
328 check_info['cmciii.psm_current'] = {
329 "inventory_function": inventory_cmciii_psm_current,
330 "check_function": check_cmciii_psm_current,
331 "service_description": "Current %s",
332 "has_perfdata": True,
336 # .--PSM plugs-----------------------------------------------------------.
337 # | ____ ____ __ __ _ |
338 # | | _ \/ ___|| \/ | _ __ | |_ _ __ _ ___ |
339 # | | |_) \___ \| |\/| | | '_ \| | | | |/ _` / __| |
340 # | | __/ ___) | | | | | |_) | | |_| | (_| \__ \ |
341 # | |_| |____/|_| |_| | .__/|_|\__,_|\__, |___/ |
342 # | |_| |___/ |
343 # '----------------------------------------------------------------------'
346 def inventory_cmciii_psm_plugs(parsed):
347 for entry in parsed.get("psm_plugs", {}):
348 yield entry, {}
351 def check_cmciii_psm_plugs(item, params, parsed):
352 if item in parsed.get("psm_plugs", {}):
353 state_readable = parsed["psm_plugs"][item]["Status"]
354 if state_readable == "OK":
355 state = 0
356 else:
357 state = 2
358 return state, "Status: %s" % state_readable
361 check_info['cmciii.psm_plugs'] = {
362 "inventory_function": inventory_cmciii_psm_plugs,
363 "check_function": check_cmciii_psm_plugs,
364 "service_description": "%s",
368 # .--IO------------------------------------------------------------------.
369 # | ___ ___ |
370 # | |_ _/ _ \ |
371 # | | | | | | |
372 # | | | |_| | |
373 # | |___\___/ |
374 # | |
375 # '----------------------------------------------------------------------'
378 def inventory_cmciii_io(parsed):
379 for entry in parsed.get("io", {}):
380 yield entry, {}
383 def check_cmciii_io(item, params, parsed):
384 if item in parsed.get("io", {}):
385 attrs = parsed["io"][item]
386 state_readable = attrs["Status"]
387 relay = attrs.get("Relay")
388 logic = attrs.get("Logic")
389 infotext = "Status: %s" % state_readable
391 if logic is not None:
392 infotext += ", Logic: %s" % attrs["Logic"]
394 if relay is not None:
395 if state_readable == "OK":
396 state = 0
397 else:
398 state = 2
399 infotext += ", Relay: %s" % relay
401 else: # input relay
402 if state_readable in ["OK", "Off"]:
403 state = 0
404 elif state_readable == "On":
405 state = 1
406 else:
407 state = 2
408 infotext += ", Delay %s" % attrs.get("Delay")
410 return state, infotext
413 check_info['cmciii.io'] = {
414 "inventory_function": inventory_cmciii_io,
415 "check_function": check_cmciii_io,
416 "service_description": "%s",
420 # .--access--------------------------------------------------------------.
421 # | |
422 # | __ _ ___ ___ ___ ___ ___ |
423 # | / _` |/ __/ __/ _ \/ __/ __| |
424 # | | (_| | (_| (_| __/\__ \__ \ |
425 # | \__,_|\___\___\___||___/___/ |
426 # | |
427 # '----------------------------------------------------------------------'
430 def inventory_cmciii_access(parsed):
431 for entry in parsed.get("access", {}):
432 yield entry, None
435 def check_cmciii_access(item, params, parsed):
436 if item in parsed.get("access", {}):
437 attrs = parsed["access"][item]
438 state_readable = attrs["Status"]
440 if state_readable == "Closed":
441 state = 0
442 elif state_readable == "Open":
443 state = 1
444 else:
445 state = 2
447 return state, "%s: %s, Delay: %s, Sensitivity: %s" % \
448 (attrs["DescName"], state_readable, \
449 attrs["Delay"], \
450 attrs["Sensitivity"])
453 check_info['cmciii.access'] = {
454 "inventory_function": inventory_cmciii_access,
455 "check_function": check_cmciii_access,
456 "service_description": "%s",
460 # .--temperature---------------------------------------------------------.
461 # | _ _ |
462 # | | |_ ___ _ __ ___ _ __ ___ _ __ __ _| |_ _ _ _ __ ___ |
463 # | | __/ _ \ '_ ` _ \| '_ \ / _ \ '__/ _` | __| | | | '__/ _ \ |
464 # | | || __/ | | | | | |_) | __/ | | (_| | |_| |_| | | | __/ |
465 # | \__\___|_| |_| |_| .__/ \___|_| \__,_|\__|\__,_|_| \___| |
466 # | |_| |
467 # '----------------------------------------------------------------------'
470 def inventory_cmciii_temp(parsed):
471 for entry in parsed.get("temp", {}).iterkeys():
472 yield entry, {}
475 def check_cmciii_temp(item, params, parsed):
476 if item in parsed.get("temp", {}):
477 attrs = parsed["temp"][item]
478 state, infotext, perfdata = check_temperature(
479 attrs["Value"],
480 params,
481 "cmciii.temp.%s" % item,
482 dev_levels=(attrs.get("SetPtHighWarning"), attrs.get("SetPtHighAlarm")),
483 dev_levels_lower=(attrs.get("SetPtLowWarning"), attrs.get("SetPtLowAlarm")),
484 dev_status_name=attrs.get("Status"))
486 descr = attrs.get("DescName", "").replace("Temperature", "")
487 if descr and descr not in item:
488 infotext = "[%s] %s" % (descr, infotext)
489 return state, infotext, perfdata
492 check_info['cmciii.temp'] = {
493 "inventory_function": inventory_cmciii_temp,
494 "check_function": check_cmciii_temp,
495 "service_description": "Temperature %s",
496 "has_perfdata": True,
497 "group": "temperature",
498 "includes": ["temperature.include"]
502 # .--temp. in/out--------------------------------------------------------.
503 # | _ _ __ _ |
504 # | | |_ ___ _ __ ___ _ __ (_)_ __ / /__ _ _| |_ |
505 # | | __/ _ \ '_ ` _ \| '_ \ | | '_ \ / / _ \| | | | __| |
506 # | | || __/ | | | | | |_) | | | | | |/ / (_) | |_| | |_ |
507 # | \__\___|_| |_| |_| .__(_) |_|_| |_/_/ \___/ \__,_|\__| |
508 # | |_| |
509 # '----------------------------------------------------------------------'
512 def inventory_cmciii_temp_in_out(parsed):
513 for entry in parsed.get("temp_in_out", {}):
514 yield entry, {}
517 def check_cmciii_temp_in_out(item, params, parsed):
518 if item in parsed.get("temp_in_out", {}):
519 attrs = parsed["temp_in_out"][item]
520 return check_temperature(attrs["Value"], params, "cmciii.temp_in_out.%s" % item)
523 check_info['cmciii.temp_in_out'] = {
524 "inventory_function": inventory_cmciii_temp_in_out,
525 "check_function": check_cmciii_temp_in_out,
526 "service_description": "Temperature %s",
527 "has_perfdata": True,
528 "group": "temperature",
529 "includes": ["temperature.include"]
533 # .--CAN current---------------------------------------------------------.
534 # | ____ _ _ _ _ |
535 # | / ___| / \ | \ | | ___ _ _ _ __ _ __ ___ _ __ | |_ |
536 # | | | / _ \ | \| | / __| | | | '__| '__/ _ \ '_ \| __| |
537 # | | |___ / ___ \| |\ | | (__| |_| | | | | | __/ | | | |_ |
538 # | \____/_/ \_\_| \_| \___|\__,_|_| |_| \___|_| |_|\__| |
539 # | |
540 # '----------------------------------------------------------------------'
543 def inventory_cmciii_can_current(parsed):
544 for entry in parsed.get("can_current", {}):
545 yield entry, None
548 def check_cmciii_can_current(item, params, parsed):
549 if item in parsed.get("can_current", {}):
550 attrs = parsed["can_current"][item]
551 state_readable = attrs["Status"]
552 value = attrs["Value"]
553 warn = attrs["SetPtHighWarning"]
554 crit = attrs["SetPtHighAlarm"]
556 if state_readable == "OK":
557 state = 0
558 else:
559 state = 2
561 return state, "Status: %s, Current: %s mA (warn/crit at %s/%s mA)" % \
562 (state_readable, value, warn, crit), \
563 [("current", value / 1000, warn, crit )]
566 check_info['cmciii.can_current'] = {
567 "inventory_function": inventory_cmciii_can_current,
568 "check_function": check_cmciii_can_current,
569 "service_description": "%s",
570 "has_perfdata": True,
574 # .--humidity------------------------------------------------------------.
575 # | _ _ _ _ _ |
576 # | | |__ _ _ _ __ ___ (_) __| (_) |_ _ _ |
577 # | | '_ \| | | | '_ ` _ \| |/ _` | | __| | | | |
578 # | | | | | |_| | | | | | | | (_| | | |_| |_| | |
579 # | |_| |_|\__,_|_| |_| |_|_|\__,_|_|\__|\__, | |
580 # | |___/ |
581 # '----------------------------------------------------------------------'
584 def inventory_cmciii_humidity(parsed):
585 for entry in parsed.get("humidity", {}):
586 yield entry, {}
589 def check_cmciii_humidity(item, params, parsed):
590 if item in parsed.get("humidity", {}):
591 attrs = parsed["humidity"][item]
592 state_readable = attrs["Status"]
594 if state_readable == "OK":
595 state = 0
596 else:
597 state = 2
599 yield state, "Status: %s" % state_readable
600 yield check_humidity(attrs["Value"], params)
603 check_info['cmciii.humidity'] = {
604 "inventory_function": inventory_cmciii_humidity,
605 "check_function": check_cmciii_humidity,
606 "service_description": "%s",
607 "has_perfdata": True,
608 "group": "humidity",
609 "includes": ["humidity.include"]
613 # .--phase---------------------------------------------------------------.
614 # | _ |
615 # | _ __ | |__ __ _ ___ ___ |
616 # | | '_ \| '_ \ / _` / __|/ _ \ |
617 # | | |_) | | | | (_| \__ \ __/ |
618 # | | .__/|_| |_|\__,_|___/\___| |
619 # | |_| |
620 # '----------------------------------------------------------------------'
623 def inventory_cmciii_phase(parsed):
624 return inventory_elphase(parsed.get("phase", {}))
627 def check_cmciii_phase(item, params, parsed):
628 return check_elphase(item, params, parsed.get("phase", {}))
631 check_info['cmciii.phase'] = {
632 "inventory_function": inventory_cmciii_phase,
633 "check_function": check_cmciii_phase,
634 "service_description": "Input %s",
635 "has_perfdata": True,
636 "group": "el_inphase",
637 "includes": ["elphase.include"],