#!/usr/bin/env python3 import json import logging from datetime import datetime, timedelta from os import environ from re import sub from flask import Flask, abort, jsonify, render_template, request from psycopg2.pool import ThreadedConnectionPool app = Flask(__name__) app.config.from_file(environ['APP_CONFIG'], json.load) if not app.debug: log = logging.StreamHandler() log.setLevel(logging.INFO) app.logger.addHandler(log) pg_pool = ThreadedConnectionPool( minconn=1, maxconn=20, user=app.config['DB_USER'], password=app.config['DB_PASS'], database=app.config['DB_NAME'], host='localhost', ) def check_freshness(cur): cur.execute('select status_update_time from icinga_programstatus;') if datetime.utcnow() - cur.fetchone()[0] > timedelta(minutes=5): abort(503) def get_nodename(identifier): if identifier in HOSTS: return HOSTS[identifier] abort(404) @app.route('/status.json') def services_as_json(): conn = pg_pool.getconn() results = [] try: cur = conn.cursor() check_freshness(cur) cur.execute( ''' select objs.name1, objs.name2, icinga_servicestatus.current_state, icinga_servicestatus.scheduled_downtime_depth, icinga_servicestatus.state_type, icinga_servicestatus.output, icinga_servicestatus.problem_has_been_acknowledged, icinga_servicestatus.status_update_time, icinga_servicestatus.last_state_change, ( select vars.varvalue from icinga_customvariables vars, icinga_services where objs.object_id = icinga_services.service_object_id and icinga_services.host_object_id = vars.object_id and vars.varname = 'pretty_name' ) from icinga_objects objs left join icinga_servicestatus on objs.object_id = icinga_servicestatus.service_object_id left join icinga_servicegroup_members sgrm on objs.object_id = sgrm.service_object_id where objs.objecttype_id = 2 and objs.is_active = 1 and sgrm.servicegroup_id = %s ;''', (app.config['SERVICEGROUP_ID'],), ) for ( host_name, service_name, state, downtime_depth, state_type, output, acked, update_time, last_state_change, pretty_name, ) in cur.fetchall(): if last_state_change is None: last_state_change = update_time for regex, replacement in app.config.get('NAME_REPLACEMENTS', {}).items(): service_name = sub(regex, replacement, service_name) results.append( { 'type': 'Service', 'attrs': { 'acknowledgement': acked, 'display_name': service_name, 'downtime_depth': downtime_depth, 'host_name': pretty_name, 'last_check': update_time.timestamp(), 'last_state_change': last_state_change.timestamp(), 'state': state, 'state_type': state_type, 'last_check_result': { 'output': output, }, '__custom': { 'last_check': update_time.strftime('%Y-%m-%d %H:%M:%S UTC'), 'last_state_change': last_state_change.strftime( '%Y-%m-%d %H:%M:%S UTC' ), }, }, } ) cur.close() finally: pg_pool.putconn(conn) return jsonify({'results': results}) @app.route('/') def statuspage(): return render_template('statuspage.html') if __name__ == '__main__': app.run(host='::')