#!/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
import os
import sys

import lib.args
import lib.base
import lib.disk
from lib.globals import STATE_OK, STATE_UNKNOWN

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

DESCRIPTION = """Checks the percentage of used inodes on local filesystems. Fetches a list of local
devices that are in use and have a filesystem. Filesystems that do not report inode
usage (such as some network filesystems) are skipped automatically.
Alerts when inode usage exceeds the configured thresholds."""

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=lib.args.help('--always-ok'),
        dest='ALWAYS_OK',
        action='store_true',
        default=False,
    )

    parser.add_argument(
        '-c',
        '--critical',
        help='CRIT threshold for inode usage in percent. 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='WARN threshold for inode usage in percent. Default: %(default)s',
        dest='WARN',
        type=float,
        default=DEFAULT_WARN,
    )

    args, _ = parser.parse_known_args()
    return args


def main():
    """The main function. This is where the magic happens."""

    # parse the command line
    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,
                uom='%',
                warn=args.WARN,
                crit=args.CRIT,
                _min=0,
                _max=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:
        lib.base.cu()
