Class MCollective::Application::Inventory
In: plugins/mcollective/application/inventory.rb
Parent: MCollective::Application

Methods

Public Instance methods

[Source]

     # File plugins/mcollective/application/inventory.rb, line 198
198:     def agents
199:         @node[:agents]
200:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 194
194:     def classes
195:         @node[:classes]
196:     end

Writes a crude DOT graph to a file

[Source]

     # 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

[Source]

     # 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

[Source]

     # File plugins/mcollective/application/inventory.rb, line 190
190:     def facts
191:         @node[:facts]
192:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 182
182:     def fields(&blk)
183:         @flds = blk
184:     end

Helpers to create a simple DSL for scriptlets

[Source]

     # File plugins/mcollective/application/inventory.rb, line 178
178:     def format(fmt)
179:         @fmt = fmt
180:     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

[Source]

     # File plugins/mcollective/application/inventory.rb, line 270
270:     def formatted_inventory(&blk)
271:         require 'formatr'
272: 
273:         raise "Need to give a block to formatted_inventory" unless block_given?
274: 
275:         blk.call if block_given?
276: 
277:         raise "Need to define page body format" if @page_body.nil?
278: 
279:         body_fmt = FormatR::Format.new(@page_heading, @page_body)
280:         body_fmt.setPageLength(@page_length)
281:         time = Time.now
282: 
283:         util = rpcclient("rpcutil")
284:         util.progress = false
285: 
286:         util.inventory do |t, resp|
287:             @node = {:identity => resp[:sender],
288:                      :facts    => resp[:data][:facts],
289:                      :classes  => resp[:data][:classes],
290:                      :agents   => resp[:data][:agents]}
291: 
292:             body_fmt.printFormat(binding)
293:         end
294:     rescue Exception => e
295:         STDERR.puts "Could not create report: #{e.class}: #{e}"
296:         exit 1
297:     end

Get all the known collectives and nodes that belong to them

[Source]

    # 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

[Source]

     # File plugins/mcollective/application/inventory.rb, line 186
186:     def identity
187:         @node[:identity]
188:     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

[Source]

     # File plugins/mcollective/application/inventory.rb, line 222
222:     def inventory(&blk)
223:         raise "Need to give a block to inventory" unless block_given?
224: 
225:         blk.call if block_given?
226: 
227:         raise "Need to define a format" if @fmt.nil?
228:         raise "Need to define inventory fields" if @flds.nil?
229: 
230:         util = rpcclient("rpcutil")
231:         util.progress = false
232: 
233:         util.inventory do |t, resp|
234:             @node = {:identity => resp[:sender],
235:                      :facts    => resp[:data][:facts],
236:                      :classes  => resp[:data][:classes],
237:                      :agents   => resp[:data][:agents]}
238: 
239:             puts @fmt % @flds.call
240:         end
241:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 305
305:     def main
306:         if configuration[:script]
307:             if File.exist?(configuration[:script])
308:                 eval(File.read(configuration[:script]))
309:             else
310:                 raise "Could not find script to run: #{configuration[:script]}"
311:             end
312: 
313:         elsif configuration[:collectivemap]
314:             collectives_map(configuration[:collectivemap])
315: 
316:         elsif configuration[:collectives]
317:             collectives_report
318: 
319:         else
320:             node_inventory
321:         end
322:     end

[Source]

     # 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 "                   Process ID: #{nodestats[:pid]}"
146:                 puts "               Total Messages: #{nodestats[:total]}"
147:                 puts "      Messages Passed Filters: #{nodestats[:passed]}"
148:                 puts "            Messages Filtered: #{nodestats[:filtered]}"
149:                 puts "                 Replies Sent: #{nodestats[:replies]}"
150:                 puts "         Total Processor Time: #{nodestats[:times][:utime]} seconds"
151:                 puts "                  System Time: #{nodestats[:times][:stime]} seconds"
152: 
153:                 puts
154:             end
155: 
156:             puts "   Agents:"
157:             resp[:data][:agents].sort.in_groups_of(3, "") do |agents|
158:                 puts "      %-15s %-15s %-15s" % agents
159:             end
160:             puts
161: 
162:             puts "   Configuration Management Classes:"
163:             resp[:data][:classes].sort.in_groups_of(2, "") do |klasses|
164:                 puts "      %-30s %-30s" % klasses
165:             end
166:             puts
167: 
168:             puts "   Facts:"
169:             resp[:data][:facts].sort_by{|f| f[0]}.each do |f|
170:                 puts "      #{f[0]} => #{f[1]}"
171:             end
172: 
173:             break
174:         end
175:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 210
210:     def page_body(fmt)
211:         @page_body = fmt
212:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 206
206:     def page_heading(fmt)
207:         @page_heading = fmt
208:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 202
202:     def page_length(len)
203:         @page_length = len
204:     end

[Source]

    # 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

[Source]

    # 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

[Validate]