Skip to content

Instantly share code, notes, and snippets.

@jn0
Created April 21, 2017 10:41
Show Gist options
  • Save jn0/73bbfdc690ef14de4b06dd83eb1d1ca9 to your computer and use it in GitHub Desktop.
Save jn0/73bbfdc690ef14de4b06dd83eb1d1ca9 to your computer and use it in GitHub Desktop.
zpool status block for zabbix/grafana
#!/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