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

# Example output from agent:
# <<<mkbackup>>>
# [[[site:heute2:encrypted]]]
# {'bytes_per_second': 0,
#  'finished': 1467733556.67532,
#  'output': '2016-07-05 17:45:56 --- Starting backup (Check_MK-Klappspaten-heute2-encrypted) ---\n2016-07-05 17:45:56 Cleaning up previously completed backup\n2016-07-05 17:45:56
# --- Backup completed (Duration: 0:00:00, Size: 6.49 MB, IO: 0.00 B/s) ---\n',
#  'pid': 14850,
#  'size': 6809879,
#  'started': 1467733556.39216,
#  'state': 'finished',
#  'success': True}
#
# <<<mkbackup>>>
# [[[system:backup-single]]]
# {
#     "bytes_per_second": 141691.8939750615,
#     "finished": 1468914936.47381,
#     "next_schedule": 1468973400.0,
#     "output": "2016-07-19 07:55:07 --- Starting backup (Check_MK_Appliance-alleine-backup+single to klappspaten) ---\n2016-07-19 07:55:07 Performing system backup (system.tar)\n2016-07-19 07:55:10 Performing system data backup (system-data.tar)\n2016-07-19 07:55:19 Performing site backup: migrate\n2016-07-19 07:55:19 The Check_MK version of this site does not support online backups. The site seems to be at least partially running. Stopping the site during backup and starting it again after completion.\n2016-07-19 07:55:19 Stopping site\n2016-07-19 07:55:23 Start offline site backup\n2016-07-19 07:55:23 Starting site again\n2016-07-19 07:55:27 Performing site backup: test\n2016-07-19 07:55:35 Verifying backup consistency\n2016-07-19 07:55:36 Cleaning up previously completed backup\n2016-07-19 07:55:36 --- Backup completed (Duration: 0:00:28, Size: 380.65 MB, IO: 138.37 kB/s) ---\n",
#     "pid": 28038,
#     "size": 399144997,
#     "started": 1468914907.521488,
#     "state": "finished",
#     "success": true
# }

def parse_mkbackup(info):
    try:
        import simplejson as json
    except ImportError:
        import json

    parsed = {}

    job, json_data = None, ""
    for l in info:
        line = " ".join(l)
        if line.startswith("[[["):
            head = line[3:-3].split(":")
            if len(head) == 3:
                site_id, job_id = head[1:]
                sites  = parsed.setdefault("site", {})
                jobs   = sites.setdefault(site_id, {})
                job    = jobs[job_id] = {}
            else:
                job_id = head[-1]
                system = parsed.setdefault("system", {})
                job    = system[job_id] = {}

        elif job != None:
            json_data += line
            if line == "}":
                job.update(json.loads(json_data))

    return parsed


def check_mkbackup(job_state):
    if job_state["state"] in [ "started", "running" ]:
        duration = time.time() - job_state["started"]

        yield 0, "The job is running for %s since %s" % \
            (get_age_human_readable(duration),
             get_timestamp_human_readable(job_state["started"])), \
            [ ("backup_duration", duration),
              ("backup_avgspeed", job_state["bytes_per_second"]) ]

    elif job_state["state"] == "finished":
        if job_state["success"] == False:
            yield 2, "Backup failed"
        else:
            yield 0, "Backup completed"

        duration = job_state["finished"] - job_state["started"]
        yield 0, "it was running for %s from %s till %s" % \
            (get_age_human_readable(duration),
             get_timestamp_human_readable(job_state["started"]),
             get_timestamp_human_readable(job_state["finished"])), \
            [ ("backup_duration", duration),
              ("backup_avgspeed", job_state["bytes_per_second"]) ]

        if "size" in job_state:
            yield 0, "Size: %s" % get_bytes_human_readable(job_state["size"]), \
                    [ ("backup_size", job_state["size"]) ]

        next_run = job_state["next_schedule"]
        if next_run == "disabled":
            yield 1, "Schedule is currently disabled"

        elif next_run != None:
            if next_run < time.time():
                state = 2
            else:
                state = 0
            yield state, "Next run: %s" % get_timestamp_human_readable(next_run)



def inventory_mkbackup_system(parsed):
    for job_id in parsed.get("system", {}).keys():
        yield job_id, {}


def check_mkbackup_system(item, _no_params, parsed):
    job_state = parsed.get("system", {}).get(item)
    if not job_state:
        return

    return check_mkbackup(job_state)


check_info["mkbackup"] = {
    "parse_function"      : parse_mkbackup,
    "inventory_function"  : inventory_mkbackup_system,
    "check_function"      : check_mkbackup_system,
    "service_description" : "Backup %s",
    "has_perfdata"        : True,
}


def inventory_mkbackup_site(parsed):
    for site_id, jobs in parsed.get("site", {}).items():
        for job_id in jobs.keys():
            yield "%s backup %s" % (site_id, job_id), {}


def check_mkbackup_site(item, _no_params, parsed):
    site_id, job_id = item.split(" backup ")
    job_state = parsed.get("site", {}).get(site_id, {}).get(job_id)
    if not job_state:
        return

    return check_mkbackup(job_state)


check_info["mkbackup.site"] = {
    "inventory_function"  : inventory_mkbackup_site,
    "check_function"      : check_mkbackup_site,
    "service_description" : "OMD %s",
    "has_perfdata"        : True,
}
