#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             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-
# tails. 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.

# Author: Lars Michelsen <lm@mathias-kettner.de>

# Example output from agent:
#
# <<<postfix_mailq>>>
# -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
# CA29995448EB     4638 Fri Jul  2 14:39:01  nagios
#                                          donatehosts@mathias-kettner.de
#
# E085095448EC      240 Fri Jul  2 14:40:01  root
#                                          lm@mathias-kettner.de
#
# D9EBC95448EE     4804 Fri Jul  2 14:40:03  nagios
#                                          donatehosts@mathias-kettner.de
#
# -- 9 Kbytes in 3 Requests.
#
#
# **************
#
# <<<postfix_mailq>>>
# -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
# 748C8C3D4AB     1436 Fri Jul  2 16:39:10  lm@mathias-kettner.de
#      (connect to mail.larsmichelsen.com[78.46.117.178]:25: Connection refused)
#                                          lm@larsmichelsen.com
#
# -- 1 Kbytes in 1 Request.
#
# Yet another one (I believe, this is from sendmail, though:)
# <<<postfix_mailq>>>
#       8BITMIME   (Deferred: Connection refused by mail.gargl.com.)
#                                          <franz@gargle.com>
# q1L4ovDO002485     3176 Tue Feb 21 05:50 MAILER-DAEMON
#                  (Deferred: 451 Try again later)
#                                          <wrdlpfrmpft@karl-valentin.com>
#                 Total requests: 2
#
# **************
# new format
# <<<postfix_mailq>>>
# QUEUE_deferred 60 1
# QUEUE_active 4 0

# new format multi-instance
# <<<postfix_mailq>>>
# [[[/etc/postfix-external]]]
# QUEUE_deferred 0 0
# QUEUE_active 0 0
# <<<postfix_mailq>>>
# [[[/etc/postfix-internal]]]
# QUEUE_deferred 0 0
# QUEUE_active 0 0


factory_settings['postfix_mailq_default_levels'] = {
    "deferred" : (10, 20),
    "active"   : (200, 300), # may become large for big mailservers
}


def postfix_mailq_to_bytes(value, uom):
    uom = uom.lower()
    if uom == 'kbytes':
        return value * 1024
    elif uom == 'mbytes':
        return value * 1024 * 1024
    elif uom == 'gbytes':
        return value * 1024 * 1024 * 1024


def parse_postfix_mailq(info):
    parsed        = {}
    instance_name = ""
    for line in info:
        if line[0].startswith("[[[") and line[0].endswith("]]]"):
            instance_name = line[0][3:-3]

        queueinfo = None
        # single and old output formats
        if line[0].startswith("QUEUE_"):
            queue = line[0].split("_")[1]
            # Deal with old agent (pre 1.2.8) which did not send size
            # infos in case of different error cases
            if len(line) == 2:
                size   = 0
                length = int(line[1]) # number of mails
            else:
                size   = int(line[1]) # in bytes
                length = int(line[2]) # number of mails

            queueinfo = line[0].split("_")[1], size, length

        elif " ".join(line[-2:]) == 'is empty':
            queueinfo = "empty", 0, 0

        elif line[0] == '--' or line[0:2] == [ 'Total', 'requests:']:
            if line[0] == '--':
                size    = postfix_mailq_to_bytes(float(line[1]), line[2])
                length  = int(line[4])
            else:
                size    = 0
                length  = int(line[2])

            queueinfo = "mail", size, length

        if queueinfo is not None:
            parsed.setdefault(instance_name, [])
            parsed[instance_name].append( queueinfo )

    return parsed


def inventory_postfix_mailq(parsed):
    for queue in parsed:
        yield queue, {}


def check_postfix_mailq(item, params, parsed):
    if item is None:
        item = ""

    if item not in parsed:
        yield 3, "Item not found"
        return

    if type(params) is not dict:
        params = { "deferred" : params }

    for what, size, length in parsed[item]:
        warn, crit = params.get(what, (None, None))
        if what in [ "active", "deferred", "mail" ]:
            state    = 0
            infotext = "%s%s queue length: %d" % (what[0].upper(), what[1:], length)

            if what in [ "deferred", "mail" ]:
                length_var = "length"
                size_var   = "size"
            else:
                length_var = "mail_queue_active_length"
                size_var   = "mail_queue_active_size"

            if crit is not None and length >= crit:
                state = 2
                infotext += " (warn/crit at %d/%d)" % (warn, crit)
            elif warn is not None and length >= warn:
                state = 1
                infotext += " (warn/crit at %d/%d)" % (warn, crit)

            yield state, infotext, [ (length_var, length, warn, crit), (size_var, size) ]

        elif what == "empty":
            yield 0, 'The mailqueue is empty', [ ('length', 0, warn, crit), ('size', 0) ]


check_info["postfix_mailq"] = {
    'parse_function'          : parse_postfix_mailq,
    'inventory_function'      : inventory_postfix_mailq,
    'check_function'          : check_postfix_mailq,
    'service_description'     : 'Postfix Queue %s',
    'default_levels_variable' : 'postfix_mailq_default_levels',
    'group'                   : "mail_queue_length",
    'has_perfdata'            : True,
}
