mcollective-client 1.3.3

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 (103) hide show
  1. data/bin/mc-call-agent +54 -0
  2. data/bin/mco +27 -0
  3. data/lib/mcollective.rb +70 -0
  4. data/lib/mcollective/agents.rb +160 -0
  5. data/lib/mcollective/application.rb +354 -0
  6. data/lib/mcollective/applications.rb +145 -0
  7. data/lib/mcollective/client.rb +292 -0
  8. data/lib/mcollective/config.rb +202 -0
  9. data/lib/mcollective/connector.rb +18 -0
  10. data/lib/mcollective/connector/base.rb +24 -0
  11. data/lib/mcollective/facts.rb +39 -0
  12. data/lib/mcollective/facts/base.rb +86 -0
  13. data/lib/mcollective/log.rb +103 -0
  14. data/lib/mcollective/logger.rb +5 -0
  15. data/lib/mcollective/logger/base.rb +73 -0
  16. data/lib/mcollective/logger/console_logger.rb +61 -0
  17. data/lib/mcollective/logger/file_logger.rb +46 -0
  18. data/lib/mcollective/logger/syslog_logger.rb +53 -0
  19. data/lib/mcollective/matcher.rb +16 -0
  20. data/lib/mcollective/matcher/parser.rb +93 -0
  21. data/lib/mcollective/matcher/scanner.rb +123 -0
  22. data/lib/mcollective/message.rb +201 -0
  23. data/lib/mcollective/monkey_patches.rb +104 -0
  24. data/lib/mcollective/optionparser.rb +164 -0
  25. data/lib/mcollective/pluginmanager.rb +180 -0
  26. data/lib/mcollective/pluginpackager.rb +26 -0
  27. data/lib/mcollective/pluginpackager/agent_definition.rb +79 -0
  28. data/lib/mcollective/pluginpackager/standard_definition.rb +59 -0
  29. data/lib/mcollective/registration.rb +16 -0
  30. data/lib/mcollective/registration/base.rb +75 -0
  31. data/lib/mcollective/rpc.rb +188 -0
  32. data/lib/mcollective/rpc/actionrunner.rb +142 -0
  33. data/lib/mcollective/rpc/agent.rb +441 -0
  34. data/lib/mcollective/rpc/audit.rb +38 -0
  35. data/lib/mcollective/rpc/client.rb +793 -0
  36. data/lib/mcollective/rpc/ddl.rb +258 -0
  37. data/lib/mcollective/rpc/helpers.rb +339 -0
  38. data/lib/mcollective/rpc/progress.rb +63 -0
  39. data/lib/mcollective/rpc/reply.rb +61 -0
  40. data/lib/mcollective/rpc/request.rb +51 -0
  41. data/lib/mcollective/rpc/result.rb +41 -0
  42. data/lib/mcollective/rpc/stats.rb +185 -0
  43. data/lib/mcollective/runnerstats.rb +90 -0
  44. data/lib/mcollective/security.rb +26 -0
  45. data/lib/mcollective/security/base.rb +237 -0
  46. data/lib/mcollective/shell.rb +87 -0
  47. data/lib/mcollective/ssl.rb +246 -0
  48. data/lib/mcollective/unix_daemon.rb +37 -0
  49. data/lib/mcollective/util.rb +274 -0
  50. data/lib/mcollective/vendor.rb +41 -0
  51. data/lib/mcollective/vendor/require_vendored.rb +2 -0
  52. data/lib/mcollective/windows_daemon.rb +25 -0
  53. data/spec/Rakefile +16 -0
  54. data/spec/fixtures/application/test.rb +7 -0
  55. data/spec/fixtures/test-cert.pem +15 -0
  56. data/spec/fixtures/test-private.pem +15 -0
  57. data/spec/fixtures/test-public.pem +6 -0
  58. data/spec/monkey_patches/instance_variable_defined.rb +7 -0
  59. data/spec/spec.opts +1 -0
  60. data/spec/spec_helper.rb +25 -0
  61. data/spec/unit/agents_spec.rb +280 -0
  62. data/spec/unit/application_spec.rb +636 -0
  63. data/spec/unit/applications_spec.rb +155 -0
  64. data/spec/unit/array.rb +30 -0
  65. data/spec/unit/config_spec.rb +148 -0
  66. data/spec/unit/facts/base_spec.rb +118 -0
  67. data/spec/unit/facts_spec.rb +39 -0
  68. data/spec/unit/log_spec.rb +71 -0
  69. data/spec/unit/logger/base_spec.rb +110 -0
  70. data/spec/unit/logger/syslog_logger_spec.rb +86 -0
  71. data/spec/unit/matcher/parser_spec.rb +106 -0
  72. data/spec/unit/matcher/scanner_spec.rb +71 -0
  73. data/spec/unit/message_spec.rb +401 -0
  74. data/spec/unit/optionparser_spec.rb +113 -0
  75. data/spec/unit/pluginmanager_spec.rb +173 -0
  76. data/spec/unit/pluginpackager/agent_definition_spec.rb +130 -0
  77. data/spec/unit/pluginpackager/standard_definition_spec.rb +75 -0
  78. data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +533 -0
  79. data/spec/unit/plugins/mcollective/connector/stomp/eventlogger_spec.rb +34 -0
  80. data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +417 -0
  81. data/spec/unit/plugins/mcollective/packagers/ospackage_spec.rb +229 -0
  82. data/spec/unit/plugins/mcollective/security/psk_spec.rb +156 -0
  83. data/spec/unit/registration/base_spec.rb +77 -0
  84. data/spec/unit/rpc/actionrunner_spec.rb +213 -0
  85. data/spec/unit/rpc/agent_spec.rb +155 -0
  86. data/spec/unit/rpc/client_spec.rb +523 -0
  87. data/spec/unit/rpc/ddl_spec.rb +388 -0
  88. data/spec/unit/rpc/helpers_spec.rb +55 -0
  89. data/spec/unit/rpc/reply_spec.rb +143 -0
  90. data/spec/unit/rpc/request_spec.rb +115 -0
  91. data/spec/unit/rpc/result_spec.rb +66 -0
  92. data/spec/unit/rpc/stats_spec.rb +288 -0
  93. data/spec/unit/runnerstats_spec.rb +40 -0
  94. data/spec/unit/security/base_spec.rb +279 -0
  95. data/spec/unit/shell_spec.rb +144 -0
  96. data/spec/unit/ssl_spec.rb +244 -0
  97. data/spec/unit/symbol.rb +11 -0
  98. data/spec/unit/unix_daemon.rb +41 -0
  99. data/spec/unit/util_spec.rb +342 -0
  100. data/spec/unit/vendor_spec.rb +34 -0
  101. data/spec/unit/windows_daemon.rb +43 -0
  102. data/spec/windows_spec.opts +1 -0
  103. metadata +242 -0
@@ -0,0 +1,63 @@
1
+ module MCollective
2
+ module RPC
3
+ # Class that shows a progress bar, currently only supports a twirling
4
+ # progress bar.
5
+ #
6
+ # You can specify a size for the progress bar if you want if you dont
7
+ # it will use the helper functions to figure out terminal dimensions
8
+ # and draw an appropriately sized bar
9
+ #
10
+ # p = Progress.new
11
+ # 100.times {|i| print p.twirl(i+1, 100) + "\r"};puts
12
+ #
13
+ # * [ ==================================================> ] 100 / 100
14
+ class Progress
15
+ def initialize(size=nil)
16
+ @twirl = ['|', '/', '-', "\\", '|', '/', '-', "\\"]
17
+ @twirldex = 0
18
+
19
+ if size
20
+ @size = size
21
+ else
22
+ cols = Helpers.terminal_dimensions[0] - 22
23
+
24
+ # Defaults back to old behavior if it
25
+ # couldn't figure out the size or if
26
+ # its more than 60 wide
27
+ if cols <= 0
28
+ @size = 0
29
+ elsif cols > 60
30
+ @size = 60
31
+ else
32
+ @size = cols
33
+ end
34
+ end
35
+ end
36
+
37
+ def twirl(current, total)
38
+ # if the size is negative there is just not enough
39
+ # space on the terminal, return a simpler version
40
+ return "\r#{current} / #{total}" if @size == 0
41
+
42
+ if current == total
43
+ txt = "\r " + Helpers.colorize(:green, "*") + " [ "
44
+ else
45
+ txt = "\r #{@twirl[@twirldex]} [ "
46
+ end
47
+
48
+ dashes = ((current.to_f / total) * @size).round
49
+
50
+ dashes.times { txt << "=" }
51
+ txt << ">"
52
+
53
+ (@size - dashes).times { txt << " " }
54
+
55
+ txt << " ] #{current} / #{total}"
56
+
57
+ @twirldex == 7 ? @twirldex = 0 : @twirldex += 1
58
+
59
+ return txt
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,61 @@
1
+ module MCollective
2
+ module RPC
3
+ # Simple class to manage compliant replies to MCollective::RPC
4
+ class Reply
5
+ attr_accessor :statuscode, :statusmsg, :data
6
+
7
+ def initialize
8
+ @data = {}
9
+ @statuscode = 0
10
+ @statusmsg = "OK"
11
+ end
12
+
13
+ # Helper to fill in statusmsg and code on failure
14
+ def fail(msg, code=1)
15
+ @statusmsg = msg
16
+ @statuscode = code
17
+ end
18
+
19
+ # Helper that fills in statusmsg and code but also raises an appropriate error
20
+ def fail!(msg, code=1)
21
+ @statusmsg = msg
22
+ @statuscode = code
23
+
24
+ case code
25
+ when 1
26
+ raise RPCAborted, msg
27
+
28
+ when 2
29
+ raise UnknownRPCAction, msg
30
+
31
+ when 3
32
+ raise MissingRPCData, msg
33
+
34
+ when 4
35
+ raise InvalidRPCData, msg
36
+
37
+ else
38
+ raise UnknownRPCError, msg
39
+ end
40
+ end
41
+
42
+ # Write to the data hash
43
+ def []=(key, val)
44
+ @data[key] = val
45
+ end
46
+
47
+ # Read from the data hash
48
+ def [](key)
49
+ @data[key]
50
+ end
51
+
52
+ # Returns a compliant Hash of the reply that should be sent
53
+ # over the middleware
54
+ def to_hash
55
+ return {:statuscode => @statuscode,
56
+ :statusmsg => @statusmsg,
57
+ :data => @data}
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ module MCollective
2
+ module RPC
3
+ # Simple class to manage compliant requests for MCollective::RPC agents
4
+ class Request
5
+ attr_accessor :time, :action, :data, :sender, :agent, :uniqid, :caller
6
+
7
+ def initialize(msg)
8
+ @time = msg[:msgtime]
9
+ @action = msg[:body][:action]
10
+ @data = msg[:body][:data]
11
+ @sender = msg[:senderid]
12
+ @agent = msg[:body][:agent]
13
+ @uniqid = msg[:requestid]
14
+ @caller = msg[:callerid] || "unknown"
15
+ end
16
+
17
+ # If data is a hash, quick helper to get access to it's include? method
18
+ # else returns false
19
+ def include?(key)
20
+ return false unless @data.is_a?(Hash)
21
+ return @data.include?(key)
22
+ end
23
+
24
+ # If no :process_results is specified always respond else respond
25
+ # based on the supplied property
26
+ def should_respond?
27
+ return @data[:process_results] if @data.include?(:process_results)
28
+
29
+ return true
30
+ end
31
+
32
+ # If data is a hash, gives easy access to its members, else returns nil
33
+ def [](key)
34
+ return nil unless @data.is_a?(Hash)
35
+ return @data[key]
36
+ end
37
+
38
+ def to_hash
39
+ return {:agent => @agent,
40
+ :action => @action,
41
+ :data => @data}
42
+ end
43
+
44
+ def to_json
45
+ to_hash.merge!({:sender => @sender,
46
+ :callerid => @callerid,
47
+ :uniqid => @uniqid}).to_json
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,41 @@
1
+ module MCollective
2
+ module RPC
3
+ # Simple class to manage compliant results from MCollective::RPC agents
4
+ #
5
+ # Currently it just fakes Hash behaviour to the result to remain backward
6
+ # compatible but it also knows which agent and action produced it so you
7
+ # can associate results to a DDL
8
+ class Result
9
+ attr_reader :agent, :action, :results
10
+
11
+ include Enumerable
12
+
13
+ def initialize(agent, action, result={})
14
+ @agent = agent
15
+ @action = action
16
+ @results = result
17
+ end
18
+
19
+ def [](idx)
20
+ @results[idx]
21
+ end
22
+
23
+ def []=(idx, item)
24
+ @results[idx] = item
25
+ end
26
+
27
+ def each
28
+ @results.each_pair {|k,v| yield(k,v) }
29
+ end
30
+
31
+ def to_json(*a)
32
+ {:agent => @agent,
33
+ :action => @action,
34
+ :sender => @results[:sender],
35
+ :statuscode => @results[:statuscode],
36
+ :statusmsg => @results[:statusmsg],
37
+ :data => @results[:data]}.to_json(*a)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,185 @@
1
+ module MCollective
2
+ module RPC
3
+ # Class to wrap all the stats and to keep track of some timings
4
+ class Stats
5
+ attr_accessor :noresponsefrom, :starttime, :discoverytime, :blocktime, :responses, :totaltime
6
+ attr_accessor :discovered, :discovered_nodes, :okcount, :failcount, :noresponsefrom, :responsesfrom
7
+
8
+ def initialize
9
+ reset
10
+ end
11
+
12
+ # Resets stats, if discovery time is set we keep it as it was
13
+ def reset
14
+ @noresponsefrom = []
15
+ @responsesfrom = []
16
+ @responses = 0
17
+ @starttime = Time.now.to_f
18
+ @discoverytime = 0 unless @discoverytime
19
+ @blocktime = 0
20
+ @totaltime = 0
21
+ @discovered = 0
22
+ @discovered_nodes = []
23
+ @okcount = 0
24
+ @failcount = 0
25
+ @noresponsefrom = []
26
+ end
27
+
28
+ # returns a hash of our stats
29
+ 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}
41
+ end
42
+
43
+ # Fake hash access to keep things backward compatible
44
+ def [](key)
45
+ to_hash[key]
46
+ rescue
47
+ nil
48
+ end
49
+
50
+ # increment the count of ok hosts
51
+ def ok
52
+ @okcount += 1
53
+ rescue
54
+ @okcount = 1
55
+ end
56
+
57
+ # increment the count of failed hosts
58
+ def fail
59
+ @failcount += 1
60
+ rescue
61
+ @failcount = 1
62
+ end
63
+
64
+ # Re-initializes the object with stats from the basic client
65
+ def client_stats=(stats)
66
+ @noresponsefrom = stats[:noresponsefrom]
67
+ @responses = stats[:responses]
68
+ @starttime = stats[:starttime]
69
+ @blocktime = stats[:blocktime]
70
+ @totaltime = stats[:totaltime]
71
+ @discoverytime = stats[:discoverytime] if @discoverytime == 0
72
+ end
73
+
74
+ # Utility to time discovery from :start to :end
75
+ def time_discovery(action)
76
+ if action == :start
77
+ @discovery_start = Time.now.to_f
78
+ elsif action == :end
79
+ @discoverytime = Time.now.to_f - @discovery_start
80
+ else
81
+ raise("Uknown discovery action #{action}")
82
+ end
83
+ rescue
84
+ @discoverytime = 0
85
+ end
86
+
87
+ # helper to time block execution time
88
+ def time_block_execution(action)
89
+ if action == :start
90
+ @block_start = Time.now.to_f
91
+ elsif action == :end
92
+ @blocktime += Time.now.to_f - @block_start
93
+ else
94
+ raise("Uknown block action #{action}")
95
+ end
96
+ rescue
97
+ @blocktime = 0
98
+ end
99
+
100
+ # Update discovered and discovered_nodes based on
101
+ # discovery results
102
+ def discovered_agents(agents)
103
+ @discovered_nodes = agents
104
+ @discovered = agents.size
105
+ end
106
+
107
+ # Helper to calculate total time etc
108
+ def finish_request
109
+ @totaltime = @blocktime + @discoverytime
110
+
111
+ # figures out who we had no responses from
112
+ dhosts = @discovered_nodes.clone
113
+ @responsesfrom.each {|r| dhosts.delete(r)}
114
+ @noresponsefrom = dhosts
115
+ rescue
116
+ @totaltime = 0
117
+ @noresponsefrom = []
118
+ end
119
+
120
+ # Helper to keep track of who we received responses from
121
+ def node_responded(node)
122
+ @responsesfrom << node
123
+ rescue
124
+ @responsesfrom = [node]
125
+ end
126
+
127
+ # Returns a blob of text representing the request status based on the
128
+ # stats contained in this class
129
+ def report(caption = "rpc stats", verbose = false)
130
+ result_text = []
131
+
132
+ if verbose
133
+ result_text << Helpers.colorize(:yellow, "---- #{caption} ----")
134
+
135
+ if @discovered
136
+ @responses < @discovered ? color = :red : color = :reset
137
+ result_text << " Nodes: %s / %s" % [ Helpers.colorize(color, @discovered), Helpers.colorize(color, @responses) ]
138
+ else
139
+ result_text << " Nodes: #{@responses}"
140
+ end
141
+
142
+ @failcount < 0 ? color = :red : color = :reset
143
+
144
+ result_text << " Pass / Fail: %s / %s" % [Helpers.colorize(color, @okcount), Helpers.colorize(color, @failcount) ]
145
+ result_text << " Start Time: %s" % [Time.at(@starttime)]
146
+ result_text << " Discovery Time: %.2fms" % [@discoverytime * 1000]
147
+ result_text << " Agent Time: %.2fms" % [@blocktime * 1000]
148
+ result_text << " Total Time: %.2fms" % [@totaltime * 1000]
149
+ else
150
+ if @discovered
151
+ @responses < @discovered ? color = :red : color = :green
152
+
153
+ result_text << "Finished processing %s / %s hosts in %.2f ms" % [Helpers.colorize(color, @responses), Helpers.colorize(color, @discovered), @blocktime * 1000]
154
+ else
155
+ result_text << "Finished processing %s hosts in %.2f ms" % [Helpers.colorize(:bold, @responses), @blocktime * 1000]
156
+ end
157
+ end
158
+
159
+ if no_response_report != ""
160
+ result_text << "" << no_response_report
161
+ end
162
+
163
+ result_text.join("\n")
164
+ end
165
+
166
+ # Returns a blob of text indicating what nodes did not respond
167
+ def no_response_report
168
+ result_text = []
169
+
170
+ if @noresponsefrom.size > 0
171
+ result_text << Helpers.colorize(:red, "\nNo response from:\n")
172
+
173
+ @noresponsefrom.each_with_index do |c,i|
174
+ result_text << "" if i % 4 == 0
175
+ result_text << "%30s" % [c]
176
+ end
177
+
178
+ result_text << ""
179
+ end
180
+
181
+ result_text.join("\n")
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,90 @@
1
+ module MCollective
2
+ # Class to store stats about the mcollectived, it should live in the PluginManager
3
+ # so that agents etc can get hold of it and return the stats to callers
4
+ class RunnerStats
5
+ def initialize
6
+ @starttime = Time.now.to_i
7
+ @validated = 0
8
+ @unvalidated = 0
9
+ @filtered = 0
10
+ @passed = 0
11
+ @total = 0
12
+ @replies = 0
13
+ @ttlexpired = 0
14
+
15
+ @mutex = Mutex.new
16
+ end
17
+
18
+ # Records a message that failed TTL checks
19
+ def ttlexpired
20
+ Log.debug("Incrementing ttl expired stat")
21
+ @ttlexpired += 1
22
+ end
23
+
24
+ # Records a message that passed the filters
25
+ def passed
26
+ Log.debug("Incrementing passed stat")
27
+ @passed += 1
28
+ end
29
+
30
+ # Records a message that didnt pass the filters
31
+ def filtered
32
+ Log.debug("Incrementing filtered stat")
33
+ @filtered += 1
34
+ end
35
+
36
+ # Records a message that validated ok
37
+ def validated
38
+ Log.debug("Incrementing validated stat")
39
+ @validated += 1
40
+ end
41
+
42
+ def unvalidated
43
+ Log.debug("Incrementing unvalidated stat")
44
+ @unvalidated += 1
45
+ end
46
+
47
+ # Records receipt of a message
48
+ def received
49
+ Log.debug("Incrementing total stat")
50
+ @total += 1
51
+ end
52
+
53
+ # Records sending a message
54
+ def sent
55
+ @mutex.synchronize do
56
+ Log.debug("Incrementing replies stat")
57
+ @replies += 1
58
+ end
59
+ end
60
+
61
+ # Returns a hash with all stats
62
+ def to_hash
63
+ stats = {:validated => @validated,
64
+ :unvalidated => @unvalidated,
65
+ :passed => @passed,
66
+ :filtered => @filtered,
67
+ :starttime => @starttime,
68
+ :total => @total,
69
+ :ttlexpired => @ttlexpired,
70
+ :replies => @replies}
71
+
72
+ reply = {:stats => stats,
73
+ :threads => [],
74
+ :pid => Process.pid,
75
+ :times => {} }
76
+
77
+ ::Process.times.each_pair{|k,v|
78
+ k = k.to_sym
79
+ reply[:times][k] = v
80
+ }
81
+
82
+ Thread.list.each do |t|
83
+ reply[:threads] << "#{t.inspect}"
84
+ end
85
+
86
+ reply[:agents] = Agents.agentlist
87
+ reply
88
+ end
89
+ end
90
+ end