#!/usr/bin/ruby # Copyright (c) 2004, 2005 Peter Palfrader require "yaml" ORG="relativity" SHORTORG="rela" CONTACTGROUP="weaselgroup" GENERATED_PREFIX="/etc/NOREPLY/generated/nagios/" MAX_CHECK_ATTEMPTS_DEFAULT=6 class Nrpe def initialize @checks = {} end def make_name( name, check ) name = name.tr_s("^a-zA-Z", "_").gsub("process", "ps") result = "#{ SHORTORG }_" + name[0,19] hash = '' skew = '' while (@checks.has_key?(result + hash)) # hash it, so that we don't lose uniqeness by cutting it off hash = (check+skew).crypt("$1$") hash = hash[-5,5] # 5 chars are enough hash.tr!("/", "_") skew += ' ' # change it a bit so the hash changes end result += hash return result # max of 32 or so chars end def add( name, check ) if @checks.has_value? check @checks.each_pair{ |key, value| return key if value == check } end key = make_name(name, check) @checks[ key ] = check return key end def checks return @checks end end $nrpe = Nrpe.new() def warn (msg) STDERR.puts msg end config = YAML::load( File.open( 'nagios-master.cfg' ) ) %w{auto-hosts.cfg auto-hostgroups.cfg auto-services.cfg auto-dependencies.cfg}.each{ |file| File.delete(GENERATED_PREFIX+"#{file}") if FileTest.file?(GENERATED_PREFIX+"#{file}") } ################################# # create a few hostgroups ################################# config['hostgroups'].each_value{ |hg| hg['members'] = [] } config['servers'].each_pair{ |name, server| throw "No hostgroups defined for #{name}" unless server['hostgroups'] server['hostgroups'].split(/,/).each{ |hg| hg.strip! throw "Hostgroup #{hg} is not defined" unless config['hostgroups'].has_key?(hg) config['hostgroups'][hg]['members'] << name }; } # create all config['hostgroups']['all'] = {} config['hostgroups']['all']['alias'] = "all servers" config['hostgroups']['all']['members'] = [] config['hostgroups']['pingable'] = {} config['hostgroups']['pingable']['alias'] = "pingable servers" config['hostgroups']['pingable']['members'] = [] config['servers'].each_key{ |name| config['hostgroups']['all']['members'] << name config['hostgroups']['pingable']['members'] << name unless (config['servers'][name]['pingable'] == false) } ####### # Hosts and Hostgroups f = File.new(GENERATED_PREFIX+"auto-hosts.cfg", "w") config['servers'].each_pair{ |name, server| if server.has_key?('ip') STDERR.puts("Host definition for #{name} has an 'ip' field. Please use address instead"); server['address'] = server['ip']; server.delete('ip'); end server['host_name'] = name server['alias'] = name unless server.has_key?('alias') server['check_command'] = 'check-host-alive' unless (server['pingable'] == false || server.has_key?('check_command')) server['use'] = 'generic-host' unless server.has_key?('use'); f.puts "define host{" server.each_pair{ |key, value| next if %w(hostgroups pingable).include? key f.puts " #{key} #{value}" } f.puts "}" f.puts } f = File.new(GENERATED_PREFIX+"auto-hostgroups.cfg", "w") config['hostgroups'].each_pair{ |name, hg| next if hg['private'] hg['contact_groups'] = CONTACTGROUP unless hg.has_key?('contact_groups') f.puts "define hostgroup{" f.puts " hostgroup_name #{ name }" f.puts " alias #{ hg['alias'] }" f.puts " contact_groups #{ hg['contact_groups'] }" f.puts " members "+hg['members'].join(",") f.puts "}" } ####### # Services and Dependencies def addService(hosts, service, f, deps) hosts_comma = hosts.join(',') f.puts "define service{" f.puts " use generic-service" f.puts " host_name #{ hosts_comma }" f.puts " service_description #{ service['name'] }" f.puts " check_command #{ service['check'] }" if service['check'] service['max_check_attempts']=MAX_CHECK_ATTEMPTS_DEFAULT unless service['max_check_attempts'] service['max_check_attempts']=MAX_CHECK_ATTEMPTS_DEFAULT+service['max_check_attempts'] if service['max_check_attempts'] < 0 if service['nrpe'] check = $nrpe.add(service['name'], service['nrpe']) f.puts " check_command #{ ORG }_check_nrpe!#{ check }" service['depends'] = 'process - nrpe' unless service['depends'] or service['name'] == 'process - nrpe' end # put additional keys into services service.each_pair{ |key, value| # known keys: next if %w(name check hosts nrpe remotecheck hostgroups excludehosts excludehostgroups depends runfrom).include? key f.puts " #{key} #{value}" } f.puts "}" if service['depends'] service['depends'].each{ |prerequisite| hosts.each{ |host| prerequisite_host = host pre = prerequisite # split off a hostname if there's one bananasplit = prerequisite.split(':') if bananasplit.size == 2 prerequisite_host = bananasplit[0] pre = bananasplit[1] elsif bananasplit.size > 2 throw "Cannot prase prerequisite #{prerequisite} for service #{service['name']} into host:service" end deps.puts "define servicedependency{" deps.puts " host_name #{ prerequisite_host }" deps.puts " service_description #{ pre }" deps.puts " dependent_host_name #{ host }" deps.puts " dependent_service_description #{ service['name'] }" deps.puts " execution_failure_criteria n" deps.puts " notification_failure_criteria w,u,c" deps.puts "}" } } end end f = File.new(GENERATED_PREFIX+"auto-services.cfg", "w") deps = File.new(GENERATED_PREFIX+"auto-dependencies.cfg", "w") config['services'].each{ |service| throw "Empty service or service not a hash" unless service.kind_of?(Hash) throw "nrpe, check, and remotecheck are mutually exclusive in service #{service['name']}" if (service['nrpe'] ? 1 : 0) + (service['check'] ? 1 : 0) + (service['remotecheck'] ? 1 : 0) >= 2 # Figure out the hosts this service applies to service['hosts'] = "" unless service['hosts'] service['hosts'].delete!(" \t") hosts = service['hosts'].split(/,/) if service['hostgroups'] then service['hostgroups'].delete(" \t").split(/,/).each{ |hg| unless config['hostgroups'][hg] throw "hostgroup #{hg} does not exist- used in service #{service['name']}" end hosts = hosts.concat config['hostgroups'][hg]['members'] } end excludehosts = [] if service['excludehosts'] then excludehosts = service['excludehosts'].delete(" \t").split(/,/) end if service['excludehostgroups'] then service['excludehostgroups'].delete(" \t").split(/,/).each{ |hg| unless config['hostgroups'][hg] throw "hostgroup #{hg} does not exist- used in service #{service['name']}" end excludehosts = excludehosts.concat config['hostgroups'][hg]['members'] } end excludehosts.each{ |host| if hosts.delete(host) == nil throw "Cannot remove host #{host} from service #{service['name']}: it's not included anyway" end } throw "no hosts for service #{service['name']}" if hosts.empty? if service['runfrom'] throw "need remotecheck with runfrom" unless service['remotecheck'] relay = service['runfrom'] hosts.each{ |host| host_ip = (config['servers'][host] ? config['servers'][host]['ip'] : gateway_name_to_ip[host] ) check = $nrpe.add("#{host}_#{service['name']}", service['remotecheck'].gsub(/\$HOSTADDRESS\$/, host_ip)) service['check'] = "#{ ORG }_check_nrpe_host!#{ config['servers'][ relay ]['ip'] }!#{ check }" if (service['depends'] == nil) service['depends'] = [] elsif service['depends'].kind_of?(String) d = [ service['depends'] ]; service['depends'] = d end service['depends'] << "#{ relay }:process - nrpe"; addService( [ host ], service, f, deps) } else throw "must not remotecheck without runfrom" if service['remotecheck'] addService(hosts, service, f, deps) end } f = File.new(GENERATED_PREFIX+"nrpe_#{ ORG }.cfg", "w") $nrpe.checks.each_pair{ |name, check| f.puts "command[#{ name }]=#{ check }" }