dtk-node-agent 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +21 -4
  3. data/bin/dtk-node-agent +17 -0
  4. data/lib/config/install.config +2 -2
  5. data/lib/dtk-node-agent/installer.rb +30 -25
  6. data/lib/dtk-node-agent/version.rb +18 -1
  7. metadata +23 -110
  8. data/mcollective_additions/debian.mcollective.init +0 -92
  9. data/mcollective_additions/plugins/README.md +0 -1
  10. data/mcollective_additions/plugins/v1.2/agent/discovery.rb +0 -39
  11. data/mcollective_additions/plugins/v1.2/agent/get_log_fragment.ddl +0 -15
  12. data/mcollective_additions/plugins/v1.2/agent/get_log_fragment.rb +0 -79
  13. data/mcollective_additions/plugins/v1.2/agent/git_access.ddl +0 -9
  14. data/mcollective_additions/plugins/v1.2/agent/git_access.rb +0 -79
  15. data/mcollective_additions/plugins/v1.2/agent/netstat.ddl +0 -9
  16. data/mcollective_additions/plugins/v1.2/agent/netstat.rb +0 -34
  17. data/mcollective_additions/plugins/v1.2/agent/puppet_apply.ddl +0 -9
  18. data/mcollective_additions/plugins/v1.2/agent/puppet_apply.rb +0 -630
  19. data/mcollective_additions/plugins/v1.2/agent/rpcutil.ddl +0 -204
  20. data/mcollective_additions/plugins/v1.2/agent/rpcutil.rb +0 -101
  21. data/mcollective_additions/plugins/v1.2/facts/pbuilder_facts.rb +0 -35
  22. data/mcollective_additions/plugins/v2.2/agent/action_agent.ddl +0 -9
  23. data/mcollective_additions/plugins/v2.2/agent/action_agent.rb +0 -47
  24. data/mcollective_additions/plugins/v2.2/agent/dev_manager.ddl +0 -9
  25. data/mcollective_additions/plugins/v2.2/agent/dev_manager.rb +0 -111
  26. data/mcollective_additions/plugins/v2.2/agent/discovery.rb +0 -39
  27. data/mcollective_additions/plugins/v2.2/agent/dtk_node_agent_git_client.rb +0 -94
  28. data/mcollective_additions/plugins/v2.2/agent/execute_tests.ddl +0 -9
  29. data/mcollective_additions/plugins/v2.2/agent/execute_tests.rb +0 -111
  30. data/mcollective_additions/plugins/v2.2/agent/execute_tests_v2.ddl +0 -9
  31. data/mcollective_additions/plugins/v2.2/agent/execute_tests_v2.rb +0 -131
  32. data/mcollective_additions/plugins/v2.2/agent/get_log_fragment.ddl +0 -15
  33. data/mcollective_additions/plugins/v2.2/agent/get_log_fragment.rb +0 -79
  34. data/mcollective_additions/plugins/v2.2/agent/git_access.ddl +0 -9
  35. data/mcollective_additions/plugins/v2.2/agent/git_access.rb +0 -61
  36. data/mcollective_additions/plugins/v2.2/agent/netstat.ddl +0 -9
  37. data/mcollective_additions/plugins/v2.2/agent/netstat.rb +0 -34
  38. data/mcollective_additions/plugins/v2.2/agent/ps.ddl +0 -9
  39. data/mcollective_additions/plugins/v2.2/agent/ps.rb +0 -37
  40. data/mcollective_additions/plugins/v2.2/agent/puppet_apply.ddl +0 -9
  41. data/mcollective_additions/plugins/v2.2/agent/puppet_apply.rb +0 -818
  42. data/mcollective_additions/plugins/v2.2/agent/puppet_cancel.ddl +0 -10
  43. data/mcollective_additions/plugins/v2.2/agent/puppet_cancel.rb +0 -78
  44. data/mcollective_additions/plugins/v2.2/agent/rpcutil.ddl +0 -204
  45. data/mcollective_additions/plugins/v2.2/agent/rpcutil.rb +0 -101
  46. data/mcollective_additions/plugins/v2.2/agent/ssh_agent.ddl +0 -13
  47. data/mcollective_additions/plugins/v2.2/agent/ssh_agent.rb +0 -97
  48. data/mcollective_additions/plugins/v2.2/agent/sync_agent_code.ddl +0 -10
  49. data/mcollective_additions/plugins/v2.2/agent/sync_agent_code.rb +0 -85
  50. data/mcollective_additions/plugins/v2.2/agent/tail.ddl +0 -11
  51. data/mcollective_additions/plugins/v2.2/agent/tail.rb +0 -67
  52. data/mcollective_additions/plugins/v2.2/audit/logfile.rb +0 -26
  53. data/mcollective_additions/plugins/v2.2/connector/r8stomp.rb +0 -238
  54. data/mcollective_additions/plugins/v2.2/connector/stomp.rb +0 -349
  55. data/mcollective_additions/plugins/v2.2/connector/stomp_em.rb +0 -191
  56. data/mcollective_additions/plugins/v2.2/data/agent_data.ddl +0 -22
  57. data/mcollective_additions/plugins/v2.2/data/agent_data.rb +0 -17
  58. data/mcollective_additions/plugins/v2.2/data/collective_data.ddl +0 -20
  59. data/mcollective_additions/plugins/v2.2/data/collective_data.rb +0 -9
  60. data/mcollective_additions/plugins/v2.2/data/fact_data.ddl +0 -28
  61. data/mcollective_additions/plugins/v2.2/data/fact_data.rb +0 -55
  62. data/mcollective_additions/plugins/v2.2/data/fstat_data.ddl +0 -89
  63. data/mcollective_additions/plugins/v2.2/data/fstat_data.rb +0 -56
  64. data/mcollective_additions/plugins/v2.2/discovery/flatfile.ddl +0 -11
  65. data/mcollective_additions/plugins/v2.2/discovery/flatfile.rb +0 -48
  66. data/mcollective_additions/plugins/v2.2/discovery/mc.ddl +0 -11
  67. data/mcollective_additions/plugins/v2.2/discovery/mc.rb +0 -30
  68. data/mcollective_additions/plugins/v2.2/discovery/stdin.ddl +0 -11
  69. data/mcollective_additions/plugins/v2.2/discovery/stdin.rb +0 -66
  70. data/mcollective_additions/plugins/v2.2/facts/pbuilder_facts.rb +0 -37
  71. data/mcollective_additions/plugins/v2.2/facts/yaml_facts.rb +0 -61
  72. data/mcollective_additions/plugins/v2.2/registration/agentlist.rb +0 -10
  73. data/mcollective_additions/plugins/v2.2/security/sshkey.ddl +0 -9
  74. data/mcollective_additions/plugins/v2.2/security/sshkey.rb +0 -362
  75. data/mcollective_additions/plugins/v2.2/util/puppetrunner.rb +0 -36
  76. data/mcollective_additions/plugins/v2.2/validator/array_validator.ddl +0 -7
  77. data/mcollective_additions/plugins/v2.2/validator/array_validator.rb +0 -9
  78. data/mcollective_additions/plugins/v2.2/validator/ipv4address_validator.ddl +0 -7
  79. data/mcollective_additions/plugins/v2.2/validator/ipv4address_validator.rb +0 -16
  80. data/mcollective_additions/plugins/v2.2/validator/ipv6address_validator.ddl +0 -7
  81. data/mcollective_additions/plugins/v2.2/validator/ipv6address_validator.rb +0 -16
  82. data/mcollective_additions/plugins/v2.2/validator/length_validator.ddl +0 -7
  83. data/mcollective_additions/plugins/v2.2/validator/length_validator.rb +0 -11
  84. data/mcollective_additions/plugins/v2.2/validator/regex_validator.ddl +0 -7
  85. data/mcollective_additions/plugins/v2.2/validator/regex_validator.rb +0 -9
  86. data/mcollective_additions/plugins/v2.2/validator/shellsafe_validator.ddl +0 -7
  87. data/mcollective_additions/plugins/v2.2/validator/shellsafe_validator.rb +0 -13
  88. data/mcollective_additions/plugins/v2.2/validator/typecheck_validator.ddl +0 -7
  89. data/mcollective_additions/plugins/v2.2/validator/typecheck_validator.rb +0 -28
  90. data/mcollective_additions/redhat.mcollective.init +0 -139
  91. data/mcollective_additions/redhat.mcollective.service +0 -14
  92. data/mcollective_additions/server.cfg +0 -22
  93. data/src/etc/logrotate.d/mcollective +0 -10
  94. data/src/etc/mcollective.default +0 -6
@@ -1,10 +0,0 @@
1
- metadata :name => "sync agents code",
2
- :description => "Agent to sync agent's code from git repo",
3
- :author => "Reactor8",
4
- :license => "",
5
- :version => "",
6
- :url => "",
7
- :timeout => 600
8
- action "run", :description => "sync agents code" do
9
- end
10
-
@@ -1,85 +0,0 @@
1
- require 'rubygems'
2
- require 'puppet'
3
- require 'grit'
4
- require 'tempfile'
5
- require 'fileutils'
6
-
7
- AGENT_MCOLLECTIVE_LOCATION = "#{::MCollective::Config.instance.libdir.join}/mcollective/agent/"
8
-
9
- module MCollective
10
- module Agent
11
- class Sync_agent_code < RPC::Agent
12
- def initialize()
13
- super()
14
- @log = Log.instance
15
- @reply_data = nil
16
- end
17
-
18
- def old_run_action
19
- ret ||= Response.new()
20
- #git_server_url = request[:git_server_url]
21
- raise "git server is not set in facts" unless git_server_url = Facts["git-server"]
22
- branch = request[:branch]
23
- cmd_opts = {:raise => true, :timeout => 60}
24
-
25
- begin
26
- # Amar: if git repo dir exists pull code, otherwise (first converge case) clone agent's project from git
27
- if File.directory?(AgentGitPath)
28
- grit_repo = ::Grit::Repo.new(AgentGitPath)
29
- grit_repo.git.send(:pull, cmd_opts)
30
- @log.info("Latest agent code pulled from GIT Repositoy.")
31
- else
32
- clone_args = [git_server_url, AgentGitPath]
33
- clone_args += ["-b", branch] if branch
34
- ::Grit::Git.new("").clone(cmd_opts, *clone_args)
35
- @log.info("Agent project successfully cloned from GIT Repository.")
36
- end
37
- # Copy latest agents to mcollective agent's directory
38
- agents = Dir.glob("#{AgentGitPath}/mcollective_additions/plugins/v2.2/agent/*")
39
- FileUtils.cp_r(agents, AgentMcollectivePath)
40
- @log.info("Agent files copied to mcollective destination.")
41
- # System call to restart mcollective
42
- system("sudo /etc/init.d/mcollective restart")
43
- @log.info("mcollective system restart completed.")
44
-
45
- ret.set_status_succeeded!()
46
- rescue Exception => e
47
- @log.error("Error in syncing agent's code with GIT Repository: '#{git_server_url}'. Error: #{e}")
48
- ret.set_status_failed!()
49
- error_info = { :errors => { :message => "Error in syncing agent's code with GIT Repository: '#{git_server_url}'." } }
50
- ret.merge!(error_info)
51
- end
52
-
53
- return ret
54
- end
55
-
56
- end
57
- #TODO: this should be common accross Agents
58
- class Response < Hash
59
- def initialize(hash={})
60
- super()
61
- self.merge!(hash)
62
- self[:status] = :unknown unless hash.has_key?(:status)
63
- end
64
-
65
- def to_hash()
66
- Hash.new.merge(self)
67
- end
68
-
69
- def failed?()
70
- self[:status] == :failed
71
- end
72
-
73
- def set_status_failed!()
74
- self[:status] = :failed
75
- end
76
- def set_status_succeeded!()
77
- self[:status] = :succeeded
78
- end
79
- def set_dynamic_attributes!(dynamic_attributes)
80
- self[:dynamic_attributes] = dynamic_attributes
81
- end
82
- end
83
- end
84
- end
85
-
@@ -1,11 +0,0 @@
1
- metadata :name => "tailing log",
2
- :description => "Agent to tail log",
3
- :author => "Reactor8",
4
- :license => "",
5
- :version => "",
6
- :url => "",
7
- :timeout => 2
8
- action "get_log", :description => "returns log content" do
9
- end
10
- action "grep", :description => "returns log content from multiple nodes" do
11
- end
@@ -1,67 +0,0 @@
1
- module MCollective
2
- module Agent
3
- class Tail < RPC::Agent
4
-
5
- # number of lines that will be returned on first request
6
- BATCH_SIZE_OF_LOG = 50
7
-
8
- action "get_log" do
9
- begin
10
- unless File.exists? request[:log_path]
11
- reply[:data] = { :error => "File #{request[:log_path]} not found on given node."}
12
- reply[:pbuilderid] = Facts["pbuilderid"]
13
- reply[:status] = :ok
14
- return
15
- end
16
-
17
- # returns total number of lines in file, one is to start next iteration with new line
18
- last_line = `wc -l #{request[:log_path]} | awk '{print $1}'`.to_i + 1
19
- # if there is start line from CLI request we use it, if not we take last BATCH_SIZE_OF_LOG lines
20
- if request[:start_line].empty?
21
- # If BATCH_SIZE_OF_LOG is bigger than last_line, then start line will be 0
22
- start_line = (last_line > BATCH_SIZE_OF_LOG) ? last_line-BATCH_SIZE_OF_LOG : 0
23
- else
24
- start_line = request[:start_line]
25
- end
26
-
27
- # returns needed lines
28
- if (request[:grep_option].nil? || request[:grep_option].empty?)
29
- output = `tail -n +#{start_line} #{request[:log_path]}`
30
- else
31
- output = `tail -n +#{start_line} #{request[:log_path]} | grep #{request[:grep_option]}`
32
- end
33
-
34
- reply[:data] = { :output => output, :last_line => last_line }
35
- reply[:pbuilderid] = Facts["pbuilderid"]
36
- reply[:status] = :ok
37
- rescue Exception => e
38
- Log.error e
39
- end
40
- end
41
-
42
- action "grep" do
43
- begin
44
- unless File.exists? request[:log_path]
45
- reply[:data] = { :error => "File #{request[:log_path]} not found on given node."}
46
- reply[:pbuilderid] = Facts["pbuilderid"]
47
- reply[:status] = :ok
48
- return
49
- end
50
-
51
- # returns needed lines
52
- if (request[:stop_on_first_match].empty? || request[:stop_on_first_match].nil? || request[:stop_on_first_match].eql?('false'))
53
- output = `more #{request[:log_path]} | grep #{request[:grep_pattern]}`
54
- else
55
- output = `more #{request[:log_path]} | grep #{request[:grep_pattern]} | tail -1`
56
- end
57
- reply[:data] = { :output => output}
58
- reply[:pbuilderid] = Facts["pbuilderid"]
59
- reply[:status] = :ok
60
- rescue Exception => e
61
- Log.error e
62
- end
63
- end
64
-
65
- end
66
- end
67
- end
@@ -1,26 +0,0 @@
1
- module MCollective
2
- module RPC
3
- # An audit plugin that just logs to a file
4
- #
5
- # You can configure which file it logs to with the setting
6
- #
7
- # plugin.rpcaudit.logfile
8
-
9
- class Logfile<Audit
10
- require 'pp'
11
-
12
- def audit_request(request, connection)
13
- logfile = Config.instance.pluginconf["rpcaudit.logfile"] || "/var/log/mcollective-audit.log"
14
-
15
- now = Time.now
16
- # Already told timezone to be in UTC so we don't look it up again
17
- # This avoids platform specific timezone representation issues
18
- now_iso8601 = now.utc.strftime("%Y-%m-%d %H:%M:%S UTC")
19
-
20
- File.open(logfile, "a") do |f|
21
- f.puts("[#{now_iso8601}] reqid=#{request.uniqid}: reqtime=#{request.time} caller=#{request.caller}@#{request.sender} agent=#{request.agent} action=#{request.action} data=#{request.data.pretty_print_inspect}")
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,238 +0,0 @@
1
- require 'stomp'
2
-
3
- module MCollective
4
- module Connector
5
- # Handles sending and receiving messages over the Stomp protocol
6
- #
7
- # This plugin supports version 1.1 or 1.1.6 and newer of the Stomp rubygem
8
- # the versions between those had multi threading issues.
9
- #
10
- # For all versions you can configure it as follows:
11
- #
12
- # connector = stomp
13
- # plugin.stomp.host = stomp.your.net
14
- # plugin.stomp.port = 6163
15
- # plugin.stomp.user = you
16
- # plugin.stomp.password = secret
17
- #
18
- # All of these can be overriden per user using environment variables:
19
- #
20
- # STOMP_SERVER, STOMP_PORT, STOMP_USER, STOMP_PASSWORD
21
- #
22
- # Version 1.1.6 onward support supplying multiple connections and it will
23
- # do failover between these servers, you can configure it as follows:
24
- #
25
- # connector = stomp
26
- # plugin.stomp.pool.size = 2
27
- #
28
- # plugin.stomp.pool.host1 = stomp1.your.net
29
- # plugin.stomp.pool.port1 = 6163
30
- # plugin.stomp.pool.user1 = you
31
- # plugin.stomp.pool.password1 = secret
32
- # plugin.stomp.pool.ssl1 = true
33
- #
34
- # plugin.stomp.pool.host2 = stomp2.your.net
35
- # plugin.stomp.pool.port2 = 6163
36
- # plugin.stomp.pool.user2 = you
37
- # plugin.stomp.pool.password2 = secret
38
- # plugin.stomp.pool.ssl2 = false
39
- #
40
- # Using this method you can supply just STOMP_USER and STOMP_PASSWORD
41
- # you have to supply the hostname for each pool member in the config.
42
- # The port will default to 6163 if not specified.
43
- #
44
- # In addition you can set the following options but only when using
45
- # pooled configuration:
46
- #
47
- # plugin.stomp.pool.initial_reconnect_delay = 0.01
48
- # plugin.stomp.pool.max_reconnect_delay = 30.0
49
- # plugin.stomp.pool.use_exponential_back_off = true
50
- # plugin.stomp.pool.back_off_multiplier = 2
51
- # plugin.stomp.pool.max_reconnect_attempts = 0
52
- # plugin.stomp.pool.randomize = false
53
- # plugin.stomp.pool.timeout = -1
54
- #
55
- # For versions of ActiveMQ that supports message priorities
56
- # you can set a priority, this will cause a "priority" header
57
- # to be emitted if present:
58
- #
59
- # plugin.stomp.priority = 4
60
- #
61
- class Stomp<Base
62
- attr_reader :connection
63
-
64
- #modifications so connect at initialization and there is not multiple connections per thread
65
- def initialize
66
- @config = Config.instance
67
- @subscriptions = []
68
- ###BEGIN R8 CUSTOMIZATION
69
- if Thread.current[:stomp_client]
70
- @connection = Thread.current[:stomp_client]
71
- else
72
- connect()
73
- Thread.current[:stomp_client] = @connection
74
- end
75
- ###END R8 CUSTOMIZATION
76
- end
77
-
78
- def disconnect
79
- Log.debug("Disconnecting from Stomp")
80
- @connection.disconnect
81
- end
82
-
83
- # Connects to the Stomp middleware
84
- def connect
85
- if @connection
86
- Log.debug("Already connection, not re-initializing connection")
87
- return
88
- end
89
- begin
90
- host = nil
91
- port = nil
92
- user = nil
93
- password = nil
94
- @base64 = get_bool_option("stomp.base64", false)
95
- @msgpriority = get_option("stomp.priority", 0).to_i
96
-
97
- # Maintain backward compat for older stomps
98
- unless @config.pluginconf.include?("stomp.pool.size")
99
- host = get_env_or_option("STOMP_SERVER", "stomp.host")
100
- port = get_env_or_option("STOMP_PORT", "stomp.port", 6163).to_i
101
- user = get_env_or_option("STOMP_USER", "stomp.user")
102
- password = get_env_or_option("STOMP_PASSWORD", "stomp.password")
103
-
104
- Log.debug("Connecting to #{host}:#{port}")
105
- @connection = ::Stomp::Connection.new(user, password, host, port, true)
106
- else
107
- pools = @config.pluginconf["stomp.pool.size"].to_i
108
- hosts = []
109
-
110
- 1.upto(pools) do |poolnum|
111
- host = {}
112
-
113
- host[:host] = get_option("stomp.pool.host#{poolnum}")
114
- host[:port] = get_option("stomp.pool.port#{poolnum}", 6163).to_i
115
- host[:login] = get_env_or_option("STOMP_USER", "stomp.pool.user#{poolnum}")
116
- host[:passcode] = get_env_or_option("STOMP_PASSWORD", "stomp.pool.password#{poolnum}")
117
- host[:ssl] = get_bool_option("stomp.pool.ssl#{poolnum}", false)
118
-
119
- Log.debug("Adding #{host[:host]}:#{host[:port]} to the connection pool")
120
- hosts << host
121
- end
122
-
123
- raise "No hosts found for the STOMP connection pool" if hosts.size == 0
124
-
125
- connection = {:hosts => hosts}
126
-
127
- # Various STOMP gem options, defaults here matches defaults for 1.1.6 the meaning of
128
- # these can be guessed, the documentation isn't clear
129
- connection[:initial_reconnect_delay] = get_option("stomp.pool.initial_reconnect_delay", 0.01).to_f
130
- connection[:max_reconnect_delay] = get_option("stomp.pool.max_reconnect_delay", 30.0).to_f
131
- connection[:use_exponential_back_off] = get_bool_option("stomp.pool.use_exponential_back_off", true)
132
- connection[:back_off_multiplier] = get_bool_option("stomp.pool.back_off_multiplier", 2).to_i
133
- connection[:max_reconnect_attempts] = get_option("stomp.pool.max_reconnect_attempts", 0)
134
- connection[:randomize] = get_bool_option("stomp.pool.randomize", false)
135
- connection[:backup] = get_bool_option("stomp.pool.backup", false)
136
- connection[:timeout] = get_option("stomp.pool.timeout", -1).to_i
137
-
138
- @connection = ::Stomp::Connection.new(connection)
139
- end
140
- rescue Exception => e
141
- raise("Could not connect to Stomp Server: #{e}")
142
- end
143
- end
144
-
145
- # Receives a message from the Stomp connection
146
- def receive
147
- Log.debug("Waiting for a message from Stomp")
148
- msg = @connection.receive
149
-
150
- # STOMP puts the payload in the body variable, pass that
151
- # into the payload of MCollective::Request and discard all the
152
- # other headers etc that stomp provides
153
- if @base64
154
- Request.new(SSL.base64_decode(msg.body))
155
- else
156
- Request.new(msg.body)
157
- end
158
- end
159
-
160
- # Sends a message to the Stomp connection
161
- def send(target, msg)
162
- Log.debug("Sending a message to Stomp target '#{target}'")
163
-
164
- msg = SSL.base64_encode(msg) if @base64
165
-
166
- # deal with deprecation warnings in newer stomp gems
167
- if @connection.respond_to?("publish")
168
- @connection.publish(target, msg, msgheaders)
169
- else
170
- @connection.send(target, msg, msgheaders)
171
- end
172
- end
173
-
174
- # Subscribe to a topic or queue
175
- def subscribe(source)
176
- unless @subscriptions.include?(source)
177
- Log.debug("Subscribing to #{source}")
178
- @connection.subscribe(source)
179
- @subscriptions << source
180
- end
181
- end
182
-
183
- # Subscribe to a topic or queue
184
- def unsubscribe(source)
185
- Log.debug("Unsubscribing from #{source}")
186
- @connection.unsubscribe(source)
187
- @subscriptions.delete(source)
188
- end
189
-
190
- private
191
- def msgheaders
192
- headers = {}
193
- headers = {"priority" => @msgpriority} if (@msgpriority and @msgpriority > 0)
194
-
195
- return headers
196
- end
197
-
198
- # looks in the environment first then in the config file
199
- # for a specific option, accepts an optional default.
200
- #
201
- # raises an exception when it cant find a value anywhere
202
- def get_env_or_option(env, opt, default=nil)
203
- return ENV[env] if ENV.include?(env)
204
- return @config.pluginconf[opt] if @config.pluginconf.include?(opt)
205
- return default if default
206
-
207
- raise("No #{env} environment or plugin.#{opt} configuration option given")
208
- end
209
-
210
- # looks for a config option, accepts an optional default
211
- #
212
- # raises an exception when it cant find a value anywhere
213
- def get_option(opt, default=nil)
214
- return @config.pluginconf[opt] if @config.pluginconf.include?(opt)
215
- return default if default
216
-
217
- raise("No plugin.#{opt} configuration option given")
218
- end
219
-
220
- # gets a boolean option from the config, supports y/n/true/false/1/0
221
- def get_bool_option(opt, default)
222
- return default unless @config.pluginconf.include?(opt)
223
-
224
- val = @config.pluginconf[opt]
225
-
226
- if val =~ /^1|yes|true/
227
- return true
228
- elsif val =~ /^0|no|false/
229
- return false
230
- else
231
- return default
232
- end
233
- end
234
- end
235
- end
236
- end
237
-
238
- # vi:tabstop=4:expandtab:ai
@@ -1,349 +0,0 @@
1
- require 'stomp'
2
-
3
- module MCollective
4
- module Connector
5
- # Handles sending and receiving messages over the Stomp protocol
6
- #
7
- # This plugin supports version 1.1 or 1.1.6 and newer of the Stomp rubygem
8
- # the versions between those had multi threading issues.
9
- #
10
- # For all versions you can configure it as follows:
11
- #
12
- # connector = stomp
13
- # plugin.stomp.host = stomp.your.net
14
- # plugin.stomp.port = 6163
15
- # plugin.stomp.user = you
16
- # plugin.stomp.password = secret
17
- #
18
- # All of these can be overriden per user using environment variables:
19
- #
20
- # STOMP_SERVER, STOMP_PORT, STOMP_USER, STOMP_PASSWORD
21
- #
22
- # Version 1.1.6 onward support supplying multiple connections and it will
23
- # do failover between these servers, you can configure it as follows:
24
- #
25
- # connector = stomp
26
- # plugin.stomp.pool.size = 2
27
- #
28
- # plugin.stomp.pool.host1 = stomp1.your.net
29
- # plugin.stomp.pool.port1 = 6163
30
- # plugin.stomp.pool.user1 = you
31
- # plugin.stomp.pool.password1 = secret
32
- # plugin.stomp.pool.ssl1 = true
33
- #
34
- # plugin.stomp.pool.host2 = stomp2.your.net
35
- # plugin.stomp.pool.port2 = 6163
36
- # plugin.stomp.pool.user2 = you
37
- # plugin.stomp.pool.password2 = secret
38
- # plugin.stomp.pool.ssl2 = false
39
- #
40
- # Using this method you can supply just STOMP_USER and STOMP_PASSWORD
41
- # you have to supply the hostname for each pool member in the config.
42
- # The port will default to 6163 if not specified.
43
- #
44
- # In addition you can set the following options but only when using
45
- # pooled configuration:
46
- #
47
- # plugin.stomp.pool.initial_reconnect_delay = 0.01
48
- # plugin.stomp.pool.max_reconnect_delay = 30.0
49
- # plugin.stomp.pool.use_exponential_back_off = true
50
- # plugin.stomp.pool.back_off_multiplier = 2
51
- # plugin.stomp.pool.max_reconnect_attempts = 0
52
- # plugin.stomp.pool.randomize = false
53
- # plugin.stomp.pool.timeout = -1
54
- #
55
- # You can set the initial connetion timeout - this is when your stomp server is simply
56
- # unreachable - after which it would failover to the next in the pool:
57
- #
58
- # plugin.stomp.pool.connect_timeout = 30
59
- #
60
- # For versions of ActiveMQ that supports message priorities
61
- # you can set a priority, this will cause a "priority" header
62
- # to be emitted if present:
63
- #
64
- # plugin.stomp.priority = 4
65
- #
66
- class Stomp<Base
67
- # Older stomp gems do not have these error classes, in order to be able to
68
- # handle these exceptions if they are present and still support older gems
69
- # we're assigning the constants to a dummy exception that will never be thrown
70
- # by us. End result is that the code catching these exceptions become noops on
71
- # older gems but on newer ones they become usable and handle those new errors
72
- # intelligently
73
- class DummyError<RuntimeError; end
74
-
75
- ::Stomp::Error = DummyError unless defined?(::Stomp::Error)
76
- ::Stomp::Error::NoCurrentConnection = DummyError unless defined?(::Stomp::Error::NoCurrentConnection)
77
- ::Stomp::Error::DuplicateSubscription = DummyError unless defined?(::Stomp::Error::DuplicateSubscription)
78
-
79
- # Class for Stomp 1.1.9 callback based logging
80
- class EventLogger
81
- def on_connecting(params=nil)
82
- Log.info("Connection attempt %d to %s" % [params[:cur_conattempts], stomp_url(params)])
83
- rescue
84
- end
85
-
86
- def on_connected(params=nil)
87
- Log.info("Conncted to #{stomp_url(params)}")
88
- rescue
89
- end
90
-
91
- def on_disconnect(params=nil)
92
- Log.info("Disconnected from #{stomp_url(params)}")
93
- rescue
94
- end
95
-
96
- def on_connectfail(params=nil)
97
- Log.info("Connection to #{stomp_url(params)} failed on attempt #{params[:cur_conattempts]}")
98
- rescue
99
- end
100
-
101
- def on_miscerr(params, errstr)
102
- Log.error("Unexpected error on connection #{stomp_url(params)}: #{errstr}")
103
- rescue
104
- end
105
-
106
- def on_ssl_connecting(params)
107
- Log.info("Performing SSL connection to #{stomp_url(params)}")
108
- rescue
109
- end
110
-
111
- def on_ssl_connected(params)
112
- Log.info("Connected SSL socket #{stomp_url(params)}")
113
- rescue
114
- end
115
-
116
- def stomp_url(params)
117
- "%s://%s@%s:%d" % [ params[:cur_ssl] ? "stomp+ssl" : "stomp", params[:cur_login], params[:cur_host], params[:cur_port]]
118
- end
119
- end
120
-
121
- attr_reader :connection
122
-
123
- def initialize
124
- Log.info("MCollective 2.2.x will be the last to fully support the 'stomp' connector, please migrate to the 'activemq' or 'rabbitmq' connector")
125
-
126
- @config = Config.instance
127
- @subscriptions = []
128
- end
129
-
130
- # Connects to the Stomp middleware
131
- def connect(connector = ::Stomp::Connection)
132
- if @connection
133
- Log.debug("Already connection, not re-initializing connection")
134
- return
135
- end
136
-
137
- begin
138
- host = nil
139
- port = nil
140
- user = nil
141
- password = nil
142
- @base64 = get_bool_option("stomp.base64", false)
143
- @msgpriority = get_option("stomp.priority", 0).to_i
144
-
145
- # Maintain backward compat for older stomps
146
- unless @config.pluginconf.include?("stomp.pool.size")
147
- host = get_env_or_option("STOMP_SERVER", "stomp.host")
148
- port = get_env_or_option("STOMP_PORT", "stomp.port", 6163).to_i
149
- user = get_env_or_option("STOMP_USER", "stomp.user")
150
- password = get_env_or_option("STOMP_PASSWORD", "stomp.password")
151
-
152
- Log.debug("Connecting to #{host}:#{port}")
153
- @connection = connector.new(user, password, host, port, true)
154
- else
155
- pools = @config.pluginconf["stomp.pool.size"].to_i
156
- hosts = []
157
-
158
- 1.upto(pools) do |poolnum|
159
- host = {}
160
-
161
- host[:host] = get_option("stomp.pool.host#{poolnum}")
162
- host[:port] = get_option("stomp.pool.port#{poolnum}", 6163).to_i
163
- host[:login] = get_env_or_option("STOMP_USER", "stomp.pool.user#{poolnum}")
164
- host[:passcode] = get_env_or_option("STOMP_PASSWORD", "stomp.pool.password#{poolnum}")
165
- host[:ssl] = get_bool_option("stomp.pool.ssl#{poolnum}", false)
166
-
167
- Log.debug("Adding #{host[:host]}:#{host[:port]} to the connection pool")
168
- hosts << host
169
- end
170
-
171
- raise "No hosts found for the STOMP connection pool" if hosts.size == 0
172
-
173
- connection = {:hosts => hosts}
174
-
175
- # Various STOMP gem options, defaults here matches defaults for 1.1.6 the meaning of
176
- # these can be guessed, the documentation isn't clear
177
- connection[:initial_reconnect_delay] = get_option("stomp.pool.initial_reconnect_delay", 0.01).to_f
178
- connection[:max_reconnect_delay] = get_option("stomp.pool.max_reconnect_delay", 30.0).to_f
179
- connection[:use_exponential_back_off] = get_bool_option("stomp.pool.use_exponential_back_off", true)
180
- connection[:back_off_multiplier] = get_bool_option("stomp.pool.back_off_multiplier", 2).to_i
181
- connection[:max_reconnect_attempts] = get_option("stomp.pool.max_reconnect_attempts", 0).to_i
182
- connection[:randomize] = get_bool_option("stomp.pool.randomize", false)
183
- connection[:backup] = get_bool_option("stomp.pool.backup", false)
184
- connection[:timeout] = get_option("stomp.pool.timeout", -1).to_i
185
- connection[:connect_timeout] = Integer(get_option("stomp.pool.connect_timeout", 30))
186
- connection[:reliable] = true
187
-
188
- connection[:logger] = EventLogger.new
189
-
190
- @connection = connector.new(connection)
191
- end
192
- rescue Exception => e
193
- raise("Could not connect to Stomp Server: #{e}")
194
- end
195
- end
196
-
197
- # Receives a message from the Stomp connection
198
- def receive
199
- Log.debug("Waiting for a message from Stomp")
200
-
201
- # When the Stomp library > 1.2.0 is mid reconnecting due to its reliable connection
202
- # handling it sets the connection to closed. If we happen to be receiving at just
203
- # that time we will get an exception warning about the closed connection so handling
204
- # that here with a sleep and a retry.
205
- begin
206
- msg = @connection.receive
207
- rescue ::Stomp::Error::NoCurrentConnection
208
- sleep 1
209
- retry
210
- end
211
-
212
- Message.new(msg.body, msg, :base64 => @base64, :headers => msg.headers)
213
- end
214
-
215
- # Sends a message to the Stomp connection
216
- def publish(msg)
217
- msg.base64_encode! if @base64
218
-
219
- raise "Cannot set specific reply to targets with the STOMP plugin" if msg.reply_to
220
-
221
- if msg.type == :direct_request
222
- msg.discovered_hosts.each do |node|
223
- target = make_target(msg.agent, msg.type, msg.collective, node)
224
-
225
- Log.debug("Sending a direct message to STOMP target '#{target}'")
226
-
227
- publish_msg(target, msg.payload)
228
- end
229
- else
230
- target = make_target(msg.agent, msg.type, msg.collective)
231
-
232
- Log.debug("Sending a broadcast message to STOMP target '#{target}'")
233
-
234
- publish_msg(target, msg.payload)
235
- end
236
- end
237
-
238
- # Subscribe to a topic or queue
239
- def subscribe(agent, type, collective)
240
- source = make_target(agent, type, collective)
241
-
242
- unless @subscriptions.include?(source)
243
- Log.debug("Subscribing to #{source}")
244
- @connection.subscribe(source)
245
- @subscriptions << source
246
- end
247
- rescue ::Stomp::Error::DuplicateSubscription
248
- Log.debug("Received subscription for #{source[:name]} but already had a subscription, ignoring")
249
- end
250
-
251
- # Actually sends the message to the middleware
252
- def publish_msg(target, msg)
253
- # deal with deprecation warnings in newer stomp gems
254
- if @connection.respond_to?("publish")
255
- @connection.publish(target, msg, msgheaders)
256
- else
257
- @connection.send(target, msg, msgheaders)
258
- end
259
- end
260
-
261
- # Subscribe to a topic or queue
262
- def unsubscribe(agent, type, collective)
263
- source = make_target(agent, type, collective)
264
-
265
- Log.debug("Unsubscribing from #{source}")
266
- @connection.unsubscribe(source)
267
- @subscriptions.delete(source)
268
- end
269
-
270
- # Disconnects from the Stomp connection
271
- def disconnect
272
- Log.debug("Disconnecting from Stomp")
273
- @connection.disconnect
274
- end
275
-
276
- def msgheaders
277
- headers = {}
278
- headers = {"priority" => @msgpriority} if @msgpriority > 0
279
-
280
- return headers
281
- end
282
-
283
- # looks in the environment first then in the config file
284
- # for a specific option, accepts an optional default.
285
- #
286
- # raises an exception when it cant find a value anywhere
287
- def get_env_or_option(env, opt, default=nil)
288
- return ENV[env] if ENV.include?(env)
289
- return @config.pluginconf[opt] if @config.pluginconf.include?(opt)
290
- return default if default
291
-
292
- raise("No #{env} environment or plugin.#{opt} configuration option given")
293
- end
294
-
295
- # looks for a config option, accepts an optional default
296
- #
297
- # raises an exception when it cant find a value anywhere
298
- def get_option(opt, default=nil)
299
- return @config.pluginconf[opt] if @config.pluginconf.include?(opt)
300
- return default if default
301
-
302
- raise("No plugin.#{opt} configuration option given")
303
- end
304
-
305
- # gets a boolean option from the config, supports y/n/true/false/1/0
306
- def get_bool_option(opt, default)
307
- return default unless @config.pluginconf.include?(opt)
308
-
309
- val = @config.pluginconf[opt]
310
-
311
- if val =~ /^1|yes|true/
312
- return true
313
- elsif val =~ /^0|no|false/
314
- return false
315
- else
316
- return default
317
- end
318
- end
319
-
320
- def make_target(agent, type, collective, target_node=nil)
321
- raise("Unknown target type #{type}") unless [:directed, :broadcast, :reply, :request, :direct_request].include?(type)
322
- raise("Unknown collective '#{collective}' known collectives are '#{@config.collectives.join ', '}'") unless @config.collectives.include?(collective)
323
-
324
- prefix = @config.topicprefix
325
-
326
- case type
327
- when :reply
328
- suffix = :reply
329
- when :broadcast
330
- suffix = :command
331
- when :request
332
- suffix = :command
333
- when :direct_request
334
- agent = nil
335
- prefix = @config.queueprefix
336
- suffix = Digest::MD5.hexdigest(target_node)
337
- when :directed
338
- agent = nil
339
- prefix = @config.queueprefix
340
- # use a md5 since hostnames might have illegal characters that
341
- # the middleware dont understand
342
- suffix = Digest::MD5.hexdigest(@config.identity)
343
- end
344
-
345
- ["#{prefix}#{collective}", agent, suffix].compact.join(@config.topicsep)
346
- end
347
- end
348
- end
349
- end