commit
bd136345c0
59
README.md
59
README.md
|
@ -1,32 +1,37 @@
|
||||||
# Monit Dashboard
|
# Monit Dashboard
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
Python web application to get a dashboard of a bunch of [Monit][monit]
|
|
||||||
servers at a glance.
|
Python web application to get a dashboard of a bunch of [Monit] servers at a
|
||||||
|
glance.
|
||||||
|
|
||||||
## How does it work?
|
## 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.
|
Every 300 seconds (hardcoded) the application ask for the data served by the
|
||||||
Then, thanks to the built-in web server, it is displayed in a single
|
Monit built-in web server in a XMl report from each configured server. Then,
|
||||||
HTML page.
|
thanks to the built-in web server, it is displayed in a single HTML page.
|
||||||
|
|
||||||
## Pre requisites
|
## Pre requisites
|
||||||
|
|
||||||
### Debian GNU/Linux
|
### Debian GNU/Linux
|
||||||
|
|
||||||
#### Web.py framework
|
#### Web.py framework
|
||||||
|
|
||||||
- `apt install python-webpy`
|
- `apt install python-webpy`
|
||||||
|
|
||||||
#### Python libraries
|
#### Python libraries
|
||||||
|
|
||||||
- `apt install python-xmltodict python-requests`
|
- `apt install python-xmltodict python-requests`
|
||||||
|
|
||||||
### CentOS
|
### CentOS
|
||||||
|
|
||||||
#### Python PIP
|
#### Python PIP
|
||||||
|
|
||||||
- `yum install epel-release`
|
- `yum install epel-release`
|
||||||
- `yum install python-pip`
|
- `yum install python-pip`
|
||||||
|
|
||||||
#### Web.py framework
|
#### Web.py framework
|
||||||
|
|
||||||
- `pip install web.py`
|
- `pip install web.py`
|
||||||
|
|
||||||
#### Python libaries
|
#### Python libaries
|
||||||
|
@ -34,52 +39,58 @@ HTML page.
|
||||||
- `yum install python-requests python-xmltodict python-simplejson`
|
- `yum install python-requests python-xmltodict python-simplejson`
|
||||||
|
|
||||||
## Requisites
|
## Requisites
|
||||||
- Config file `conf/servers.json` prior run. You might find a sample
|
|
||||||
file at `conf/servers.json.example`.
|
- 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.
|
- Please see [Config](#config) section for further details.
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
`./bin/monit-dashboard.py`
|
`./bin/monit-dashboard.py`
|
||||||
|
|
||||||
By default, it will be reachable at http://localhost:8080. You might
|
By default, it will be reachable at <http://localhost:8080>. You might change
|
||||||
change the port by adjusting `app.run(port=8080)` in
|
the port by adjusting `app.run(port=8080)` in `bin/monit-dashboard.py` file.
|
||||||
`bin/monit-dashboard.py` file.
|
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- [web.py 0.3 tutorial][webpy-tutorial]
|
- [web.py 0.3 tutorial][webpy-tutorial]
|
||||||
- [Learn Python the hard way, ex 50][lpthw]
|
- [Learn Python the hard way, ex 50][lpthw]
|
||||||
- [A template example][template-example]
|
- [A template example][template-example]
|
||||||
- [How to change HTTP server port][port]
|
- [How to change HTTP server port][port]
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
- Placed in `conf/servers.json`
|
- Placed in `conf/servers.json`
|
||||||
- Sample settings as follows:
|
- Sample settings as follows:
|
||||||
```
|
|
||||||
{
|
```
|
||||||
|
{
|
||||||
"My server to monit": {
|
"My server to monit": {
|
||||||
"url": "http://example.com:2812",
|
"url": "http://example.com:2812",
|
||||||
"user": "monit",
|
"user": "monit",
|
||||||
"passwd": "*****"
|
"passwd": "*****"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
```
|
||||||
```
|
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
- [Original idea][idea]
|
- [Original idea][idea]
|
||||||
- Frontend support: Júlia Vázquez
|
- Frontend support: Júlia Vázquez
|
||||||
- [Icons][icons]
|
- [Icons]
|
||||||
- [Accordion menu][accordion]
|
- [Accordion menu][accordion]
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
[AGPL][license]
|
[AGPL][license]
|
||||||
|
|
||||||
|
[accordion]: http://www.w3schools.com/howto/howto_js_accordion.asp
|
||||||
|
[icons]: https://commons.wikimedia.org/wiki/User:House
|
||||||
|
[idea]: https://imil.net/blog/2016/03/16/Fetch-monit-status-in-JSON/
|
||||||
|
[license]: LICENSE
|
||||||
|
[lpthw]: https://learnpythonthehardway.org/book/ex50.html
|
||||||
[monit]: https://mmonit.com/monit/
|
[monit]: https://mmonit.com/monit/
|
||||||
|
[port]: https://stackoverflow.com/questions/14444913/web-py-specify-address-and-port
|
||||||
|
[template-example]: https://stackoverflow.com/questions/28508869/using-web-py-to-dynamically-output-values-from-process-initiated-by-form-submiss
|
||||||
[webpy]: http://webpy.org/
|
[webpy]: http://webpy.org/
|
||||||
[webpy-tutorial]: http://webpy.org/tutorial3.en
|
[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
|
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import web
|
import web
|
||||||
import requests, xmltodict, json, os, sys
|
import requests
|
||||||
|
import xmltodict
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
urls = ('/', 'index',
|
urls = ('/', 'index',
|
||||||
'/help', 'help'
|
'/help', 'help'
|
||||||
)
|
)
|
||||||
|
|
||||||
app = web.application(urls, globals())
|
app = web.application(urls, globals())
|
||||||
render = web.template.render('templates/', base="layout")
|
render = web.template.render('templates/', base="layout")
|
||||||
|
|
||||||
## Uncomment to turn debug off
|
# Uncomment to turn debug off
|
||||||
web.config.debug = False
|
web.config.debug = False
|
||||||
|
|
||||||
## Variables
|
# Variables
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
## Functions
|
# Functions
|
||||||
|
|
||||||
|
|
||||||
def getMonit():
|
def getMonit():
|
||||||
output = []
|
output = []
|
||||||
|
@ -30,7 +35,8 @@ def getMonit():
|
||||||
|
|
||||||
for site in cf:
|
for site in cf:
|
||||||
s = cf[site]
|
s = cf[site]
|
||||||
r = requests.get(s['url'] + xmlQuery, auth = (s['user'], s['passwd']))
|
r = requests.get(s['url'] + xmlQuery,
|
||||||
|
auth=(s['user'], s['passwd']))
|
||||||
|
|
||||||
allstat = json.loads(json.dumps(xmltodict.parse(r.text)['monit']))
|
allstat = json.loads(json.dumps(xmltodict.parse(r.text)['monit']))
|
||||||
|
|
||||||
|
@ -43,29 +49,35 @@ def getMonit():
|
||||||
status[name] = int(service['status'])
|
status[name] = int(service['status'])
|
||||||
checks[service['name']] = status[name]
|
checks[service['name']] = status[name]
|
||||||
|
|
||||||
server = dict(name = site, url = s['url'], result = checks)
|
server = dict(name=site, url=s['url'], result=checks)
|
||||||
|
|
||||||
output.append(server)
|
output.append(server)
|
||||||
|
|
||||||
print(datetime.datetime.now())
|
print(datetime.datetime.now())
|
||||||
return(output)
|
return(output)
|
||||||
|
|
||||||
## Classes
|
# Classes
|
||||||
|
|
||||||
|
|
||||||
class monitDashboard(web.application):
|
class monitDashboard(web.application):
|
||||||
|
|
||||||
def run(self, port=8080, *middleware):
|
def run(self, port=8080, *middleware):
|
||||||
func = self.wsgifunc(*middleware)
|
func = self.wsgifunc(*middleware)
|
||||||
return web.httpserver.runsimple(func, ('0.0.0.0', port))
|
return web.httpserver.runsimple(func, ('0.0.0.0', port))
|
||||||
|
|
||||||
|
|
||||||
class index(object):
|
class index(object):
|
||||||
|
|
||||||
def GET(self):
|
def GET(self):
|
||||||
return render.index(output = getMonit(), now = datetime.datetime.now())
|
return render.index(output=getMonit(), now=datetime.datetime.now())
|
||||||
|
|
||||||
|
|
||||||
class help(object):
|
class help(object):
|
||||||
|
|
||||||
def GET(self):
|
def GET(self):
|
||||||
return render.help()
|
return render.help()
|
||||||
|
|
||||||
## Main
|
# Main
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = monitDashboard(urls, globals())
|
app = monitDashboard(urls, globals())
|
||||||
app.run(port=8080)
|
app.run(port=8080)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
.server-link a {
|
.server-link a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
|
@ -16,57 +16,57 @@ td {
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: arial;
|
font-family: arial;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:nth-child(odd) {
|
tr:nth-child(odd) {
|
||||||
background-color:#fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:nth-child(even) {
|
tr:nth-child(even) {
|
||||||
background-color:#f2f2f2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #cb0017;
|
color: #cb0017;
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.accordion {
|
button.accordion {
|
||||||
color: #444;
|
color: #444;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
transition: 0.4s;
|
transition: 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.panel {
|
div.panel {
|
||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.panel.show {
|
div.panel.show {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.green {
|
.green {
|
||||||
background-color: #79bd8f;
|
background-color: #79bd8f;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.green:hover {
|
.green:hover {
|
||||||
background-color: #588a68;
|
background-color: #588a68;
|
||||||
}
|
}
|
||||||
|
|
||||||
.red {
|
.red {
|
||||||
background-color: #d9534f;
|
background-color: #d9534f;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.red:hover {
|
.red:hover {
|
||||||
background-color: #c9302c;
|
background-color: #c9302c;
|
||||||
}
|
}
|
|
@ -2,8 +2,8 @@ var acc = document.getElementsByClassName("accordion");
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
for (i = 0; i < acc.length; i++) {
|
for (i = 0; i < acc.length; i++) {
|
||||||
acc[i].onclick = function(){
|
acc[i].onclick = function() {
|
||||||
this.classList.toggle("active");
|
this.classList.toggle("active");
|
||||||
this.nextElementSibling.classList.toggle("show");
|
this.nextElementSibling.classList.toggle("show");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
<article>
|
<article>
|
||||||
<p>Please check the README file.</p>
|
<p>Please check the README file.</p>
|
||||||
</article>
|
</article>
|
|
@ -1,15 +1,18 @@
|
||||||
$def with (content)
|
$def with (content)
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Monit Dashboard</title>
|
<title>Monit Dashboard</title>
|
||||||
<link rel="stylesheet" type="text/css" href="static/monit-dashboard.css" />
|
<link rel="stylesheet" type="text/css" href="static/monit-dashboard.css" />
|
||||||
<meta http-equiv="refresh" content="300">
|
<meta http-equiv="refresh" content="300">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
$:content
|
$:content
|
||||||
|
|
||||||
<a href="/">Home</a> | <a href="/help">Help</a>
|
<a href="/">Home</a> | <a href="/help">Help</a>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
Loading…
Reference in a new issue