diff --git a/check_mk-avocent/cmk20-cmk21/Avocent-1.1.mkp b/check_mk-avocent/cmk20-cmk21/Avocent-1.1.mkp new file mode 100644 index 0000000..5901d30 Binary files /dev/null and b/check_mk-avocent/cmk20-cmk21/Avocent-1.1.mkp differ diff --git a/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/avocent_psu.py b/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/avocent_psu.py new file mode 100644 index 0000000..6f89c6b --- /dev/null +++ b/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/avocent_psu.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. +from typing import List +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + register, + Result, + Service, + SNMPTree, + startswith, + State, +) +from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( + CheckResult, + DiscoveryResult, + StringTable, +) + +Section = [] +def parse_avocent_psu(string_table: List[StringTable]) -> Section: + return string_table[0][0] + + +register.snmp_section( + name="avocent_psu", + detect=startswith(".1.3.6.1.2.1.1.1.0", "Avocent"), + parse_function=parse_avocent_psu, + fetch=[ + SNMPTree( + base=".1.3.6.1.4.1.10418.26.2.1.8", + oids=[ + "1", #Number of PSU installed + "2", #PowerSupply1 state + "3", #PowerSupply2 state + ], + ), + ], +) + +def discovery_avocent_psu(section: Section) -> DiscoveryResult: + yield Service() + + +def _power_supply_status_descr(status_nr: str) -> str: + return { + "1": "Powered On", + "2": "Powered Off", + "9999": "Power Supply is not installed", + }.get(status_nr, status_nr) + +def _power_supply_state(status_nr: str) -> State: + return { + "1": State.OK, + "2": State.CRIT, + "9999": State.OK + }.get(status_nr, State.UNKNOWN) + + + +def check_avocent_psu( + section: Section, +) -> CheckResult: + number_of_psu=section[0] + state_psu_1=section[1] + state_psu_2=section[2] + + yield Result( + state=State.OK, + summary="Number of PSU installed: %s" % number_of_psu, + ) + + yield Result( + state=_power_supply_state(state_psu_1), + summary="Power Supply 1 is %s" % _power_supply_status_descr(state_psu_1), + ) + + yield Result( + state=_power_supply_state(state_psu_2), + summary="Power Supply 2 is %s" % _power_supply_status_descr(state_psu_2), + ) + + +register.check_plugin( + name="avocent_psu", + sections=["avocent_psu"], + service_name="Power Supplies", + discovery_function=discovery_avocent_psu, + check_function=check_avocent_psu +) + diff --git a/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/avocent_sensors.py b/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/avocent_sensors.py new file mode 100644 index 0000000..4525f42 --- /dev/null +++ b/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/avocent_sensors.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +import dataclasses +from typing import Mapping + +from .agent_based_api.v1 import ( + contains, + get_value_store, + Metric, + register, + Result, + Service, + SNMPTree, + State, + startswith +) +from .agent_based_api.v1.type_defs import CheckResult, DiscoveryResult, StringTable +from .utils.temperature import check_temperature, TempParamType + +@dataclasses.dataclass(frozen=True) +class Sensor: + value: float + + +@dataclasses.dataclass(frozen=True) +class VoltageSensor(Sensor): + ... + + +@dataclasses.dataclass(frozen=True) +class Section: + temperature_sensors: Mapping[str, Sensor] + voltage_sensors: Mapping[str, Sensor] + +temperature_sensors_name = ['CPU','Board'] +voltage_sensors_name = ['PSU 1','PSU 2'] + +def parse_avocent_sensors(string_table: StringTable) -> Section: + temperature_sensors = {} + voltage_sensors = {} + position = 0 + for temp_sens_name in temperature_sensors_name: + temperature_sensors[temp_sens_name] = Sensor(value=int(string_table[0][position])) + position +=1 + + pos = 2 + for volt_sens_name in voltage_sensors_name: + voltage_sensors[volt_sens_name] = Sensor(value=float(string_table[0][pos])/100) + pos += 1 + + return Section( + temperature_sensors=temperature_sensors, + voltage_sensors=voltage_sensors, + ) + +register.snmp_section( + name="avocent_sensors", + detect=startswith(".1.3.6.1.2.1.1.1.0", "Avocent"), + parse_function=parse_avocent_sensors, + fetch=SNMPTree( + base=".1.3.6.1.4.1.10418.26.2.7", + oids=[ + "1", #acsSensorsInternalCurrentCPUTemperature + "6", #acsSensorsInternalCurrentBoardTemperature + "17", #acsSensorsVoltagePowerSupply1 + "18", #acsSensorsVoltagePowerSupply2 + ], + ), +) + + + +def discover_avocent_voltage_sensors(section: Section) -> DiscoveryResult: + yield from (Service(item=sensor_name) for sensor_name in section.voltage_sensors) + + +def check_avocent_voltage_sensors( + item: str, + section: Section, +) -> CheckResult: + if not (sensor := section.voltage_sensors.get(item)): + return + + yield Result( + state=State.OK, + summary=f"{sensor.value:.1f} V", + ) + + yield Metric( + name="voltage", + value=sensor.value, + ) + + +register.check_plugin( + name="avocent_voltage_sensors", + sections=["avocent_sensors"], + service_name="Voltage %s", + discovery_function=discover_avocent_voltage_sensors, + check_function=check_avocent_voltage_sensors, +) + + +def discover_avocent_sensors_temp(section: Section) -> DiscoveryResult: + yield from (Service(item=sensor_name) for sensor_name in section.temperature_sensors) + + +def check_avocent_sensors_temp( + item: str, + params: TempParamType, + section: Section, +) -> CheckResult: + if not (sensor := section.temperature_sensors.get(item)): + return + yield from check_temperature( + reading=sensor.value, + params=params, + unique_name=item, + value_store=get_value_store(), + ) + +register.check_plugin( + name="avocent_sensors_temp", + sections=["avocent_sensors"], + service_name="Temperature %s", + discovery_function=discover_avocent_sensors_temp, + check_function=check_avocent_sensors_temp, + check_ruleset_name="temperature", + check_default_parameters={"device_levels_handling": "devdefault"}, +) diff --git a/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/utils/ucd_hr_detection.py b/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/utils/ucd_hr_detection.py new file mode 100644 index 0000000..3d63f78 --- /dev/null +++ b/check_mk-avocent/cmk20-cmk21/lib/python3/cmk/base/plugins/agent_based/utils/ucd_hr_detection.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +from ..agent_based_api.v1 import ( + all_of, + any_of, + contains, + equals, + exists, + not_contains, + not_equals, + not_exists, + not_startswith, + startswith, +) + +# We are not sure how to safely detect the UCD SNMP Daemon. We know that +# it is mainly used on Linux, but not only. But fetching and OID outside +# of the info area for scanning is not a good idea. It will slow down +# scans for *all* hosts. + +# ---ucd cpu load--------------------------------------------------------- + +# We prefer HOST-RESOURCES-MIB implementation but not in case +# of check 'ucd_cpu_load' because the HR-MIB has not data +# about cpu load + +# ---general ucd/hr------------------------------------------------------- + +HR = exists(".1.3.6.1.2.1.25.1.1.0") + +_NOT_HR = not_exists(".1.3.6.1.2.1.25.1.1.0") + +UCD = any_of( + contains(".1.3.6.1.2.1.1.1.0", "linux"), + contains(".1.3.6.1.2.1.1.1.0", "cmc-tc"), + contains(".1.3.6.1.2.1.1.1.0", "hp onboard administrator"), + contains(".1.3.6.1.2.1.1.1.0", "barracuda"), + contains(".1.3.6.1.2.1.1.1.0", "pfsense"), + contains(".1.3.6.1.2.1.1.1.0", "genugate"), + contains(".1.3.6.1.2.1.1.1.0", "bomgar"), + contains(".1.3.6.1.2.1.1.1.0", "pulse secure"), + contains(".1.3.6.1.2.1.1.1.0", "microsens"), + contains(".1.3.6.1.2.1.1.1.0", "avocent"), + all_of( # Artec email archive appliances + equals(".1.3.6.1.2.1.1.2.0", ".1.3.6.1.4.1.8072.3.2.10"), + contains(".1.3.6.1.2.1.1.1.0", "version"), + contains(".1.3.6.1.2.1.1.1.0", "serial"), + ), + all_of( + equals(".1.3.6.1.2.1.1.1.0", ""), + exists(".1.3.6.1.4.1.2021.*"), + ), +) + +_NOT_UCD = all_of( + # This is an explicit negation of the constant above. + # We don't have a generic negation function as we want + # discourage constructs like this. + # In the future this will be acomplished using the 'supersedes' + # feature (according to CMK-4232), and this can be removed. + not_contains(".1.3.6.1.2.1.1.1.0", "linux"), + not_contains(".1.3.6.1.2.1.1.1.0", "cmc-tc"), + not_contains(".1.3.6.1.2.1.1.1.0", "hp onboard administrator"), + not_contains(".1.3.6.1.2.1.1.1.0", "barracuda"), + not_contains(".1.3.6.1.2.1.1.1.0", "pfsense"), + not_contains(".1.3.6.1.2.1.1.1.0", "genugate"), + not_contains(".1.3.6.1.2.1.1.1.0", "bomgar"), + not_contains(".1.3.6.1.2.1.1.1.0", "pulse secure"), + not_contains(".1.3.6.1.2.1.1.1.0", "microsens"), + not_contains(".1.3.6.1.2.1.1.1.0", "avocent"), + any_of( # Artec email archive appliances + not_equals(".1.3.6.1.2.1.1.2.0", ".1.3.6.1.4.1.8072.3.2.10"), + not_contains(".1.3.6.1.2.1.1.1.0", "version"), + not_contains(".1.3.6.1.2.1.1.1.0", "serial"), + ), +) + +PREFER_HR_ELSE_UCD = all_of(UCD, _NOT_HR) + +# ---helper--------------------------------------------------------------- + +# Within _is_ucd or _is_ucd_mem we make use of a whitelist +# in order to expand this list of devices easily. + +_UCD_MEM = any_of( + # Devices for which ucd_mem should be used + # if and only if HR-table is not available + all_of( + contains(".1.3.6.1.2.1.1.1.0", "pfsense"), + not_exists(".1.3.6.1.2.1.25.1.1.0"), + ), + all_of( + contains(".1.3.6.1.2.1.1.1.0", "ironport model c3"), + not_exists(".1.3.6.1.2.1.25.1.1.0"), + ), + all_of( + contains(".1.3.6.1.2.1.1.1.0", "bomgar"), + not_exists(".1.3.6.1.2.1.25.1.1.0"), + ), + all_of( + # Astaro and Synology are Linux but should use hr_mem + # Otherwise Cache/Buffers are included in used memory + # generating critical state + not_startswith(".1.3.6.1.2.1.1.2.0", ".1.3.6.1.4.1.8072."), + # Otherwise use ucd_mem for listed devices in UCD. + UCD, + ), +) + +_NOT_UCD_MEM = all_of( + # This is an explicit negation of the constant above. + # We don't have a generic negation function as we want + # discourage constructs like this. + # In the future this will be acomplished using the 'supersedes' + # feature (according to CMK-4232), and this can be removed. + any_of( + not_contains(".1.3.6.1.2.1.1.1.0", "pfsense"), + exists(".1.3.6.1.2.1.25.1.1.0"), + ), + any_of( + not_contains(".1.3.6.1.2.1.1.1.0", "ironport model c3"), + exists(".1.3.6.1.2.1.25.1.1.0"), + ), + any_of( + not_contains(".1.3.6.1.2.1.1.1.0", "bomgar"), + exists(".1.3.6.1.2.1.25.1.1.0"), + ), + any_of( + # Astaro and Synology are Linux but should use hr_mem + # Otherwise Cache/Buffers are included in used memory + # generating critical state + startswith(".1.3.6.1.2.1.1.2.0", ".1.3.6.1.4.1.8072."), + # Otherwise use ucd_mem for listed devices in UCD. + _NOT_UCD, + ), +) + +# Some devices report incorrect data on both HR and UCD, eg. F5 BigIP +_NOT_BROKEN_MEM = all_of( + not_startswith(".1.3.6.1.2.1.1.2.0", ".1.3.6.1.4.1.3375"), + not_startswith(".1.3.6.1.2.1.1.2.0", ".1.3.6.1.4.1.2620"), +) + +# ---memory--------------------------------------------------------------- + +USE_UCD_MEM = all_of(_NOT_BROKEN_MEM, _UCD_MEM) + +USE_HR_MEM = all_of(_NOT_BROKEN_MEM, _NOT_UCD_MEM) diff --git a/check_mk-avocent/cmk20-cmk21/share/check_mk/checkman/avocent_sensors_temp b/check_mk-avocent/cmk20-cmk21/share/check_mk/checkman/avocent_sensors_temp new file mode 100644 index 0000000..12d2ad3 --- /dev/null +++ b/check_mk-avocent/cmk20-cmk21/share/check_mk/checkman/avocent_sensors_temp @@ -0,0 +1,15 @@ +title: Avocent ACS 800 CPU and Board Temperature +agents: snmp +catalog: hw/network/avocent +license: GPLv2 +distribution: check_mk +description: + Checks by SNMP the Temperature for CPU and Board sensors of Avocent ACS 800 devices. + + Return {OK} if no temperature rule is created, otherwise based on the level in + the configured temperature rule. +item: + CPU Temperature and Board Temperature + +discovery: + One service is created for CPU Temperature and one service for Board Temperature diff --git a/check_mk-avocent/cmk20-cmk21/share/check_mk/checkman/avocent_voltage_sensors b/check_mk-avocent/cmk20-cmk21/share/check_mk/checkman/avocent_voltage_sensors new file mode 100644 index 0000000..95b6744 --- /dev/null +++ b/check_mk-avocent/cmk20-cmk21/share/check_mk/checkman/avocent_voltage_sensors @@ -0,0 +1,15 @@ +title: Avocent ACS 800 Power Supply Voltage Sensors +agents: snmp +catalog: hw/network/avocent +license: GPLv2 +distribution: check_mk +description: + Checks by SNMP the power supply voltage sensors of Avocent ACS 800 devices. + + Returns {OK} Always. + +item: + The Voltage for each power supply. + +discovery: + Two services created, one for each Power Supply