#!/usr/bin/env python3
# Copyright (C) 2019 Checkmk 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.

# No faults:
# Agent section is empty

# From https://docs.oracle.com/cd/E23824_01/html/821-1451/glisy.html
# One fault:
# <<<solaris_fmadm:sep(58)>>>
# --------------- ------------------------------------  -------------- ---------
# TIME            EVENT-ID                              MSG-ID         SEVERITY
# --------------- ------------------------------------  -------------- ---------
# Aug 24 17:56:03 7b83c87c-78f6-6a8e-fa2b-d0cf16834049  SUN4V-8001-8H  Minor
#
# Host        : bur419-61
# Platform    : SUNW,T5440        Chassis_id  : BEL07524BN
# Product_sn  : BEL07524BN
#
# Fault class : fault.cpu.ultraSPARC-T2plus.ireg
# Affects     : cpu:///cpuid=0/serial=1F95806CD1421929
#                   faulted and taken out of service
# FRU         : "MB/CPU0" (hc://:product-id=SUNW,T5440:server-id=bur419-61:\
#               serial=3529:part=541255304/motherboard=0/cpuboard=0)
#                   faulty
# Serial ID.  : 3529
#               1F95806CD1421929
#
# Description : The number of integer register errors associated with this thread
#               has exceeded acceptable levels.
#
# Response    : The fault manager will attempt to remove the affected thread from
#               service.
#
# Impact      : System performance may be affected.
#
# Action      : Use 'fmadm faulty' to provide a more detailed view of this event.
#               Please refer to the associated reference document at
#               http://sun.com/msg/SUN4V-8001-8H for the latest service
#               procedures and policies regarding this diagnosis.

# Multiple faults:
# <<<solaris_fmadm:sep(58)>>>
# --------------- ------------------------------------  -------------- -------
# TIME            EVENT-ID                              MSG-ID         SEVERITY
# --------------- ------------------------------------  -------------- -------
# Sep 21 10:01:36 d482f935-5c8f-e9ab-9f25-d0aaafec1e6c  PCIEX-8000-5Y  Major
#
# Fault class  : fault.io.pci.device-invreq
# Affects      : dev:///pci@0,0/pci1022,7458@11/pci1000,3060@0
#                dev:///pci@0,0/pci1022,7458@11/pci1000,3060@1
#                 ok and in service
#                dev:///pci@0,0/pci1022,7458@11/pci1000,3060@2
#                dev:///pci@0,0/pci1022,7458@11/pci1000,3060@3
#                  faulty and taken out of service
# FRU          : "SLOT 2" (hc://.../pciexrc=3/pciexbus=4/pciexdev=0)
#                  repair attempted
#                "SLOT 3" (hc://.../pciexrc=3/pciexbus=4/pciexdev=1)
#                  acquitted
#                "SLOT 4" (hc://.../pciexrc=3/pciexbus=4/pciexdev=2)
#                  not present
#                "SLOT 5" (hc://.../pciexrc=3/pciexbus=4/pciexdev=3)
#                  faulty
#
#  Description  : The transmitting device sent an invalid request.
#
#  Response     : One or more device instances may be disabled
#
#  Impact       : Possible loss of services provided by the device instances
#                 associated with this fault
#
#  Action       : Use 'fmadm faulty' to provide a more detailed view of this event.
#                 Please refer to the associated reference document at
#                 http://sun.com/msg/PCIEX-8000-5Y for the latest service
#                 procedures and policies regarding this diagnosis.

# Newer outputs:
# <<<solaris_fmadm:sep(58)>>>
# --------------- ------------------------------------  -------------- ---------
# TIME            EVENT-ID                              MSG-ID         SEVERITY
# --------------- ------------------------------------  -------------- ---------
# Jun 05 22:11:06 66b65c7f-33c4-4625-94dc-b35e1926ab47  PCIEX-8000-YJ  Major
#
# Problem Status    : isolated
# Diag Engine       : eft / 1.16
# System
#     Manufacturer  : unknown
#     Name          : SPARC-Enterprise-M4000-Server
#     Part_Number   : unknown
#     Serial_Number : BCF1030049
#     Host_ID       : 856ec4fa
#
# ----------------------------------------
# Suspect 1 of 3 :
#    Problem class : fault.io.pciex.device-pcie-ce
#    Certainty   : 40%
#    Affects     : dev:////pci@0,600000/pci@0/pci@9/SUNW,emlxs@0
#    Status      : faulted and taken out of service
#
#    FRU
#      Status           : faulty
#      Location         : "/SYS/iou#0-pci#1"
#      Manufacturer     : unknown
#      Name             : unknown
#      Part_Number      : unknown
#      Revision         : unknown
#      Serial_Number    : unknown
#      Chassis
#         Manufacturer  : unknown
#         Name          : SPARC-Enterprise-M4000-Server
#         Part_Number   : unknown
#         Serial_Number : BCF1030049
# ----------------------------------------
# Suspect 2 of 3 :
#    Problem class : fault.io.pciex.device-pcie-ce
#    Certainty   : 40%
#    Affects     : dev:////pci@0,600000/pci@0/pci@9
#    Status      : faulted and taken out of service
#
#    FRU
#      Status           : faulty
#      FMRI             : "hc:///compon"nt=iou#0"
#      Manufacturer     : unknown
#      Name             : unknown
#      Part_Number      : unknown
#      Revision         : unknown
#      Serial_Number    : unknown
#      Chassis
#         Manufacturer  : unknown
#         Name          : unknown
#         Part_Number   : unknown
#         Serial_Number : unknown
#    Resource
#      Location         : "iou#0-pci#1"
# ...


# mypy: disable-error-code="attr-defined"

from cmk.base.check_api import LegacyCheckDefinition
from cmk.base.config import check_info


def parse_solaris_fmadm(string_table):
    if len(string_table) < 4:
        return {}

    event = []
    for entry in ":".join(string_table[3]).split():
        if entry:
            event.append(entry)

    parsed = {
        "event": {
            "time": " ".join(event[:-3]),
            "id": event[-3],
            "msg": event[-2],
            "severity": event[-1].lower(),
        },
        "problems": [],
    }

    # Skip header
    for line in string_table[4:]:
        stripped = [x.strip() for x in line]
        if stripped[0] in ["Problem class", "Fault class"]:
            parsed["problems"].append(":".join(stripped[1:]))

    return parsed


def inventory_solaris_fmadm(parsed):
    return [(None, None)]


def check_solaris_fmadm(_no_item, params, parsed):
    if not parsed:
        yield 0, "No faults detected"
        return

    map_state = {
        "minor": (1, "minor"),
        "major": (2, "major"),
        "critical": (2, "critical"),
    }

    event = parsed["event"]
    state, state_readable = map_state.get(event["severity"], (3, "unknown"))
    yield state, "Severity: {} ({})".format(state_readable, event["time"])

    problems = parsed["problems"]
    if problems:
        yield 0, "Problems: %s" % ", ".join(problems)


check_info["solaris_fmadm"] = LegacyCheckDefinition(
    parse_function=parse_solaris_fmadm,
    service_name="FMD Status",
    discovery_function=inventory_solaris_fmadm,
    check_function=check_solaris_fmadm,
)
