#!/usr/bin/env ruby

require 'mcollective'

include MCollective::RPC

limits = {:pattern => ".",
          :just_zombies => false}

options = rpcoptions do |parser, options|
    parser.define_head "Search for processes matching criteria"
    parser.banner = "Usage: mc-pgrep [options] <pattern>"
    parser.separator ""
    parser.separator "Process List Limiters:"

    parser.on('-z', '--zombie', 'Find only zombie processes') do |v|
        limits[:just_zombies] = v
    end
end

$0 = "mc-pgrep"

ps = rpcclient("process", :options => options)

if ARGV.length > 0
    limits[:pattern] = ARGV.shift
end

class Numeric
    def bytes_to_human
        if self > 0
            units = %w{B KB MB GB TB}
            e = (Math.log(self)/Math.log(1024)).floor
            s = "%.3f" % (to_f / 1024**e)
            s.sub(/\.?0*$/, units[e])
        else
            "0B"
        end
    end
end

stats = {:count => 0,
         :hosts => 0,
         :vsize => 0,
         :rss   => 0}

ps.list(limits).each_with_index do |result, i|
    begin
        if result[:data][:pslist].size > 0
            puts result[:sender]
            stats[:hosts] += 1

            result[:data][:pslist].each do |proc|
                proc[:state] == "Z" ? cmdline = "[#{proc[:cmdline]}]" : cmdline = proc[:cmdline]

                puts "%5d %-10s  %s  %s" % [proc[:pid], proc[:username][0,10], proc[:vsize].bytes_to_human, cmdline[0,60] ] if proc[:cmdline].match limits[:pattern]

                stats[:count] += 1
                stats[:vsize] += proc[:vsize]
                stats[:rss] += proc[:rss] * 1024
            end

            puts
        end
    rescue
        STDERR.puts "Failed to get results from #{result[:sender]}"
    end
end

puts "   ---- process list stats ----"
puts "        Matched hosts: #{stats[:hosts]}"
puts "    Matched processes: #{stats[:count]}"
puts "        Resident Size: #{stats[:rss].bytes_to_human}"
puts "         Virtual Size: #{stats[:vsize].bytes_to_human}"

# vi:tabstop=4:expandtab:ai

