tate on stretch
[mirror/dsa-nagios.git] / config / build-nagios
index 6395e80..28513c9 100755 (executable)
@@ -2,7 +2,7 @@
 
 # build nagios and nrpe config from a single master config file
 
-# Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009 Peter Palfrader <peter@palfrader.org>
+# Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Peter Palfrader <peter@palfrader.org>
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
@@ -127,13 +127,13 @@ $nrpe = Nrpe.new()
 # host/service/etc definitions
 #
 # It skips over such keys as are listed in exclude_keys
-# and also skips private keys (those starting with an underscre)
+# and also skips private keys (those starting with an underscore)
 def print_block(fd, kind, hash, exclude_keys)
        fd.puts "define #{kind} {"
-       hash.each_pair{ |key, value|
+       hash.keys.sort.each{ |key|
                next if key[0,1] == '_'
                next if exclude_keys.include? key
-               fd.puts "       #{key}          #{value}"
+               fd.puts "       #{key}          #{hash[key]}"
        }
        fd.puts "}"
        fd.puts
@@ -145,7 +145,7 @@ def merge_contacts(host, service)
                [host, service].each{ |source|
                        contacts.push source[k] if source.has_key?(k)
                }
-               service[k] = contacts.join(",") unless contacts.empty?
+               service[k] = contacts.sort.join(",") unless contacts.empty?
        }
 end
 
@@ -169,19 +169,23 @@ def addService(hosts, service, files, servers)
                service['depends'] << NRPE_PROCESS_SERVICE unless service['service_description'] == NRPE_PROCESS_SERVICE  # Depend on NRPE unless we are it
        end
 
-       hosts.each{ |host|
+       hosts.sort.each{ |host|
                s = service.clone
                set_complain_if_set s, 'host_name', host, 'Service', s['service_description']
                merge_contacts(servers[host], s)
 
-               print_block files['services'], 'service', s, %w(nrpe runfrom remotecheck
-                                                               depends
-                                                               hosts hostgroups excludehosts excludehostgroups)
+               exclude_keys = %w(nrpe runfrom remotecheck
+                                 depends
+                                 hosts hostgroups excludehosts excludehostgroups)
+               if servers[host]['no-servicegroups']
+                       exclude_keys << 'servicegroups'
+               end
+               print_block files['services'], 'service', s, exclude_keys
        }
 
        if service['depends']
-               service['depends'].each{ |prerequisite|
-                       hosts.each{ |host|
+               service['depends'].sort.each{ |prerequisite|
+                       hosts.sort.each{ |host|
                                prerequisite_host = host
                                pre = prerequisite
                                # split off a hostname if there's one
@@ -207,7 +211,7 @@ def addService(hosts, service, files, servers)
 
 
        set_complain_if_set service['_extinfo'], 'service_description' , service['service_description'], 'serviceextinfo', service['service_description']
-       set_complain_if_set service['_extinfo'], 'host_name'           , hosts.join(',')               , 'serviceextinfo', service['service_description']
+       set_complain_if_set service['_extinfo'], 'host_name'           , hosts.sort.join(',')          , 'serviceextinfo', service['service_description']
 
        print_block files['serviceextinfo'], 'serviceextinfo', service['_extinfo'], %w()
 end
@@ -239,9 +243,9 @@ def find_hosts(service, servers, hostgroups)
        hosts        = merge_hosts_and_hostgroups service, servers, hostgroups, ''
        excludehosts = merge_hosts_and_hostgroups service, servers, hostgroups, 'exclude'
 
-       excludehosts.each{ |host|
+       excludehosts.uniq.each{ |host|
                if hosts.delete(host) == nil
-                       throw "Cannot remove host #{host} from service #{service['service_description']}: it's not included anyway or excluded twice."
+                       puts "info: [service #{service['service_description']}] not excluding host #{host} - it's not included anyway."
                end
        }
 
@@ -313,7 +317,8 @@ config['servicegroups'] = {} unless config.has_key? 'servicegroups'
 ##############
 # HOSTS
 ##############
-config['servers'].each_pair{ |name, server|
+config['servers'].keys.sort.each{ |name|
+       server = config['servers'][name]
        # Formerly we used 'ip' instead of 'address' in our source file
        # Handle this change but warn                                   XXX
        if server.has_key?('ip')
@@ -327,22 +332,24 @@ config['servers'].each_pair{ |name, server|
        set_if_unset        server, 'use'          , HOST_TEMPLATE_NAME
        set_if_unset        server, 'check_command', HOST_ALIVE_CHECK    unless server['pingable'] == false
 
-       print_block files['hosts']      , 'host'       , server            , %w(hostgroups pingable)
+       print_block files['hosts']      , 'host'       , server            , %w(hostgroups pingable no-servicegroups)
 
 
 
        # Handle hostextinfo
-       #config['hostgroups'][  server['_hostgroups'].first  ]['_extinfo'].each_pair{ |k, v|
-       # find the first hostgroup that has extinfo
-       extinfo = server['_hostgroups'].collect{ |hgname | config['hostgroups'][hgname]['_extinfo'] }.delete_if{ |ei| ei.size == 0 }.first
-       if extinfo then
-               extinfo.each_pair do |k, v|
-                       # substitute hostname into the notes_url
-                       v = sprintf(v,name) if k == 'notes_url'
-
-                       set_if_unset server['_extinfo'], k ,v
+       # Compose extinfo from all the hostgroups for each server
+       config['hostgroups'].each_pair{ |hgname, hostgroup|
+               next unless server['_hostgroups'].include?(hgname)
+               hostgroup['_extinfo'].each_pair do |k, v|
+                       if v.empty?
+                               server['_extinfo'].delete(k)
+                       else
+                               # substitute hostname into the notes_url
+                               v = sprintf(v,name) if k == 'notes_url'
+                               server['_extinfo'][k] = v
+                       end
                end
-       end
+       }
 
        set_complain_if_set server['_extinfo'], 'host_name'       , name, 'hostextinfo', name
        set_if_unset        server['_extinfo'], 'vrml_image'      , server['_extinfo']['icon_image'] if server['_extinfo'].has_key?('icon_image')
@@ -356,11 +363,14 @@ config['servers'].each_pair{ |name, server|
 ##############
 # HOSTGROUPS
 ##############
-config['hostgroups'].each_pair{ |name, hg|
+config['hostgroups'].keys.sort.each{ |name|
+       hg = config['hostgroups'][name]
+
        next if hg['private']
+       throw "Empty hostgroup #{name}" if hg['_memberlist'].length == 0
 
-       set_complain_if_set hg, 'hostgroup_name', name                       , 'Hostgroup', name
-       set_complain_if_set hg, 'members'       , hg['_memberlist'].join(","), 'Hostgroup', name
+       set_complain_if_set hg, 'hostgroup_name', name                            , 'Hostgroup', name
+       set_complain_if_set hg, 'members'       , hg['_memberlist'].sort.join(","), 'Hostgroup', name
 
        print_block files['hostgroups'], 'hostgroup', hg, %w()
 }
@@ -374,6 +384,8 @@ config['services'].each{ |service|
 
        split_away_extinfo service
 
+       # make sure the depends list is an array
+       service['depends'] = ensure_array( service['depends'] )
 
        # Both 'name' and 'service_description' are valid for a service's name
        # Internally we only use service_description as that's nagios' official term
@@ -409,14 +421,16 @@ config['services'].each{ |service|
                # service also depend on NRPE on the relay
                relay = service['runfrom']
 
-               hosts.each{ |host|
+               hosts.sort.each{ |host|
                        # how to recursively copy this thing?
                        hostservice = YAML::load( service.to_yaml )
                        host_ip = config['servers'][host]['address']
-                       throw "For some reason I do not have an address for #{host}.  This shouldn't be." unless host_ip
 
                        remotecheck = hostservice['remotecheck']
-                       remotecheck.gsub!(/\$HOSTADDRESS\$/, host_ip)
+                       if remotecheck.include?('$HOSTADDRESS$') and not host_ip
+                               throw "For some reason I do not have an address for #{host} yet I need it for the remote check.  This shouldn't be."
+                       end
+                       remotecheck.gsub!(/\$HOSTADDRESS\$/, host_ip) if host_ip
                        remotecheck.gsub!(/\$HOSTNAME\$/, host)
                        check = $nrpe.add("#{host}_#{hostservice['service_description']}", remotecheck)
                        hostservice['check_command'] = "#{NRPE_CHECKNAME_HOST}!#{ config['servers'][ relay ]['address'] }!#{ check }"
@@ -442,7 +456,9 @@ config['services'].each{ |service|
 ##############
 # SERVICEGROUPS
 ##############
-config['servicegroups'].each_pair{ |name, sg|
+config['servicegroups'].keys.sort.each{ |name|
+       sg = config['servicegroups'][name]
+
        set_complain_if_set sg, 'servicegroup_name', name                       , 'Servicegroup', name
 
        print_block files['servicegroups'], 'servicegroup', sg, %w()
@@ -452,7 +468,8 @@ config['servicegroups'].each_pair{ |name, sg|
 ##############
 # NRPE config file
 ##############
-$nrpe.checks.each_pair{ |name, check|
+$nrpe.checks.keys.sort.each{ |name|
+       check = $nrpe.checks[name]
        files['nrpe'].puts "command[#{ name }]=#{ check }"
 }