From 0e115ee1fe413612ec3596fb409e17df6a4af75f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0?= Date: Sat, 7 Jan 2017 12:46:50 +0100 Subject: [PATCH] Initial commit I was working in a private repo and decided to switch to a public one without keeping the old commits. --- .gitignore | 3 ++ README.md | 87 ++++++++++++++++++++++++++++++++++++- __init__.py | 0 bin/monit-dashboard.py | 71 ++++++++++++++++++++++++++++++ conf/servers.json.example | 14 ++++++ static/img/error.png | Bin 0 -> 719 bytes static/img/ok.png | Bin 0 -> 711 bytes static/monit-dashboard.css | 72 ++++++++++++++++++++++++++++++ static/monit-dashboard.js | 9 ++++ templates/help.html | 3 ++ templates/index.html | 82 ++++++++++++++++++++++++++++++++++ templates/layout.html | 15 +++++++ tests/__init__.py | 0 13 files changed, 354 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 __init__.py create mode 100755 bin/monit-dashboard.py create mode 100644 conf/servers.json.example create mode 100644 static/img/error.png create mode 100644 static/img/ok.png create mode 100644 static/monit-dashboard.css create mode 100644 static/monit-dashboard.js create mode 100644 templates/help.html create mode 100644 templates/index.html create mode 100644 templates/layout.html create mode 100644 tests/__init__.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bb99d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +.*.swp +conf/servers.json diff --git a/README.md b/README.md index df9b82a..78a97a4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,85 @@ -# monit-dashboard - A web dashboard for rule all monit servers at a glance +# Monit Dashboard + +## Description +Python web application to get a dashboard of a bunch of [Monit][monit] +servers at a glance. + +## How does it work? +Every 300 seconds the application ask for the data served by the +Monit built-in web server in a XMl report from each configured server. +Then, thanks to the built-in web server, it is displayed in a single +HTML page. + +## Pre requisites + +### Debian GNU/Linux + +#### Web.py framework +- `apt install python-webpy` + +#### Python libraries +- `apt install python-xmltodict python-requests` + +### CentOS + +#### Python PIP +- `yum install epel-release` +- `yum install python-pip` + +#### Web.py framework +- `pip install web.py` + +#### Python libaries + +- `yum install python-requests python-xmltodict python-simplejson` + +## Requisites +- Config file `conf/servers.json` prior run. You might find a sample +file at `conf/servers.json.example`. +- Please see [Config](#config) section for further details. + +## Run +`./bin/monit-dashboard.py` + +By default, it will be reachable at http://localhost:8080. You might +change the port by adjusting `app.run(port=8080)` in +`bin/monit-dashboard.py` file. + +## References +- [web.py 0.3 tutorial][webpy-tutorial] +- [Learn Python the hard way, ex 50][lpthw] +- [A template example][template-example] +- [How to change HTTP server port][port] + +## Config +- Placed in `conf/servers.json` +- Sample settings as follows: +``` +{ + "My server to monit": { + "url": "http://example.com:2812", + "user": "monit", + "passwd": "*****" + } +} +``` + +# Credits +- [Original idea][idea] +- Frontend support: Júlia Vázquez +- [Icons][icons] +- [Accordion menu][accordion] + +# License +[AGPL][license] + +[monit]: https://mmonit.com/monit/ +[webpy]: http://webpy.org/ +[webpy-tutorial]: http://webpy.org/tutorial3.en +[port]: https://stackoverflow.com/questions/14444913/web-py-specify-address-and-port +[lpthw]: https://learnpythonthehardway.org/book/ex50.html +[template-example]: https://stackoverflow.com/questions/28508869/using-web-py-to-dynamically-output-values-from-process-initiated-by-form-submiss +[idea]: https://imil.net/blog/2016/03/16/Fetch-monit-status-in-JSON/ +[icons]: https://commons.wikimedia.org/wiki/User:House +[accordion]: http://www.w3schools.com/howto/howto_js_accordion.asp +[license]: LICENSE diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bin/monit-dashboard.py b/bin/monit-dashboard.py new file mode 100755 index 0000000..c5dc05d --- /dev/null +++ b/bin/monit-dashboard.py @@ -0,0 +1,71 @@ +#!/usr/bin/python + +import web +import requests, xmltodict, json, os, sys +import datetime + +urls = ('/', 'index', + '/help', 'help' +) + +app = web.application(urls, globals()) +render = web.template.render('templates/', base="layout") + +## Uncomment to turn debug off +web.config.debug = False + +## Variables +output = [] + +## Functions + +def getMonit(): + output = [] + server = {} + checks = {} + xmlQuery = "/_status?format=xml" + + with open('{0}/conf/servers.json'.format(os.path.expanduser('.'))) as f: + cf = json.loads(f.read()) + + for site in cf: + s = cf[site] + r = requests.get(s['url'] + xmlQuery, auth = (s['user'], s['passwd'])) + + allstat = json.loads(json.dumps(xmltodict.parse(r.text)['monit'])) + + services = allstat['service'] + status = {} + checks = {} + + for service in services: + name = service['name'] + status[name] = int(service['status']) + checks[service['name']] = status[name] + + server = dict(name = site, url = s['url'], result = checks) + + output.append(server) + + print(datetime.datetime.now()) + return(output) + +## Classes + +class monitDashboard(web.application): + def run(self, port=8080, *middleware): + func = self.wsgifunc(*middleware) + return web.httpserver.runsimple(func, ('0.0.0.0', port)) + +class index(object): + def GET(self): + return render.index(output = getMonit(), now = datetime.datetime.now()) + +class help(object): + def GET(self): + return render.help() + +## Main +if __name__ == "__main__": + app = monitDashboard(urls, globals()) + app.run(port=8080) diff --git a/conf/servers.json.example b/conf/servers.json.example new file mode 100644 index 0000000..7cbdbe4 --- /dev/null +++ b/conf/servers.json.example @@ -0,0 +1,14 @@ +{ + Server A": { + "url": "http://one.example.com:2812", + "user": "monit", + "passwd": "secret" + }, + + "Server B": { + "url": "http://two.example.com:2812", + "user": "monit", + "passwd": "secret" + } + +} diff --git a/static/img/error.png b/static/img/error.png new file mode 100644 index 0000000000000000000000000000000000000000..5e52ae6e42596c6c328f7023a41013fbf15e08bb GIT binary patch literal 719 zcmV;=0xgZBD3z!ggALiE}0oA2{^-#kCw zQ|J*p;H|+6Akl(5018xqjbr%w9O~EQDOZI81Z;Q#qghCE<9)Jz#JHNK<&(F8bzvkv7@Ape}ZLO`lOR>SVTmcrYVJJR5TDnRi&0rOD&xiLsdlsDGUusbAMk%MC@u+ z@_l^{^tG!6&j5Uh1g<~;0Cy-ve03F1B!X?4l&7aDPfuf;Chl;Udn+rr!(jkiem}mc zDW`f*T?*Uw_HlO0|sS76wsfDJ&a)jht= zCWu^oi$J5%Ws~z<1#B0v3vgO4cbKefmLJI^%}NEgs^V5vnw1JW$s|@L)8TDg&?~ES)`*qPg`q&mhM7bo%uT2^R;#7>*_4f(OIYiB!O(* z1z_<7+S&`XwHIiE)GW{jDh7!ImElD|H9%Vo78#f|YYQEImVyT72G7HOPme$Ly zZI|2HuCTRRVdt>Y!EvRd^D1YT)h=#p+&tELc&+vFUgsUKAs}#LV9>^(u+3rNo5NFf zreyEQ&e@xjyEiv~Uw-rP=GGIfZ718NoS(Aw?$(_TcJ6wx>(Jvv$DbWP@$AIO=O<4+ zKXvxS*|RUto_l%j{LAx~UthlZ=IZsg*KfVMb^HD8dmrvS`1s)Qr^in|KY9B3>9a4- zo_~4%;_Hk5|NkrWT=)(QIL(qEzhDM7b`DN1UOrVdbxkd87grCj%Bt$xx`xK4$unlo zx^nf}^*eXpzI*@SEo-U3d5|XY5Ih7AFNU%M~7gh~1 znc6vFQ@QVy-)FAA)k(Lss`&rk-@v#^?&nfA)7a}wT|5=(JQh7O!efLz57?{^Ip>p* z=_B(vGvcfNtzV|xD+4$7s%-q~60Y3d;_i~PLGI^!z2*%aSqskD>*t0|3`-G8>tB~< zcKy{X4o{KgCARC67awI(5^|rpXQ$H74Q*%5A`h)Ov+zu`cJbNYI@{tsrwL5g@cU89 z@w!OVI)96(z(j#Fa@Fh%W%n~*&*JFJTHsdpZR7WY@}WyaCuT +

Please check the README file.

+ diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..28512df --- /dev/null +++ b/templates/index.html @@ -0,0 +1,82 @@ +$def with (output, now) + +$ errors = 0 +$ color = "green" +$for server in range(len(output)): + $code: + errors = 0 + color = "green" + + $for check in output[server]['result'].keys(): + $ isError = output[server]['result'].get(check) + $if isError != 0: + $code: + errors=errors+1 + + $if errors > 0: + $code: + color = "red" + +
+ +
+ + + + + $for check in output[server]['result'].keys(): + $ isError = output[server]['result'].get(check) + $if isError != 0: + + + + + $else: + + + + + +
+ $output[server]['name'] +
$check
$check
+
+ $else: + $code: + color = "green" + +
+ +
+ + + + + $for check in output[server]['result'].keys(): + $ isError = output[server]['result'].get(check) + $if isError != 0: + + + + + $else: + + + + + +
+ $output[server]['name'] +
$check
$check
+
+ +


+ +Latest update: $now.day/$now.month/$now.year, $now.hour:$now.minute:$now.second +

+ + diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 0000000..5bb58e8 --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,15 @@ +$def with (content) + + + + Monit Dashboard + + + + + +$:content + +Home | Help + + diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29