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 200
200:     def agents
201:         @node[:agents]
202:     end

[Source]

     # File plugins/mcollective/application/inventory.rb, line 196
196:     def classes
197:         @node[:classes]
198:     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 192
192:     def facts
193:         @node[:facts]
194:     end

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[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 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

[Source]

     # 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

[Source]

     # 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

[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 "                  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

[Source]

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

[Source]

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

[Source]

     # File plugins/mcollective/application/inventory.rb, line 204
204:     def page_length(len)
205:         @page_length = len
206:     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]