#!/usr/bin/env python
# -*- coding: utf-8 -*-
# kate: space-indent on; indent-width 4; replace-tabs on;

"""
 *  Copyright (C) 2011-2016, it-novum GmbH <community@openattic.org>
 *
 *  openATTIC 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; version 2.
 *
 *  This package is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
"""

from __future__ import division

import sys
import os
import posix

from time import time
from optparse import OptionParser
from ConfigParser import ConfigParser
from configobj import ConfigObj

distro_config = [ '/etc/default/openattic', '/etc/sysconfig/openattic' ]
for filename in distro_config:
    if os.path.isfile(filename):
        config = ConfigObj(filename)
        break

sys.path.append(config['OADIR'])
from nagios.conf.distro import distro_settings

settings = distro_settings()

sys_hz = posix.sysconf( posix.sysconf_names['SC_CLK_TCK'] )

# read /proc/stat
fd = open("/proc/stat", "r")
try:
    sys_stats = [ line.split() for line in fd ]
except:
    print "Failed reading system statistics."
    sys.exit(2)

# Count CPUs
cpumax = 0
for stats in sys_stats[1:]:
    if stats[0].startswith("cpu"):
        cpuidx = int(stats[0][3:])
        cpumax = max(cpumax, cpuidx)
cpucount = cpumax + 1

cpu_stats = sys_stats[0]

fields = ["cpu", "user", "nice", "system", "idle"]

if len(cpu_stats) > 5:
    fields.extend(["iowait", "irq", "softirq"])

if len(cpu_stats) > 8:
    fields.append("steal")

if len(cpu_stats) > 9:
    fields.append("guest")

if len(cpu_stats) > 10:
    fields.append("guestnice")

stats = dict( zip( fields, cpu_stats ) )
del stats["cpu"]

#print cpu_stats
#print stats

# load savedstate
savedstate = ConfigParser()
cputime = "{}/cputime".format(settings["NAGIOS_STATE_DIR"])
havestate  = bool( savedstate.read(cputime) ) and savedstate.has_section("state")


def wrapdiff(curr, last):
    """ Calculate the difference between last and curr.

        If last > curr, try to guess the boundary at which the value must have wrapped
        by trying the maximum values of 64, 32 and 16 bit signed and unsigned ints.
    """
    if last <= curr:
        return curr - last

    boundary = None
    for chkbound in (64,63,32,31,16,15):
        if last > 2**chkbound:
            break
        boundary = chkbound
    if boundary is None:
        raise ArithmeticError("Couldn't determine boundary")
    return 2**boundary - last + curr


exit = 0

if havestate:
    perfdata = {}

    dt = time() - savedstate.getfloat("state", "timestamp")

    for field in stats:
        if savedstate.has_option("state", field):
            dticks = wrapdiff( int(stats[field]), savedstate.getint("state", field) )
            dsecs  = dticks / sys_hz
            perfdata[field] = dsecs / dt / cpucount * 100

    busy  = 100 - perfdata["idle"]

    print "User %.2f%%, Sys %.2f%%, IOwait %.2f%%, Idle %.2f%%|%s" % (
        perfdata["user"], perfdata["system"], perfdata["iowait"], perfdata["idle"],
        ' '.join([ "%s=%.2f" % ( field, perfdata[field] ) for field in fields[1:] if field in perfdata ])
        )

    if busy >= 50:
        exit = 1
    if busy >= 80:
        exit = 2
    if perfdata["iowait"] >= 30:
        exit = 1
    if perfdata["iowait"] >= 50:
        exit = 2

else:
    print "Need state info, please wait until Nagios checks again."
    exit = 3
    savedstate.add_section("state")

for field in stats:
    savedstate.set("state", field, stats[field])

savedstate.set("state", "timestamp", time())

savedstate.write( open( cputime, "wb" ) )

sys.exit(exit)
