This file is indexed.

/usr/share/mcollective/plugins/mcollective/application/nettest.rb is in mcollective-plugins-nettest 0.0.0~git20120507.df2fa81-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
module MCollective
  class Application::Nettest < Application
    description "Network tests from a mcollective host"

    usage <<-END_OF_USAGE
mco nettest [OPTIONS] [FILTERS] <ACTION> <HOST NAME> [PORT]

The ACTION can be one of the following:

    ping    - return round-trip time between this and remote host
    connect - check connectivity of remote host on specific port
        END_OF_USAGE

    def post_option_parser(configuration)
      if ARGV.size < 2
        raise "Please specify an action and optional arguments"
      else
        # We trust that validation will be handled correctly
        # as per accompanying DDL file ...
        action = ARGV.shift

        host_name   = ARGV.shift
        remote_port = ARGV.shift

        unless action.match(/^(ping|connect)$/)
          raise "Action can only to be ping or connect"
        end

        case action
          when /^ping$/
            arguments = {:fqdn => host_name}
          when /^connect$/
            arguments = {:fqdn => host_name,
                         :port => remote_port}
        end

        configuration[:action]    = action
        configuration[:arguments] = arguments
      end
    end

    def validate_configuration(configuration)
      # We have to ask this question because you do NOT want
      # your entire network of bazillion machines to simply
      # go and hammer some poor remote host ...  You may get
      # your network blocked or whatnot, and that would be
      # quite an unpleasant thing to have place so better to
      # be sorry and safe ...
      if MCollective::Util.empty_filter?(options[:filter])
        print "Do you really want to perform network tests unfiltered? (y/n): "

        STDOUT.flush

        # Only match letter "y" or complete word "yes" ...
        exit! unless STDIN.gets.strip.match(/^(?:y|yes)$/i)
      end
    end

    def print_statistics(statistics, action_statistics, type)
      puts "\n---- nettest summary ----"
      puts "           Nodes: %d / %d" % [statistics[:responses] + statistics[:noresponsefrom].size, statistics[:responses]]

      if action_statistics.size > 0
        case type
          when "ping"
            times = action_statistics[:ping]

            sum     = times.inject(0) { |v, i| v + i }
            average = sum / times.size.to_f

            puts "         Results: replies=%d, maximum=%.3f ms, minimum=%.3f ms, average=%.3f ms" % [times.size, times.max, times.min, average]

          when "connect"
            puts "         Results: connected=%d, connection refused=%d, timed out=%d" % [action_statistics[:connect][0], action_statistics[:connect][1], action_statistics[:connect][2]]
        end
      else
        puts "         Results: No responses received"
      end

      puts "    Elapsed Time: %.2f s\n" % [ statistics[:blocktime] ]
    end

    def process_connect_result(result, node, action_statistics, verbose)
      action_statistics[:connect] ||= [ 0, 0, 0 ]

      # This is to be in line with the usual format of output ...
      result = result.tr("A-Z", "a-z")

      case result
        when "connected"
          action_statistics[:connect][0] += 1

        when "refused"
          action_statistics[:connect][1] += 1

        when "timeout"
          action_statistics[:connect][2] += 1
      end

      if verbose
        puts "%-40s status=%s\n\t\t%s" % [node[:sender], result, node[:statusmsg]]
      else
        puts "%-40s status=%s" % [node[:sender], result]
      end
    end

    def process_ping_result(result, node, action_statistics, verbose)
      action_statistics[:ping] ||= []

      result = Float(result) rescue 0.0

      if verbose
        puts "%-40s time=%.3f\n\t\t%s" % [node[:sender], result, node[:statusmsg]]
      else
        puts "%-40s time=%.3f" % [node[:sender], result]
      end

      action_statistics[:ping] << result
    end

    def main
      action_statistics = {}

      action = configuration[:action]
      arguments = configuration[:arguments]

      rpc_nettest = rpcclient("nettest", {:options => options})

      rpc_nettest.send(action, arguments).each do |node|
        # We want new line here ...
        puts if action_statistics.size.zero? and not rpc_nettest.progress

        data = node[:data]

        # If the status code is non-zero and data is empty then we
        # assume that something out of an ordinary had place and
        # therefore assume that there was some sort of error ...
        unless node[:statuscode].zero? and data
          result = "error"
        else
          result = data[:rtt] || data[:connect]
        end

        case action
          when "ping"
            process_ping_result(result, node, action_statistics, rpc_nettest.verbose)

          when "connect"
            process_connect_result(result, node, action_statistics, rpc_nettest.verbose)
        end
      end

      print_statistics(rpc_nettest.stats, action_statistics, action)
    end
  end
end