diff options
author | mh <mh@immerda.ch> | 2010-11-29 23:23:10 +0100 |
---|---|---|
committer | mh <mh@immerda.ch> | 2010-11-29 23:23:10 +0100 |
commit | 5e24e0e85d354300078f0b10b80cbc44a0f76f10 (patch) | |
tree | 970a16e4a3b2510603a141b27557823d34a12f23 | |
parent | bec32391d6678a9f52f71658d98a2700ddd31f60 (diff) |
replace puppetlast with much more improved version
-rw-r--r-- | files/master/lastcheck.rb | 140 | ||||
-rw-r--r-- | files/master/lastruncheck | 220 | ||||
-rw-r--r-- | files/master/puppetlast | 26 | ||||
-rw-r--r-- | manifests/puppetmaster.pp | 6 | ||||
-rw-r--r-- | manifests/puppetmaster/checklastrun.pp | 19 | ||||
-rw-r--r-- | manifests/puppetmaster/checklastrun/disable.pp | 3 |
6 files changed, 240 insertions, 174 deletions
diff --git a/files/master/lastcheck.rb b/files/master/lastcheck.rb deleted file mode 100644 index f83ccde..0000000 --- a/files/master/lastcheck.rb +++ /dev/null @@ -1,140 +0,0 @@ -require 'rubygems' -require 'active_support' -require 'puppet/application' - -module Puppet::Lastcheck - module Puppet::Lastcheck::Tests - def self.included(klass) - klass.extend ClassMethods - end - def self.tests - @tests ||= {} - end - module ClassMethods - def add_test(name, options={}) - include "Puppet::Lastcheck::Tests::#{name.to_s.classify}".constantize - Puppet::Lastcheck::Tests.tests[name] = options - attr_accessor "ignore_#{name}".to_sym - option("--ignore-#{name.to_s.gsub(/_/,'-')}") do - self.send("ignore_#{name}=", true) - end - end - end - module Util - def facts_hosts - return @facts_hosts if @facts_hosts - require 'puppet/indirector/facts/yaml' - @facts_hopsts = Puppet::Node::Facts.search("*").collect do |node| - { :hostname => node.name, :expired => node.expired?, :timestamp => node.values[:_timestamp], :expiration => node.expiration } - end - end - end - end -end - -module Puppet::Lastcheck::Tests::NoFact - def analyze_no_facts - signed_hosts.each{|host| add_failed_host(host,"No facts available") unless facts_hosts.any?{|fhost| fhost[:hostname] == host } } - end - def setup_no_facts - Puppet::SSL::Host.ca_location = :only - end - - private - def signed_hosts - ca.list - end - - def ca - @ca ||= Puppet::SSL::CertificateAuthority.new - end -end - -module Puppet::Lastcheck::Tests::ExpiredFact - include Puppet::Lastcheck::Tests::Util - def analyze_expired_facts - facts_hosts.each{|host| add_failed_host(host[:hostname],"Expired at #{host[:expiration]}") if host[:expired] } - end -end -module Puppet::Lastcheck::Tests::TimedOutFact - include Puppet::Lastcheck::Tests::Util - def analyze_timed_out_facts - require 'time' - facts_hosts.each{|host| add_failed_host(host[:hostname], "Last facts save at #{host[:timestamp]}") if Time.parse(host[:timestamp]) < (Time.now - @timeout) } - end - - def setup_timed_out_facts - if @timeout - ignore_expired_facts ||= true - end - end -end -module Puppet::Lastcheck::Tests::Storedconfig - def analyze_storedconfigs - storedconfigs_hosts.each do |host| - if !facts_hosts.any?{|fact_host| fact_host[:hostname] == host.name } - add_failed_host(host.name, "In storedconfigs but no facts available!") - elsif host.updated_at < (Time.now - @timeout) - add_failed_host(host.name, "Last update in storedconfigs at #{host.updated_at}") - end - end - end - - private - def storedconfigs_hosts - return @storedconfigs_hosts if @storedconfigs_hosts - Puppet::Rails.connect - @storedconfigs_hosts = Puppet::Rails::Host.all - end -end -class Puppet::Application::Lastcheck < Puppet::Application - - should_parse_config - run_mode :master - - include Puppet::Lastcheck::Tests - add_test :no_facts - add_test :expired_facts, :ignore_by_default => true - add_test :timed_out_facts - add_test :storedconfigs - - option("--timeout TIMEOUT") do |v| - @timeout = v.to_i - end - - def main - Puppet::Lastcheck::Tests.tests.keys.each do |test| - self.send("analyze_#{test}") unless self.send("ignore_#{test}") - end - print unless @failing_hosts.empty? - end - - def setup - exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs? - - Puppet::Util::Log.newdestination :console - Puppet::Node::Facts.terminus_class = :yaml - - Puppet::Lastcheck::Tests.tests.keys.each do |test| - self.send("ignore_#{test}=", Puppet::Lastcheck::Tests.tests[test][:ignore_by_default]||false) unless self.send("ignore_#{test}") - self.send("setup_#{test}") if self.respond_to?("setup_#{test}") - end - - @failing_hosts = {} - unless @timeout - @timeout = Puppet[:runinterval] - end - end - - private - def print - puts 'The following hosts are out of date:' - puts '------------------------------------' - @failing_hosts.keys.each{ |host| puts "#{host} - Reason: #{@failing_hosts[host][:reason]}" } - end - - def add_failed_host(hostname,reason) - @failing_hosts[hostname] = { :reason => reason } unless @failing_hosts[hostname] - end - -end diff --git a/files/master/lastruncheck b/files/master/lastruncheck new file mode 100644 index 0000000..8e31601 --- /dev/null +++ b/files/master/lastruncheck @@ -0,0 +1,220 @@ +#!/usr/bin/env ruby +require 'puppet/application' + +module Puppet::Lastcheck + module Puppet::Lastcheck::Tests + def self.included(klass) + klass.extend ClassMethods + end + def self.tests + @tests ||= {} + end + module ClassMethods + def add_test(name, options={}) + include Puppet::Lastcheck::Tests.const_get(name.to_s.split('_').collect{|s| s.capitalize }.join('')) + Puppet::Lastcheck::Tests.tests[name] = options + attr_accessor "ignore_#{name}".to_sym + option("--ignore-#{name.to_s.gsub(/_/,'-')}") do + self.send("ignore_#{name}=", true) + end + end + end + module Util + def facts_hosts + return @facts_hosts if @facts_hosts + require 'puppet/indirector/facts/yaml' + @facts_hosts = Puppet::Node::Facts.search("*").collect do |node| + { :hostname => node.name, :expired => node.expired?, :timestamp => node.values[:_timestamp], :expiration => node.expiration } + end + end + end + end + module Puppet::Lastcheck::Reports + def self.included(klass) + klass.extend ClassMethods + end + def ordered_reports + @ordered_reports ||= Puppet::Lastcheck::Reports.reports.keys.sort{|a,b| Puppet::Lastcheck::Reports.reports[a][:priority] <=> Puppet::Lastcheck::Reports.reports[b][:priority] } + end + + def self.reports + @reports ||= {} + end + module ClassMethods + def add_report(name, options={}) + include Puppet::Lastcheck::Reports.const_get(name.to_s.split('_').collect{|s| s.capitalize }.join('')) + Puppet::Lastcheck::Reports.reports[name] = options + Puppet::Lastcheck::Reports.reports[name][:priority] ||= 100 + attr_accessor "report_to_#{name}".to_sym + option("--report-to-#{name.to_s.gsub(/_/,'-')}") do + self.send("report_to_#{name}=", true) + end + end + end + end +end + +module Puppet::Lastcheck::Tests::NoFacts + def analyze_no_facts + signed_hosts.each{|host| add_failed_host(host,"No facts available") unless facts_hosts.any?{|fhost| fhost[:hostname] == host } } + end + def setup_no_facts + Puppet::SSL::Host.ca_location = :only + end + + private + def signed_hosts + ca.list + end + + def ca + @ca ||= Puppet::SSL::CertificateAuthority.new + end +end + +module Puppet::Lastcheck::Tests::ExpiredFacts + include Puppet::Lastcheck::Tests::Util + def analyze_expired_facts + facts_hosts.each{|host| add_failed_host(host[:hostname],"Expired at #{host[:expiration]}") if host[:expired] } + end +end +module Puppet::Lastcheck::Tests::TimedOutFacts + include Puppet::Lastcheck::Tests::Util + def analyze_timed_out_facts + require 'time' + facts_hosts.each{|host| add_failed_host(host[:hostname], "Last facts save at #{host[:timestamp]}") if Time.parse(host[:timestamp]) < (Time.now - @timeout) } + end + + def setup_timed_out_facts + if @timeout + ignore_expired_facts ||= true + end + end +end +module Puppet::Lastcheck::Tests::Storedconfigs + def analyze_storedconfigs + storedconfigs_hosts.each do |host| + if !facts_hosts.any?{|fact_host| fact_host[:hostname] == host.name } + add_failed_host(host.name, "In storedconfigs but no facts available!") + elsif host.updated_at < (Time.now - @timeout) + add_failed_host(host.name, "Last update in storedconfigs at #{host.updated_at}") + end + end + end + + private + def storedconfigs_hosts + return @storedconfigs_hosts if @storedconfigs_hosts + Puppet::Rails.connect + @storedconfigs_hosts = Puppet::Rails::Host.all + end +end +module Puppet::Lastcheck::Reports::Console + def deliver_report_to_console(failing_hosts) + unless failing_hosts.empty? + puts 'The following hosts are out of date:' + puts '------------------------------------' + host_length = 0 + failing_hosts.keys.each{|host| host_length = host.length if host.length > host_length } + failing_hosts.keys.each{ |host| puts "#{pretty_puts(host,host_length)} - Reason: #{failing_hosts[host][:reason]}" } + 1 + else + 0 + end + end +end +module Puppet::Lastcheck::Reports::Nagios + def deliver_report_to_nagios(failing_hosts) + unless failing_hosts.empty? + puts "PUPPETLAST CRITICAL: #{failing_hosts.size} outdated hosts: #{failing_hosts.keys.join(',')}" + 2 + else + puts "PUPPETLAST OK: No outdated hosts" + 0 + end + end +end +# +# = Synopsis +# +# Verifiying your puppet runs. Check different places to verify +# whether your clients actually still runs successfully. +# Also checks for left overs of legacy hosts. +# +# = Usage +# +# puppet lastcheck [-h|--help] +class Puppet::Application::Lastcheck < Puppet::Application + + should_parse_config + run_mode :master + + include Puppet::Lastcheck::Tests + add_test :no_facts + add_test :expired_facts, :ignore_by_default => true + add_test :timed_out_facts + add_test :storedconfigs + + include Puppet::Lastcheck::Reports + add_report :console, :priority => 50 + add_report :nagios + + option("--timeout TIMEOUT") do |v| + @timeout = v.to_i + end + + option("--ignore-hosts HOSTS") do |v| + @ignore_hosts = v.split(',') + end + + def main + + Puppet::Lastcheck::Tests.tests.keys.each do |test| + self.send("analyze_#{test}") unless self.send("ignore_#{test}") + end + exitcode = 0 + ordered_reports.each do |report| + if self.send("report_to_#{report}") + tmpexitcode = self.send("deliver_report_to_#{report}",@failing_hosts) + exitcode = tmpexitcode unless exitcode > 0 + end + end + exit(exitcode) + end + + def setup + exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs? + + Puppet::Util::Log.newdestination :console + Puppet::Node::Facts.terminus_class = :yaml + + Puppet::Lastcheck::Tests.tests.keys.each do |test| + self.send("ignore_#{test}=", Puppet::Lastcheck::Tests.tests[test][:ignore_by_default]||false) unless self.send("ignore_#{test}") + self.send("setup_#{test}") if self.respond_to?("setup_#{test}") and !self.send("ignore_#{test}") + end + report = nil + report_activated = false + ordered_reports.each do |report| + report_activated ||= self.send("report_to_#{report}") + end + self.report_to_console = true unless report_activated + + @ignore_hosts = [] unless @ignore_hosts + @failing_hosts = {} + unless @timeout + @timeout = Puppet[:runinterval] + end + end + + private + + def add_failed_host(hostname,reason) + @failing_hosts[hostname] = { :reason => reason } unless (@failing_hosts[hostname] || @ignore_hosts.include?(hostname)) + end + + def pretty_puts(str,length) + sprintf("%0-#{length}s",str) + end +end + +Puppet::Application.find('lastcheck').new.run diff --git a/files/master/puppetlast b/files/master/puppetlast deleted file mode 100644 index af2ca77..0000000 --- a/files/master/puppetlast +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env ruby -# Puppetlast, a script to output the last check-in time of nodes. Also outputs the cached configuration state, if expired or not. -# -# AJ "Fujin" Christensen <aj@junglist.gen.nz> -# changed by admin+puppet(at)immerda.ch to fit our needs -# -require 'puppet' -require 'time' - -Puppet[:config] = "/etc/puppet/puppet.conf" -Puppet.parse_config -Puppet::Node::Facts.terminus_class = :yaml - -all = false -timeout = 120 -ARGV.each do |arg| - if arg.to_s == '--all' - all = true - else - timeout = arg.to_i - end -end - -Puppet::Node::Facts.search("*").sort { |a,b| a.name <=> b.name }.each do |node| - puts "#{node.name} #{node.expired? ? 'cached expired, ' : ''}last checked #{((Time.now - Time.parse(node.values[:_timestamp])) / 60).floor} minutes ago" if (((Time.now - Time.parse(node.values[:_timestamp])) / 60).floor > timeout or all) -end diff --git a/manifests/puppetmaster.pp b/manifests/puppetmaster.pp index 36116b4..74df5e7 100644 --- a/manifests/puppetmaster.pp +++ b/manifests/puppetmaster.pp @@ -13,11 +13,11 @@ class puppet::puppetmaster inherits puppet { include puppet::puppetmaster::base - case $puppetmaster_checklastrun { - '': { $puppetmaster_checklastrun = '40 10,22 * * *' } + case $puppetmaster_lastruncheck_cron { + '',undef: { $puppetmaster_lastruncheck_cron = '40 10,22 * * *' } } - if $puppetmaster_checklastrun { + if $puppetmaster_lastruncheck_cron { include puppet::puppetmaster::checklastrun } else { include puppet::puppetmaster::checklastrun::disable diff --git a/manifests/puppetmaster/checklastrun.pp b/manifests/puppetmaster/checklastrun.pp index 1cf5311..72a97ce 100644 --- a/manifests/puppetmaster/checklastrun.pp +++ b/manifests/puppetmaster/checklastrun.pp @@ -1,11 +1,22 @@ class puppet::puppetmaster::checklastrun { - file{"/usr/local/bin/puppetlast": - source => [ "puppet:///modules/site-puppet/master/puppetlast", - "puppet:///modules/puppet/master/puppetlast" ], + $puppet_lastruncheck_ignorehosts_str = $puppet_lastruncheck_ignorehosts ? { + '' => '', + undef => '', + default => "--ignore-hosts ${puppet_lastruncheck_ignorehosts}" + } + + $puppet_lastruncheck_timeout_str = $puppet_lastruncheck_timeout ? { + '' => '', + undef => '', + default => "--timeout ${puppet_lastruncheck_timeout}" + } + + file{"/usr/local/sbin/puppetlast": + source => [ "puppet:///modules/puppet/master/lastruncheck" ], owner => root, group => 0, mode => 0700; } file{'/etc/cron.d/puppetlast.cron': - content => "${puppetmaster_checklastrun} root /usr/local/bin/puppetlast ${puppetmaster_checklastrun_timeout}\n", + content => "${puppetmaster_lastruncheck_cron} root /usr/local/sbin/puppetlast ${puppet_lastruncheck_timeout_str} ${puppet_lastruncheck_ignorehosts_str} ${$puppet_lastruncheck_additionaloptions}\n", require => File["/usr/local/bin/puppetlast"], owner => root, group => 0, mode => 0644, } diff --git a/manifests/puppetmaster/checklastrun/disable.pp b/manifests/puppetmaster/checklastrun/disable.pp index 47c0130..3fc91d0 100644 --- a/manifests/puppetmaster/checklastrun/disable.pp +++ b/manifests/puppetmaster/checklastrun/disable.pp @@ -1,5 +1,6 @@ class puppet::puppetmaster::checklastrun::disable inherits puppet::puppetmaster::checklastrun { - File['/usr/local/bin/puppetlast']{ + File['/usr/local/sbin/puppetlast']{ + source => undef, ensure => absent, } File['/etc/cron.d/puppetlast.cron']{ |