#!/usr/bin/env python # # Program: check_xml # Version: 1.0 # Date : Nov 14, 2014 # Author : 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. # # # Description: # Nagios plugin to make services based on XML file or URL. # The plugin generates the service based on Xpath based search # # Command line usage example: # ./check_xml -u 'http://adobe_flash_media_server:1111/admin/getServerStats?auser=admin&apswd=admin' -n 'data/io/connected,total_connects,total_disconnects' -l 'connected:80:100' # ./check_xml -f teste-file.xml -n './status,timestamp:./Users/connected:./Users/user/name,email' -l 'connected:80:100' # # Nagios configuration example: # define command { # command_name check_xml # command_line $USER1$/check_xml -u "$ARG1$" -n "$ARG2$" -l "$ARG3$" -p # } # # define service { # use generic_service # host_name HOST_1 # service_description Adobe Flash Media Server Connections # check_command check_xml!data/io/connected,total_connects,total_disconnects!connected:80:100 # } # # # Importing necessary python modules import sys from urllib2 import urlopen, HTTPError, URLError from optparse import OptionParser # Plugin options definitions parser = OptionParser() parser.add_option('-u', '--url', dest='url', default=False, help='XML Document URL') parser.add_option('-f', '--file', dest='file', default=False, help='XML Document File') parser.add_option('-l', '--levels', dest='levels', default='', help='Thresholds based on the node name\nThe format must be like: "node_name:warn:crit". Ex.: "users_connected:80:100,total_users:100:150"') parser.add_option('-n', '--childnode', dest='childNode', default=False, help='Retrive childNode(s) value(s) from given XPath format,\n plus conma separated child nodes \nEx.: /Users/user/name,email,address') parser.add_option('-p', '--perfdata', dest='perfdata', action='store_true', help='Generate perfdata') options, args = parser.parse_args() # Variables definitions result = [] info = '' textinfo = '' url = options.url file = options.file childNode = options.childNode levels = options.levels.strip().split(',') perf = options.perfdata perfdata = [] # 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 'CRIT - %s' % err sys.exit(1) except URLError as err: print 'CRIT - %s' % err sys.exit(1) elif file: try: xml = open(file) except Exception as err: print 'CRIT - %s' % err sys.exit(1) else: print 'UNKNOWN - No XML URL/File 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)[0] textinfo = '%s: %s' % (node.tag, node.text) if levels and levels[0] != '': for level in [ x.split(':') for x in levels if node.tag in x ]: if float(node.text) > float(level[2]): textinfo = '%s: %s (crit)' % (node.tag, node.text) elif float(node.text) > float(level[1]): textinfo = '%s: %s (warn)' % (node.tag, node.text) perfdata.append('%s=%s;%s;%s;' % (node.tag, node.text, level[1], level[2])) 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, 'CRIT') break elif '(warn)' in info: status = (1, 'WARN') 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])