]> gitweb.fluxo.info Git - puppet-puppet.git/commitdiff
Using custom puppetlast command thanks to immerda's module
authorSilvio Rhatto <rhatto@riseup.net>
Wed, 23 Feb 2011 18:21:00 +0000 (15:21 -0300)
committerSilvio Rhatto <rhatto@riseup.net>
Wed, 23 Feb 2011 18:21:00 +0000 (15:21 -0300)
files/lastruncheck [new file with mode: 0644]
manifests/puppetmasterd.pp

diff --git a/files/lastruncheck b/files/lastruncheck
new file mode 100644 (file)
index 0000000..babe74f
--- /dev/null
@@ -0,0 +1,222 @@
+#!/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].to_s) < (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.last_compile.nil?
+        add_failed_host(host.name, "No entry in storedconfigs")
+      elsif host.last_compile < (Time.now - @timeout)
+        add_failed_host(host.name, "Last compile time in storedconfigs at #{host.last_compile}")
+      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
index c8ccc7aa3444aa6678911000509184cef5c0c6ed..92a388e81a95158f03d7b1e9aebf0a9fc87432df 100644 (file)
@@ -89,12 +89,13 @@ class puppetmasterd {
 
   # cron rule to execute puppetlast once a week as a report
   cron { "puppetlast":
-    command  => "puppetlast",
+    command  => "/usr/local/sbin/puppetlast",
     user     => root,
     hour     => "0",
     minute   => "0",
     weekday  => "0",
     ensure   => present,
+    require  => File["/usr/local/sbin/puppetlast"],
   }
 
   # cron rule to restart puppetmaster before restarting the nodes
@@ -106,6 +107,15 @@ class puppetmasterd {
     ensure   => absent,
   }
 
+  # custom puppetlast command, thanks to immerda module:
+  # http://git.puppet.immerda.ch/?p=module-puppet.git;a=summary
+  file { "/usr/local/sbin/puppetlast":
+    source => "puppet:///modules/puppet/lastruncheck",
+    owner  => root,
+    group  => root,
+    mode   => 0700,
+  }
+
   # restart the master from time to time to avoid memory problems
   # thanks to https://labs.riseup.net/code/projects/shared-puppet
   file { "/etc/cron.d/puppetmaster":