2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
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", "")
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]
43 def cmciii_phase_get_item_and_key(container
, device
, var_type
):
46 itemname
.append(container
[1])
47 itemname
+= [ "Phase", container
[2].replace("Phase", "")\
48 .replace("L", "").strip() ]
49 itemname
= " ".join(itemname
)
51 key
= "_".join(container
[3:]).lower()
52 if key
== "power_apparent":
54 elif key
.endswith("_active"):
55 key
= key
.replace("_active", "")
57 key
= " ".join(container
[3:])
61 def parse_cmciii(info
):
76 dev_table
, var_table
= info
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(" ", "_")
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
, {
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:
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"):
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"):
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"):
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"):
146 itemname
, key
= cmciii_phase_get_item_and_key(container
, device
, var_type
)
151 if this_table
is None:
154 if var_type
in ["1", "7", "15", "20", "21", "90", "92", "93"]:
158 # neg. scale: "-X" => "/ X"
159 # pos. scale: "X" => "* X"
162 value
= float(value_int
) * (-1.0 / float(scale
))
164 value
= float(value_int
) * float(scale
)
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")), {
189 "_location_" : location
})
190 found_temp_in_out
= True
191 if found_temp_in_out
:
192 del parsed
["temp"][entry
]
197 # .--state---------------------------------------------------------------.
199 # | ___| |_ __ _| |_ ___ |
200 # | / __| __/ _` | __/ _ \ |
201 # | \__ \ || (_| | || __/ |
202 # | |___/\__\__,_|\__\___| |
204 # +----------------------------------------------------------------------+
206 # '----------------------------------------------------------------------'
209 def inventory_cmciii_state(parsed
):
210 for entry
in parsed
["state"]:
214 def check_cmciii_state(item
, params
, parsed
):
216 '1': (3, "not available"),
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"],
238 ".1.3.6.1.4.1.2606.7.4.1.2.1",
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",
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-------------------------------------------------------------.
262 # | ___ ___ _ __ ___ ___ _ __ ___ |
263 # | / __|/ _ \ '_ \/ __|/ _ \| '__/ __| |
264 # | \__ \ __/ | | \__ \ (_) | | \__ \ |
265 # | |___/\___|_| |_|___/\___/|_| |___/ |
267 # '----------------------------------------------------------------------'
270 def inventory_cmciii_sensor(parsed
):
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 # | |_| |____/|_| |_| \___|\__,_|_| |_| \___|_| |_|\__| |
302 # '----------------------------------------------------------------------'
305 def inventory_cmciii_psm_current(parsed
):
306 for entry
in parsed
.get("psm_current", {}):
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":
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 # | |_| |____/|_| |_| | .__/|_|\__,_|\__, |___/ |
343 # '----------------------------------------------------------------------'
346 def inventory_cmciii_psm_plugs(parsed
):
347 for entry
in parsed
.get("psm_plugs", {}):
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":
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------------------------------------------------------------------.
375 # '----------------------------------------------------------------------'
378 def inventory_cmciii_io(parsed
):
379 for entry
in parsed
.get("io", {}):
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":
399 infotext
+= ", Relay: %s" % relay
402 if state_readable
in ["OK", "Off"]:
404 elif state_readable
== "On":
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--------------------------------------------------------------.
422 # | __ _ ___ ___ ___ ___ ___ |
423 # | / _` |/ __/ __/ _ \/ __/ __| |
424 # | | (_| | (_| (_| __/\__ \__ \ |
425 # | \__,_|\___\___\___||___/___/ |
427 # '----------------------------------------------------------------------'
430 def inventory_cmciii_access(parsed
):
431 for entry
in parsed
.get("access", {}):
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":
442 elif state_readable
== "Open":
447 return state
, "%s: %s, Delay: %s, Sensitivity: %s" % \
448 (attrs
["DescName"], state_readable
, \
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---------------------------------------------------------.
462 # | | |_ ___ _ __ ___ _ __ ___ _ __ __ _| |_ _ _ _ __ ___ |
463 # | | __/ _ \ '_ ` _ \| '_ \ / _ \ '__/ _` | __| | | | '__/ _ \ |
464 # | | || __/ | | | | | |_) | __/ | | (_| | |_| |_| | | | __/ |
465 # | \__\___|_| |_| |_| .__/ \___|_| \__,_|\__|\__,_|_| \___| |
467 # '----------------------------------------------------------------------'
470 def inventory_cmciii_temp(parsed
):
471 for entry
in parsed
.get("temp", {}).iterkeys():
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(
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--------------------------------------------------------.
504 # | | |_ ___ _ __ ___ _ __ (_)_ __ / /__ _ _| |_ |
505 # | | __/ _ \ '_ ` _ \| '_ \ | | '_ \ / / _ \| | | | __| |
506 # | | || __/ | | | | | |_) | | | | | |/ / (_) | |_| | |_ |
507 # | \__\___|_| |_| |_| .__(_) |_|_| |_/_/ \___/ \__,_|\__| |
509 # '----------------------------------------------------------------------'
512 def inventory_cmciii_temp_in_out(parsed
):
513 for entry
in parsed
.get("temp_in_out", {}):
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---------------------------------------------------------.
535 # | / ___| / \ | \ | | ___ _ _ _ __ _ __ ___ _ __ | |_ |
536 # | | | / _ \ | \| | / __| | | | '__| '__/ _ \ '_ \| __| |
537 # | | |___ / ___ \| |\ | | (__| |_| | | | | | __/ | | | |_ |
538 # | \____/_/ \_\_| \_| \___|\__,_|_| |_| \___|_| |_|\__| |
540 # '----------------------------------------------------------------------'
543 def inventory_cmciii_can_current(parsed
):
544 for entry
in parsed
.get("can_current", {}):
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":
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------------------------------------------------------------.
576 # | | |__ _ _ _ __ ___ (_) __| (_) |_ _ _ |
577 # | | '_ \| | | | '_ ` _ \| |/ _` | | __| | | | |
578 # | | | | | |_| | | | | | | | (_| | | |_| |_| | |
579 # | |_| |_|\__,_|_| |_| |_|_|\__,_|_|\__|\__, | |
581 # '----------------------------------------------------------------------'
584 def inventory_cmciii_humidity(parsed
):
585 for entry
in parsed
.get("humidity", {}):
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":
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,
609 "includes": ["humidity.include"]
613 # .--phase---------------------------------------------------------------.
615 # | _ __ | |__ __ _ ___ ___ |
616 # | | '_ \| '_ \ / _` / __|/ _ \ |
617 # | | |_) | | | | (_| \__ \ __/ |
618 # | | .__/|_| |_|\__,_|___/\___| |
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"],