Class | MCollective::Application::Inventory |
In: |
plugins/mcollective/application/inventory.rb
|
Parent: | MCollective::Application |
# File plugins/mcollective/application/inventory.rb, line 227 227: def agents 228: @node[:agents] 229: end
# File plugins/mcollective/application/inventory.rb, line 223 223: def classes 224: @node[:classes] 225: 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 219 219: def facts 220: @node[:facts] 221: end
# File plugins/mcollective/application/inventory.rb, line 211 211: def fields(&blk) 212: @flds = blk 213: end
Helpers to create a simple DSL for scriptlets
# File plugins/mcollective/application/inventory.rb, line 207 207: def format(fmt) 208: @fmt = fmt 209: 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 299 299: def formatted_inventory(&blk) 300: require 'formatr' 301: 302: raise "Need to give a block to formatted_inventory" unless block_given? 303: 304: blk.call if block_given? 305: 306: raise "Need to define page body format" if @page_body.nil? 307: 308: body_fmt = FormatR::Format.new(@page_heading, @page_body) 309: body_fmt.setPageLength(@page_length) 310: time = Time.now 311: 312: util = rpcclient("rpcutil") 313: util.progress = false 314: 315: util.inventory do |t, resp| 316: @node = {:identity => resp[:sender], 317: :facts => resp[:data][:facts], 318: :classes => resp[:data][:classes], 319: :agents => resp[:data][:agents]} 320: 321: body_fmt.printFormat(binding) 322: end 323: rescue Exception => e 324: STDERR.puts "Could not create report: #{e.class}: #{e}" 325: exit 1 326: 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 215 215: def identity 216: @node[:identity] 217: 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 251 251: def inventory(&blk) 252: raise "Need to give a block to inventory" unless block_given? 253: 254: blk.call if block_given? 255: 256: raise "Need to define a format" if @fmt.nil? 257: raise "Need to define inventory fields" if @flds.nil? 258: 259: util = rpcclient("rpcutil") 260: util.progress = false 261: 262: util.inventory do |t, resp| 263: @node = {:identity => resp[:sender], 264: :facts => resp[:data][:facts], 265: :classes => resp[:data][:classes], 266: :agents => resp[:data][:agents]} 267: 268: puts @fmt % @flds.call 269: end 270: end
# File plugins/mcollective/application/inventory.rb, line 334 334: def main 335: if configuration[:script] 336: if File.exist?(configuration[:script]) 337: eval(File.read(configuration[:script])) 338: else 339: raise "Could not find script to run: #{configuration[:script]}" 340: end 341: 342: elsif configuration[:collectivemap] 343: collectives_map(configuration[:collectivemap]) 344: 345: elsif configuration[:collectives] 346: collectives_report 347: 348: else 349: node_inventory 350: end 351: 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}).first 133: 134: unless nodestats[:statuscode] == 0 135: STDERR.puts "Failed to retrieve daemon_stats from #{node}: #{nodestats[:statusmsg]}" 136: else 137: util.custom_request("inventory", {}, node, {"identity" => node}).each do |resp| 138: unless resp[:statuscode] == 0 139: STDERR.puts "Failed to retrieve inventory for #{node}: #{resp[:statusmsg]}" 140: next 141: end 142: 143: data = resp[:data] 144: 145: begin 146: puts "Inventory for #{resp[:sender]}:" 147: puts 148: 149: nodestats = nodestats[:data] 150: 151: puts " Server Statistics:" 152: puts " Version: #{nodestats[:version]}" 153: puts " Start Time: #{Time.at(nodestats[:starttime])}" 154: puts " Config File: #{nodestats[:configfile]}" 155: puts " Collectives: #{data[:collectives].join(', ')}" if data.include?(:collectives) 156: puts " Main Collective: #{data[:main_collective]}" if data.include?(:main_collective) 157: puts " Process ID: #{nodestats[:pid]}" 158: puts " Total Messages: #{nodestats[:total]}" 159: puts " Messages Passed Filters: #{nodestats[:passed]}" 160: puts " Messages Filtered: #{nodestats[:filtered]}" 161: puts " Replies Sent: #{nodestats[:replies]}" 162: puts " Total Processor Time: #{nodestats[:times][:utime]} seconds" 163: puts " System Time: #{nodestats[:times][:stime]} seconds" 164: 165: puts 166: 167: puts " Agents:" 168: if data[:agents].size > 0 169: data[:agents].sort.in_groups_of(3, "") do |agents| 170: puts " %-15s %-15s %-15s" % agents 171: end 172: else 173: puts " No agents installed" 174: end 175: 176: puts 177: 178: puts " Configuration Management Classes:" 179: if data[:classes].size > 0 180: data[:classes].sort.in_groups_of(2, "") do |klasses| 181: puts " %-30s %-30s" % klasses 182: end 183: else 184: puts " No classes applied" 185: end 186: 187: puts 188: 189: puts " Facts:" 190: if data[:facts].size > 0 191: data[:facts].sort_by{|f| f[0]}.each do |f| 192: puts " #{f[0]} => #{f[1]}" 193: end 194: else 195: puts " No facts known" 196: end 197: 198: break 199: rescue Exception => e 200: STDERR.puts "Failed to display node inventory: #{e.class}: #{e}" 201: end 202: end 203: end 204: end
# File plugins/mcollective/application/inventory.rb, line 239 239: def page_body(fmt) 240: @page_body = fmt 241: end
# File plugins/mcollective/application/inventory.rb, line 235 235: def page_heading(fmt) 236: @page_heading = fmt 237: end
# File plugins/mcollective/application/inventory.rb, line 231 231: def page_length(len) 232: @page_length = len 233: 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