From ad94bfa84ed681728a97ed2c4bb537dbae6a190d Mon Sep 17 00:00:00 2001 From: Steve Kemp Date: Mon, 2 Mar 2015 12:07:00 +0000 Subject: Test for IPv4 and IPv6 addresses explicitly. If we're given an IPv4 or IPv6 address then use it, if not then attempt to resolve the name that we've been given to one/other/both of these types and test in turn. --- lib/custodian/protocoltest/ping.rb | 80 +++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/lib/custodian/protocoltest/ping.rb b/lib/custodian/protocoltest/ping.rb index 3d3d0d7..8f3911d 100644 --- a/lib/custodian/protocoltest/ping.rb +++ b/lib/custodian/protocoltest/ping.rb @@ -10,6 +10,11 @@ require 'custodian/testfactory' ### DNSHOSTS must run ping otherwise .. ### # +# We take care to resolve any value we test, so that we can test explicitly +# for the family involved. (i.e. If we're ping-testing example.com then +# we will explicitly look for an IPv4 and IPv6 address to test, rather than +# just using 'example.com'.) +# # module Custodian @@ -65,6 +70,7 @@ module Custodian # Find the binary we're going to invoke. # binary = nil + binary = "./bin/multi-ping" binary = "/usr/bin/multi-ping" if ( File.exists?( "/usr/bin/multi-ping" ) ) if ( binary.nil? ) @@ -86,15 +92,79 @@ module Custodian # - # Run the test: Avoiding the use of the shell. + # Get the timeout period. # - if ( system( binary, @host ) == true ) - return true - else - @error = "Ping failed." + settings = Custodian::Settings.instance() + period = settings.timeout() + + + + # + # Perform the DNS lookups of the specified name. + # + ips = Array.new() + + # + # Does the name look like an IP? + # + begin + x = IPAddr.new( @host ) + if ( x.ipv4? or x.ipv6? ) + ips.push( @host ) + end + rescue ArgumentError + end + + + # + # OK if it didn't look like an IP address then attempt to + # look it up, as both IPv4 and IPv6. + # + begin + timeout( period ) do + + Resolv::DNS.open do |dns| + ress = dns.getresources(@host, Resolv::DNS::Resource::IN::A) + ress.map { |r| ips.push( r.address.to_s ) } + ress = dns.getresources(@host, Resolv::DNS::Resource::IN::AAAA) + ress.map { |r| ips.push( r.address.to_s ) } + end + end + rescue Timeout::Error => e + @error = "Timed-out performing DNS lookups: #{e}" + return nil + end + + + # + # Did we fail to perform a DNS lookup? + # + if ( ips.empty? ) + @error = "#{@host} failed to resolve to either IPv4 or IPv6" return false end + + # + # Run the test, avoiding the use of the shell, for each of the + # IPv4 and IPv6 addresses we discovered, or the host that we + # were given. + # + ips.each do |ip| + if ( system( binary, ip ) != true ) + @error = "Ping failed for #{ip} - from #{@host} " + return false + end + end + + # + # If there was a failure then the previous loop would have + # set the @error value and returned false. + # + # So by the time we reach here we know that all the addresses + # were pingable. + # + return true end -- cgit v1.2.1