Class | MCollective::Application::Inventory |
In: |
plugins/mcollective/application/inventory.rb
|
Parent: | MCollective::Application |
# File plugins/mcollective/application/inventory.rb, line 200 200: def agents 201: @node[:agents] 202: end
# File plugins/mcollective/application/inventory.rb, line 196 196: def classes 197: @node[:classes] 198: end
Writes a crude DOT graph to a file
# File plugins/mcollective/application/inventory.rb, line 86 86: def collectives_map(file) 87: File.open(file, "w") do |graph| 88: puts "Retrieving collective info...." 89: collectives = get_collectives 90: 91: graph.puts 'graph {' 92: 93: collectives[:collectives].keys.sort.each do |collective| 94: graph.puts ' subgraph "%s" {' % [ collective ] 95: 96: collectives[:collectives][collective].each do |member| 97: graph.puts ' "%s" -- "%s"' % [ member, collective ] 98: end 99: 100: graph.puts ' }' 101: end 102: 103: graph.puts '}' 104: 105: puts "Graph of #{collectives[:total_nodes]} nodes has been written to #{file}" 106: end 107: end
Prints a report of all known sub collectives
# File plugins/mcollective/application/inventory.rb, line 110 110: def collectives_report 111: collectives = get_collectives 112: 113: puts " %-30s %s" % [ "Collective", "Nodes" ] 114: puts " %-30s %s" % [ "==========", "=====" ] 115: 116: collectives[:collectives].sort_by {|key,count| count.size}.each do |collective| 117: puts " %-30s %d" % [ collective[0], collective[1].size ] 118: end 119: 120: puts 121: puts " %30s %d" % [ "Total nodes:", collectives[:nodes] ] 122: puts 123: end
# File plugins/mcollective/application/inventory.rb, line 192 192: def facts 193: @node[:facts] 194: end
# File plugins/mcollective/application/inventory.rb, line 184 184: def fields(&blk) 185: @flds = blk 186: end
Helpers to create a simple DSL for scriptlets
# File plugins/mcollective/application/inventory.rb, line 180 180: def format(fmt) 181: @fmt = fmt 182: end
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 plugins/mcollective/application/inventory.rb, line 272 272: def formatted_inventory(&blk) 273: require 'formatr' 274: 275: raise "Need to give a block to formatted_inventory" unless block_given? 276: 277: blk.call if block_given? 278: 279: raise "Need to define page body format" if @page_body.nil? 280: 281: body_fmt = FormatR::Format.new(@page_heading, @page_body) 282: body_fmt.setPageLength(@page_length) 283: time = Time.now 284: 285: util = rpcclient("rpcutil") 286: util.progress = false 287: 288: util.inventory do |t, resp| 289: @node = {:identity => resp[:sender], 290: :facts => resp[:data][:facts], 291: :classes => resp[:data][:classes], 292: :agents => resp[:data][:agents]} 293: 294: body_fmt.printFormat(binding) 295: end 296: rescue Exception => e 297: STDERR.puts "Could not create report: #{e.class}: #{e}" 298: exit 1 299: end
Get all the known collectives and nodes that belong to them
# File plugins/mcollective/application/inventory.rb, line 60 60: def get_collectives 61: util = rpcclient("rpcutil") 62: util.progress = false 63: 64: collectives = {} 65: nodes = 0 66: total = 0 67: 68: util.collective_info do |r, cinfo| 69: begin 70: if cinfo[:data] && cinfo[:data][:collectives] 71: cinfo[:data][:collectives].each do |collective| 72: collectives[collective] ||= [] 73: collectives[collective] << cinfo[:sender] 74: end 75: 76: nodes += 1 77: total += 1 78: end 79: end 80: end 81: 82: {:collectives => collectives, :nodes => nodes, :total_nodes => total} 83: end
# File plugins/mcollective/application/inventory.rb, line 188 188: def identity 189: @node[:identity] 190: end
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 plugins/mcollective/application/inventory.rb, line 224 224: def inventory(&blk) 225: raise "Need to give a block to inventory" unless block_given? 226: 227: blk.call if block_given? 228: 229: raise "Need to define a format" if @fmt.nil? 230: raise "Need to define inventory fields" if @flds.nil? 231: 232: util = rpcclient("rpcutil") 233: util.progress = false 234: 235: util.inventory do |t, resp| 236: @node = {:identity => resp[:sender], 237: :facts => resp[:data][:facts], 238: :classes => resp[:data][:classes], 239: :agents => resp[:data][:agents]} 240: 241: puts @fmt % @flds.call 242: end 243: end
# File plugins/mcollective/application/inventory.rb, line 307 307: def main 308: if configuration[:script] 309: if File.exist?(configuration[:script]) 310: eval(File.read(configuration[:script])) 311: else 312: raise "Could not find script to run: #{configuration[:script]}" 313: end 314: 315: elsif configuration[:collectivemap] 316: collectives_map(configuration[:collectivemap]) 317: 318: elsif configuration[:collectives] 319: collectives_report 320: 321: else 322: node_inventory 323: end 324: end
# File plugins/mcollective/application/inventory.rb, line 125 125: def node_inventory 126: node = configuration[:node] 127: 128: util = rpcclient("rpcutil") 129: util.identity_filter node 130: util.progress = false 131: 132: nodestats = util.custom_request("daemon_stats", {}, node, {"identity" => node}) 133: 134: util.custom_request("inventory", {}, node, {"identity" => node}).each do |resp| 135: puts "Inventory for #{resp[:sender]}:" 136: puts 137: 138: if nodestats.is_a?(Array) 139: nodestats = nodestats.first[:data] 140: 141: puts " Server Statistics:" 142: puts " Version: #{nodestats[:version]}" 143: puts " Start Time: #{Time.at(nodestats[:starttime])}" 144: puts " Config File: #{nodestats[:configfile]}" 145: puts " Collectives: #{resp[:data][:collectives].join(', ')}" if resp[:data].include?(:collectives) 146: puts " Main Collective: #{resp[:data][:main_collective]}" if resp[:data].include?(:main_collective) 147: puts " Process ID: #{nodestats[:pid]}" 148: puts " Total Messages: #{nodestats[:total]}" 149: puts " Messages Passed Filters: #{nodestats[:passed]}" 150: puts " Messages Filtered: #{nodestats[:filtered]}" 151: puts " Replies Sent: #{nodestats[:replies]}" 152: puts " Total Processor Time: #{nodestats[:times][:utime]} seconds" 153: puts " System Time: #{nodestats[:times][:stime]} seconds" 154: 155: puts 156: end 157: 158: puts " Agents:" 159: resp[:data][:agents].sort.in_groups_of(3, "") do |agents| 160: puts " %-15s %-15s %-15s" % agents 161: end 162: puts 163: 164: puts " Configuration Management Classes:" 165: resp[:data][:classes].sort.in_groups_of(2, "") do |klasses| 166: puts " %-30s %-30s" % klasses 167: end 168: puts 169: 170: puts " Facts:" 171: resp[:data][:facts].sort_by{|f| f[0]}.each do |f| 172: puts " #{f[0]} => #{f[1]}" 173: end 174: 175: break 176: end 177: end
# File plugins/mcollective/application/inventory.rb, line 212 212: def page_body(fmt) 213: @page_body = fmt 214: end
# File plugins/mcollective/application/inventory.rb, line 208 208: def page_heading(fmt) 209: @page_heading = fmt 210: end
# File plugins/mcollective/application/inventory.rb, line 204 204: def page_length(len) 205: @page_length = len 206: end
# File plugins/mcollective/application/inventory.rb, line 49 49: def post_option_parser(configuration) 50: configuration[:node] = ARGV.shift if ARGV.size > 0 51: end
# File plugins/mcollective/application/inventory.rb, line 53 53: def validate_configuration(configuration) 54: unless configuration[:node] || configuration[:script] || configuration[:collectives] || configuration[:collectivemap] 55: raise "Need to specify either a node name, script to run or other options" 56: end 57: end