1module MCollective
2  module Agent
3    class Nrpe<RPC::Agent
4
5      action "runallcommands" do
6        reply[:commands] = {}
7        p = Nrpe.all_command_plugins
8        p.each do |name,cmd|
9          exitcode, output = Nrpe.run(name)
10
11          reply[:commands][name] = {
12            :exitcode => exitcode,
13            :output => output,
14          }
15        end
16      end
17
18      action "runcommand" do
19        args = request[:args].to_s.split('!')
20        reply[:exitcode], reply[:output] = Nrpe.run(request[:command], args)
21        reply[:command] = request[:command]
22
23        case reply[:exitcode]
24          when 0
25            reply.statusmsg = "OK"
26
27          when 1
28            reply.fail "WARNING"
29
30          when 2
31            reply.fail "CRITICAL"
32
33          else
34            reply.fail "UNKNOWN"
35        end
36
37        if reply[:output] =~ /^(.+)\|(.+)$/
38          reply[:output] = $1
39          reply[:perfdata] = $2
40        else
41          reply[:perfdata] = ""
42        end
43      end
44
45      # Runs an Nrpe command and returns the command output and exitcode
46      # If the command does not exist run will return exitcode 3.
47      #
48      # The Nrpe configuration directory and file containing checks
49      # must be specified in server.cfg
50      #
51      # Example :
52      #          plugin.nrpe.conf_dir = /etc/nagios/nrpe
53      #          plugin.nrpe.conf_file = checks.nrpe
54      def self.run(command, args=[])
55        nrpe_command = Nrpe.plugin_for_command(command, args)
56
57        return 3, "No such command: #{command}" unless nrpe_command
58
59        output = ""
60        shell = ::MCollective::Shell.new(nrpe_command, {:stdout => output, :chomp => true})
61        shell.runcommand
62        exitcode = shell.status.exitstatus
63        return exitcode, output
64      end
65
66      def self.plugin_for_command(command, args)
67        plugins = Nrpe.all_command_plugins
68
69        if plugins.include?(command)
70          return self.expand_command_args(plugins[command], args)
71        end
72
73        return nil
74      end
75
76      def self.expand_command_args(command, args)
77        copy = command.dup # work on a copy to avoid mutating our arguments
78        args.each_with_index do |value, index|
79          copy.gsub!(/\$ARG#{index + 1}\$/, value)
80        end
81        return copy
82      end
83
84      def self.all_command_plugins
85        commands = {}
86        fnames = []
87        config = Config.instance
88
89        fdir = config.pluginconf["nrpe.conf_dir"] || "/etc/nagios/nrpe.d"
90
91        if config.pluginconf["nrpe.conf_file"]
92          fnames << "#{fdir}/#{config.pluginconf['nrpe.conf_file']}"
93        else
94          fnames |= Dir.glob("#{fdir}/*.cfg")
95        end
96
97        fnames.each do |fname|
98          if File.exist?(fname)
99            File.readlines(fname).each do |check|
100              check.chomp!
101
102              if check =~ /^command\[(.+?)\]\s*=\s*(.+)$/
103                commands[$1] = $2
104              end
105            end
106          end
107        end
108
109        return commands
110      end
111    end
112  end
113end
114