#!/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.

# <<<oracle_jobs>>>
# IODBSZ1 SYS SM$CLEAN_AUTO_SPLIT_MERGE SCHEDULED 0 763 TRUE 24.04.13 00:00:00,600000 EUROPE/VIENNA - SUCCEEDED
# IODBSZ1 SYS RSE$CLEAN_RECOVERABLE_SCRIPT SCHEDULED 0 763 TRUE 24.04.13 00:00:00,100000 EUROPE/VIENNA - SUCCEEDED
# IODBSZ1 SYS BSLN_MAINTAIN_STATS_JOB SCHEDULED 0 110 TRUE 29.04.13 00:00:00,300000 +01:00 BSLN_MAINTAIN_STATS_SCHED SUCCEEDED
# IODBSZ1 SYS DRA_REEVALUATE_OPEN_FAILURES SCHEDULED 0 97 TRUE 01.01.70 00:00:00,000000 +02:00 MAINTENANCE_WINDOW_GROUP SUCCEEDED
# IODBSZ1 SYS ORA$AUTOTASK_CLEAN SCHEDULED 0 763 TRUE 24.04.13 03:00:00,900000 EUROPE/VIENNA DAILY_PURGE_SCHEDULE SUCCEEDED
# IODBSZ1 SYS PURGE_LOG SCHEDULED 0 763 TRUE 24.04.13 03:00:00,800000 EUROPE/VIENNA DAILY_PURGE_SCHEDULE SUCCEEDED
# IODBSZ1 ORACLE_OCM MGMT_CONFIG_JOB SCHEDULED 0 97 TRUE 01.01.70 00:00:00,000000 +02:00 MAINTENANCE_WINDOW_GROUP SUCCEEDED
# IODBSZ1 ORACLE_OCM MGMT_STATS_CONFIG_JOB SCHEDULED 0 3 TRUE 01.05.13 01:01:01,000000 +01:00 - SUCCEEDED
# IODBSZ1 EXFSYS RLM$SCHDNEGACTION SCHEDULED 0 18954 TRUE 23.04.13 14:51:57,000000 +02:00 - SUCCEEDED
# IODBSZ1 EXFSYS RLM$EVTCLEANUP SCHEDULED 0 18202 TRUE 23.04.13 13:41:48,200000 +01:00 - SUCCEEDED

# new output
# <<<oracle_jobs:sep(124)>>>
# QS1|SYS|SM$CLEAN_AUTO_SPLIT_MERGE|SCHEDULED|1|877|TRUE|02-AUG-15 12.00.00.500000 AM EUROPE/VIENNA|-|SUCCEEDED
# QS1|SYS|RSE$CLEAN_RECOVERABLE_SCRIPT|SCHEDULED|0|877|TRUE|02-AUG-15 12.00.00.800000 AM EUROPE/VIENNA|-|SUCCEEDED
# QS1|SYS|FGR$AUTOPURGE_JOB|DISABLED||0|FALSE|01-JAN-70 12.00.00.000000 AM +02:00|-|
# QS1|SYS|BSLN_MAINTAIN_STATS_JOB|SCHEDULED|12|128|TRUE|02-AUG-15 12.00.00.600000 AM +01:00|BSLN_MAINTAIN_STATS_SCHED|SUCCEEDED
# QS1|SYS|DRA_REEVALUATE_OPEN_FAILURES|SCHEDULED|0|156|TRUE|01-JAN-70 12.00.00.000000 AM +02:00|MAINTENANCE_WINDOW_GROUP|SUCCEEDED
# QS1|SYS|HM_CREATE_OFFLINE_DICTIONARY|DISABLED||0|FALSE|01-JAN-70 12.00.00.000000 AM +02:00|MAINTENANCE_WINDOW_GROUP|
# QS1|SYS|ORA$AUTOTASK_CLEAN|SCHEDULED|0|877|TRUE|02-AUG-15 03.00.00.200000 AM EUROPE/VIENNA|DAILY_PURGE_SCHEDULE|SUCCEEDED
# QS1|SYS|FILE_WATCHER|DISABLED||0|FALSE|01-JAN-70 12.00.00.000000 AM +02:00|FILE_WATCHER_SCHEDULE|
# QS1|SYS|PURGE_LOG|SCHEDULED|0|877|TRUE|02-AUG-15 03.00.00.700000 AM EUROPE/VIENNA|DAILY_PURGE_SCHEDULE|SUCCEEDED
# QS1|ORACLE_OCM|MGMT_STATS_CONFIG_JOB|DISABLED|0|2|FALSE|01-MAY-15 01.01.01.100000 AM +01:00|-|
# QS1|ORACLE_OCM|MGMT_CONFIG_JOB|DISABLED|0|40|FALSE|08-APR-15 01.01.01.200000 AM +01:00|-|
# QS1|DBADMIN|DATENEXPORT-FUR|COMPLETED|0|3|FALSE|22-AUG-14 01.11.00.000000 AM EUROPE/BERLIN|-|



factory_settings["oracle_jobs_defaults"] = {
    "disabled": True,
}

def inventory_oracle_jobs(info):
    for line in info:
        if len(line) >= 3:
            yield "%s.%s.%s" % ( line[0], line[1], line[2] ), {}

def check_oracle_jobs(item, params, info):
    if item.count('.') == 2:
        sid, job_owner, job_name = item.split('.')
    else:
        # old format without job owner. Simply ignore owner.
        sid, job_name = item.split('.')
        job_owner = None

    data_found = False
    for line in info:
        service_found = False

        if line[0] == sid:
            data_found = True

        if line[0] == sid and (line[1] == job_owner or job_owner == None) and line[2] == job_name:

            service_found = True
            param_disabled = params["disabled"]

            if len(line) == 10:
                # new agent output with '|' separator
                sid, job_owner, job_name, job_state, job_runtime, job_run_count, \
                job_enabled, job_nextrun, job_schedule, job_status = line

            else:
                # old agent format
                # the extraction of data is complicated due to missing field separator
                job_name = line[2]
                job_state = line[3]
                job_runtime = line[4]
                job_enabled = line[6]
                job_nextrun = " ".join(line[7:-3])
                job_schedule = line[-2]
                job_status = line[-1]

            break

    if not data_found:
        # In case of missing information we assume that the login into
        # the database has failed and we simply skip this check. It won't
        # switch to UNKNOWN, but will get stale.
        raise MKCounterWrapped("Login not possible for check %s" % item)

    if not service_found:
        return (2, 'Job is missing')

    state = 0
    output = []
    perfdata = []


    txt = "Job-State: %s" % job_state
    if job_state == "BROKEN":
        txt += "(!!)"
        state = max(state, 2)
    output.append(txt)

    txt = "Enabled: %s" % (job_enabled == "TRUE" and "Yes" or "No")
    if job_enabled != "TRUE" and job_state != 'RUNNING':
        if param_disabled:
            txt += ' ignored'
        else:
            txt += "(!)"
            state = max(state, 1)
    output.append(txt)

    if job_runtime == '' or job_runtime == 'SCHEDULED':
        last_duration = 0
    else:
        last_duration = int(job_runtime.replace('.',',').split(',',1)[0])
        # bugfix for an error in mk_oracle agent with missing round over last_duration
        output.append("Last Duration: %s" % (get_age_human_readable(last_duration)))

    if "run_duration" in params:
        warn, crit = params["run_duration"]

        output.append(" (warn/crit at %ds/%ds)" % (warn, crit))

        if last_duration >= crit:
            output.append("(!!)")
            state = max(state, 2)
        elif last_duration >= warn:
            output.append("(!)")
            state = max(state, 1)

    perfdata.append(("duration", last_duration))

    # 01.05.13 01:01:01,000000 +01:00
    if job_nextrun.startswith("01.01.70 00:00:00"):
        if job_schedule == "-" and job_state != "DISABLED":
            job_nextrun = "not scheduled(!)"
            state = max(state, 1)
        else:
            job_nextrun = job_schedule
    output.append("Next Run: %s" % job_nextrun)

    # A job who is running forever has no last run state and job_status is
    # STOPPED
    if job_state == "RUNNING" and job_runtime == '' and job_status == 'STOPPED':
        txt = 'Job is running forever'
    else:
        txt = "Last Run Status: %s" % (job_status)
        if job_status != "SUCCEEDED" and job_status != "":
            txt += "(!!)"
            state = max(state, 2)
    output.append(txt)

    if job_state == "DISABLED" and "status_disabled_jobs" in params:
        state = params["status_disabled_jobs"]

    return (state, ", ".join(output), perfdata)

check_info['oracle_jobs'] = {
    "service_description"     : "ORA %s Job",
    "group"                   : "oracle_jobs",
    "check_function"          : check_oracle_jobs,
    "inventory_function"      : inventory_oracle_jobs,
    "has_perfdata"            : True,
    "default_levels_variable" : "oracle_jobs_defaults",
}
