Created
April 21, 2017 10:41
-
-
Save jn0/73bbfdc690ef14de4b06dd83eb1d1ca9 to your computer and use it in GitHub Desktop.
zpool status block for zabbix/grafana
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
''' | |
Make use of backend's CSS (it's a "bootstrap" deep in its heart). | |
Note: any inline "style" elements are filtered out! | |
JFYI: | |
.p-a-0 { padding:0 } | |
Usage: | |
0. Put this script to, say, /etc/zabbix/oss-status.py | |
1. Check /etc/zabbix/zabbix_agentd.conf to make sure you have | |
Include=/etc/zabbix/zabbix_agentd.d/ | |
line there and uncommented. | |
2. Create /etc/zabbix/zabbix_agentd.d/ossNN.conf with the line | |
UserParameter= oss.zpool, python /etc/zabbix/oss-status.py | |
3. Make zabbix agent sure about your changes. | |
''' | |
import subprocess | |
import re | |
import sys | |
MAX_LINES_FOR_1_COLUMN = 4 # make table two-columns if more lines fetched | |
class goodPopen(subprocess.Popen): | |
'''You don't want to .wait() it yourself.''' | |
def __enter__(self, *av): | |
'Nothing special, just provide the interface.' | |
return self | |
def __exit__(self, xt, xv, tb): | |
'Do what you mostly forget to. Let exceptions to go.' | |
self.wait() | |
#end class goodPopen | |
# make sure zabbix cannot do anything else! | |
def fetch_status(status_cmd=('sudo', '/usr/sbin/zpool', 'status')): | |
'Run status command, grab output, return filtered.' | |
values = [] | |
with goodPopen(status_cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE) as pipe: | |
for line in pipe.stdout.xreadlines(): | |
if not re.search('ONLINE|OFFLINE|DEGRADED|FAULTED|REMOVED|UNAVAIL', line): | |
continue | |
values.append(tuple(line.split()[:2])) # (<pool>, <status>) | |
return values | |
def render_value(value, | |
success_classes=('text-success',), | |
error_classes=('text-error',)): | |
'Returns display string and CSS class(es) for an appropriate entry.' | |
pool, status = value | |
if status == 'ONLINE': | |
klass = ' '.join(success_classes) | |
displ = pool | |
else: | |
klass = ' '.join(error_classes) | |
displ = pool + '<br />' + status # display status value, if not "ok" | |
return displ, klass | |
def main(): | |
values = fetch_status() | |
header = values.pop(0) # the 1st line is the header (the whole pool status) | |
displ, klass = render_value(('pool state', header[1]), | |
success_classes=('text-success', | |
'icon-gf', 'icon-gf-online',), | |
error_classes=('alert', 'alert-error', | |
'icon-gf', 'icon-gf-event-error',)) | |
colspan = (len(values) > MAX_LINES_FOR_1_COLUMN) and ' colspan=2' or '' | |
output_string = '<table class="max-width text-center"><thead>' \ | |
+ '<tr><th' + colspan + ' class="text-center ' + klass + '">' + displ + '</th></tr>' \ | |
+ '</thead><tbody>' | |
tds = ['<td class="p-a-0 ' + cls + '">' + dsp + '</td>' | |
for dsp, cls in map(render_value, values)] | |
tr = '' | |
for td in tds: | |
if colspan: | |
# quite simplified: only two columns supported | |
if tr: | |
output_string += '<tr class=p-a-0>' + tr + td + '</tr>\n' | |
tr = '' | |
else: | |
tr = td | |
else: | |
output_string += '<tr>' + td + '</tr>\n' | |
print output_string + "</tbody></table>" | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main()) | |
# EOF # |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment