#!/usr/bin/env python3
# ***************************************************************************
#  IIIIII NNN  NNN  Copyright (C) 2022 Innovative Networks, Inc.
#    II    NNN  N   All Rights Reserved. Any redistribution or reproduction
#    II    N NN N   of part or all of the content of this program in any form
#    II    N  NNN   without expressed written consent of the copyright holder
#  IIIIII NNN  NNN  is strictly prohibited.  Please contact admins@in-kc.com
#   Be Innovative.  for additional information.
# ***************************************************************************
#  ScriptName.py - Title of the Script
#  Author - Ian Perry <iperry@indigex.com>
#
#  Purpose:  Tell what the script does
#
#  Version History:
#       2022.12.05 - Modified to get more information.
# ***************************************************************************

try:
    from inmon_utils import *
except:
    import sys
    print("Failed to import inmon_utils")
    exit(3)
import hpilo
import argparse
import logging
import pprint
import ssl


parser = argparse.ArgumentParser(description="Checks health status of HP iLO devices 3+")
parser.add_argument('-H', '--hostname', dest='hostname', help='Hostname for the iLO',   required=True)
parser.add_argument('-u', '--username', dest='username', help='Logon username',         required=True)
parser.add_argument('-p', '--password', dest='password', help='Logon password',         required=True)
parser.add_argument('-d', '--debug', dest='debug', help='Enable debugging output', action='store_true')
parser.add_argument('-i', '--insecure', dest='insecure', help='Enable RSA ciphers', action='store_true')

args = parser.parse_args()

if args.debug:
    log_level = getattr(logging, "DEBUG")
else:
    log_level = getattr(logging, "WARN")

logging.basicConfig(level=log_level)
logger = logging.getLogger("hpIlo.py")


if args.insecure:
    pass

ilo = hpilo.Ilo(args.hostname, args.username, args.password)
try:
    ilo.get_product_name()
except Exception as e:
    print(f"Encountered an error: {e}")
    sys.exit(3)

returnstat = 0
returntext = ""
returndata = ""
temp_uom = ""

health = ilo.get_embedded_health()
logger.debug(pprint.pformat(health))

def iterdict(d, prepath=()):
    for k, v in d.items():
        path = prepath + (k,)
        if v == "Degraded" or v == "Critical":
            yield f"{'.'.join(path)}"
        elif hasattr(v, 'items'):
            yield from iterdict(v, path)

# Check drive status

if not "drive" in health['health_at_a_glance'] or (health['health_at_a_glance']['drive']['status'] != 'OK'):
    if "drives_backplanes" in health:
        for drive_bay in health['drives_backplanes']:
            for drive_number, drive_info in drive_bay['drive_bays'].items():
                if (drive_info['status'] != 'Ok'):
                    returntext += f"drive {drive_number} status: {drive_info['status']}, "
                    returnstat = max(returnstat, 2)
    elif "storage" in health:
        # Check controller status
        if health['storage']['Controller on System Board']['controller_status'] != "OK":
            returntext += f"drive controller CRITICAL, "
            returnstat = max(returnstat, 2)
        storage = health['storage']['Controller on System Board']
        if 'drive_enclosures' in storage:
            for each in storage['drive_enclosures']:
                if each['status'] != "OK":
                    returntext += f"Drive enclosure {each['label']} status {each['status']}, "
                    returnstat = max(returnstat, 2)
        for each in storage['logical_drives']:
            if each['status'] != "OK":
                returntext += f"Logical drive {each['label']} status {each['status']}, "
                returnstat = max(returnstat, 2)
            for drive in each['physical_drives']:
                if drive['status'] != "OK":
                    returntext += f"Physical drive {drive['label']} status {drive['status']}, "
                    returnstat = max(returnstat, 2)



# Check fan status
if (health['health_at_a_glance']['fans']['status'] != 'OK'):
    for l, fan in health['fans'].items():
        if (fan['status'] != 'Ok'):
            returntext += f"{fan['label']} status: {fan['status']}, "
            returnstat = max(returnstat, 2)

# Check fan redundancy
if "redundancy" in health['health_at_a_glance']['fans'] and (health['health_at_a_glance']['fans']['redundancy'] != 'Redundant'):
    returntext += "Fans are not reundant! "
    returnstat = max(returnstat, 2)

# Check power supply status
if (health['health_at_a_glance']['power_supplies']['status'] != 'OK'):
    for ps in health['power_supplies']:
        if (ps['status'] != 'OK'):
            returntext += f"{ps['label']} status: {ps['status']}, "
            returnstat = max(returnstat, 2)

# Check power supply redundancy
if "redundancy" in health['health_at_a_glance']['power_supplies'] and (health['health_at_a_glance']['power_supplies']['redundancy'] != 'Redundant'):
    returntext+= "Power supplies are not redundant! "
    returnstat = max(returnstat, 2)

# Check temperature status
if (health['health_at_a_glance']['temperature']['status'] != 'OK'):
    for temp in health['temperature']:
        if (temp['status'] != 'OK' and temp['status'] != 'Not Installed'):
            returntext += f"{temp['location']} ({temp['label']}) temperature status: {temp['status']} - {temp['currentreading'][0]}{temp['currentreading'][1][0]}, "
            returnstat = max(returnstat, 2)

# Process power draw data
returndata += f"'power_reading'={health['power_supply_summary']['present_power_reading'].replace(' Watts', 'W')} "

# Process temperature performance data
for l, temp in health['temperature'].items():
    if (temp['status'] != 'Not Installed'):
        label = temp['label'].replace(' ', '_').lower()
        current_temp = temp['currentreading'][0]
        uom = temp['currentreading'][1][0]
        warn = temp['caution'][0]
        crit = temp['critical'][0]
        returndata += f"'{label}'={current_temp}{uom};{warn}{uom};{crit}{uom} "

# Process fan speed performance data
for l, fan in health['fans'].items():
    label = fan['label'].replace(' ', '_').lower()
    speed = fan['speed'][0]
    if (fan['speed'][1] == 'Percentage'):
        uom = "%"
    returndata += f"'{label}'={speed}{uom} "

# Catch all for everything else.
results = list(iterdict(health))
if results != [] or results == ['health_at_a_glance.network.status']:
    returntext += f"Status Degraded or Critical in the following locations: {', '.join(results)}"
    returnstat = max(returnstat, 2)


if (returnstat == 0):
    returnword = "OK"
elif (returnstat == 1):
    returnword = "WARN"
elif (returnstat == 2):
    returnword = "CRIT"
else:
    returnword = "UNKN"

if (returntext == ''):
    returntext = "iLO Health status normal"

print(f"{returnword} - {returntext} | {returndata}")
sys.exit(returnstat)
