#!/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 os  # pylint: disable=C0413
import sys  # pylint: disable=C0413

import lib.base  # pylint: disable=C0413
import lib.disk  # pylint: disable=C0413
from lib.globals import (STATE_CRIT, STATE_OK,  # pylint: disable=C0413
                          STATE_UNKNOWN, STATE_WARN)

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

DESCRIPTION = '''Checks the percentage of inode space used. To do this, this plugin fetches a list
                 of local devices that are in use and have a filesystem on them. Filesystems that do
                 not report inode usage are skipped.'''

DEFAULT_WARN  = 90
DEFAULT_CRIT  = 95
DEFAULT_MOUNT = '/, /tmp, /boot'


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

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

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

    parser.add_argument(
        '-c', '--critical',
        help='Set the critical threshold inode usage percentage. Default: %(default)s',
        dest='CRIT',
        type=float,
        default=DEFAULT_CRIT,
    )

    parser.add_argument(
        '--mount',
        #help='The mount point, in the format "mount1,mount2". Default: "%(default)s"',
        help=argparse.SUPPRESS,  # deprecated parameter
        dest='MOUNT',
        type=lambda s: [str(item).strip() for item in s.split(',')],
        default=DEFAULT_MOUNT,
    )

    parser.add_argument(
        '-w', '--warning',
        help='Set the warning threshold inode usage percentage. Default: %(default)s',
        dest='WARN',
        type=float,
        default=DEFAULT_WARN,
    )

    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)

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

    # analyze data
    real_disks = lib.disk.get_real_disks()
    for disk in real_disks:
        mount = disk['mp'].split(' ')[0]
        try:
            st = os.statvfs(mount)
            inodes_total = float(st.f_files)
            if not inodes_total:
                continue
            inodes_free = float(st.f_ffree)
            inodes_used = round((inodes_total - inodes_free) / inodes_total * 100, 1)

            local_state = lib.base.get_state(inodes_used, args.WARN, args.CRIT)
            state = lib.base.get_worst(local_state, state)

            msg.append(f'{mount} {inodes_used}%{lib.base.state2str(local_state, prefix=" ")}')
            perfdata += lib.base.get_perfdata(mount, inodes_used, '%', args.WARN, args.CRIT, 0, 100)
        except Exception:
            lib.base.cu('Something seems to be wrong with the input parameter')

    # build the message
    if not msg:
        lib.base.oao('Everything is ok (although nothing checked).', state)
    msg = ', '.join(msg)
    if state != STATE_OK:
        msg += '. Have a look at the README on how to find where inodes are being used.'

    # 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()
