#!/usr/bin/env python3
# -*- coding: utf-8; py-indent-offset: 4 -*-
#
# Author:  Linuxfabrik GmbH, Zurich, Switzerland
# Contact: info (at) linuxfabrik (dot) ch
#          https://www.linuxfabrik.ch/
# License: The Unlicense, see LICENSE file.

# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.md

"""See the check's README for more details.
"""

import argparse  # pylint: disable=C0413
import json  # pylint: disable=C0413
import sys  # pylint: disable=C0413

import lib.args  # pylint: disable=C0413
import lib.base  # pylint: disable=C0413
import lib.huawei  # pylint: disable=C0413
import lib.lftest  # pylint: disable=C0413
import lib.txt  # pylint: disable=C0413
from lib.globals import (STATE_CRIT, STATE_OK,  # pylint: disable=C0413
                          STATE_UNKNOWN, STATE_WARN)

__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
__version__ = '2025021501'

DESCRIPTION = """Batch query basic information about power modules on a Huawei OceanStor Dorado
                 storage system via the REST Interface, using the ``/power`` endpoint."""

DEFAULT_CACHE_EXPIRE = 15 # minutes; default session timeout period is 20 minutes
DEFAULT_INSECURE = True
DEFAULT_NO_PROXY = False
DEFAULT_SCOPE = 0
DEFAULT_TIMEOUT  = 3


def parse_args():
    """Parse command line arguments using argparse.
    """
    parser = argparse.ArgumentParser(description=DESCRIPTION)

    parser.add_argument(
        '-V', '--version',
        action='version',
        version='%(prog)s: v{} by {}'.format(__version__, __author__)
    )

    parser.add_argument(
        '--always-ok',
        help='Always returns OK.',
        dest='ALWAYS_OK',
        action='store_true',
        default=False,
    )

    parser.add_argument(
        '--cache-expire',
        help='The amount of time after which the credential cache expires, in minutes. '
             'Default: %(default)s',
        dest='CACHE_EXPIRE',
        type=int,
        default=DEFAULT_CACHE_EXPIRE,
    )

    parser.add_argument(
        '--device-id',
        help='Huawei OceanStor Dorado API Device ID.',
        dest='DEVICE_ID',
        required=True,
    )

    parser.add_argument(
        '--insecure',
        help='This option explicitly allows to perform "insecure" SSL connections. '
             'Default: %(default)s',
        dest='INSECURE',
        action='store_true',
        default=DEFAULT_INSECURE,
    )

    parser.add_argument(
        '--no-proxy',
        help='Do not use a proxy. '
             'Default: %(default)s',
        dest='NO_PROXY',
        action='store_true',
        default=DEFAULT_NO_PROXY,
    )

    parser.add_argument(
        '--password',
        help='Huawei OceanStor Dorado API Password.',
        dest='PASSWORD',
        required=True,
    )

    parser.add_argument(
        '--scope',
        help='Huawei OceanStor Dorado API Scope.',
        dest='SCOPE',
        default=DEFAULT_SCOPE,
    )

    parser.add_argument(
        '--test',
        help='For unit tests. Needs "path-to-stdout-file,path-to-stderr-file,expected-retc".',
        dest='TEST',
        type=lib.args.csv,
    )

    parser.add_argument(
        '--timeout',
        help='Network timeout in seconds. '
             'Default: %(default)s (seconds)',
        dest='TIMEOUT',
        type=int,
        default=DEFAULT_TIMEOUT,
    )

    parser.add_argument(
        '-u', '--url',
        help='Huawei OceanStor Dorado API URL.',
        dest='URL',
        required=True,
    )

    parser.add_argument(
        '--username',
        help='Huawei OceanStor Dorado API Username.',
        dest='USERNAME',
        required=True,
    )

    return parser.parse_args()


def main():
    """The main function. Hier spielt die Musik.
    """

    # parse the command line, exit with UNKNOWN if it fails
    try:
        args = parse_args()
    except SystemExit:
        sys.exit(STATE_UNKNOWN)

    if not args.URL.startswith('http'):
        lib.base.cu('--url parameter has to start with "http://" or https://".')

    # fetch data
    if args.TEST is None:
        result = lib.huawei.get_data('power', args)
    else:
        # do not call the command, put in test data
        stdout, stderr, retc = lib.lftest.test(args.TEST)
        result = json.loads(stdout)

    # no valuable result?
    if not result:
        lib.base.cu('Got no valuable response from {}.'.format(args.URL))
    if result.get('error').get('code') != 0:
        lib.base.oao('{} {}'.format(
            result.get('error').get('description'),
            result.get('error').get('suggestion'),
        ), STATE_UNKNOWN)

    # init some vars
    msg = ''
    state = STATE_OK
    perfdata = ''

    # analyze the data
    table_data = []
    for power in result.get('data'):
        health_state = STATE_OK
        if lib.huawei.get_health_status(power.get('HEALTHSTATUS')) != 'Normal (1)':
            health_state = STATE_WARN
            state = lib.base.get_worst(state, health_state)

        power['UUID'] = lib.huawei.get_uuid(power)

        running_state = STATE_OK
        if lib.huawei.get_running_status(power.get('RUNNINGSTATUS')) != 'Normal (1)' and \
           lib.huawei.get_running_status(power.get('RUNNINGSTATUS')) != 'Running (2)' and \
           lib.huawei.get_running_status(power.get('RUNNINGSTATUS')) != 'Online (27)':
            running_state = STATE_WARN
            state = lib.base.get_worst(state, running_state)

        perfdata += lib.base.get_perfdata('{}_HEALTHSTATUS'.format(power['UUID']), power['HEALTHSTATUS'], None, None, 2, 0, 2)
        perfdata += lib.base.get_perfdata('{}_RUNNINGSTATUS'.format(power['UUID']), power['RUNNINGSTATUS'], None, None, None, 0, None)
        perfdata += lib.base.get_perfdata('{}_INPUTVOLTAGE'.format(power['UUID']), power['INPUTVOLTAGE'], None, None, None, 0, None)
        perfdata += lib.base.get_perfdata('{}_OUTPUTVOLTAGE'.format(power['UUID']), power['OUTPUTVOLTAGE'], None, None, None, 0, None)
        perfdata += lib.base.get_perfdata('{}_TEMPERATURE'.format(power['UUID']), power['TEMPERATURE'], None, None, None, 0, None)

        power['health_state'] = lib.base.state2str(health_state, empty_ok=False)
        power['running_state'] = lib.base.state2str(running_state, empty_ok=False)

        table_data.append(power)

    if table_data:
        keys = ['UUID', 'LOCATION', 'MANUFACTURER', 'MODEL', 'SERIALNUMBER', 'PRODUCEDATE', 'INPUTVOLTAGE', 'OUTPUTVOLTAGE', 'TEMPERATURE', 'health_state', 'running_state']
        headers = ['UUID', 'Location', 'Manufacturer', 'Model', 'SerialNumber', 'Produced', 'In (MV)', 'Out (MV)', 'Temp', 'Health', 'Running']
        msg += lib.base.get_table(table_data, keys, header=headers)

    msg += '\nFetched API {} {}'.format(
        result.get('counter', 0),
        lib.txt.pluralize('time', result.get('counter', 0),),
    )

    if state == STATE_CRIT:
        msg = 'There are critical errors.\n\n' + msg
    elif state == STATE_WARN:
        msg = 'There are warnings.\n\n' + msg
    else:
        msg = 'Everything is ok.\n\n' + msg

    # over and out
    lib.base.oao(msg, state, perfdata, always_ok=args.ALWAYS_OK)


if __name__ == '__main__':
    try:
        main()
    except Exception:   # pylint: disable=W0703
        lib.base.cu()
