Checks for Fujitsu Primergy Physical and Logical Drives

Hello,

I’ve made SNMP Storage Checks for Fujitsu Primergy Servers. They check physical and logical drives.
I release them under the GNU General Public License v3.0. I’m not a software developer, so I can’t fix any specific bugs or give in depth support. Please regard this plugin as the work of a CheckMK hobbyist, with no support or any liability.

I tested it with Checkmk 2.1.0p24 and 2.2.0p4.

#!/usr/bin/python3
# Creates a Check for each Logical Drive on a Fujitsu Primergy Server. 2 is operational, all other results are critical.
# GNU General Public License v3.0
# copy into ./local/lib/check_mk/base/agent_based/primergy_logical_drives.py

from .agent_based_api.v1 import *


def discover_primergy_logical_drives(section):
    for _logical_drive_name, _status in section:
        yield Service(item=_logical_drive_name)


def check_primergy_logical_drives(item, section):
    # Dictionary for SNMP Check
    _dict_svrLogicalDriveStatusEx = dict([
        (1, 'unknown'),
        (2, 'operational - drive is OK, all disks working properly'),
        (3, 'partiallyDegraded - one disk in this array failed, reduced redundancy still available'),
        (4, 'degraded - one disk in this array failed, redundancy lost'),
        (5, 'failed - too many disks in this array failed, drive no longer available'),
        (6, 'rebuilding - drive is currently rebuilding'),
        (7, 'checking - drive is currently executing a consistency check'),
        (8, 'mdcing - drive is currently executing a consistency check and fixes inconsistencies'),
        (9, 'initializing - drive is currently being initialized'),
        (10, 'backgroundInitializing - drive is currently being initialized in background'),
        (11, 'migrating - drive is currently being modified (online RAID extension)'),
        (12, 'copying - drive is currently executing a copyback or redundant copy operation'),
        (13, 'offline - drive is temporarily not operational'),
        (14, 'spareInUse - drive is using a hot spare'),
        (15, 'erasing - drive is being erased'),
    ])
    for _logical_drive_name, _status in section:
        if _logical_drive_name == item:
            if _status == "":
                _status = "1"
            _status = int(_status)
            _status_verbose = _dict_svrLogicalDriveStatusEx[_status]
            if _status == 2 or 7 or 9 or 10:
                s = State.OK
            elif _status == 1 or 3 or 6 or 8 or 11 or 12 or 14:
                s = State.WARN
            else:
                s = State.CRIT
            yield Result(
                state=s,
                summary=f"Raid {_logical_drive_name} is {_status_verbose}"
            )
            return


register.check_plugin(
    name="primergy_logical_drives",
    service_name="LD %s",
    discovery_function=discover_primergy_logical_drives,
    check_function=check_primergy_logical_drives,
)

register.snmp_section(
    name="primergy_logical_drives",
    detect=startswith(".1.3.6.1.2.1.1.1.0", "Primergy"),
    fetch=SNMPTree(
        base=".1.3.6.1.4.1.231.2.49.1.6.2.1",
        oids=[
            "11.0",  # _logical_drive_name
            "19.0",  # _status
        ],
    ),
)
#!/usr/bin/python3
# Creates a Check for each Physical Drive on a Fujitsu Primergy Server.
# GNU General Public License v3.0
# copy into ./local/lib/check_mk/base/agent_based/primergy_physical_drives.py

from .agent_based_api.v1 import *


def discover_primergy_physical_drives(section):
    for _svrPhysicalDeviceIdx, _svrPhysicalDeviceInfo, _svrPhysicalDeviceVendorName, _svrPhysicalDeviceSmartStatus, _svrPhysicalDeviceStatus, _svrPhysicalDeviceSerialNumber in section:
        yield Service(item=_svrPhysicalDeviceIdx.zfill(3) + " " + _svrPhysicalDeviceVendorName + " " + _svrPhysicalDeviceInfo)


def check_primergy_physical_drives(item, section):
    # Dictionary for SNMP Check
    _dict_svrPhysicalDeviceStatus = dict([
        (1, 'unknown'),
        (2, 'noDisk - device is not a hard disk'),
        (3, 'online - device is available and working properly'),
        (4, 'ready - device can be used for new configuration'),
        (5, 'failed - device is available but no longer working'),
        (6, 'rebuilding - device is restoring fault tolerance'),
        (7, 'hotspareGlobal - device is a hot spare device for use in any array'),
        (8, 'hotspareDedicated - device is a hot spare device for use in a dedicated array'),
        (9, 'offline - device is set to non-working state'),
        (10, 'unconfiguredFailed - device is not configured but a failure has occurred'),
        (11, 'formatting - device is currently being formatted'),
        (12, 'dead - device is not available or not responding'),
    ])
    _dict_svrPhysicalDeviceSmartStatus = dict([
        (1, 'ok'),
        (2, 'failurePredicted'),
        (3, 'smartNotAvailable'),
        (4, 'smartMonitoringDisabled'),
    ])
    for _svrPhysicalDeviceIdx, _svrPhysicalDeviceInfo, _svrPhysicalDeviceVendorName, _svrPhysicalDeviceSmartStatus, _svrPhysicalDeviceStatus, _svrPhysicalDeviceSerialNumber in section:
        if _svrPhysicalDeviceIdx.zfill(3) + " " + _svrPhysicalDeviceVendorName + " " + _svrPhysicalDeviceInfo == item:
            if _svrPhysicalDeviceSmartStatus == "":
                _svrPhysicalDeviceSmartStatus = "3"
            _svrPhysicalDeviceSmartStatus = int(_svrPhysicalDeviceSmartStatus)
            _svrPhysicalDeviceSmartStatus_verbose = _dict_svrPhysicalDeviceSmartStatus[_svrPhysicalDeviceSmartStatus]
            if _svrPhysicalDeviceStatus == "":
                _svrPhysicalDeviceStatus = "1"
            _svrPhysicalDeviceStatus = int(_svrPhysicalDeviceStatus)
            _svrPhysicalDeviceStatus_verbose = _dict_svrPhysicalDeviceStatus[_svrPhysicalDeviceStatus]
            if _svrPhysicalDeviceSmartStatus == 1 or 3 or 4 and _svrPhysicalDeviceStatus == 2 or 3 or 7 or 8:
                s = State.OK
            elif _svrPhysicalDeviceStatus == 1 or 4 or 6 or 9 or 11:
                s = State.WARN
            else:
                s = State.CRIT
            yield Result(
                state=s,
                summary=f"SerialNumber: {_svrPhysicalDeviceSerialNumber} - SMART status is {_svrPhysicalDeviceSmartStatus_verbose} - Device status is {_svrPhysicalDeviceStatus_verbose}"
            )
            return


register.check_plugin(
    name="primergy_physical_drives",
    service_name="PD %s",
    discovery_function=discover_primergy_physical_drives,
    check_function=check_primergy_physical_drives,
)

register.snmp_section(
    name="primergy_physical_drives",
    detect=startswith(".1.3.6.1.2.1.1.1.0", "Primergy"),
    fetch=SNMPTree(
        base=".1.3.6.1.4.1.231.2.49.1.5.2.1",
        oids=[
            "19",  # svrPhysicalDeviceIdx
            "5",  # svrPhysicalDeviceInfo
            "6",  # svrPhysicalDeviceVendorName
            "14",  # svrPhysicalDeviceSmartStatus
            "15",  # svrPhysicalDeviceStatus
            "17",  # svrPhysicalDeviceSerialNumber
        ],
    ),
)

3 Likes