#!/usr/bin/python -tt

# Things to check:
#
#   Is puppet disabled via a lockfile?
#   Is /var/lib/puppet/state/state.yaml being updated?
#       (The current check warns at 7200 and crits at 14400)

import os
import datetime
import optparse
import puppetstatus
from subprocess import Popen, PIPE

pidfile = '/var/run/puppet/puppetd.pid'
state = '/var/lib/puppet/state/state.yaml'

def unknown(msg):
    print 'UNKNOWN: %s' % msg
    sys.exit(3)

def crit(msg):
    print 'CRIT: %s' % msg
    sys.exit(2)

def warn(msg):
    print 'WARN: %s' % msg
    sys.exit(1)

def ok(msg):
    print 'OK: %s' % msg
    sys.exit(0)

def format_timedelta(td):
    """Format a datetime.timedelta object"""
    days = td.days
    hours = td.seconds // 3600
    minutes = (td.seconds % 3600) // 60
    seconds = td.seconds % 60
    s = '%d seconds ago' % seconds
    if minutes:
        s = '%d minutes and %s' % (minutes, s)
    if hours:
        s = '%d hours, %s' % (hours, s)
    if days:
        s = '%d days, %s' % (days, s)
    return s

usage = '%prog <warn_seconds> <crit_seconds>'
parser = optparse.OptionParser(usage=usage)
opts, args = parser.parse_args()

if len(args) != 2:
    unknown(parser.get_usage().strip())

try:
    warn_seconds, crit_seconds = map(int, args)
except Exception, exc:
    unknown('Unable to parse arguments: %s' % exc)

s = puppetstatus.PuppetStatus()

if s.disabled:
    if s.reason:
        if puppetstatus.PID_RE.match(s.reason):
            status = 'Puppet is dead but lockfile containing a pid exists.'
        else:
            status = 'Puppet is disabled: %s' % s.reason
    else:
        status = 'Puppet is disabled, but no reason was given.'
    warn(status)

try:
    cmd = ['service', 'puppet', 'status']
    p = Popen(cmd, stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate()
except Exception, error:
    unknown('Unable to get service status: %s' % error)
if p.returncode != 0:
    status = stdout and stdout or stderr
    warn(status.strip())

if not os.path.isfile(state):
    # Should perhaps be CRIT
    warn('Puppet has never run, no %s found.' % state)

# Check mtime on state file
now = datetime.datetime.now()
mtime = datetime.datetime.fromtimestamp(os.path.getmtime(state))
delta = now - mtime
lastrun = 'Puppet was last run %s' % format_timedelta(delta)

# Convert timedelta to seconds
age = delta.seconds
if delta.days:
    age += delta.days * 86400

if mtime > now:
    warn('Puppet state file modified in the future: %s' % mtime)
elif age > crit_seconds:
    crit(lastrun)
elif age > warn_seconds:
    warn(lastrun)
else:
    ok(lastrun)
