| 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