#!/usr/bin/env python # # Program: check_sfan_http_agent # Version: 1.0 # Date : June 5, 2017 # Author : Gregor Verweyen , based on check_xml from Phillipe Smith # License: GPL (summary below and full text at http://www.fsf.org/licenses/gpl.txt) # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # Required: Speedfan http://www.almico.com/speedfan.php and speedfanhttpagent https://www.poweradmin.com/speedfanhttpagent/ # Description: # Nagios plugin to make SpeedFan services via speedfanhttpagent based on XML file or URL. # The plugin generates the service based on Xpath based search # # if the url 'http://host:port/?format=xml' is opened the data will be presentetd like this. Fro SpeedFan GUI you can see which values that are e.g. # 1st value = mainboar temperature, second value = CPU temperature... # # ... # # 35 # 38 # 43 # ... # # # 497 # 489 # ... # # Usage example: # # define command { # command_name sfan-fanspeed # command_line $USER1$/check_sfan_http_agent -a $HOSTADDRESS$ -p 8167 -t 'fan' -n $ARG1$ -l '100:900:0:1200:0:1500' -x # } # # define command { # command_name sfan-temperature # command_line $USER1$/check_sfan_http_agent -a $HOSTADDRESS$ -p 8167 -t 'temp' -n $ARG1$ -l ':54::65:0:100' -x # } # # define command { # command_name sfan-voltage # command_line $USER1$/check_sfan_http_agent -a $HOSTADDRESS$ -p 8167 -t 'volt' -n $ARG1$ -l '0.8:0.9:0.75:0.95:0.5:1' -x # } # # Service for monitoring the fan speed process # define service{ # use generic-service,srv-pnp # host_name Home WIN7 # service_description CPU Fan # check_command sfan-fanspeed!2 # } # define service{ # use generic-service,srv-pnp # host_name Home WIN7 # service_description MB Fan # check_command sfan-fanspeed!1 # } # # Importing necessary python modules import sys from urllib2 import urlopen, HTTPError, URLError from optparse import OptionParser # Plugin options definitions parser = OptionParser() parser.add_option('-a', '--host', dest='host', default=False, help='required - Host where speedfanhttpagent is running') parser.add_option('-p', '--port', dest='port', default=False, help='required - Port of speedfanhttpagent') parser.add_option('-l', '--levels', dest='levels', default=False, help='optional - Limits for WARNING and CRITICAL.\nThe format must be like: "lowwarn:highwarn:lowcrit:highcrit[:min:max]".\n min:max are optional, however, if only one is specified the two colons need to be there e.g. ::100 to just specify a max value, same for the first 4 values, if one is not needed the colon must exist so levels either contains 4 :::: or 6 :::::: with or without preceeding values') parser.add_option('-t', '--type', dest='type', default='temp', help='optional, defaults to temp - Retrieve the value type, can be temp, fan or volt') parser.add_option('-n', '--number', dest='number', default=1, help='optional, defaults to 1 - Retrieve number of the value for the selected type') parser.add_option('-x', '--perfdata', dest='perfdata', action='store_true', help='optional - Generate perfdata') options, args = parser.parse_args() # Variables definitions result = [] info = '' textinfo = '' itemtext = '' host = options.host port = options.port type = options.type number = options.number perfdata = [] if options.levels: levels = options.levels.strip().split(',') else: levels = False perf = options.perfdata url = False if host and port: url = 'http://%s:%s/?format=xml' %(host, port) if type == 'temp': childNode = 'temperatures/temperature' elif type == 'fan': childNode = 'fans/fan' else: childNode = 'voltages/voltage' # Try import python xml module try: import xml.etree.cElementTree as elt except ImportError: import xml.etree.ElementTree as elt # Try retrieve XML informations from a http url if url: try: xml = urlopen(url) except HTTPError as err: print 'CRITICAL - %s' % err sys.exit(1) except URLError as err: print 'CRITICAL - %s' % err sys.exit(1) else: print 'UNKNOWN - No XML URL or no Xpath search passed.\n' parser.print_help() sys.exit(3) # Variable that will receive the XML content xmltree = elt.ElementTree(file=xml) output = [] # Defining the XML nodes parents and childs # based on the search made if childNode: for node in childNode.split(':'): if '/' in node: parent = '/'.join(node.split('/')[:-1]) + '/' child = node.split('/')[-1].split(',') else: parent = './' child = node.split(',') # Loop through child nodes to define the service for value in child: node = parent + value.strip() if xmltree.findall(node): node = xmltree.findall(node)[int(number)-1] if 'temperature' in node.tag: itemtext = 'Temperature' elif 'fan' in node.tag: itemtext = 'Speed' elif 'voltage' in node.tag: itemtext = 'Volt' textinfo = '%s: %s' % (itemtext, node.text) if levels: for level in [ x.split(':') for x in levels ]: if level[0] != '' and float(node.text) < float(level[0]): textinfo = '%s: %s (warn)' % (itemtext, node.text) elif level[1] != '' and float(node.text) > float(level[1]): textinfo = '%s: %s (warn)' % (itemtext, node.text) elif level[2] != '' and float(node.text) < float(level[2]): textinfo = '%s: %s (crit)' % (itemtext, node.text) elif level[3] != '' and float(node.text) > float(level[3]): textinfo = '%s: %s (crit)' % (itemtext, node.text) if len(level) > 4: perfdata.append('%s=%s;%s:%s;%s:%s;%s;%s' % (itemtext, node.text, level[0], level[1], level[2], level[3], level[4], level[5])) else: perfdata.append('%s=%s;%s:%s;%s:%s;' % (itemtext, node.text, level[0], level[1], level[2], level[3])) else: if not node.text.isalpha(): perfdata.append('%s=%s;' % (node.tag, node.text)) result.append(textinfo) else: print 'UNKNOWN - No XML URL/File or no Xpath search passed.\n' parser.print_help() sys.exit(3) # Service state definition for info in result: if '(crit)' in info: status = (2, 'CRITICAL') break elif '(warn)' in info: status = (1, 'WARNING') break else: status = (0, 'OK') break # Printing the result if perf: print '%s - %s | %s' % (status[1], ', '.join(result), ' '.join(perfdata)) else: print '%s - %s' % (status[1], ', '.join(result)) # Exiting based on the status number sys.exit(status[0])