class MCollective::Application::Inventory
Public Instance Methods
agents()
click to toggle source
# File lib/mcollective/application/inventory.rb, line 219 def agents @node[:agents] end
classes()
click to toggle source
# File lib/mcollective/application/inventory.rb, line 215 def classes @node[:classes] end
collectives_map(file)
click to toggle source
Writes a crude DOT graph to a file
# File lib/mcollective/application/inventory.rb, line 55 def collectives_map(file) File.open(file, "w") do |graph| puts "Retrieving collective info...." collectives = get_collectives graph.puts 'graph {' collectives[:collectives].keys.sort.each do |collective| graph.puts ' subgraph "%s" {' % [ collective ] collectives[:collectives][collective].each do |member| graph.puts ' "%s" -- "%s"' % [ member, collective ] end graph.puts ' }' end graph.puts '}' puts "Graph of #{collectives[:total_nodes]} nodes has been written to #{file}" end end
collectives_report()
click to toggle source
Prints a report of all known sub collectives
# File lib/mcollective/application/inventory.rb, line 79 def collectives_report collectives = get_collectives puts " %-30s %s" % [ "Collective", "Nodes" ] puts " %-30s %s" % [ "==========", "=====" ] collectives[:collectives].sort_by {|key,count| count.size}.each do |collective| puts " %-30s %d" % [ collective[0], collective[1].size ] end puts puts " %30s %d" % [ "Total nodes:", collectives[:nodes] ] puts end
facts()
click to toggle source
# File lib/mcollective/application/inventory.rb, line 211 def facts @node[:facts] end
fields(&blk)
click to toggle source
# File lib/mcollective/application/inventory.rb, line 203 def fields(&blk) @flds = blk end
format(fmt)
click to toggle source
Helpers to create a simple DSL for scriptlets
# File lib/mcollective/application/inventory.rb, line 199 def format(fmt) @fmt = fmt end
formatted_inventory(&blk)
click to toggle source
Use the ruby formatr gem to build reports using Perls formats
It is kind of ugly but brings a lot of flexibility in report writing without building an entire reporting language.
You need to have formatr installed to enable reports like:
formatted_inventory do page_length 20 page_heading <<TOP Node Report @<<<<<<<<<<<<<<<<<<<<<<<<< time Hostname: Customer: Distribution: ------------------------------------------------------------------------- TOP page_body <<BODY @<<<<<<<<<<<<<<<< @<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< identity, facts["customer"], facts["lsbdistdescription"] @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< facts["processor0"] BODY end
# File lib/mcollective/application/inventory.rb, line 291 def formatted_inventory(&blk) require 'formatr' raise "Need to give a block to formatted_inventory" unless block_given? blk.call if block_given? raise "Need to define page body format" if @page_body.nil? body_fmt = FormatR::Format.new(@page_heading, @page_body) body_fmt.setPageLength(@page_length) time = Time.now util = rpcclient("rpcutil") util.progress = false util.inventory do |t, resp| @node = {:identity => resp[:sender], :facts => resp[:data][:facts], :classes => resp[:data][:classes], :agents => resp[:data][:agents]} body_fmt.printFormat(binding) end rescue Exception => e STDERR.puts "Could not create report: #{e.class}: #{e}" exit 1 end
get_collectives()
click to toggle source
Get all the known collectives and nodes that belong to them
# File lib/mcollective/application/inventory.rb, line 29 def get_collectives util = rpcclient("rpcutil") util.progress = false collectives = {} nodes = 0 total = 0 util.collective_info do |r, cinfo| begin if cinfo[:data] && cinfo[:data][:collectives] cinfo[:data][:collectives].each do |collective| collectives[collective] ||= [] collectives[collective] << cinfo[:sender] end nodes += 1 total += 1 end end end {:collectives => collectives, :nodes => nodes, :total_nodes => total} end
identity()
click to toggle source
# File lib/mcollective/application/inventory.rb, line 207 def identity @node[:identity] end
inventory(&blk)
click to toggle source
Expects a simple printf style format and apply it to each node:
inventory do format "%s:\t\t%s\t\t%s" fields { [ identity, facts["serialnumber"], facts["productname"] ] } end
# File lib/mcollective/application/inventory.rb, line 243 def inventory(&blk) raise "Need to give a block to inventory" unless block_given? blk.call if block_given? raise "Need to define a format" if @fmt.nil? raise "Need to define inventory fields" if @flds.nil? util = rpcclient("rpcutil") util.progress = false util.inventory do |t, resp| @node = {:identity => resp[:sender], :facts => resp[:data][:facts], :classes => resp[:data][:classes], :agents => resp[:data][:agents]} puts @fmt % @flds.call end end
main()
click to toggle source
# File lib/mcollective/application/inventory.rb, line 326 def main if configuration[:script] if File.exist?(configuration[:script]) eval(File.read(configuration[:script])) else raise "Could not find script to run: #{configuration[:script]}" end elsif configuration[:collectivemap] collectives_map(configuration[:collectivemap]) elsif configuration[:collectives] collectives_report else node_inventory end end
node_inventory()
click to toggle source
# File lib/mcollective/application/inventory.rb, line 94 def node_inventory node = configuration[:node] util = rpcclient("rpcutil") util.identity_filter node util.progress = false nodestats = util.custom_request("daemon_stats", {}, node, {"identity" => node}).first unless nodestats STDERR.puts "Did not receive any results from node #{node}" exit 1 end unless nodestats[:statuscode] == 0 STDERR.puts "Failed to retrieve daemon_stats from #{node}: #{nodestats[:statusmsg]}" else util.custom_request("inventory", {}, node, {"identity" => node}).each do |resp| unless resp[:statuscode] == 0 STDERR.puts "Failed to retrieve inventory for #{node}: #{resp[:statusmsg]}" next end data = resp[:data] begin puts "Inventory for #{resp[:sender]}:" puts nodestats = nodestats[:data] puts " Server Statistics:" puts " Version: #{nodestats[:version]}" puts " Start Time: #{Time.at(nodestats[:starttime])}" puts " Config File: #{nodestats[:configfile]}" puts " Collectives: #{data[:collectives].join(', ')}" if data.include?(:collectives) puts " Main Collective: #{data[:main_collective]}" if data.include?(:main_collective) puts " Process ID: #{nodestats[:pid]}" puts " Total Messages: #{nodestats[:total]}" puts " Messages Passed Filters: #{nodestats[:passed]}" puts " Messages Filtered: #{nodestats[:filtered]}" puts " Expired Messages: #{nodestats[:ttlexpired]}" puts " Replies Sent: #{nodestats[:replies]}" puts " Total Processor Time: #{nodestats[:times][:utime]} seconds" puts " System Time: #{nodestats[:times][:stime]} seconds" puts puts " Agents:" if data[:agents].size > 0 data[:agents].sort.in_groups_of(3, "") do |agents| puts " %-15s %-15s %-15s" % agents end else puts " No agents installed" end puts puts " Data Plugins:" if data[:data_plugins].size > 0 data[:data_plugins].sort.in_groups_of(3, "") do |plugins| puts " %-15s %-15s %-15s" % plugins.map{|p| p.gsub("_data", "")} end else puts " No data plugins installed" end puts puts " Configuration Management Classes:" if data[:classes].size > 0 field_size = MCollective::Util.field_size(data[:classes], 30) fields_num = MCollective::Util.field_number(field_size) format = " " + (" %-#{field_size}s" * fields_num) data[:classes].sort.in_groups_of(fields_num, "") do |klasses| puts format % klasses end else puts " No classes applied" end puts puts " Facts:" if data[:facts].size > 0 data[:facts].sort_by{|f| f[0]}.each do |f| puts " #{f[0]} => #{f[1]}" end else puts " No facts known" end break rescue Exception => e STDERR.puts "Failed to display node inventory: #{e.class}: #{e}" end end end halt util.stats end
page_body(fmt)
click to toggle source
# File lib/mcollective/application/inventory.rb, line 231 def page_body(fmt) @page_body = fmt end
page_heading(fmt)
click to toggle source
# File lib/mcollective/application/inventory.rb, line 227 def page_heading(fmt) @page_heading = fmt end
page_length(len)
click to toggle source
# File lib/mcollective/application/inventory.rb, line 223 def page_length(len) @page_length = len end
post_option_parser(configuration)
click to toggle source
# File lib/mcollective/application/inventory.rb, line 18 def post_option_parser(configuration) configuration[:node] = ARGV.shift if ARGV.size > 0 end
validate_configuration(configuration)
click to toggle source
# File lib/mcollective/application/inventory.rb, line 22 def validate_configuration(configuration) unless configuration[:node] || configuration[:script] || configuration[:collectives] || configuration[:collectivemap] raise "Need to specify either a node name, script to run or other options" end end