mcollective-client 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mcollective-client might be problematic. Click here for more details.

Files changed (140) hide show
  1. data/lib/mcollective.rb +32 -23
  2. data/lib/mcollective/agent.rb +5 -0
  3. data/lib/mcollective/agents.rb +5 -16
  4. data/lib/mcollective/aggregate.rb +61 -0
  5. data/lib/mcollective/aggregate/base.rb +40 -0
  6. data/lib/mcollective/aggregate/result.rb +9 -0
  7. data/lib/mcollective/aggregate/result/base.rb +25 -0
  8. data/lib/mcollective/aggregate/result/collection_result.rb +19 -0
  9. data/lib/mcollective/aggregate/result/numeric_result.rb +13 -0
  10. data/lib/mcollective/application.rb +7 -4
  11. data/lib/mcollective/applications.rb +3 -14
  12. data/lib/mcollective/cache.rb +145 -0
  13. data/lib/mcollective/client.rb +10 -87
  14. data/lib/mcollective/config.rb +22 -8
  15. data/lib/mcollective/data.rb +87 -0
  16. data/lib/mcollective/data/base.rb +67 -0
  17. data/lib/mcollective/data/result.rb +40 -0
  18. data/lib/mcollective/ddl.rb +113 -0
  19. data/lib/mcollective/ddl/agentddl.rb +185 -0
  20. data/lib/mcollective/ddl/base.rb +220 -0
  21. data/lib/mcollective/ddl/dataddl.rb +56 -0
  22. data/lib/mcollective/ddl/discoveryddl.rb +52 -0
  23. data/lib/mcollective/ddl/validatorddl.rb +6 -0
  24. data/lib/mcollective/discovery.rb +143 -0
  25. data/lib/mcollective/generators.rb +7 -0
  26. data/lib/mcollective/generators/agent_generator.rb +51 -0
  27. data/lib/mcollective/generators/base.rb +46 -0
  28. data/lib/mcollective/generators/data_generator.rb +51 -0
  29. data/lib/mcollective/generators/templates/action_snippet.erb +13 -0
  30. data/lib/mcollective/generators/templates/data_input_snippet.erb +7 -0
  31. data/lib/mcollective/generators/templates/ddl.erb +8 -0
  32. data/lib/mcollective/generators/templates/plugin.erb +7 -0
  33. data/lib/mcollective/logger/console_logger.rb +15 -15
  34. data/lib/mcollective/matcher.rb +167 -0
  35. data/lib/mcollective/matcher/parser.rb +60 -25
  36. data/lib/mcollective/matcher/scanner.rb +156 -78
  37. data/lib/mcollective/message.rb +47 -6
  38. data/lib/mcollective/monkey_patches.rb +17 -0
  39. data/lib/mcollective/optionparser.rb +18 -1
  40. data/lib/mcollective/pluginmanager.rb +3 -3
  41. data/lib/mcollective/pluginpackager.rb +10 -3
  42. data/lib/mcollective/pluginpackager/agent_definition.rb +28 -20
  43. data/lib/mcollective/pluginpackager/standard_definition.rb +11 -9
  44. data/lib/mcollective/registration/base.rb +3 -1
  45. data/lib/mcollective/rpc.rb +18 -24
  46. data/lib/mcollective/rpc/agent.rb +37 -113
  47. data/lib/mcollective/rpc/client.rb +186 -64
  48. data/lib/mcollective/rpc/helpers.rb +42 -80
  49. data/lib/mcollective/rpc/progress.rb +3 -3
  50. data/lib/mcollective/rpc/reply.rb +37 -13
  51. data/lib/mcollective/rpc/request.rb +17 -6
  52. data/lib/mcollective/rpc/result.rb +9 -5
  53. data/lib/mcollective/rpc/stats.rb +71 -24
  54. data/lib/mcollective/security/base.rb +41 -34
  55. data/lib/mcollective/shell.rb +1 -1
  56. data/lib/mcollective/ssl.rb +34 -0
  57. data/lib/mcollective/util.rb +194 -23
  58. data/lib/mcollective/validator.rb +80 -0
  59. data/spec/fixtures/util/1.in +10 -0
  60. data/spec/fixtures/util/1.out +10 -0
  61. data/spec/fixtures/util/2.in +1 -0
  62. data/spec/fixtures/util/2.out +1 -0
  63. data/spec/fixtures/util/3.in +1 -0
  64. data/spec/fixtures/util/3.out +2 -0
  65. data/spec/fixtures/util/4.in +5 -0
  66. data/spec/fixtures/util/4.out +9 -0
  67. data/spec/spec.opts +1 -1
  68. data/spec/spec_helper.rb +2 -0
  69. data/spec/unit/agents_spec.rb +34 -19
  70. data/spec/unit/aggregate/base_spec.rb +57 -0
  71. data/spec/unit/aggregate/result/base_spec.rb +28 -0
  72. data/spec/unit/aggregate/result/collection_result_spec.rb +18 -0
  73. data/spec/unit/aggregate/result/numeric_result_spec.rb +22 -0
  74. data/spec/unit/aggregate_spec.rb +110 -0
  75. data/spec/unit/application_spec.rb +8 -3
  76. data/spec/unit/applications_spec.rb +2 -2
  77. data/spec/unit/cache_spec.rb +115 -0
  78. data/spec/unit/client_spec.rb +78 -0
  79. data/spec/unit/config_spec.rb +32 -34
  80. data/spec/unit/data/base_spec.rb +90 -0
  81. data/spec/unit/data/result_spec.rb +64 -0
  82. data/spec/unit/data_spec.rb +158 -0
  83. data/spec/unit/ddl/agentddl_spec.rb +217 -0
  84. data/spec/unit/{rpc/ddl_spec.rb → ddl/base_spec.rb} +238 -224
  85. data/spec/unit/ddl/dataddl_spec.rb +65 -0
  86. data/spec/unit/ddl/discoveryddl_spec.rb +58 -0
  87. data/spec/unit/ddl_spec.rb +84 -0
  88. data/spec/unit/discovery_spec.rb +196 -0
  89. data/spec/unit/facts/base_spec.rb +1 -1
  90. data/spec/unit/generators/agent_generator_spec.rb +72 -0
  91. data/spec/unit/generators/base_spec.rb +83 -0
  92. data/spec/unit/generators/data_generator_spec.rb +37 -0
  93. data/spec/unit/generators/snippets/agent_ddl +19 -0
  94. data/spec/unit/generators/snippets/data_ddl +20 -0
  95. data/spec/unit/logger/console_logger_spec.rb +76 -0
  96. data/spec/unit/logger/syslog_logger_spec.rb +2 -2
  97. data/spec/unit/matcher/parser_spec.rb +27 -10
  98. data/spec/unit/matcher/scanner_spec.rb +108 -5
  99. data/spec/unit/matcher_spec.rb +260 -0
  100. data/spec/unit/message_spec.rb +35 -13
  101. data/spec/unit/optionparser_spec.rb +2 -2
  102. data/spec/unit/pluginpackager/agent_definition_spec.rb +59 -42
  103. data/spec/unit/pluginpackager/standard_definition_spec.rb +10 -8
  104. data/spec/unit/pluginpackager_spec.rb +131 -0
  105. data/spec/unit/plugins/mcollective/aggregate/average_spec.rb +45 -0
  106. data/spec/unit/plugins/mcollective/aggregate/sum_spec.rb +31 -0
  107. data/spec/unit/plugins/mcollective/aggregate/summary_spec.rb +45 -0
  108. data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +1 -1
  109. data/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +478 -0
  110. data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +2 -0
  111. data/spec/unit/plugins/mcollective/data/agent_data_spec.rb +43 -0
  112. data/spec/unit/plugins/mcollective/data/fstat_data_spec.rb +135 -0
  113. data/spec/unit/plugins/mcollective/discovery/flatfile_spec.rb +48 -0
  114. data/spec/unit/plugins/mcollective/discovery/mc_spec.rb +40 -0
  115. data/spec/unit/plugins/mcollective/packagers/debpackage_packager_spec.rb +41 -15
  116. data/spec/unit/plugins/mcollective/packagers/ospackage_spec.rb +1 -1
  117. data/spec/unit/plugins/mcollective/packagers/rpmpackage_packager_spec.rb +22 -38
  118. data/spec/unit/plugins/mcollective/validator/array_validator_spec.rb +19 -0
  119. data/spec/unit/plugins/mcollective/validator/ipv4address_validator_spec.rb +19 -0
  120. data/spec/unit/plugins/mcollective/validator/ipv6address_validator_spec.rb +19 -0
  121. data/spec/unit/plugins/mcollective/validator/length_validator_spec.rb +19 -0
  122. data/spec/unit/plugins/mcollective/validator/regex_validator_spec.rb +19 -0
  123. data/spec/unit/plugins/mcollective/validator/shellsafe_validator_spec.rb +21 -0
  124. data/spec/unit/plugins/mcollective/validator/typecheck_validator_spec.rb +23 -0
  125. data/spec/unit/registration/base_spec.rb +1 -1
  126. data/spec/unit/rpc/actionrunner_spec.rb +2 -2
  127. data/spec/unit/rpc/agent_spec.rb +41 -65
  128. data/spec/unit/rpc/client_spec.rb +430 -134
  129. data/spec/unit/rpc/reply_spec.rb +31 -1
  130. data/spec/unit/rpc/request_spec.rb +33 -12
  131. data/spec/unit/rpc/result_spec.rb +7 -0
  132. data/spec/unit/rpc/stats_spec.rb +14 -14
  133. data/spec/unit/rpc_spec.rb +16 -0
  134. data/spec/unit/security/base_spec.rb +8 -8
  135. data/spec/unit/ssl_spec.rb +20 -2
  136. data/spec/unit/string_spec.rb +15 -0
  137. data/spec/unit/util_spec.rb +141 -21
  138. data/spec/unit/validator_spec.rb +67 -0
  139. metadata +145 -7
  140. data/lib/mcollective/rpc/ddl.rb +0 -258
@@ -2,15 +2,6 @@ module MCollective
2
2
  module RPC
3
3
  # Various utilities for the RPC system
4
4
  class Helpers
5
- # Checks in PATH returns true if the command is found
6
- def self.command_in_path?(command)
7
- found = ENV["PATH"].split(File::PATH_SEPARATOR).map do |p|
8
- File.exist?(File.join(p, command))
9
- end
10
-
11
- found.include?(true)
12
- end
13
-
14
5
  # Parse JSON output as produced by printrpc and extract
15
6
  # the "sender" of each rpc response
16
7
  #
@@ -42,54 +33,6 @@ module MCollective
42
33
  end
43
34
  end
44
35
 
45
- # Figures out the columns and liens of the current tty
46
- #
47
- # Returns [0, 0] if it can't figure it out or if you're
48
- # not running on a tty
49
- def self.terminal_dimensions
50
- return [0, 0] unless STDOUT.tty?
51
-
52
- return [80, 40] if Util.windows?
53
-
54
- if ENV["COLUMNS"] && ENV["LINES"]
55
- return [ENV["COLUMNS"].to_i, ENV["LINES"].to_i]
56
-
57
- elsif ENV["TERM"] && command_in_path?("tput")
58
- return [`tput cols`.to_i, `tput lines`.to_i]
59
-
60
- elsif command_in_path?('stty')
61
- return `stty size`.scan(/\d+/).map {|s| s.to_i }
62
- else
63
- return [0, 0]
64
- end
65
- rescue
66
- [0, 0]
67
- end
68
-
69
- # Return color codes, if the config color= option is false
70
- # just return a empty string
71
- def self.color(code)
72
- colorize = Config.instance.color
73
-
74
- colors = {:red => "",
75
- :green => "",
76
- :yellow => "",
77
- :cyan => "",
78
- :bold => "",
79
- :reset => ""}
80
-
81
- if colorize
82
- return colors[code] || ""
83
- else
84
- return ""
85
- end
86
- end
87
-
88
- # Helper to return a string in specific color
89
- def self.colorize(code, msg)
90
- "#{self.color(code)}#{msg}#{self.color(:reset)}"
91
- end
92
-
93
36
  # Returns a blob of text representing the results in a standard way
94
37
  #
95
38
  # It tries hard to do sane things so you often
@@ -109,7 +52,7 @@ module MCollective
109
52
  # hostnames, it will just print the result as if it's one huge result,
110
53
  # handy for things like showing a combined mailq.
111
54
  def self.rpcresults(result, flags = {})
112
- flags = {:verbose => false, :flatten => false, :format => :console}.merge(flags)
55
+ flags = {:verbose => false, :flatten => false, :format => :console, :force_display_mode => false}.merge(flags)
113
56
 
114
57
  result_text = ""
115
58
  ddl = nil
@@ -133,26 +76,31 @@ module MCollective
133
76
  sender = r[:sender]
134
77
  status = r[:statuscode]
135
78
  message = r[:statusmsg]
136
- display = ddl[:display]
137
79
  result = r[:data]
138
80
 
81
+ if flags[:force_display_mode]
82
+ display = flags[:force_display_mode]
83
+ else
84
+ display = ddl[:display]
85
+ end
86
+
139
87
  # appand the results only according to what the DDL says
140
88
  case display
141
- when :ok
142
- if status == 0
143
- result_text << text_for_result(sender, status, message, result, ddl)
144
- end
89
+ when :ok
90
+ if status == 0
91
+ result_text << text_for_result(sender, status, message, result, ddl)
92
+ end
145
93
 
146
- when :failed
147
- if status > 0
148
- result_text << text_for_result(sender, status, message, result, ddl)
149
- end
94
+ when :failed
95
+ if status > 0
96
+ result_text << text_for_result(sender, status, message, result, ddl)
97
+ end
150
98
 
151
- when :always
152
- result_text << text_for_result(sender, status, message, result, ddl)
99
+ when :always
100
+ result_text << text_for_result(sender, status, message, result, ddl)
153
101
 
154
- when :flatten
155
- result_text << text_for_flattened_result(status, result)
102
+ when :flatten
103
+ result_text << text_for_flattened_result(status, result)
156
104
 
157
105
  end
158
106
  rescue Exception => e
@@ -170,14 +118,14 @@ module MCollective
170
118
  # Return text representing a result
171
119
  def self.text_for_result(sender, status, msg, result, ddl)
172
120
  statusses = ["",
173
- colorize(:red, "Request Aborted"),
174
- colorize(:yellow, "Unknown Action"),
175
- colorize(:yellow, "Missing Request Data"),
176
- colorize(:yellow, "Invalid Request Data"),
177
- colorize(:red, "Unknown Request Status")]
121
+ Util.colorize(:red, "Request Aborted"),
122
+ Util.colorize(:yellow, "Unknown Action"),
123
+ Util.colorize(:yellow, "Missing Request Data"),
124
+ Util.colorize(:yellow, "Invalid Request Data"),
125
+ Util.colorize(:red, "Unknown Request Status")]
178
126
 
179
127
  result_text = "%-40s %s\n" % [sender, statusses[status]]
180
- result_text << " %s\n" % [colorize(:yellow, msg)] unless msg == "OK"
128
+ result_text << " %s\n" % [Util.colorize(:yellow, msg)] unless msg == "OK"
181
129
 
182
130
  # only print good data, ignore data that results from failure
183
131
  if [0, 1].include?(status)
@@ -192,7 +140,7 @@ module MCollective
192
140
  end
193
141
  end
194
142
 
195
- result.keys.each do |k|
143
+ result.keys.sort_by{|k| k}.each do |k|
196
144
  # get all the output fields nicely lined up with a
197
145
  # 3 space front padding
198
146
  begin
@@ -289,7 +237,7 @@ module MCollective
289
237
  end
290
238
  else
291
239
  unless r[:statuscode] == 0
292
- result_text << "%-40s %s\n" % [r[:sender], colorize(:red, r[:statusmsg])]
240
+ result_text << "%-40s %s\n" % [r[:sender], Util.colorize(:red, r[:statusmsg])]
293
241
  end
294
242
  end
295
243
  end
@@ -319,7 +267,11 @@ module MCollective
319
267
  options[:batch_sleep_time] = v
320
268
  end
321
269
 
322
- parser.on('--limit-nodes COUNT', '--ln', 'Send request to only a subset of nodes, can be a percentage') do |v|
270
+ parser.on('--limit-seed NUMBER', Integer, 'Seed value for deterministic random batching') do |v|
271
+ options[:limit_seed] = v
272
+ end
273
+
274
+ parser.on('--limit-nodes COUNT', '--ln', '--limit', 'Send request to only a subset of nodes, can be a percentage') do |v|
323
275
  raise "Invalid limit specified: #{v} valid limits are /^\d+%*$/" unless v =~ /^\d+%*$/
324
276
 
325
277
  if v =~ /^\d+$/
@@ -333,6 +285,16 @@ module MCollective
333
285
  options[:progress_bar] = false
334
286
  options[:output_format] = :json
335
287
  end
288
+
289
+ parser.on('--display MODE', 'Influence how results are displayed. One of ok, all or failed') do |v|
290
+ if v == "all"
291
+ options[:force_display_mode] = :always
292
+ else
293
+ options[:force_display_mode] = v.intern
294
+ end
295
+
296
+ raise "--display has to be one of 'ok', 'all' or 'failed'" unless [:ok, :failed, :always].include?(options[:force_display_mode])
297
+ end
336
298
  end
337
299
  end
338
300
  end
@@ -19,7 +19,7 @@ module MCollective
19
19
  if size
20
20
  @size = size
21
21
  else
22
- cols = Helpers.terminal_dimensions[0] - 22
22
+ cols = Util.terminal_dimensions[0] - 22
23
23
 
24
24
  # Defaults back to old behavior if it
25
25
  # couldn't figure out the size or if
@@ -40,9 +40,9 @@ module MCollective
40
40
  return "\r#{current} / #{total}" if @size == 0
41
41
 
42
42
  if current == total
43
- txt = "\r " + Helpers.colorize(:green, "*") + " [ "
43
+ txt = "\r %s [ " % Util.colorize(:green, "*")
44
44
  else
45
- txt = "\r #{@twirl[@twirldex]} [ "
45
+ txt = "\r %s [ " % Util.colorize(:red, @twirl[@twirldex])
46
46
  end
47
47
 
48
48
  dashes = ((current.to_f / total) * @size).round
@@ -4,10 +4,30 @@ module MCollective
4
4
  class Reply
5
5
  attr_accessor :statuscode, :statusmsg, :data
6
6
 
7
- def initialize
7
+ def initialize(action, ddl)
8
8
  @data = {}
9
9
  @statuscode = 0
10
10
  @statusmsg = "OK"
11
+ @ddl = ddl
12
+ @action = action
13
+
14
+ begin
15
+ initialize_data
16
+ rescue Exception => e
17
+ Log.warn("Could not pre-populate reply data from the DDL: %s: %s" % [e.class, e.to_s ])
18
+ end
19
+ end
20
+
21
+ def initialize_data
22
+ unless @ddl.actions.include?(@action)
23
+ raise "No action '%s' defined for agent '%s' in the DDL" % [@action, @ddl.pluginname]
24
+ end
25
+
26
+ interface = @ddl.action_interface(@action)
27
+
28
+ interface[:output].keys.each do |output|
29
+ @data[output] = interface[:output][output][:default]
30
+ end
11
31
  end
12
32
 
13
33
  # Helper to fill in statusmsg and code on failure
@@ -22,20 +42,20 @@ module MCollective
22
42
  @statuscode = code
23
43
 
24
44
  case code
25
- when 1
26
- raise RPCAborted, msg
45
+ when 1
46
+ raise RPCAborted, msg
27
47
 
28
- when 2
29
- raise UnknownRPCAction, msg
48
+ when 2
49
+ raise UnknownRPCAction, msg
30
50
 
31
- when 3
32
- raise MissingRPCData, msg
51
+ when 3
52
+ raise MissingRPCData, msg
33
53
 
34
- when 4
35
- raise InvalidRPCData, msg
54
+ when 4
55
+ raise InvalidRPCData, msg
36
56
 
37
- else
38
- raise UnknownRPCError, msg
57
+ else
58
+ raise UnknownRPCError, msg
39
59
  end
40
60
  end
41
61
 
@@ -49,12 +69,16 @@ module MCollective
49
69
  @data[key]
50
70
  end
51
71
 
72
+ def fetch(key, default)
73
+ @data.fetch(key, default)
74
+ end
75
+
52
76
  # Returns a compliant Hash of the reply that should be sent
53
77
  # over the middleware
54
78
  def to_hash
55
79
  return {:statuscode => @statuscode,
56
- :statusmsg => @statusmsg,
57
- :data => @data}
80
+ :statusmsg => @statusmsg,
81
+ :data => @data}
58
82
  end
59
83
  end
60
84
  end
@@ -2,9 +2,9 @@ module MCollective
2
2
  module RPC
3
3
  # Simple class to manage compliant requests for MCollective::RPC agents
4
4
  class Request
5
- attr_accessor :time, :action, :data, :sender, :agent, :uniqid, :caller
5
+ attr_accessor :time, :action, :data, :sender, :agent, :uniqid, :caller, :ddl
6
6
 
7
- def initialize(msg)
7
+ def initialize(msg, ddl)
8
8
  @time = msg[:msgtime]
9
9
  @action = msg[:body][:action]
10
10
  @data = msg[:body][:data]
@@ -12,6 +12,7 @@ module MCollective
12
12
  @agent = msg[:body][:agent]
13
13
  @uniqid = msg[:requestid]
14
14
  @caller = msg[:callerid] || "unknown"
15
+ @ddl = ddl
15
16
  end
16
17
 
17
18
  # If data is a hash, quick helper to get access to it's include? method
@@ -35,16 +36,26 @@ module MCollective
35
36
  return @data[key]
36
37
  end
37
38
 
39
+ def fetch(key, default)
40
+ return nil unless @data.is_a?(Hash)
41
+ return @data.fetch(key, default)
42
+ end
43
+
38
44
  def to_hash
39
45
  return {:agent => @agent,
40
- :action => @action,
41
- :data => @data}
46
+ :action => @action,
47
+ :data => @data}
48
+ end
49
+
50
+ # Validate the request against the DDL
51
+ def validate!
52
+ @ddl.validate_rpc_request(@action, @data)
42
53
  end
43
54
 
44
55
  def to_json
45
56
  to_hash.merge!({:sender => @sender,
46
- :callerid => @callerid,
47
- :uniqid => @uniqid}).to_json
57
+ :callerid => @callerid,
58
+ :uniqid => @uniqid}).to_json
48
59
  end
49
60
  end
50
61
  end
@@ -24,17 +24,21 @@ module MCollective
24
24
  @results[idx] = item
25
25
  end
26
26
 
27
+ def fetch(key, default)
28
+ @results.fetch(key, default)
29
+ end
30
+
27
31
  def each
28
32
  @results.each_pair {|k,v| yield(k,v) }
29
33
  end
30
34
 
31
35
  def to_json(*a)
32
36
  {:agent => @agent,
33
- :action => @action,
34
- :sender => @results[:sender],
35
- :statuscode => @results[:statuscode],
36
- :statusmsg => @results[:statusmsg],
37
- :data => @results[:data]}.to_json(*a)
37
+ :action => @action,
38
+ :sender => @results[:sender],
39
+ :statuscode => @results[:statuscode],
40
+ :statusmsg => @results[:statusmsg],
41
+ :data => @results[:data]}.to_json(*a)
38
42
  end
39
43
  end
40
44
  end
@@ -4,6 +4,7 @@ module MCollective
4
4
  class Stats
5
5
  attr_accessor :noresponsefrom, :starttime, :discoverytime, :blocktime, :responses, :totaltime
6
6
  attr_accessor :discovered, :discovered_nodes, :okcount, :failcount, :noresponsefrom, :responsesfrom
7
+ attr_accessor :requestid, :aggregate_summary, :ddl
7
8
 
8
9
  def initialize
9
10
  reset
@@ -23,21 +24,25 @@ module MCollective
23
24
  @okcount = 0
24
25
  @failcount = 0
25
26
  @noresponsefrom = []
27
+ @requestid = nil
28
+ @aggregate_summary = []
26
29
  end
27
30
 
28
31
  # returns a hash of our stats
29
32
  def to_hash
30
- {:noresponsefrom => @noresponsefrom,
31
- :starttime => @starttime,
32
- :discoverytime => @discoverytime,
33
- :blocktime => @blocktime,
34
- :responses => @responses,
35
- :totaltime => @totaltime,
36
- :discovered => @discovered,
37
- :discovered_nodes => @discovered_nodes,
38
- :noresponsefrom => @noresponsefrom,
39
- :okcount => @okcount,
40
- :failcount => @failcount}
33
+ {:noresponsefrom => @noresponsefrom,
34
+ :starttime => @starttime,
35
+ :discoverytime => @discoverytime,
36
+ :blocktime => @blocktime,
37
+ :responses => @responses,
38
+ :totaltime => @totaltime,
39
+ :discovered => @discovered,
40
+ :discovered_nodes => @discovered_nodes,
41
+ :noresponsefrom => @noresponsefrom,
42
+ :okcount => @okcount,
43
+ :requestid => @requestid,
44
+ :failcount => @failcount,
45
+ :aggregate_summary => @aggregate_summary}
41
46
  end
42
47
 
43
48
  # Fake hash access to keep things backward compatible
@@ -68,6 +73,7 @@ module MCollective
68
73
  @starttime = stats[:starttime]
69
74
  @blocktime = stats[:blocktime]
70
75
  @totaltime = stats[:totaltime]
76
+ @requestid = stats[:requestid]
71
77
  @discoverytime = stats[:discoverytime] if @discoverytime == 0
72
78
  end
73
79
 
@@ -124,24 +130,58 @@ module MCollective
124
130
  @responsesfrom = [node]
125
131
  end
126
132
 
133
+ def text_for_aggregates
134
+ result = StringIO.new
135
+
136
+ @aggregate_summary.each do |aggregate|
137
+ output_item = aggregate.result[:output]
138
+
139
+ begin
140
+ action_interface = @ddl.action_interface(aggregate.action)
141
+ display_as = action_interface[:output][output_item][:display_as]
142
+ rescue
143
+ display_as = output_item
144
+ end
145
+
146
+ aggregate_report = aggregate.to_s
147
+
148
+ result.puts Util.colorize(:bold, "Summary of %s:" % display_as)
149
+ result.puts
150
+ unless aggregate_report == ""
151
+ result.puts aggregate.to_s
152
+ else
153
+ result.puts Util.colorize(:yellow, " No aggregate summary could be computed")
154
+ end
155
+ result.puts
156
+ end
157
+
158
+ result.string
159
+ end
160
+
127
161
  # Returns a blob of text representing the request status based on the
128
162
  # stats contained in this class
129
- def report(caption = "rpc stats", verbose = false)
163
+ def report(caption = "rpc stats", summarize = true, verbose = false)
130
164
  result_text = []
131
165
 
132
166
  if verbose
133
- result_text << Helpers.colorize(:yellow, "---- #{caption} ----")
167
+ if @aggregate_summary.size > 0 && summarize
168
+ result_text << text_for_aggregates
169
+ else
170
+ result_text << ""
171
+ end
172
+
173
+ result_text << Util.colorize(:yellow, "---- #{caption} ----")
134
174
 
135
175
  if @discovered
136
176
  @responses < @discovered ? color = :red : color = :reset
137
- result_text << " Nodes: %s / %s" % [ Helpers.colorize(color, @discovered), Helpers.colorize(color, @responses) ]
177
+ result_text << " Nodes: %s / %s" % [ Util.colorize(color, @discovered), Util.colorize(color, @responses) ]
138
178
  else
139
179
  result_text << " Nodes: #{@responses}"
140
180
  end
141
181
 
142
182
  @failcount < 0 ? color = :red : color = :reset
143
183
 
144
- result_text << " Pass / Fail: %s / %s" % [Helpers.colorize(color, @okcount), Helpers.colorize(color, @failcount) ]
184
+ result_text << " Pass / Fail: %s / %s" % [Util.colorize(color, @okcount), Util.colorize(color, @failcount) ]
145
185
  result_text << " Start Time: %s" % [Time.at(@starttime)]
146
186
  result_text << " Discovery Time: %.2fms" % [@discoverytime * 1000]
147
187
  result_text << " Agent Time: %.2fms" % [@blocktime * 1000]
@@ -150,9 +190,15 @@ module MCollective
150
190
  if @discovered
151
191
  @responses < @discovered ? color = :red : color = :green
152
192
 
153
- result_text << "Finished processing %s / %s hosts in %.2f ms" % [Helpers.colorize(color, @responses), Helpers.colorize(color, @discovered), @blocktime * 1000]
193
+ if @aggregate_summary.size > 0 && summarize
194
+ result_text << text_for_aggregates
195
+ else
196
+ result_text << ""
197
+ end
198
+
199
+ result_text << "Finished processing %s / %s hosts in %.2f ms" % [Util.colorize(color, @responses), Util.colorize(color, @discovered), @blocktime * 1000]
154
200
  else
155
- result_text << "Finished processing %s hosts in %.2f ms" % [Helpers.colorize(:bold, @responses), @blocktime * 1000]
201
+ result_text << "Finished processing %s hosts in %.2f ms" % [Util.colorize(:bold, @responses), @blocktime * 1000]
156
202
  end
157
203
  end
158
204
 
@@ -165,20 +211,21 @@ module MCollective
165
211
 
166
212
  # Returns a blob of text indicating what nodes did not respond
167
213
  def no_response_report
168
- result_text = []
214
+ result_text = StringIO.new
169
215
 
170
216
  if @noresponsefrom.size > 0
171
- result_text << Helpers.colorize(:red, "\nNo response from:\n")
217
+ result_text.puts
218
+ result_text.puts Util.colorize(:red, "No response from:")
219
+ result_text.puts
172
220
 
173
- @noresponsefrom.each_with_index do |c,i|
174
- result_text << "" if i % 4 == 0
175
- result_text << "%30s" % [c]
221
+ @noresponsefrom.sort.in_groups_of(3) do |c|
222
+ result_text.puts " %-30s%-30s%-30s" % c
176
223
  end
177
224
 
178
- result_text << ""
225
+ result_text.puts
179
226
  end
180
227
 
181
- result_text.join("\n")
228
+ result_text.string
182
229
  end
183
230
  end
184
231
  end