1module MCollective
2  module Agent
3    class Nettest<RPC::Agent
4      activate_when do
5        begin
6          require 'net/ping/icmp'
7          require 'mcollective/util/nettest_agent'
8
9          true
10        rescue LoadError => e
11          Log.warn('Cannot load Nettest_agent plugin. Nettest_agent plugin requires the net/ping gem and util/nettest_agent class to run.')
12
13          false
14        end
15      end
16
17      action "ping" do
18        if ipaddr = Util::NettestAgent.get_ip_from_hostname(request[:fqdn])
19          reply[:rtt] = Nettest.testping(ipaddr)
20          reply.fail!('Cannot reach host') unless reply[:rtt]
21        else
22          reply.fail!('Cannot resolve hostname')
23        end
24      end
25
26      action "connect" do
27        if ipaddr = Util::NettestAgent.get_ip_from_hostname(request[:fqdn])
28          reply[:connect], reply[:connect_status], reply[:connect_time] = Nettest.testconnect(ipaddr, request[:port])
29        else
30          reply.fail!('Cannot resolve hostname')
31        end
32      end
33
34      # Does the actual work of the ping action
35      def self.testping(ipaddr)
36        icmp = Net::Ping::ICMP.new(ipaddr)
37
38        if icmp.ping?
39          return (icmp.duration * 1000)
40        else
41          return nil
42        end
43      end
44
45      # Does the actual work of the connect action
46      # #testconnet will try and make a connection to a
47      # given ip address, returning the time it took to
48      # establish the connection, the connection status
49      # and a boolean value stating if the connection could
50      # be made.
51      def self.testconnect(ipaddr, port)
52        connected = false
53        connect_string = nil
54        connect_time = nil
55
56        begin
57          Timeout.timeout(2) do
58            begin
59              time = Time.now
60              t = TCPSocket.new(ipaddr, port)
61              t.close
62              connect_time = Time.now - time
63              connected = true
64              connect_string =  'Connected'
65            rescue
66              connect_string = 'Connection Refused'
67            end
68          end
69        rescue Timeout::Error
70          connect_string =  'Connection Timeout'
71        end
72
73        return connected, connect_string, connect_time
74      end
75    end
76  end
77end
78