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.
- data/lib/mcollective.rb +32 -23
- data/lib/mcollective/agent.rb +5 -0
- data/lib/mcollective/agents.rb +5 -16
- data/lib/mcollective/aggregate.rb +61 -0
- data/lib/mcollective/aggregate/base.rb +40 -0
- data/lib/mcollective/aggregate/result.rb +9 -0
- data/lib/mcollective/aggregate/result/base.rb +25 -0
- data/lib/mcollective/aggregate/result/collection_result.rb +19 -0
- data/lib/mcollective/aggregate/result/numeric_result.rb +13 -0
- data/lib/mcollective/application.rb +7 -4
- data/lib/mcollective/applications.rb +3 -14
- data/lib/mcollective/cache.rb +145 -0
- data/lib/mcollective/client.rb +10 -87
- data/lib/mcollective/config.rb +22 -8
- data/lib/mcollective/data.rb +87 -0
- data/lib/mcollective/data/base.rb +67 -0
- data/lib/mcollective/data/result.rb +40 -0
- data/lib/mcollective/ddl.rb +113 -0
- data/lib/mcollective/ddl/agentddl.rb +185 -0
- data/lib/mcollective/ddl/base.rb +220 -0
- data/lib/mcollective/ddl/dataddl.rb +56 -0
- data/lib/mcollective/ddl/discoveryddl.rb +52 -0
- data/lib/mcollective/ddl/validatorddl.rb +6 -0
- data/lib/mcollective/discovery.rb +143 -0
- data/lib/mcollective/generators.rb +7 -0
- data/lib/mcollective/generators/agent_generator.rb +51 -0
- data/lib/mcollective/generators/base.rb +46 -0
- data/lib/mcollective/generators/data_generator.rb +51 -0
- data/lib/mcollective/generators/templates/action_snippet.erb +13 -0
- data/lib/mcollective/generators/templates/data_input_snippet.erb +7 -0
- data/lib/mcollective/generators/templates/ddl.erb +8 -0
- data/lib/mcollective/generators/templates/plugin.erb +7 -0
- data/lib/mcollective/logger/console_logger.rb +15 -15
- data/lib/mcollective/matcher.rb +167 -0
- data/lib/mcollective/matcher/parser.rb +60 -25
- data/lib/mcollective/matcher/scanner.rb +156 -78
- data/lib/mcollective/message.rb +47 -6
- data/lib/mcollective/monkey_patches.rb +17 -0
- data/lib/mcollective/optionparser.rb +18 -1
- data/lib/mcollective/pluginmanager.rb +3 -3
- data/lib/mcollective/pluginpackager.rb +10 -3
- data/lib/mcollective/pluginpackager/agent_definition.rb +28 -20
- data/lib/mcollective/pluginpackager/standard_definition.rb +11 -9
- data/lib/mcollective/registration/base.rb +3 -1
- data/lib/mcollective/rpc.rb +18 -24
- data/lib/mcollective/rpc/agent.rb +37 -113
- data/lib/mcollective/rpc/client.rb +186 -64
- data/lib/mcollective/rpc/helpers.rb +42 -80
- data/lib/mcollective/rpc/progress.rb +3 -3
- data/lib/mcollective/rpc/reply.rb +37 -13
- data/lib/mcollective/rpc/request.rb +17 -6
- data/lib/mcollective/rpc/result.rb +9 -5
- data/lib/mcollective/rpc/stats.rb +71 -24
- data/lib/mcollective/security/base.rb +41 -34
- data/lib/mcollective/shell.rb +1 -1
- data/lib/mcollective/ssl.rb +34 -0
- data/lib/mcollective/util.rb +194 -23
- data/lib/mcollective/validator.rb +80 -0
- data/spec/fixtures/util/1.in +10 -0
- data/spec/fixtures/util/1.out +10 -0
- data/spec/fixtures/util/2.in +1 -0
- data/spec/fixtures/util/2.out +1 -0
- data/spec/fixtures/util/3.in +1 -0
- data/spec/fixtures/util/3.out +2 -0
- data/spec/fixtures/util/4.in +5 -0
- data/spec/fixtures/util/4.out +9 -0
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/agents_spec.rb +34 -19
- data/spec/unit/aggregate/base_spec.rb +57 -0
- data/spec/unit/aggregate/result/base_spec.rb +28 -0
- data/spec/unit/aggregate/result/collection_result_spec.rb +18 -0
- data/spec/unit/aggregate/result/numeric_result_spec.rb +22 -0
- data/spec/unit/aggregate_spec.rb +110 -0
- data/spec/unit/application_spec.rb +8 -3
- data/spec/unit/applications_spec.rb +2 -2
- data/spec/unit/cache_spec.rb +115 -0
- data/spec/unit/client_spec.rb +78 -0
- data/spec/unit/config_spec.rb +32 -34
- data/spec/unit/data/base_spec.rb +90 -0
- data/spec/unit/data/result_spec.rb +64 -0
- data/spec/unit/data_spec.rb +158 -0
- data/spec/unit/ddl/agentddl_spec.rb +217 -0
- data/spec/unit/{rpc/ddl_spec.rb → ddl/base_spec.rb} +238 -224
- data/spec/unit/ddl/dataddl_spec.rb +65 -0
- data/spec/unit/ddl/discoveryddl_spec.rb +58 -0
- data/spec/unit/ddl_spec.rb +84 -0
- data/spec/unit/discovery_spec.rb +196 -0
- data/spec/unit/facts/base_spec.rb +1 -1
- data/spec/unit/generators/agent_generator_spec.rb +72 -0
- data/spec/unit/generators/base_spec.rb +83 -0
- data/spec/unit/generators/data_generator_spec.rb +37 -0
- data/spec/unit/generators/snippets/agent_ddl +19 -0
- data/spec/unit/generators/snippets/data_ddl +20 -0
- data/spec/unit/logger/console_logger_spec.rb +76 -0
- data/spec/unit/logger/syslog_logger_spec.rb +2 -2
- data/spec/unit/matcher/parser_spec.rb +27 -10
- data/spec/unit/matcher/scanner_spec.rb +108 -5
- data/spec/unit/matcher_spec.rb +260 -0
- data/spec/unit/message_spec.rb +35 -13
- data/spec/unit/optionparser_spec.rb +2 -2
- data/spec/unit/pluginpackager/agent_definition_spec.rb +59 -42
- data/spec/unit/pluginpackager/standard_definition_spec.rb +10 -8
- data/spec/unit/pluginpackager_spec.rb +131 -0
- data/spec/unit/plugins/mcollective/aggregate/average_spec.rb +45 -0
- data/spec/unit/plugins/mcollective/aggregate/sum_spec.rb +31 -0
- data/spec/unit/plugins/mcollective/aggregate/summary_spec.rb +45 -0
- data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +1 -1
- data/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +478 -0
- data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +2 -0
- data/spec/unit/plugins/mcollective/data/agent_data_spec.rb +43 -0
- data/spec/unit/plugins/mcollective/data/fstat_data_spec.rb +135 -0
- data/spec/unit/plugins/mcollective/discovery/flatfile_spec.rb +48 -0
- data/spec/unit/plugins/mcollective/discovery/mc_spec.rb +40 -0
- data/spec/unit/plugins/mcollective/packagers/debpackage_packager_spec.rb +41 -15
- data/spec/unit/plugins/mcollective/packagers/ospackage_spec.rb +1 -1
- data/spec/unit/plugins/mcollective/packagers/rpmpackage_packager_spec.rb +22 -38
- data/spec/unit/plugins/mcollective/validator/array_validator_spec.rb +19 -0
- data/spec/unit/plugins/mcollective/validator/ipv4address_validator_spec.rb +19 -0
- data/spec/unit/plugins/mcollective/validator/ipv6address_validator_spec.rb +19 -0
- data/spec/unit/plugins/mcollective/validator/length_validator_spec.rb +19 -0
- data/spec/unit/plugins/mcollective/validator/regex_validator_spec.rb +19 -0
- data/spec/unit/plugins/mcollective/validator/shellsafe_validator_spec.rb +21 -0
- data/spec/unit/plugins/mcollective/validator/typecheck_validator_spec.rb +23 -0
- data/spec/unit/registration/base_spec.rb +1 -1
- data/spec/unit/rpc/actionrunner_spec.rb +2 -2
- data/spec/unit/rpc/agent_spec.rb +41 -65
- data/spec/unit/rpc/client_spec.rb +430 -134
- data/spec/unit/rpc/reply_spec.rb +31 -1
- data/spec/unit/rpc/request_spec.rb +33 -12
- data/spec/unit/rpc/result_spec.rb +7 -0
- data/spec/unit/rpc/stats_spec.rb +14 -14
- data/spec/unit/rpc_spec.rb +16 -0
- data/spec/unit/security/base_spec.rb +8 -8
- data/spec/unit/ssl_spec.rb +20 -2
- data/spec/unit/string_spec.rb +15 -0
- data/spec/unit/util_spec.rb +141 -21
- data/spec/unit/validator_spec.rb +67 -0
- metadata +145 -7
- data/lib/mcollective/rpc/ddl.rb +0 -258
data/lib/mcollective.rb
CHANGED
@@ -11,6 +11,7 @@ require 'rbconfig'
|
|
11
11
|
require 'tempfile'
|
12
12
|
require 'tmpdir'
|
13
13
|
require 'mcollective/monkey_patches'
|
14
|
+
require 'mcollective/cache'
|
14
15
|
|
15
16
|
# == The Marionette Collective
|
16
17
|
#
|
@@ -23,42 +24,50 @@ require 'mcollective/monkey_patches'
|
|
23
24
|
# http://www.devco.net/archives/2009/10/18/middleware_for_systems_administration.php
|
24
25
|
module MCollective
|
25
26
|
# Exceptions for the RPC system
|
27
|
+
class DDLValidationError<RuntimeError;end
|
28
|
+
class ValidatorError<RuntimeError; end
|
29
|
+
class MsgDoesNotMatchRequestID < RuntimeError; end
|
30
|
+
class MsgTTLExpired<RuntimeError;end
|
31
|
+
class NotTargettedAtUs<RuntimeError;end
|
26
32
|
class RPCError<StandardError;end
|
33
|
+
class SecurityValidationFailed<RuntimeError;end
|
34
|
+
|
35
|
+
class InvalidRPCData<RPCError;end
|
36
|
+
class MissingRPCData<RPCError;end
|
27
37
|
class RPCAborted<RPCError;end
|
28
38
|
class UnknownRPCAction<RPCError;end
|
29
|
-
class MissingRPCData<RPCError;end
|
30
|
-
class InvalidRPCData<RPCError;end
|
31
39
|
class UnknownRPCError<RPCError;end
|
32
|
-
class NotTargettedAtUs<RuntimeError;end
|
33
|
-
class SecurityValidationFailed<RuntimeError;end
|
34
|
-
class DDLValidationError<RuntimeError;end
|
35
|
-
class MsgTTLExpired<RuntimeError;end
|
36
|
-
class MsgDoesNotMatchRequestID < RuntimeError; end
|
37
40
|
|
38
|
-
|
39
|
-
autoload :Config, "mcollective/config"
|
40
|
-
autoload :Log, "mcollective/log"
|
41
|
-
autoload :Logger, "mcollective/logger"
|
42
|
-
autoload :Runner, "mcollective/runner"
|
43
|
-
autoload :RunnerStats, "mcollective/runnerstats"
|
41
|
+
autoload :Agent, "mcollective/agent"
|
44
42
|
autoload :Agents, "mcollective/agents"
|
43
|
+
autoload :Aggregate, "mcollective/aggregate"
|
44
|
+
autoload :Application, "mcollective/application"
|
45
|
+
autoload :Applications, "mcollective/applications"
|
45
46
|
autoload :Client, "mcollective/client"
|
46
|
-
autoload :
|
47
|
-
autoload :Optionparser, "mcollective/optionparser"
|
47
|
+
autoload :Config, "mcollective/config"
|
48
48
|
autoload :Connector, "mcollective/connector"
|
49
|
-
autoload :
|
49
|
+
autoload :Data, "mcollective/data"
|
50
|
+
autoload :DDL, "mcollective/ddl"
|
51
|
+
autoload :Discovery, "mcollective/discovery"
|
50
52
|
autoload :Facts, "mcollective/facts"
|
51
|
-
autoload :
|
52
|
-
autoload :
|
53
|
-
autoload :RPC, "mcollective/rpc"
|
53
|
+
autoload :Logger, "mcollective/logger"
|
54
|
+
autoload :Log, "mcollective/log"
|
54
55
|
autoload :Matcher, "mcollective/matcher"
|
55
56
|
autoload :Message, "mcollective/message"
|
57
|
+
autoload :Optionparser, "mcollective/optionparser"
|
58
|
+
autoload :Generators, "mcollective/generators"
|
59
|
+
autoload :PluginManager, "mcollective/pluginmanager"
|
60
|
+
autoload :PluginPackager, "mcollective/pluginpackager"
|
61
|
+
autoload :Registration, "mcollective/registration"
|
62
|
+
autoload :RPC, "mcollective/rpc"
|
63
|
+
autoload :Runner, "mcollective/runner"
|
64
|
+
autoload :RunnerStats, "mcollective/runnerstats"
|
65
|
+
autoload :Security, "mcollective/security"
|
66
|
+
autoload :Shell, "mcollective/shell"
|
56
67
|
autoload :SSL, "mcollective/ssl"
|
57
|
-
autoload :
|
58
|
-
autoload :
|
68
|
+
autoload :Util, "mcollective/util"
|
69
|
+
autoload :Validator, "mcollective/validator"
|
59
70
|
autoload :Vendor, "mcollective/vendor"
|
60
|
-
autoload :Shell, "mcollective/shell"
|
61
|
-
autoload :PluginPackager, "mcollective/pluginpackager"
|
62
71
|
|
63
72
|
MCollective::Vendor.load_vendored
|
64
73
|
|
data/lib/mcollective/agents.rb
CHANGED
@@ -54,6 +54,11 @@ module MCollective
|
|
54
54
|
if activate_agent?(agentname)
|
55
55
|
PluginManager << {:type => "#{agentname}_agent", :class => classname, :single_instance => single_instance}
|
56
56
|
|
57
|
+
# Attempt to instantiate the agent once so any validation and hooks get run
|
58
|
+
# this does a basic sanity check on the agent as a whole, if this fails it
|
59
|
+
# will be removed from the plugin list
|
60
|
+
PluginManager["#{agentname}_agent"]
|
61
|
+
|
57
62
|
Util.subscribe(Util.make_subscriptions(agentname, :broadcast)) unless @@agents.include?(agentname)
|
58
63
|
|
59
64
|
@@agents[agentname] = {:file => agentfile}
|
@@ -108,22 +113,6 @@ module MCollective
|
|
108
113
|
PluginManager.include?("#{agentname}_agent")
|
109
114
|
end
|
110
115
|
|
111
|
-
# Returns the help for an agent after first trying to get
|
112
|
-
# rid of some indentation infront
|
113
|
-
def help(agentname)
|
114
|
-
raise("No such agent") unless include?(agentname)
|
115
|
-
|
116
|
-
body = PluginManager["#{agentname}_agent"].help.split("\n")
|
117
|
-
|
118
|
-
if body.first =~ /^(\s+)\S/
|
119
|
-
indent = $1
|
120
|
-
|
121
|
-
body = body.map {|b| b.gsub(/^#{indent}/, "")}
|
122
|
-
end
|
123
|
-
|
124
|
-
body.join("\n")
|
125
|
-
end
|
126
|
-
|
127
116
|
# Dispatches a message to an agent, accepts a block that will get run if there are
|
128
117
|
# any replies to process from the agent
|
129
118
|
def dispatch(request, connection)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
autoload :Result, 'mcollective/aggregate/result'
|
4
|
+
autoload :Base, 'mcollective/aggregate/base'
|
5
|
+
|
6
|
+
attr_accessor :ddl, :functions, :action
|
7
|
+
|
8
|
+
def initialize(ddl)
|
9
|
+
@functions = []
|
10
|
+
@ddl = ddl
|
11
|
+
@action = ddl[:action]
|
12
|
+
|
13
|
+
create_functions
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates instances of the Aggregate functions and stores them in the function array.
|
17
|
+
# All aggregate call and summarize method calls operate on these function as a batch.
|
18
|
+
def create_functions
|
19
|
+
@ddl[:aggregate].each_with_index do |agg, i|
|
20
|
+
contains_output?(agg[:args][0])
|
21
|
+
|
22
|
+
output = agg[:args][0]
|
23
|
+
arguments = agg[:args][1..(agg[:args].size)]
|
24
|
+
|
25
|
+
@functions << load_function(agg[:function]).new(output, arguments, agg[:format], @action)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check if the function param is defined as an output for the action in the ddl
|
30
|
+
def contains_output?(output)
|
31
|
+
raise "'#{@ddl[:action]}' action does not contain output '#{output}'" unless @ddl[:output].keys.include?(output)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Call all the appropriate functions with the reply data received from RPC::Client
|
35
|
+
def call_functions(reply)
|
36
|
+
@functions.each do |function|
|
37
|
+
Log.debug("Calling aggregate function #{function} for result")
|
38
|
+
function.process_result(reply[:data][function.output_name], reply)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Finalizes the function returning a result object
|
43
|
+
def summarize
|
44
|
+
summary = @functions.map do |function|
|
45
|
+
function.summarize
|
46
|
+
end
|
47
|
+
|
48
|
+
summary.sort{|x,y| x.result[:output] <=> y.result[:output]}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Loads function from disk for use
|
52
|
+
def load_function(function_name)
|
53
|
+
function_name = function_name.to_s.capitalize
|
54
|
+
|
55
|
+
PluginManager.loadclass("MCollective::Aggregate::#{function_name}") unless Aggregate.const_defined?(function_name)
|
56
|
+
Aggregate.const_get(function_name)
|
57
|
+
rescue Exception
|
58
|
+
raise "Aggregate function file '#{function_name.downcase}.rb' cannot be loaded"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
class Base
|
4
|
+
attr_accessor :name, :result, :output_name, :action, :aggregate_format, :arguments
|
5
|
+
|
6
|
+
def initialize(output_name, arguments, aggregate_format, action)
|
7
|
+
@name = self.class.to_s
|
8
|
+
@output_name = output_name
|
9
|
+
|
10
|
+
# Any additional arguments passed in the ddl after the output field will
|
11
|
+
# be stored in the arguments array which can be used in the function
|
12
|
+
@arguments = arguments
|
13
|
+
@aggregate_format = aggregate_format
|
14
|
+
@action = action
|
15
|
+
@result = {:value => nil, :type => nil, :output => output_name}
|
16
|
+
|
17
|
+
startup_hook
|
18
|
+
end
|
19
|
+
|
20
|
+
['startup_hook', 'process_result'].each do |method|
|
21
|
+
define_method method do
|
22
|
+
raise RuntimeError, "'#{method}' method of function class #{@name} has not yet been implemented"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Stops execution of the function and returns a specific ResultObject,
|
27
|
+
# aggregate functions will most likely override this but this is the simplest
|
28
|
+
# case so we might as well default to that
|
29
|
+
def summarize
|
30
|
+
raise "Result type is not set while trying to summarize aggregate function results" unless @result[:type]
|
31
|
+
|
32
|
+
result_class(@result[:type]).new(@result, @aggregate_format, @action)
|
33
|
+
end
|
34
|
+
|
35
|
+
def result_class(type)
|
36
|
+
Result.const_get("#{type.to_s.capitalize}Result")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
module Result
|
4
|
+
autoload :Base, 'mcollective/aggregate/result/base'
|
5
|
+
autoload :NumericResult, 'mcollective/aggregate/result/numeric_result'
|
6
|
+
autoload :CollectionResult, 'mcollective/aggregate/result/collection_result'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
module Result
|
4
|
+
class Base
|
5
|
+
attr_accessor :result, :aggregate_format, :action
|
6
|
+
|
7
|
+
def initialize(result, aggregate_format, action)
|
8
|
+
raise "No aggregate_format defined in ddl or aggregate function" unless aggregate_format
|
9
|
+
|
10
|
+
@result = result
|
11
|
+
@aggregate_format = aggregate_format
|
12
|
+
@action = action
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
raise "'to_s' method not implemented for result class '#{self.class}'"
|
17
|
+
end
|
18
|
+
|
19
|
+
def result_type
|
20
|
+
@result[:type]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
module Result
|
4
|
+
class CollectionResult<Base
|
5
|
+
def to_s
|
6
|
+
return "" if @result[:value].keys.include?(nil)
|
7
|
+
|
8
|
+
result = StringIO.new
|
9
|
+
|
10
|
+
@result[:value].sort{|x,y| x[1] <=> y[1]}.reverse.each do |value|
|
11
|
+
result.puts " " + @aggregate_format % [value[0], value[1]]
|
12
|
+
end
|
13
|
+
|
14
|
+
result.string.chomp
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -171,12 +171,12 @@ module MCollective
|
|
171
171
|
end
|
172
172
|
|
173
173
|
# type was given and its not one of our special types, just pass it onto optparse
|
174
|
-
opts_array << carg[:type] if carg[:type]
|
174
|
+
opts_array << carg[:type] if carg[:type] && ![:boolean, :bool, :array].include?(carg[:type])
|
175
175
|
|
176
176
|
opts_array << carg[:description]
|
177
177
|
|
178
178
|
# Handle our special types else just rely on the optparser to handle the types
|
179
|
-
if carg[:type]
|
179
|
+
if [:bool, :boolean].include?(carg[:type])
|
180
180
|
parser.send(*opts_array) do |v|
|
181
181
|
validate_option(carg[:validate], carg[:name], v)
|
182
182
|
|
@@ -255,9 +255,11 @@ module MCollective
|
|
255
255
|
raise(e)
|
256
256
|
end
|
257
257
|
|
258
|
-
err_dest.puts "
|
258
|
+
err_dest.puts "\nThe %s application failed to run, use -v for full error details: %s\n" % [ Util.colorize(:bold, $0), Util.colorize(:red, e.to_s)]
|
259
259
|
|
260
260
|
if options.nil? || options[:verbose]
|
261
|
+
e.backtrace.first << Util.colorize(:red, " <----")
|
262
|
+
err_dest.puts "\n%s %s" % [ Util.colorize(:red, e.to_s), Util.colorize(:bold, "(#{e.class.to_s})")]
|
261
263
|
e.backtrace.each{|l| err_dest.puts "\tfrom #{l}"}
|
262
264
|
end
|
263
265
|
|
@@ -307,7 +309,7 @@ module MCollective
|
|
307
309
|
# Exit with 0 if no discovery were done and > 0 responses were received
|
308
310
|
# Exit with 1 if no nodes were discovered
|
309
311
|
# Exit with 2 if nodes were discovered but some RPC requests failed
|
310
|
-
# Exit with 3 if nodes were discovered, but not responses
|
312
|
+
# Exit with 3 if nodes were discovered, but not responses received
|
311
313
|
# Exit with 4 if no discovery were done and no responses were received
|
312
314
|
def halt(stats)
|
313
315
|
request_stats = {:discoverytime => 0,
|
@@ -347,6 +349,7 @@ module MCollective
|
|
347
349
|
# cli options wouldnt take effect which could have a disasterous outcome
|
348
350
|
def rpcclient(agent, flags = {})
|
349
351
|
flags[:options] = options unless flags.include?(:options)
|
352
|
+
flags[:exit_on_failure] = false
|
350
353
|
|
351
354
|
super
|
352
355
|
end
|
@@ -11,10 +11,10 @@ module MCollective
|
|
11
11
|
begin
|
12
12
|
load_application(appname)
|
13
13
|
rescue Exception => e
|
14
|
-
e.backtrace.first <<
|
14
|
+
e.backtrace.first << Util.colorize(:red, " <----")
|
15
15
|
STDERR.puts "Application '#{appname}' failed to load:"
|
16
16
|
STDERR.puts
|
17
|
-
STDERR.puts
|
17
|
+
STDERR.puts Util.colorize(:red, " #{e} (#{e.class})")
|
18
18
|
STDERR.puts
|
19
19
|
STDERR.puts " %s" % [e.backtrace.join("\n ")]
|
20
20
|
exit 1
|
@@ -36,18 +36,7 @@ module MCollective
|
|
36
36
|
def self.list
|
37
37
|
load_config
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
Config.instance.libdir.each do |libdir|
|
42
|
-
applicationdir = "#{libdir}/mcollective/application"
|
43
|
-
next unless File.directory?(applicationdir)
|
44
|
-
|
45
|
-
Dir.entries(applicationdir).grep(/\.rb$/).each do |application|
|
46
|
-
applist << File.basename(application, ".rb")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
applist
|
39
|
+
PluginManager.find("application")
|
51
40
|
rescue SystemExit
|
52
41
|
exit 1
|
53
42
|
rescue Exception => e
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module MCollective
|
2
|
+
# A class to manage a number of named caches. Each cache can have a unique
|
3
|
+
# timeout for keys in it and each cache has an independent Mutex protecting
|
4
|
+
# access to it.
|
5
|
+
#
|
6
|
+
# This cache is setup early in the process of loading the mcollective
|
7
|
+
# libraries, before any threads are created etc making it suitable as a
|
8
|
+
# cross thread cache or just a store for Mutexes you need to use across
|
9
|
+
# threads like in an Agent or something.
|
10
|
+
#
|
11
|
+
# # sets up a new cache, noop if it already exist
|
12
|
+
# Cache.setup(:ddl, 600)
|
13
|
+
# => true
|
14
|
+
#
|
15
|
+
# # writes an item to the :ddl cache, this item will
|
16
|
+
# # be valid on the cache for 600 seconds
|
17
|
+
# Cache.write(:ddl, :something, "value")
|
18
|
+
# => "value"
|
19
|
+
#
|
20
|
+
# # reads from the cache, read failures due to non existing
|
21
|
+
# # data or expired data will raise an exception
|
22
|
+
# Cache.read(:ddl, :something)
|
23
|
+
# => "value"
|
24
|
+
#
|
25
|
+
# # time left till expiry, raises if nothing is found
|
26
|
+
# Cache.ttl(:ddl, :something)
|
27
|
+
# => 500
|
28
|
+
#
|
29
|
+
# # forcibly evict something from the cache
|
30
|
+
# Cache.invalidate!(:ddl, :something)
|
31
|
+
# => "value"
|
32
|
+
#
|
33
|
+
# # deletes an entire named cache and its mutexes
|
34
|
+
# Cache.delete!(:ddl)
|
35
|
+
# => true
|
36
|
+
#
|
37
|
+
# # you can also just use this cache as a global mutex store
|
38
|
+
# Cache.setup(:mylock)
|
39
|
+
#
|
40
|
+
# Cache.synchronize(:mylock) do
|
41
|
+
# do_something()
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
module Cache
|
45
|
+
# protects access to @cache_locks and top level @cache
|
46
|
+
@locks_mutex = Mutex.new
|
47
|
+
|
48
|
+
# stores a mutex per named cache
|
49
|
+
@cache_locks = {}
|
50
|
+
|
51
|
+
# the named caches protected by items in @cache_locks
|
52
|
+
@cache = {}
|
53
|
+
|
54
|
+
def self.setup(cache_name, ttl=300)
|
55
|
+
@locks_mutex.synchronize do
|
56
|
+
break if @cache_locks.include?(cache_name)
|
57
|
+
|
58
|
+
@cache_locks[cache_name] = Mutex.new
|
59
|
+
|
60
|
+
@cache_locks[cache_name].synchronize do
|
61
|
+
@cache[cache_name] = {:max_age => Float(ttl)}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.has_cache?(cache_name)
|
69
|
+
@locks_mutex.synchronize do
|
70
|
+
@cache.include?(cache_name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.delete!(cache_name)
|
75
|
+
@locks_mutex.synchronize do
|
76
|
+
raise("No cache called '%s'" % cache_name) unless @cache_locks.include?(cache_name)
|
77
|
+
|
78
|
+
@cache_locks.delete(cache_name)
|
79
|
+
@cache.delete(cache_name)
|
80
|
+
end
|
81
|
+
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.write(cache_name, key, value)
|
86
|
+
raise("No cache called '%s'" % cache_name) unless @cache.include?(cache_name)
|
87
|
+
|
88
|
+
@cache_locks[cache_name].synchronize do
|
89
|
+
@cache[cache_name][key] ||= {}
|
90
|
+
@cache[cache_name][key][:cache_create_time] = Time.now
|
91
|
+
@cache[cache_name][key][:value] = value
|
92
|
+
end
|
93
|
+
|
94
|
+
value
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.read(cache_name, key)
|
98
|
+
raise("No cache called '%s'" % cache_name) unless @cache.include?(cache_name)
|
99
|
+
|
100
|
+
unless ttl(cache_name, key) > 0
|
101
|
+
Log.debug("Cache expired on '%s' key '%s'" % [cache_name, key])
|
102
|
+
raise("Cache for item '%s' on cache '%s' has expired" % [key, cache_name])
|
103
|
+
end
|
104
|
+
|
105
|
+
Log.debug("Cache hit on '%s' key '%s'" % [cache_name, key])
|
106
|
+
|
107
|
+
@cache_locks[cache_name].synchronize do
|
108
|
+
@cache[cache_name][key][:value]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.ttl(cache_name, key)
|
113
|
+
raise("No cache called '%s'" % cache_name) unless @cache.include?(cache_name)
|
114
|
+
|
115
|
+
@cache_locks[cache_name].synchronize do
|
116
|
+
unless @cache[cache_name].include?(key)
|
117
|
+
Log.debug("Cache miss on '%s' key '%s'" % [cache_name, key])
|
118
|
+
raise("No item called '%s' for cache '%s'" % [key, cache_name])
|
119
|
+
end
|
120
|
+
|
121
|
+
@cache[cache_name][:max_age] - (Time.now - @cache[cache_name][key][:cache_create_time])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.synchronize(cache_name)
|
126
|
+
raise("No cache called '%s'" % cache_name) unless @cache.include?(cache_name)
|
127
|
+
|
128
|
+
raise ("No block supplied to synchronize") unless block_given?
|
129
|
+
|
130
|
+
@cache_locks[cache_name].synchronize do
|
131
|
+
yield
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.invalidate!(cache_name, key)
|
136
|
+
raise("No cache called '%s'" % cache_name) unless @cache.include?(cache_name)
|
137
|
+
|
138
|
+
@cache_locks[cache_name].synchronize do
|
139
|
+
return false unless @cache[cache_name].include?(key)
|
140
|
+
|
141
|
+
@cache[cache_name].delete(key)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|