Project

General

Profile

« Previous | Next » 

Revision 0f791ba5

Added by Daniel Lobato Garcia over 7 years ago

Fixes #17837 - Fix hosts:scan_out_of_sync task

The task relies on Ping, which was removed since Ruby 1.9. I've moved it
to rely on net-ping instead. Notice the ping now relies on the 'ping'
binary being in the foreman user path for this to work with foreman-rake

View differences:

Gemfile
gem 'net-scp'
gem 'net-ssh'
gem 'net-ldap', '>= 0.8.0'
gem 'net-ping', :require => false
gem 'activerecord-session_store', '>= 0.1.1', '< 2'
gem 'sprockets', '~> 3'
gem 'sprockets-rails', '>= 2.3.3', '< 3'
lib/tasks/hosts.rake
# TRANSLATORS: do not translate
desc <<-END_DESC
Try to figure out the out of sync hosts real status
This task search hosts that have been out of sync for longer than
twice your out of sync interval by using DNS lookups and ping.
try to search them by DNS lookups and ping, if a host is not in DNS it will allow you to delete it.
Once it finishes scanning, it will prompt you to delete hosts that
don't have DNS entries nor respond to ping.
legend:
You can provide the number of seconds after which a host is considered
out of sync by using the environment variable 'OUTOFSYNC_INTERVAL'.
Legend:
"." - pingable
"x" - no ping response
Example:
Examples:
rake hosts:scan_out_of_sync RAILS_ENV="production"
rake hosts:scan_out_of_sync RAILS_ENV="production" OUTOFSYNC_INTERVAL=3600
END_DESC
namespace :hosts do
task :scan_out_of_sync => :environment do
require 'ping'
require 'net/ping/external'
require 'resolv'
def printhosts(list, description)
unless list.empty?
puts
puts "found #{list.size} #{description} hosts:"
puts "Found #{list.size} #{description}:"
puts "Name".ljust(40)+"Environment".ljust(20)+"Last Report"
puts "#{"*"*80}"
puts '*' * 80
list.each do |h|
puts h.name.ljust(40) + h.environment.to_s.ljust(20) + h.last_report.to_s(:short)
end
end
end
def out_of_sync_interval
return ENV['OUTOFSYNC_INTERVAL'] if ENV['OUTOFSYNC_INTERVAL'].present?
2 * (Setting[:puppet_interval] + Setting[:outofsync_interval])
end
pingable = []
missingdns = []
offline = []
Host.out_of_sync(1.hour.ago).all(:order => 'environment_id asc').collect do |host|
Host::Managed.out_of_sync(out_of_sync_interval.to_i.seconds.ago).
order('environment_id ASC').collect do |host|
$stdout.flush
ip = Resolv::DNS.new.getaddress(host.name).to_s rescue nil
if ip.empty?
missingdns << host
else
puts "conflict IP address for #{host.name}" unless ip == host.ip
if Ping.pingecho host.ip
if host.ip.blank?
puts "Host #{host.name} does not have an IP in Foreman. It resolved to IP: '#{ip}' through DNS. Skipping..."
next
end
all_host_ips = host.interfaces.pluck(:ip)
puts "Conflict IP address for #{host.name}" unless all_host_ips.include? ip
begin
if Net::Ping::External.new(host.ip).ping
print "."
pingable << host
else
print "x"
offline << host
end
rescue => e
Rails.logger.warn "Could not ping host #{host.name} due to an exception: #{e} - skipping"
end
end
end
puts
if missingdns.empty?
puts "All out of sync hosts exists in DNS"
puts "All out of sync hosts exist in DNS"
else
printhosts(missingdns, "hosts with no DNS entry")
puts "ctrl-c to abort - any other key to remove these hosts"
$stdin.gets
puts "Are you sure you want to continue? This task will delete the hosts above [y/N]"
input = STDIN.gets.chomp
abort("No action taken. Bye!") unless input.downcase == "y"
missingdns.each {|h| h.destroy }
missingdns.each do |h|
print "Destroying host #{h.fqdn}... "
h.destroy
puts "DESTROYED"
end
end
printhosts(offline, "offline hosts")
printhosts(pingable, "online hosts which are not running puppet")
printhosts(pingable, "online hosts which are not reporting back")
end
end

Also available in: Unified diff