sensu 0.9.6.beta.4 → 0.9.6.beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/sensu/api.rb +22 -18
- data/lib/sensu/base.rb +2 -12
- data/lib/sensu/client.rb +44 -28
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/redis.rb +81 -0
- data/lib/sensu/server.rb +79 -59
- data/lib/sensu/settings.rb +80 -32
- metadata +5 -6
- data/lib/sensu/patches/amqp.rb +0 -7
- data/lib/sensu/patches/redis.rb +0 -71
data/lib/sensu/api.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'base')
|
2
|
+
require File.join(File.dirname(__FILE__), 'redis')
|
2
3
|
|
3
4
|
require 'thin'
|
4
5
|
require 'sinatra/async'
|
5
|
-
require 'redis'
|
6
|
-
|
7
|
-
require File.join(File.dirname(__FILE__), 'patches', 'redis')
|
8
6
|
|
9
7
|
module Sensu
|
10
8
|
class API < Sinatra::Base
|
@@ -26,13 +24,17 @@ module Sensu
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def self.setup(options={})
|
27
|
+
$logger = Cabin::Channel.get
|
29
28
|
base = Sensu::Base.new(options)
|
30
|
-
$logger = base.logger
|
31
29
|
$settings = base.settings
|
32
30
|
$logger.debug('connecting to redis', {
|
33
31
|
:settings => $settings[:redis]
|
34
32
|
})
|
35
|
-
$redis = Redis.connect($settings[:redis])
|
33
|
+
$redis = Sensu::Redis.connect($settings[:redis])
|
34
|
+
$redis.on_disconnect = Proc.new do
|
35
|
+
$logger.warn('reconnecting to redis')
|
36
|
+
$redis.reconnect!
|
37
|
+
end
|
36
38
|
$logger.debug('connecting to rabbitmq', {
|
37
39
|
:settings => $settings[:rabbitmq]
|
38
40
|
})
|
@@ -45,7 +47,15 @@ module Sensu
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def
|
50
|
+
def healthy?
|
51
|
+
unless $redis.connected?
|
52
|
+
unless env['REQUEST_PATH'] == '/info'
|
53
|
+
halt 500
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def request_log
|
49
59
|
$logger.info([env['REQUEST_METHOD'], env['REQUEST_PATH']].join(' '), {
|
50
60
|
:remote_address => env['REMOTE_ADDR'],
|
51
61
|
:user_agent => env['HTTP_USER_AGENT'],
|
@@ -71,7 +81,8 @@ module Sensu
|
|
71
81
|
|
72
82
|
before do
|
73
83
|
content_type 'application/json'
|
74
|
-
request_log
|
84
|
+
request_log
|
85
|
+
healthy?
|
75
86
|
end
|
76
87
|
|
77
88
|
aget '/info' do
|
@@ -80,16 +91,10 @@ module Sensu
|
|
80
91
|
:version => Sensu::VERSION
|
81
92
|
},
|
82
93
|
:health => {
|
83
|
-
:redis => 'ok',
|
84
|
-
:rabbitmq => 'ok'
|
94
|
+
:redis => $redis.connected? ? 'ok' : 'down',
|
95
|
+
:rabbitmq => $rabbitmq.connected? ? 'ok' : 'down'
|
85
96
|
}
|
86
97
|
}
|
87
|
-
if $redis.reconnecting?
|
88
|
-
response[:health][:redis] = 'down'
|
89
|
-
end
|
90
|
-
if $rabbitmq.reconnecting?
|
91
|
-
response[:health][:rabbitmq] = 'down'
|
92
|
-
end
|
93
98
|
body response.to_json
|
94
99
|
end
|
95
100
|
|
@@ -378,10 +383,9 @@ module Sensu
|
|
378
383
|
:signal => signal
|
379
384
|
})
|
380
385
|
$logger.warn('stopping')
|
386
|
+
$redis.close
|
381
387
|
$logger.warn('stopping reactor')
|
382
|
-
EM::
|
383
|
-
EM::stop_event_loop
|
384
|
-
end
|
388
|
+
EM::stop_event_loop
|
385
389
|
end
|
386
390
|
end
|
387
391
|
end
|
data/lib/sensu/base.rb
CHANGED
@@ -10,7 +10,6 @@ require 'cabin'
|
|
10
10
|
require 'amqp'
|
11
11
|
|
12
12
|
require File.join(File.dirname(__FILE__), 'patches', 'ruby')
|
13
|
-
require File.join(File.dirname(__FILE__), 'patches', 'amqp')
|
14
13
|
|
15
14
|
require File.join(File.dirname(__FILE__), 'constants')
|
16
15
|
require File.join(File.dirname(__FILE__), 'cli')
|
@@ -20,11 +19,10 @@ require File.join(File.dirname(__FILE__), 'process')
|
|
20
19
|
|
21
20
|
module Sensu
|
22
21
|
class Base
|
23
|
-
attr_reader :options, :
|
22
|
+
attr_reader :options, :settings
|
24
23
|
|
25
24
|
def initialize(options={})
|
26
25
|
@options = Sensu::DEFAULT_OPTIONS.merge(options)
|
27
|
-
@logger = Cabin::Channel.get
|
28
26
|
setup_logging
|
29
27
|
setup_settings
|
30
28
|
setup_process
|
@@ -43,15 +41,7 @@ module Sensu
|
|
43
41
|
Dir[@options[:config_dir] + '/**/*.json'].each do |file|
|
44
42
|
@settings.load_file(file)
|
45
43
|
end
|
46
|
-
|
47
|
-
@settings.validate
|
48
|
-
rescue => error
|
49
|
-
@logger.fatal('config invalid', {
|
50
|
-
:error => error.to_s
|
51
|
-
})
|
52
|
-
@logger.fatal('SENSU NOT RUNNING!')
|
53
|
-
exit 2
|
54
|
-
end
|
44
|
+
@settings.validate
|
55
45
|
@settings.set_env
|
56
46
|
end
|
57
47
|
|
data/lib/sensu/client.rb
CHANGED
@@ -22,8 +22,8 @@ module Sensu
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def initialize(options={})
|
25
|
+
@logger = Cabin::Channel.get
|
25
26
|
base = Sensu::Base.new(options)
|
26
|
-
@logger = base.logger
|
27
27
|
@settings = base.settings
|
28
28
|
@timers = Array.new
|
29
29
|
@checks_in_progress = Array.new
|
@@ -48,8 +48,8 @@ module Sensu
|
|
48
48
|
def setup_keepalives
|
49
49
|
@logger.debug('scheduling keepalives')
|
50
50
|
publish_keepalive
|
51
|
-
@timers << EM::PeriodicTimer.new(
|
52
|
-
|
51
|
+
@timers << EM::PeriodicTimer.new(20) do
|
52
|
+
if @rabbitmq.connected?
|
53
53
|
publish_keepalive
|
54
54
|
end
|
55
55
|
end
|
@@ -90,7 +90,8 @@ module Sensu
|
|
90
90
|
substitute
|
91
91
|
end
|
92
92
|
if unmatched_tokens.empty?
|
93
|
-
execute =
|
93
|
+
execute = Proc.new do
|
94
|
+
check = check.dup
|
94
95
|
started = Time.now.to_f
|
95
96
|
begin
|
96
97
|
IO.popen(command + ' 2>&1') do |io|
|
@@ -105,14 +106,11 @@ module Sensu
|
|
105
106
|
check[:status] = 2
|
106
107
|
end
|
107
108
|
check[:duration] = ('%.3f' % (Time.now.to_f - started)).to_f
|
109
|
+
check
|
108
110
|
end
|
109
|
-
publish =
|
111
|
+
publish = Proc.new do |check|
|
110
112
|
unless check[:status].nil?
|
111
113
|
publish_result(check)
|
112
|
-
else
|
113
|
-
@logger.warn('nil exit status code', {
|
114
|
-
:check => check
|
115
|
-
})
|
116
114
|
end
|
117
115
|
@checks_in_progress.delete(check[:name])
|
118
116
|
end
|
@@ -178,28 +176,28 @@ module Sensu
|
|
178
176
|
def setup_rabbitmq_monitor
|
179
177
|
@logger.debug('monitoring rabbitmq connection')
|
180
178
|
@timers << EM::PeriodicTimer.new(5) do
|
181
|
-
if @rabbitmq.
|
182
|
-
@logger.warn('reconnecting to rabbitmq')
|
183
|
-
else
|
179
|
+
if @rabbitmq.connected?
|
184
180
|
unless @check_request_queue.subscribed?
|
185
181
|
@logger.warn('re-subscribing to client subscriptions')
|
186
182
|
setup_subscriptions
|
187
183
|
end
|
184
|
+
else
|
185
|
+
@logger.warn('reconnecting to rabbitmq')
|
188
186
|
end
|
189
187
|
end
|
190
188
|
end
|
191
189
|
|
192
|
-
def setup_standalone
|
190
|
+
def setup_standalone
|
193
191
|
@logger.debug('scheduling standalone checks')
|
194
192
|
standalone_check_count = 0
|
195
|
-
stagger =
|
193
|
+
stagger = testing? ? 0 : 7
|
196
194
|
@settings.checks.each do |check|
|
197
195
|
if check[:standalone]
|
198
196
|
standalone_check_count += 1
|
199
197
|
@timers << EM::Timer.new(stagger * standalone_check_count) do
|
200
|
-
interval =
|
198
|
+
interval = testing? ? 0.5 : check[:interval]
|
201
199
|
@timers << EM::PeriodicTimer.new(interval) do
|
202
|
-
|
200
|
+
if @rabbitmq.connected?
|
203
201
|
check[:issued] = Time.now.to_i
|
204
202
|
execute_check(check)
|
205
203
|
end
|
@@ -226,19 +224,33 @@ module Sensu
|
|
226
224
|
end
|
227
225
|
end
|
228
226
|
|
229
|
-
def
|
227
|
+
def unsubscribe(&block)
|
228
|
+
if @rabbitmq.connected?
|
229
|
+
@logger.warn('unsubscribing from client subscriptions')
|
230
|
+
@check_request_queue.unsubscribe do
|
231
|
+
if block
|
232
|
+
block.call
|
233
|
+
end
|
234
|
+
end
|
235
|
+
else
|
236
|
+
if block
|
237
|
+
block.call
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def complete_checks_in_progress(&block)
|
230
243
|
@logger.info('completing checks in progress', {
|
231
244
|
:checks_in_progress => @checks_in_progress
|
232
245
|
})
|
233
|
-
|
246
|
+
complete = EM::tick_loop do
|
234
247
|
if @checks_in_progress.empty?
|
235
248
|
:stop
|
236
249
|
end
|
237
250
|
end
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
EM::stop_event_loop
|
251
|
+
complete.on_stop do
|
252
|
+
if block
|
253
|
+
block.call
|
242
254
|
end
|
243
255
|
end
|
244
256
|
end
|
@@ -251,14 +263,18 @@ module Sensu
|
|
251
263
|
@timers.each do |timer|
|
252
264
|
timer.cancel
|
253
265
|
end
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
266
|
+
unsubscribe do
|
267
|
+
complete_checks_in_progress do
|
268
|
+
@logger.warn('stopping reactor')
|
269
|
+
EM::stop_event_loop
|
258
270
|
end
|
259
|
-
else
|
260
|
-
EM::stop_event_loop
|
261
271
|
end
|
262
272
|
end
|
273
|
+
|
274
|
+
private
|
275
|
+
|
276
|
+
def testing?
|
277
|
+
File.basename($0) == 'rake'
|
278
|
+
end
|
263
279
|
end
|
264
280
|
end
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/redis.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module Sensu
|
4
|
+
class Redis < Redis::Client
|
5
|
+
attr_accessor :host, :port, :password, :on_disconnect
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
super
|
9
|
+
@logger = Cabin::Channel.get
|
10
|
+
@connected = false
|
11
|
+
@closing_connection = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def connection_completed
|
15
|
+
@connected = true
|
16
|
+
if @password
|
17
|
+
auth(@password).callback do |reply|
|
18
|
+
unless reply == 'OK'
|
19
|
+
@logger.fatal('redis authentication failed')
|
20
|
+
close_connection
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
info.callback do |reply|
|
25
|
+
redis_version = reply.split(/\n/).first.split(/:/).last.chomp
|
26
|
+
if redis_version < '1.3.14'
|
27
|
+
@logger.fatal('redis version must be >= 2.0 RC 1')
|
28
|
+
close_connection
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def reconnect!
|
34
|
+
EM::Timer.new(1) do
|
35
|
+
reconnect(@host, @port)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def close
|
40
|
+
@closing_connection = true
|
41
|
+
close_connection
|
42
|
+
end
|
43
|
+
|
44
|
+
def unbind
|
45
|
+
@connected = false
|
46
|
+
super
|
47
|
+
if @on_disconnect && !@closing_connection
|
48
|
+
@on_disconnect.call
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def connected?
|
53
|
+
@connected
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.connect(options)
|
57
|
+
options ||= Hash.new
|
58
|
+
if options.is_a?(String)
|
59
|
+
begin
|
60
|
+
uri = URI.parse(options)
|
61
|
+
host = uri.host
|
62
|
+
port = uri.port || 6379
|
63
|
+
password = uri.password
|
64
|
+
rescue
|
65
|
+
@logger.fatal('invalid redis url')
|
66
|
+
@logger.fatal('SENSU NOT RUNNING!')
|
67
|
+
exit 2
|
68
|
+
end
|
69
|
+
else
|
70
|
+
host = options[:host] || 'localhost'
|
71
|
+
port = options[:port] || 6379
|
72
|
+
password = options[:password]
|
73
|
+
end
|
74
|
+
EM::connect(host, port, self) do |redis|
|
75
|
+
redis.host = host
|
76
|
+
redis.port = port
|
77
|
+
redis.password = password
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/sensu/server.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'base')
|
2
|
-
|
3
|
-
require 'redis'
|
4
|
-
|
5
|
-
require File.join(File.dirname(__FILE__), 'patches', 'redis')
|
2
|
+
require File.join(File.dirname(__FILE__), 'redis')
|
6
3
|
|
7
4
|
module Sensu
|
8
5
|
class Server
|
@@ -27,8 +24,8 @@ module Sensu
|
|
27
24
|
end
|
28
25
|
|
29
26
|
def initialize(options={})
|
27
|
+
@logger = Cabin::Channel.get
|
30
28
|
base = Sensu::Base.new(options)
|
31
|
-
@logger = base.logger
|
32
29
|
@settings = base.settings
|
33
30
|
@timers = Array.new
|
34
31
|
@handlers_in_progress = 0
|
@@ -38,7 +35,13 @@ module Sensu
|
|
38
35
|
@logger.debug('connecting to redis', {
|
39
36
|
:settings => @settings[:redis]
|
40
37
|
})
|
41
|
-
@redis = Redis.connect(@settings[:redis])
|
38
|
+
@redis = Sensu::Redis.connect(@settings[:redis])
|
39
|
+
unless testing?
|
40
|
+
@redis.on_disconnect = Proc.new do
|
41
|
+
@logger.fatal('redis connection closed')
|
42
|
+
stop('TERM')
|
43
|
+
end
|
44
|
+
end
|
42
45
|
end
|
43
46
|
|
44
47
|
def setup_rabbitmq
|
@@ -63,7 +66,7 @@ module Sensu
|
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
66
|
-
def check_subdued?(check,
|
69
|
+
def check_subdued?(check, subdue_at)
|
67
70
|
subdue = false
|
68
71
|
if check[:subdue].is_a?(Hash)
|
69
72
|
if check[:subdue].has_key?(:start) && check[:subdue].has_key?(:end)
|
@@ -93,8 +96,8 @@ module Sensu
|
|
93
96
|
end
|
94
97
|
end
|
95
98
|
if subdue
|
96
|
-
(!check[:subdue].has_key?(:at) &&
|
97
|
-
(check[:subdue].has_key?(:at) && check[:subdue][:at].to_sym ==
|
99
|
+
(!check[:subdue].has_key?(:at) && subdue_at == :handler) ||
|
100
|
+
(check[:subdue].has_key?(:at) && check[:subdue][:at].to_sym == subdue_at)
|
98
101
|
else
|
99
102
|
false
|
100
103
|
end
|
@@ -109,11 +112,8 @@ module Sensu
|
|
109
112
|
else
|
110
113
|
['default']
|
111
114
|
end
|
112
|
-
handler_list.reject! do |handler_name|
|
113
|
-
!@settings.handler_exists?(handler_name)
|
114
|
-
end
|
115
115
|
handler_list.map! do |handler_name|
|
116
|
-
if @settings[:handlers][handler_name][:type] == 'set'
|
116
|
+
if @settings.handler_exists?(handler_name) && @settings[:handlers][handler_name][:type] == 'set'
|
117
117
|
@settings[:handlers][handler_name][:handlers]
|
118
118
|
else
|
119
119
|
handler_name
|
@@ -122,7 +122,16 @@ module Sensu
|
|
122
122
|
handler_list.flatten!
|
123
123
|
handler_list.uniq!
|
124
124
|
handler_list.reject! do |handler_name|
|
125
|
-
|
125
|
+
unless @settings.handler_exists?(handler_name)
|
126
|
+
@logger.warn('unknown handler', {
|
127
|
+
:handler => {
|
128
|
+
:name => handler_name
|
129
|
+
}
|
130
|
+
})
|
131
|
+
true
|
132
|
+
else
|
133
|
+
false
|
134
|
+
end
|
126
135
|
end
|
127
136
|
handler_list.map do |handler_name|
|
128
137
|
@settings[:handlers][handler_name].merge(:name => handler_name)
|
@@ -131,31 +140,23 @@ module Sensu
|
|
131
140
|
|
132
141
|
def handle_event(event)
|
133
142
|
unless check_subdued?(event[:check], :handler)
|
134
|
-
report = proc do |output|
|
135
|
-
if output.is_a?(String)
|
136
|
-
output.split(/\n+/).each do |line|
|
137
|
-
@logger.info('handler output', {
|
138
|
-
:output => line
|
139
|
-
})
|
140
|
-
end
|
141
|
-
end
|
142
|
-
@handlers_in_progress -= 1
|
143
|
-
end
|
144
143
|
handlers = check_handlers(event[:check])
|
145
144
|
handlers.each do |handler|
|
146
|
-
@logger.
|
145
|
+
@logger.info('handling event', {
|
147
146
|
:event => event,
|
148
147
|
:handler => handler
|
149
148
|
})
|
150
149
|
@handlers_in_progress += 1
|
151
150
|
case handler[:type]
|
152
151
|
when 'pipe'
|
153
|
-
execute =
|
152
|
+
execute = Proc.new do
|
154
153
|
begin
|
155
154
|
IO.popen(handler[:command] + ' 2>&1', 'r+') do |io|
|
156
155
|
io.write(event.to_json)
|
157
156
|
io.close_write
|
158
|
-
io.read
|
157
|
+
io.read.split(/\n+/).each do |line|
|
158
|
+
@logger.debug(line)
|
159
|
+
end
|
159
160
|
end
|
160
161
|
rescue Errno::ENOENT => error
|
161
162
|
@logger.error('handler does not exist', {
|
@@ -177,7 +178,10 @@ module Sensu
|
|
177
178
|
})
|
178
179
|
end
|
179
180
|
end
|
180
|
-
|
181
|
+
complete = Proc.new do
|
182
|
+
@handlers_in_progress -= 1
|
183
|
+
end
|
184
|
+
EM::defer(execute, complete)
|
181
185
|
when 'amqp'
|
182
186
|
exchange_name = handler[:exchange][:name]
|
183
187
|
exchange_type = handler[:exchange].has_key?(:type) ? handler[:exchange][:type].to_sym : :direct
|
@@ -324,18 +328,18 @@ module Sensu
|
|
324
328
|
end
|
325
329
|
end
|
326
330
|
|
327
|
-
def setup_publisher
|
331
|
+
def setup_publisher
|
328
332
|
@logger.debug('scheduling check requests')
|
329
333
|
check_count = 0
|
330
|
-
stagger =
|
334
|
+
stagger = testing? ? 0 : 7
|
331
335
|
@settings.checks.each do |check|
|
332
336
|
unless check[:publish] == false || check[:standalone]
|
333
337
|
check_count += 1
|
334
338
|
@timers << EM::Timer.new(stagger * check_count) do
|
335
|
-
interval =
|
339
|
+
interval = testing? ? 0.5 : check[:interval]
|
336
340
|
@timers << EM::PeriodicTimer.new(interval) do
|
337
341
|
unless check_subdued?(check, :publisher)
|
338
|
-
|
342
|
+
if @rabbitmq.connected?
|
339
343
|
payload = {
|
340
344
|
:name => check[:name],
|
341
345
|
:issued => Time.now.to_i
|
@@ -369,7 +373,7 @@ module Sensu
|
|
369
373
|
def setup_keepalive_monitor
|
370
374
|
@logger.debug('monitoring client keepalives')
|
371
375
|
@timers << EM::PeriodicTimer.new(30) do
|
372
|
-
|
376
|
+
if @rabbitmq.connected?
|
373
377
|
@logger.debug('checking for stale client info')
|
374
378
|
@redis.smembers('clients').callback do |clients|
|
375
379
|
clients.each do |client_name|
|
@@ -382,17 +386,17 @@ module Sensu
|
|
382
386
|
time_since_last_keepalive = Time.now.to_i - client[:timestamp]
|
383
387
|
case
|
384
388
|
when time_since_last_keepalive >= 180
|
385
|
-
check[:output] = 'No keep-alive sent from
|
389
|
+
check[:output] = 'No keep-alive sent from client in over 180 seconds'
|
386
390
|
check[:status] = 2
|
387
391
|
publish_result(client, check)
|
388
392
|
when time_since_last_keepalive >= 120
|
389
|
-
check[:output] = 'No keep-alive sent from
|
393
|
+
check[:output] = 'No keep-alive sent from client in over 120 seconds'
|
390
394
|
check[:status] = 1
|
391
395
|
publish_result(client, check)
|
392
396
|
else
|
393
397
|
@redis.hexists('events:' + client[:name], 'keepalive').callback do |exists|
|
394
398
|
if exists
|
395
|
-
check[:output] = 'Keep-alive sent from
|
399
|
+
check[:output] = 'Keep-alive sent from client'
|
396
400
|
check[:status] = 0
|
397
401
|
publish_result(client, check)
|
398
402
|
end
|
@@ -434,7 +438,7 @@ module Sensu
|
|
434
438
|
end
|
435
439
|
|
436
440
|
def resign_as_master(&block)
|
437
|
-
if @is_master
|
441
|
+
if @redis.connected? && @is_master
|
438
442
|
@redis.del('lock:master').callback do
|
439
443
|
@logger.warn('resigned as master')
|
440
444
|
if block
|
@@ -442,7 +446,6 @@ module Sensu
|
|
442
446
|
end
|
443
447
|
end
|
444
448
|
else
|
445
|
-
@logger.warn('not currently master')
|
446
449
|
if block
|
447
450
|
block.call
|
448
451
|
end
|
@@ -465,9 +468,7 @@ module Sensu
|
|
465
468
|
def setup_rabbitmq_monitor
|
466
469
|
@logger.debug('monitoring rabbitmq connection')
|
467
470
|
@timers << EM::PeriodicTimer.new(5) do
|
468
|
-
if @rabbitmq.
|
469
|
-
@logger.warn('reconnecting to rabbitmq')
|
470
|
-
else
|
471
|
+
if @rabbitmq.connected?
|
471
472
|
unless @keepalive_queue.subscribed?
|
472
473
|
@logger.warn('re-subscribing to keepalives')
|
473
474
|
setup_keepalives
|
@@ -476,23 +477,42 @@ module Sensu
|
|
476
477
|
@logger.warn('re-subscribing to results')
|
477
478
|
setup_results
|
478
479
|
end
|
480
|
+
else
|
481
|
+
@logger.warn('reconnecting to rabbitmq')
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
def unsubscribe(&block)
|
487
|
+
if @rabbitmq.connected?
|
488
|
+
@logger.warn('unsubscribing from keepalives')
|
489
|
+
@keepalive_queue.unsubscribe do
|
490
|
+
@logger.warn('unsubscribing from results')
|
491
|
+
@result_queue.unsubscribe do
|
492
|
+
if block
|
493
|
+
block.call
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
else
|
498
|
+
if block
|
499
|
+
block.call
|
479
500
|
end
|
480
501
|
end
|
481
502
|
end
|
482
503
|
|
483
|
-
def
|
504
|
+
def complete_handlers_in_progress(&block)
|
484
505
|
@logger.info('completing handlers in progress', {
|
485
506
|
:handlers_in_progress => @handlers_in_progress
|
486
507
|
})
|
487
|
-
|
508
|
+
complete = EM::tick_loop do
|
488
509
|
if @handlers_in_progress == 0
|
489
510
|
:stop
|
490
511
|
end
|
491
512
|
end
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
EM::stop_event_loop
|
513
|
+
complete.on_stop do
|
514
|
+
if block
|
515
|
+
block.call
|
496
516
|
end
|
497
517
|
end
|
498
518
|
end
|
@@ -505,21 +525,21 @@ module Sensu
|
|
505
525
|
@timers.each do |timer|
|
506
526
|
timer.cancel
|
507
527
|
end
|
508
|
-
|
509
|
-
@logger.warn('unsubscribing from keepalives')
|
510
|
-
@keepalive_queue.unsubscribe do
|
511
|
-
@logger.warn('unsubscribing from results')
|
512
|
-
@result_queue.unsubscribe do
|
513
|
-
resign_as_master do
|
514
|
-
stop_reactor
|
515
|
-
end
|
516
|
-
end
|
517
|
-
end
|
518
|
-
else
|
528
|
+
unsubscribe do
|
519
529
|
resign_as_master do
|
520
|
-
|
530
|
+
complete_handlers_in_progress do
|
531
|
+
@redis.close
|
532
|
+
@logger.warn('stopping reactor')
|
533
|
+
EM::stop_event_loop
|
534
|
+
end
|
521
535
|
end
|
522
536
|
end
|
523
537
|
end
|
538
|
+
|
539
|
+
private
|
540
|
+
|
541
|
+
def testing?
|
542
|
+
File.basename($0) == 'rake'
|
543
|
+
end
|
524
544
|
end
|
525
545
|
end
|
data/lib/sensu/settings.rb
CHANGED
@@ -172,74 +172,108 @@ module Sensu
|
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
175
|
+
def invalid(reason, details={})
|
176
|
+
@logger.fatal('invalid settings', {
|
177
|
+
:reason => reason
|
178
|
+
}.merge(details))
|
179
|
+
@logger.fatal('SENSU NOT RUNNING!')
|
180
|
+
exit 2
|
181
|
+
end
|
182
|
+
|
175
183
|
def validate_checks
|
176
184
|
unless @settings[:checks].is_a?(Hash)
|
177
|
-
|
185
|
+
invalid('missing checks configuration')
|
178
186
|
end
|
179
187
|
checks.each do |check|
|
180
188
|
unless check[:interval].is_a?(Integer) && check[:interval] > 0
|
181
|
-
|
189
|
+
invalid('check is missing interval', {
|
190
|
+
:check => check
|
191
|
+
})
|
182
192
|
end
|
183
193
|
unless check[:command].is_a?(String)
|
184
|
-
|
194
|
+
invalid('check is missing command', {
|
195
|
+
:check => check
|
196
|
+
})
|
185
197
|
end
|
186
198
|
unless check[:standalone]
|
187
199
|
unless check[:subscribers].is_a?(Array) && check[:subscribers].count > 0
|
188
|
-
|
200
|
+
invalid('check is missing subscribers', {
|
201
|
+
:check => check
|
202
|
+
})
|
189
203
|
end
|
190
204
|
check[:subscribers].each do |subscriber|
|
191
205
|
unless subscriber.is_a?(String) && !subscriber.empty?
|
192
|
-
|
206
|
+
invalid('check subscribers must each be a string', {
|
207
|
+
:check => check
|
208
|
+
})
|
193
209
|
end
|
194
210
|
end
|
195
211
|
end
|
196
212
|
if check.has_key?(:handler)
|
197
213
|
unless check[:handler].is_a?(String)
|
198
|
-
|
214
|
+
invalid('check handler must be a string', {
|
215
|
+
:check => check
|
216
|
+
})
|
199
217
|
end
|
200
218
|
end
|
201
219
|
if check.has_key?(:handlers)
|
202
220
|
unless check[:handlers].is_a?(Array)
|
203
|
-
|
221
|
+
invalid('check handlers must be an array', {
|
222
|
+
:check => check
|
223
|
+
})
|
204
224
|
end
|
205
225
|
end
|
206
226
|
if check.has_key?(:subdue)
|
207
227
|
unless check[:subdue].is_a?(Hash)
|
208
|
-
|
228
|
+
invalid('check subdue must be a hash', {
|
229
|
+
:check => check
|
230
|
+
})
|
209
231
|
end
|
210
232
|
if check[:subdue].has_key?(:start) || check[:subdue].has_key?(:end)
|
211
233
|
begin
|
212
234
|
Time.parse(check[:subdue][:start])
|
213
235
|
Time.parse(check[:subdue][:end])
|
214
236
|
rescue
|
215
|
-
|
237
|
+
invalid('check subdue start & end times must be valid', {
|
238
|
+
:check => check
|
239
|
+
})
|
216
240
|
end
|
217
241
|
end
|
218
242
|
if check[:subdue].has_key?(:days)
|
219
243
|
unless check[:subdue][:days].is_a?(Array)
|
220
|
-
|
244
|
+
invalid('check subdue days must be an array', {
|
245
|
+
:check => check
|
246
|
+
})
|
221
247
|
end
|
222
248
|
check[:subdue][:days].each do |day|
|
223
249
|
days = %w[sunday monday tuesday wednesday thursday friday saturday]
|
224
250
|
unless day.is_a?(String) && days.include?(day.downcase)
|
225
|
-
|
251
|
+
invalid('check subdue days must be valid days of the week', {
|
252
|
+
:check => check
|
253
|
+
})
|
226
254
|
end
|
227
255
|
end
|
228
256
|
end
|
229
257
|
if check[:subdue].has_key?(:exceptions)
|
230
258
|
unless check[:subdue][:exceptions].is_a?(Array)
|
231
|
-
|
259
|
+
invalid('check subdue exceptions must be an array', {
|
260
|
+
:check => check
|
261
|
+
})
|
232
262
|
end
|
233
263
|
check[:subdue][:exceptions].each do |exception|
|
234
264
|
unless exception.is_a?(Hash)
|
235
|
-
|
265
|
+
invalid('check subdue exceptions must each be a hash', {
|
266
|
+
:check => check
|
267
|
+
})
|
236
268
|
end
|
237
269
|
if exception.has_key?(:start) || exception.has_key?(:end)
|
238
270
|
begin
|
239
271
|
Time.parse(exception[:start])
|
240
272
|
Time.parse(exception[:end])
|
241
273
|
rescue
|
242
|
-
|
274
|
+
invalid('check subdue exception start & end times must be valid', {
|
275
|
+
:check => check
|
276
|
+
})
|
243
277
|
end
|
244
278
|
end
|
245
279
|
end
|
@@ -250,75 +284,89 @@ module Sensu
|
|
250
284
|
|
251
285
|
def validate_client
|
252
286
|
unless @settings[:client].is_a?(Hash)
|
253
|
-
|
287
|
+
invalid('missing client configuration')
|
254
288
|
end
|
255
289
|
unless @settings[:client][:name].is_a?(String)
|
256
|
-
|
290
|
+
invalid('client must have a name')
|
257
291
|
end
|
258
292
|
unless @settings[:client][:address].is_a?(String)
|
259
|
-
|
293
|
+
invalid('client must have an address')
|
260
294
|
end
|
261
295
|
unless @settings[:client][:subscriptions].is_a?(Array) && @settings[:client][:subscriptions].count > 0
|
262
|
-
|
296
|
+
invalid('client must have subscriptions')
|
263
297
|
end
|
264
298
|
@settings[:client][:subscriptions].each do |subscription|
|
265
299
|
unless subscription.is_a?(String) && !subscription.empty?
|
266
|
-
|
300
|
+
invalid('client subscriptions must each be a string')
|
267
301
|
end
|
268
302
|
end
|
269
303
|
end
|
270
304
|
|
271
305
|
def validate_api
|
272
306
|
unless @settings[:api].is_a?(Hash)
|
273
|
-
|
307
|
+
invalid('missing api configuration')
|
274
308
|
end
|
275
309
|
unless @settings[:api][:port].is_a?(Integer)
|
276
|
-
|
310
|
+
invalid('api port must be an integer')
|
277
311
|
end
|
278
312
|
if @settings[:api].has_key?(:user) || @settings[:api].has_key?(:password)
|
279
313
|
unless @settings[:api][:user].is_a?(String)
|
280
|
-
|
314
|
+
invalid('api user must be a string')
|
281
315
|
end
|
282
316
|
unless @settings[:api][:password].is_a?(String)
|
283
|
-
|
317
|
+
invalid('api password must be a string')
|
284
318
|
end
|
285
319
|
end
|
286
320
|
end
|
287
321
|
|
288
322
|
def validate_server
|
289
323
|
unless @settings[:handlers].is_a?(Hash)
|
290
|
-
|
324
|
+
invalid('missing handlers configuration')
|
291
325
|
end
|
292
326
|
unless @settings[:handlers].include?(:default)
|
293
|
-
|
327
|
+
invalid('missing default handler')
|
294
328
|
end
|
295
329
|
handlers.each do |handler|
|
296
330
|
unless handler[:type].is_a?(String)
|
297
|
-
|
331
|
+
invalid('handler is missing type', {
|
332
|
+
:handler => handler
|
333
|
+
})
|
298
334
|
end
|
299
335
|
case handler[:type]
|
300
336
|
when 'pipe'
|
301
337
|
unless handler[:command].is_a?(String)
|
302
|
-
|
338
|
+
invalid('handler is missing command', {
|
339
|
+
:handler => handler
|
340
|
+
})
|
303
341
|
end
|
304
342
|
when 'amqp'
|
305
343
|
unless handler[:exchange].is_a?(Hash)
|
306
|
-
|
344
|
+
invalid('handler is missing exchange hash', {
|
345
|
+
:handler => handler
|
346
|
+
})
|
307
347
|
end
|
308
348
|
unless handler[:exchange][:name].is_a?(String)
|
309
|
-
|
349
|
+
invalid('handler is missing exchange name', {
|
350
|
+
:handler => handler
|
351
|
+
})
|
310
352
|
end
|
311
353
|
if handler[:exchange].has_key?(:type)
|
312
354
|
unless %w[direct fanout topic].include?(handler[:exchange][:type])
|
313
|
-
|
355
|
+
invalid('handler exchange type is invalid', {
|
356
|
+
:handler => handler
|
357
|
+
})
|
314
358
|
end
|
315
359
|
end
|
316
360
|
when 'set'
|
317
361
|
unless handler[:handlers].is_a?(Array) && handler[:handlers].count > 0
|
318
|
-
|
362
|
+
invalid('handler set is missing handlers', {
|
363
|
+
:handler => handler
|
364
|
+
})
|
319
365
|
end
|
320
366
|
else
|
321
|
-
|
367
|
+
invalid('unknown handler type', {
|
368
|
+
:handler => handler
|
369
|
+
})
|
322
370
|
end
|
323
371
|
end
|
324
372
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 62196233
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
9
|
- 6
|
10
10
|
- beta
|
11
|
-
-
|
12
|
-
version: 0.9.6.beta.
|
11
|
+
- 5
|
12
|
+
version: 0.9.6.beta.5
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Sean Porter
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2012-05-
|
21
|
+
date: 2012-05-25 00:00:00 -07:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -193,10 +193,9 @@ files:
|
|
193
193
|
- lib/sensu/client.rb
|
194
194
|
- lib/sensu/constants.rb
|
195
195
|
- lib/sensu/logger.rb
|
196
|
-
- lib/sensu/patches/amqp.rb
|
197
|
-
- lib/sensu/patches/redis.rb
|
198
196
|
- lib/sensu/patches/ruby.rb
|
199
197
|
- lib/sensu/process.rb
|
198
|
+
- lib/sensu/redis.rb
|
200
199
|
- lib/sensu/server.rb
|
201
200
|
- lib/sensu/settings.rb
|
202
201
|
- lib/sensu/socket.rb
|
data/lib/sensu/patches/amqp.rb
DELETED
data/lib/sensu/patches/redis.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
module Redis
|
2
|
-
class Client
|
3
|
-
attr_accessor :redis_host, :redis_port, :redis_password
|
4
|
-
|
5
|
-
def connection_completed
|
6
|
-
@connected = true
|
7
|
-
@reconnecting = false
|
8
|
-
if @redis_password
|
9
|
-
auth(@redis_password).callback do |reply|
|
10
|
-
unless reply == 'OK'
|
11
|
-
raise('could not authenticate')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
info.callback do |reply|
|
16
|
-
redis_version = reply.split(/\n/).first.split(/:/).last.chomp
|
17
|
-
if redis_version < '1.3.14'
|
18
|
-
raise('redis version must be >= 2.0 RC 1')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def close
|
24
|
-
@closing_connection = true
|
25
|
-
close_connection_after_writing
|
26
|
-
end
|
27
|
-
|
28
|
-
def unbind
|
29
|
-
unless !@connected || @closing_connection
|
30
|
-
EM::Timer.new(1) do
|
31
|
-
@reconnecting = true
|
32
|
-
reconnect(@redis_host, @redis_port)
|
33
|
-
end
|
34
|
-
else
|
35
|
-
until @queue.empty?
|
36
|
-
@queue.shift.fail RuntimeError.new('connection closed')
|
37
|
-
end
|
38
|
-
unless @connected
|
39
|
-
raise('could not connect to redis')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def reconnecting?
|
45
|
-
@reconnecting || false
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.connect(options)
|
50
|
-
options ||= Hash.new
|
51
|
-
if options.is_a?(String)
|
52
|
-
begin
|
53
|
-
uri = URI.parse(options)
|
54
|
-
host = uri.host
|
55
|
-
port = uri.port || 6379
|
56
|
-
password = uri.password
|
57
|
-
rescue
|
58
|
-
raise('invalid redis url')
|
59
|
-
end
|
60
|
-
else
|
61
|
-
host = options[:host] || 'localhost'
|
62
|
-
port = options[:port] || 6379
|
63
|
-
password = options[:password]
|
64
|
-
end
|
65
|
-
EM::connect(host, port, Redis::Client) do |client|
|
66
|
-
client.redis_host = host
|
67
|
-
client.redis_port = port
|
68
|
-
client.redis_password = password
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|