#!/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.

# --VOLUME INFORMATION--
#
# Name:              Vol1
# Raid Level:        1
# Size:              932 GB
# StripeSize:        64 KB
# Num Disks:         2
# State:             Normal
# System:            True
# Initialized:       True
# Cache Policy:      Off
#
#
# --DISKS IN VOLUME: Vol1 --
#
# ID:                0-0-0-0
# Type:              Disk
# Disk Type:         SATA Disk
# State:             Normal
# Size:              932 GB
# Free Size:         0 GB
# System Disk:       False
# Usage:             Array member
# Serial Number:     AB-CDEF123456
# Model:             AB CD EF
#
# ID:                0-1-0-0
# Type:              Disk
# Disk Type:         SATA Disk
# State:             Normal
# Size:              932 GB
# Free Size:         0 GB
# System Disk:       False
# Usage:             Array member
# Serial Number:     AB-CDEF123457
# Model:             AB CD EF


# split output into the --xxx-- sections
def parse_rstcli_sections(info):
    current_section = None
    for line in info:
        if line[0].startswith("--"):
            if current_section is not None:
                yield current_section
            current_section = (":".join(line).strip("-").strip(), [])
        elif len(line) < 2:
            # On some systems, there are lines that only consist of
            # a contextless 0. Skip those to avoid parsing errors later.
            continue
        else:
            if current_section is None:
                raise MKGeneralException("error: %s" % " ".join(line))
            current_section[1].append(line)

    yield current_section


# interpret the volumes section
def parse_rstcli_volumes(rows):
    volumes = {}
    current_volume = {}

    for row in rows:
        if row[0] == "Name":
            current_volume = {}
            volumes[row[1].strip()] = current_volume
        else:
            current_volume[row[0]] = row[1].strip()

    return volumes


# interpret the disks section
def parse_rstcli_disks(rows):
    disks = []
    current_disk = {}

    for row in rows:
        if row[0] == "ID":
            current_disk = {}
            disks.append(current_disk)

        current_disk[row[0]] = row[1].strip()

    return disks


def parse_rstcli(info):
    if info == [["rstcli not found"]]:
        return {}

    rstcli_sections = parse_rstcli_sections(info)
    if rstcli_sections is None:
        return {}

    volumes = {}
    for section in rstcli_sections:
        if section[0] == "VOLUME INFORMATION":
            volumes = parse_rstcli_volumes(section[1])
        elif section[0].startswith("DISKS IN VOLUME"):
            volume = section[0].split(":")[1].strip()
            volumes[volume]["Disks"] = parse_rstcli_disks(section[1])
        else:
            raise MKGeneralException("invalid section in rstcli output: %s" % section[0])

    return volumes


def inventory_rstcli(parsed):
    return [(name, None) for name in parsed]


# Help! There is no documentation, what are the possible values?
rstcli_states = {
    "Normal": 0,
}


@get_parsed_item_data
def check_rstcli(_item, _no_params, volume):
    return rstcli_states.get(volume["State"], 3), "RAID %s, %d disks (%s), state %s" % (
        volume["Raid Level"],
        int(volume["Num Disks"]),
        volume["Size"],
        volume["State"],
    )


check_info["rstcli"] = {
    "check_function": check_rstcli,
    "inventory_function": inventory_rstcli,
    "parse_function": parse_rstcli,
    "service_description": "RAID Volume %s",
}


def inventory_rstcli_pdisks(parsed):
    for key, volume in parsed.items():
        for disk in volume["Disks"]:
            yield "%s/%s" % (key, disk["ID"]), None


def check_rstcli_pdisks(item, _no_params, parsed):
    volume, disk_id = item.rsplit("/", 1)

    disks = parsed.get(volume, {}).get("Disks", [])
    for disk in disks:
        if disk["ID"] == disk_id:
            infotext = "%s (unit: %s, size: %s, type: %s, model: %s, serial: %s)" % (
                disk["State"],
                volume,
                disk["Size"],
                disk["Disk Type"],
                disk["Model"],
                disk["Serial Number"],
            )
            return rstcli_states.get(disk["State"], 2), infotext


check_info["rstcli.pdisks"] = {
    "check_function": check_rstcli_pdisks,
    "inventory_function": inventory_rstcli_pdisks,
    "service_description": "RAID Disk %s",
}
