#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2010             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# ails.  You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.


def check_df(mountpoint, params, df_lines):
    # df outputs seven columns:
    # DEVICE FS-TYPE SIZE(KB) USED(KB) AVAIL(KB) USED(%) MOUNTPOINT
    # The mount point may contain spaces (seen on VMWare volumes)

    used_list = [ l for l in df_lines if " ".join(l[6:]).replace('\\','/') == mountpoint ]

    if len(used_list) == 0:
        return (3, "UNKNOWN - %s missing or not a partition" % mountpoint )
    used = used_list[0] # might be listed twice. We take the first occurance

    # In some rare cases the mountpoint may contain a space (happened on ESX).
    if len(used) > 7:
        used = used[0:6] + [ " ".join(used[6:]) ]

    if len(used) != 7 or used[5][-1] != '%':
        return (3, "UNKNOWN - Invalid output from agent (%s)" % (' '.join(used),))

    # Beware: the 6th column of df ("used perc") may includes 5% which are reserved
    # for the superuser, whereas the 4th colum ("used MB") does *not* include that.
    # Beware(2): the column used_mb does not account for the reserved space for
    # superusers. So we rather use the column 'avail' and subtract that from total
    # to compute the used space.

    size_mb   = int(used[2]) / 1024.0
    if size_mb == 0:
        return (1, "WARN - size of filesystem is 0 MB")

    avail_mb   = int(used[4]) / 1024.0
    used_mb = size_mb - avail_mb

    used_perc = 100.0 * (used_mb / size_mb)
    size_gb   = size_mb / 1024.0

    # Get warning and critical levels already with 'magic factor' applied
    warn_mb, crit_mb, levelstext = get_filesystem_levels(g_hostname, mountpoint, size_gb, params)

    # Take into account magic scaling factor (third optional argument
    # in check params). A factor of 1.0 changes nothing. Factor should
    # be > 0 and <= 1. A smaller factor raises levels for big file systems
    # bigger than 100 GB and lowers it for file systems smaller than 100 GB.
    # Please run df_magic_factor.py to understand how it works.

    perfdata = [(mountpoint, str(used_mb) + 'MB', warn_mb, crit_mb, 0, size_mb)]
    infotext = "%.1f%% used (%.1f of %.1f GB), %s" % \
                (used_perc, used_mb / 1024.0, size_gb, levelstext)

    if used_mb >= crit_mb:
        return (2, "CRIT - %s" % infotext, perfdata)
    elif used_mb >= warn_mb:
        return (1, "WARN - %s" % infotext, perfdata)
    else:
        return (0, "OK - %s" % infotext, perfdata)



def inventory_df(checkname, info):
    inventory = []
    for line in info:
        try:
            fs_type    = line[1]
            size_kb = int(line[2])
            if size_kb == 0 or line[5] == '-':
                continue # exclude filesystems without size
            mountpoint = " ".join(line[6:]).replace('\\', '/') # Windows \ is replaced with /

            # exclude some filesystem types and some mountpoints
            if fs_type not in inventory_df_exclude_fs and mountpoint not in inventory_df_exclude_mountpoints:
                inventory.append((mountpoint, None, inventory_df_check_params))
        except ValueError,e:
            sys.stderr.write("Invalid plugin output '%s'\n" % (line,))
            pass # ignore e.g. entries for /proc, etc. if plugin sends any

    return inventory

check_info['df']        = (check_df, "fs_%s", 1, inventory_df)
precompile_params['df'] = precompile_filesystem_levels
