#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# +------------------------------------------------------------------+
#
# 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.
#
# This check created by Shawn McKee / University of Michigan
#   September 13, 2020
#
# This check processes the cfengine agent plugin
#
# Example Input
#<<<cfengine>>>
#Installed installed
#Service enabled
#PolicyPath /var/cfengine/policy/T2
#RunStatus Start:1600019392, End:1600019440, Version:4068, PromKept:95.54%, PromRepair:3.16%, PromNotRepair:1.31%
#   error: Finished command related to promiser 'dkms-openafs' -- an error occurred, returned 1
#   error: Bulk package schedule execution failed somewhere - unknown outcome for 'dkms-openafs.*'
#   error: Finished command related to promiser '/sbin/service syslog-ng start' -- an error occurred, returned 1
#  notice: Q: "...in/service sysl": WARNING: Configuration file format is newer than the current version, please specify the current version number (3.2) in the @version directive;
#Q: "...in/service sysl": Error parsing filter expression, error compiling template: Unknown template function %% in /etc/syslog-ng/syslog-ng.conf at line 58, column 18:
#Q: "...in/service sysl": filter  f_es_3 { "$(%% ${RCPTID} 4)" eq "0" };
#Q: "...in/service sysl":                  ^^^^^^^^^^^^^^^^^^
#Q: "...in/service sysl": syslog-ng documentation: http://www.balabit.com/support/documentation/?product=syslog-ng
#Q: "...in/service sysl": mailing list: https://lists.balabit.hu/mailman/listinfo/syslog-ng
#   error: Method 'standard_services' failed in some repairs
#
#

import time

cfengine_default_values = '/var/cfengine/policy/T2'

factory_settings["cfengine_default_levels"] = {
	"PromKept": (80,90),
	"PromRepair": (None,None),
	"PromNotRepair": (2,5),
        "Run_time":     (60.0,500.0),          # Warn at 60 seconds, Crit a 500+ seconds
        "Last_run":     (4200,8400),         # Warn at 2100 seconds, Crit a 3900+
}


def inventory_cfengine(info):
        inventory = []
        for line in info:
                if line[0] == 'Installed':
                        inventory.append( (line[0], None) )
                        if line[1] == 'installed':
                                inventory.append( ('Service', None) )
                                inventory.append( ('PolicyPath', 'cfengine_default_values') )
                                inventory.append( ('RunStatus', {}) )
                                inventory.append( ('Output', None) )
        return inventory

def check_cfengine(item,params,info):
        linestr = ''
        for line in info:
                if item == 'Installed':
                        if line[0] == item:
                                if line[1] == 'not':
                                        return(0,"CFEngine not installed")
                                else: 
                                        return(0,"CFEngine is installed")
                if item == 'Service':
                        if line[0] == item:
                                if line[1] == 'disabled':
                                        return(2,"cfengine3 service not enabled")
                                else:
                                        return(0,"cfengine3 service is enabled")

                if item == 'PolicyPath':
		        policy = params
                        if line[0] == item:
                                if line[1] == policy:
                                        return(0,"Policy path is correct: %s" % line[1])
                                elif line[1] == 'none':
                                        return(2,"Policy path not found")
                                else:
                                        return(1,"Policy path unexpected: %s" % line[1])

                if item == 'RunStatus':
                        if line[0] != item:
				continue
			else:
				text = "RunStatus "
				perfdata = []
				status = 0
				stats = {}
				kv = line[3].split(":", 2)
				stats["Version"] = kv[1].rstrip(',')
				text += "Version: %s, " % kv[1].rstrip(',')
				kv = line[1].split(":", 2)
				stats["Start"] = kv[1].rstrip(',')
#				text += "Start: %s, " % kv[1].rstrip(',')
				kv = line[2].split(":", 2)
				stats["End"] = kv[1].rstrip(',')
#				text += "End: %s, " % kv[1].rstrip(',')
				stats["Run_time"] = int(stats["End"]) - int(stats["Start"])
				text += "Run_time: %s, " % stats["Run_time"]
				stats["Last_run"] = int(time.time()) - int(stats["End"])
				text += "Last_run: %s, " % stats["Last_run"]
				kv = line[4].split(":", 2)
				stats["PromKept"] = kv[1].rstrip(',')
				text += "PromKept: %s, " % kv[1].rstrip('%,')
				kv = line[5].split(":", 2)
				stats["PromRepair"] = kv[1].rstrip(',')
				text += "PromRepair: %s, " % kv[1].rstrip('%,')
				kv = line[6].split(":", 2)
				text += "PromNotRepair: %s" % kv[1].rstrip('%,')
				stats["PromNotRepair"] = kv[1].rstrip(',')
# Process limits and perfdata
				for key in params:
					if "_lower" in key:
						warn, crit = params[key]
						field = key.replace("_lower","")
						try:
							value = savefloat(stats[field])
						except:
							value = saveint(state[field])
						if value != None and crit != None and value <= crit:
							text += ", CRIT(%s)" % field
							status = max(2, status)
						elif value != None and warn != None and value <= warn:
							text += ", WARN(%s)" % field
							status = max(1, status)
						else:
							status = max(0, status)
						if isinstance(value, int):
							perfdata.append((field, "%d" % value, '', '', warn, crit))
						if isinstance(value, float):
							perfdata.append((field, "%f" % value, '', '', warn, crit))
 
					else:
						warn, crit = params[key]
						field = key
						try:
							value = savefloat(stats[field])
						except:
							value = saveint(state[field])
						if value != None and crit != None and value >= crit:
							text += ", CRIT(%s)" % field
							status = max(2, status)
						elif value != None and warn != None and value >= warn:
							text += ", WARN(%s)" % field
							status = max(1, status)
						else:
							status = max(0, status)
						if isinstance(value, int):
							perfdata.append((field, "%d" % value, warn, crit))
						if isinstance(value, float):
							perfdata.append((field, "%f" % value, warn, crit))

				return(status, text, perfdata)

                if item == 'Output': 
                        if line[0] == 'Installed' or line[0] == 'PolicyPath' or line[0] == 'Service' or line[0] == 'RunStatus':
                                continue
                        if line[1] == 'none':
                                return(0, "Good - no output")
                        else:
                                linestr += '\n' + ' '.join(line)

        return (1, "Last run output: %s" % linestr)

# declare the check to Check_MK
check_info["cfengine"] = {
    'check_function':            check_cfengine,
    'inventory_function':        inventory_cfengine,
    'service_description':       'CFEngine %s',
    'default_levels_variable':   'cfengine_default_levels',
    'has_perfdata':  True,
}
