sensu 0.18.0.beta → 0.18.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/sensu/api/process.rb +8 -3
- data/lib/sensu/client/process.rb +26 -4
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +1 -1
- data/lib/sensu/server/process.rb +57 -55
- data/sensu.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5115ea5fab3b40df251fdcef28cb7108c84c4df4
|
4
|
+
data.tar.gz: a5094e790a5b5db1963da654bea369268d122f4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebbece50c019e3c927e52669be30c38e0be7ac1b91993bf72a4cc4d7ff19f19c161d0a55b6b4bb8ee27cff375405f0ba5c7ec7dcee84c26c97edc6584c929293
|
7
|
+
data.tar.gz: d0cb1a938d07ef543925234cc2c47eda1231d138e45500d1112c693f3373e1793e7d96aea078baf3c01a605f5347d09efd7a52fb6e713983c6ca2a1b246a0bf7
|
data/CHANGELOG.md
CHANGED
@@ -13,6 +13,21 @@ Storing the latest check result for every client/check pair. This data is
|
|
13
13
|
currently exposed via the API at `/clients/:client/history` and will be
|
14
14
|
used by several upcoming features.
|
15
15
|
|
16
|
+
The Sensu API now listens on TCP port `4567` by default.
|
17
|
+
|
18
|
+
Sensu server leader election lock timestamps now include milliseconds to
|
19
|
+
reduce the chance of a conflict when attempting to elect a new leader.
|
20
|
+
|
21
|
+
### Other
|
22
|
+
|
23
|
+
The Sensu client sockets (TCP/UDP) are now stopped/closed before the
|
24
|
+
process is stopped.
|
25
|
+
|
26
|
+
Sensu server "master" election is now "leader" election.
|
27
|
+
|
28
|
+
Configuration file encoding is now forced to 8-bit ASCII and UTF-8 BOMs
|
29
|
+
are removed if present.
|
30
|
+
|
16
31
|
## 0.17.2 - 2015-04-08
|
17
32
|
|
18
33
|
### Other
|
data/lib/sensu/api/process.rb
CHANGED
@@ -40,7 +40,7 @@ module Sensu
|
|
40
40
|
setup_logger(options)
|
41
41
|
set :logger, @logger
|
42
42
|
load_settings(options)
|
43
|
-
set :api, @settings[:api]
|
43
|
+
set :api, @settings[:api] || {}
|
44
44
|
set :checks, @settings[:checks]
|
45
45
|
set :all_checks, @settings.checks
|
46
46
|
set :cors, @settings[:cors] || {
|
@@ -55,8 +55,13 @@ module Sensu
|
|
55
55
|
|
56
56
|
def start_server
|
57
57
|
Thin::Logging.silent = true
|
58
|
-
bind =
|
59
|
-
|
58
|
+
bind = settings.api[:bind] || "0.0.0.0"
|
59
|
+
port = settings.api[:port] || 4567
|
60
|
+
@logger.info("api listening", {
|
61
|
+
:bind => bind,
|
62
|
+
:port => port
|
63
|
+
})
|
64
|
+
@thin = Thin::Server.new(bind, port, self)
|
60
65
|
@thin.start
|
61
66
|
end
|
62
67
|
|
data/lib/sensu/client/process.rb
CHANGED
@@ -22,13 +22,14 @@ module Sensu
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# Override Daemon initialize() to support Sensu client check
|
25
|
-
# execution safe mode
|
25
|
+
# execution safe mode, checks in progress, and open sockets.
|
26
26
|
#
|
27
27
|
# @param options [Hash]
|
28
28
|
def initialize(options={})
|
29
29
|
super
|
30
30
|
@safe_mode = @settings[:client][:safe_mode] || false
|
31
31
|
@checks_in_progress = []
|
32
|
+
@sockets = []
|
32
33
|
end
|
33
34
|
|
34
35
|
# Create a Sensu client keepalive payload, to be sent over the
|
@@ -315,18 +316,21 @@ module Sensu
|
|
315
316
|
# TCP & UDP port 3030. The socket can be configured via the
|
316
317
|
# client definition, `:socket` with `:bind` and `:port`. The
|
317
318
|
# current instance of the Sensu logger, settings, and transport
|
318
|
-
# are passed to the socket handler, `Sensu::Client::Socket`.
|
319
|
+
# are passed to the socket handler, `Sensu::Client::Socket`. The
|
320
|
+
# TCP socket server signature (Fixnum) and UDP connection object
|
321
|
+
# are stored in `@sockets`, so that they can be managed
|
322
|
+
# elsewhere, eg. `close_sockets()`.
|
319
323
|
def setup_sockets
|
320
324
|
options = @settings[:client][:socket] || Hash.new
|
321
325
|
options[:bind] ||= "127.0.0.1"
|
322
326
|
options[:port] ||= 3030
|
323
327
|
@logger.debug("binding client tcp and udp sockets", :options => options)
|
324
|
-
EM::start_server(options[:bind], options[:port], Socket) do |socket|
|
328
|
+
@sockets << EM::start_server(options[:bind], options[:port], Socket) do |socket|
|
325
329
|
socket.logger = @logger
|
326
330
|
socket.settings = @settings
|
327
331
|
socket.transport = @transport
|
328
332
|
end
|
329
|
-
EM::open_datagram_socket(options[:bind], options[:port], Socket) do |socket|
|
333
|
+
@sockets << EM::open_datagram_socket(options[:bind], options[:port], Socket) do |socket|
|
330
334
|
socket.logger = @logger
|
331
335
|
socket.settings = @settings
|
332
336
|
socket.transport = @transport
|
@@ -352,6 +356,23 @@ module Sensu
|
|
352
356
|
end
|
353
357
|
end
|
354
358
|
|
359
|
+
# Close the Sensu client TCP and UDP sockets. This method
|
360
|
+
# iterates through `@sockets`, which contains socket server
|
361
|
+
# signatures (Fixnum) and connection objects. A signature
|
362
|
+
# indicates a TCP socket server that needs to be stopped. A
|
363
|
+
# connection object indicates a socket connection that needs to
|
364
|
+
# be closed, eg. a UDP datagram socket.
|
365
|
+
def close_sockets
|
366
|
+
@logger.info("closing client tcp and udp sockets")
|
367
|
+
@sockets.each do |socket|
|
368
|
+
if socket.is_a?(Numeric)
|
369
|
+
EM.stop_server(socket)
|
370
|
+
else
|
371
|
+
socket.close_connection
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
355
376
|
# Bootstrap the Sensu client, setting up client keepalives,
|
356
377
|
# subscriptions, and standalone check executions. This method
|
357
378
|
# sets the process/daemon `@state` to `:running`.
|
@@ -415,6 +436,7 @@ module Sensu
|
|
415
436
|
pause
|
416
437
|
@state = :stopping
|
417
438
|
complete_checks_in_progress do
|
439
|
+
close_sockets
|
418
440
|
@transport.close
|
419
441
|
super
|
420
442
|
end
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/daemon.rb
CHANGED
data/lib/sensu/server/process.rb
CHANGED
@@ -11,7 +11,7 @@ module Sensu
|
|
11
11
|
include Mutate
|
12
12
|
include Handle
|
13
13
|
|
14
|
-
attr_reader :
|
14
|
+
attr_reader :is_leader, :handling_event_count
|
15
15
|
|
16
16
|
# Create an instance of the Sensu server process, start the
|
17
17
|
# server within the EventMachine event loop, and set up server
|
@@ -26,14 +26,14 @@ module Sensu
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
# Override Daemon initialize() to support Sensu server
|
29
|
+
# Override Daemon initialize() to support Sensu server leader
|
30
30
|
# election and the handling event count.
|
31
31
|
#
|
32
32
|
# @param options [Hash]
|
33
33
|
def initialize(options={})
|
34
34
|
super
|
35
|
-
@
|
36
|
-
@timers[:
|
35
|
+
@is_leader = false
|
36
|
+
@timers[:leader] = Array.new
|
37
37
|
@handling_event_count = 0
|
38
38
|
end
|
39
39
|
|
@@ -481,8 +481,8 @@ module Sensu
|
|
481
481
|
|
482
482
|
# Schedule check executions, using EventMachine periodic timers,
|
483
483
|
# using a calculated execution splay. The timers are stored in
|
484
|
-
# the timers hash under `:
|
485
|
-
# is a task for only the Sensu server
|
484
|
+
# the timers hash under `:leader`, as check request publishing
|
485
|
+
# is a task for only the Sensu server leader, so they can be
|
486
486
|
# cancelled etc. Check requests are not published if subdued.
|
487
487
|
#
|
488
488
|
# @param checks [Array] of definitions.
|
@@ -497,9 +497,9 @@ module Sensu
|
|
497
497
|
end
|
498
498
|
execution_splay = testing? ? 0 : calculate_check_execution_splay(check)
|
499
499
|
interval = testing? ? 0.5 : check[:interval]
|
500
|
-
@timers[:
|
500
|
+
@timers[:leader] << EM::Timer.new(execution_splay) do
|
501
501
|
create_check_request.call
|
502
|
-
@timers[:
|
502
|
+
@timers[:leader] << EM::PeriodicTimer.new(interval, &create_check_request)
|
503
503
|
end
|
504
504
|
end
|
505
505
|
end
|
@@ -615,10 +615,10 @@ module Sensu
|
|
615
615
|
|
616
616
|
# Set up the client monitor, a periodic timer to run
|
617
617
|
# `determine_stale_clients()` every 30 seconds. The timer is
|
618
|
-
# stored in the timers hash under `:
|
618
|
+
# stored in the timers hash under `:leader`.
|
619
619
|
def setup_client_monitor
|
620
620
|
@logger.debug("monitoring client keepalives")
|
621
|
-
@timers[:
|
621
|
+
@timers[:leader] << EM::PeriodicTimer.new(30) do
|
622
622
|
determine_stale_clients
|
623
623
|
end
|
624
624
|
end
|
@@ -657,52 +657,53 @@ module Sensu
|
|
657
657
|
# Set up the check result aggregation pruner, using periodic
|
658
658
|
# timer to run `prune_check_result_aggregations()` every 20
|
659
659
|
# seconds. The timer is stored in the timers hash under
|
660
|
-
# `:
|
660
|
+
# `:leader`.
|
661
661
|
def setup_check_result_aggregation_pruner
|
662
662
|
@logger.debug("pruning check result aggregations")
|
663
|
-
@timers[:
|
663
|
+
@timers[:leader] << EM::PeriodicTimer.new(20) do
|
664
664
|
prune_check_result_aggregations
|
665
665
|
end
|
666
666
|
end
|
667
667
|
|
668
|
-
# Set up the
|
668
|
+
# Set up the leader duties, tasks only performed by a single
|
669
669
|
# Sensu server at a time. The duties include publishing check
|
670
670
|
# requests, monitoring for stale clients, and pruning check
|
671
671
|
# result aggregations.
|
672
|
-
def
|
672
|
+
def leader_duties
|
673
673
|
setup_check_request_publisher
|
674
674
|
setup_client_monitor
|
675
675
|
setup_check_result_aggregation_pruner
|
676
676
|
end
|
677
677
|
|
678
|
-
# Request a
|
679
|
-
# current process is the
|
678
|
+
# Request a leader election, a process to determine if the
|
679
|
+
# current process is the leader Sensu server, with its
|
680
680
|
# own/unique duties. A Redis key/value is used as a central
|
681
681
|
# lock, using the "SETNX" Redis command to set the key/value if
|
682
682
|
# it does not exist, using a timestamp for the value. If the
|
683
683
|
# current process was able to create the key/value, it is the
|
684
|
-
#
|
684
|
+
# leader, and must do the duties of the leader. If the current
|
685
685
|
# process was not able to create the key/value, but the current
|
686
686
|
# timestamp value is equal to or over 30 seconds ago, the
|
687
687
|
# "GETSET" Redis command is used to set a new timestamp and
|
688
688
|
# fetch the previous value to compare them, to determine if it
|
689
689
|
# was set by the current process. If the current process is able
|
690
|
-
# to set the timestamp value, it becomes the
|
691
|
-
# has `@
|
692
|
-
def
|
693
|
-
@redis.setnx("lock:
|
690
|
+
# to set the timestamp value, it becomes the leader. The leader
|
691
|
+
# has `@is_leader` set to `true`.
|
692
|
+
def request_leader_election
|
693
|
+
@redis.setnx("lock:leader", Time.now.to_i) do |created|
|
694
694
|
if created
|
695
|
-
@
|
696
|
-
@logger.info("i am the
|
697
|
-
|
695
|
+
@is_leader = true
|
696
|
+
@logger.info("i am the leader")
|
697
|
+
leader_duties
|
698
698
|
else
|
699
|
-
@redis.get("lock:
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
@
|
705
|
-
|
699
|
+
@redis.get("lock:leader") do |current_timestamp|
|
700
|
+
lock_timestamp = (Time.now.to_f * 1000).to_i
|
701
|
+
if lock_timestamp - current_timestamp.to_i >= 30000
|
702
|
+
@redis.getset("lock:leader", lock_timestamp) do |previous_timestamp|
|
703
|
+
if previous_timestamp == current_timestamp
|
704
|
+
@is_leader = true
|
705
|
+
@logger.info("i am now the leader")
|
706
|
+
leader_duties
|
706
707
|
end
|
707
708
|
end
|
708
709
|
end
|
@@ -711,41 +712,42 @@ module Sensu
|
|
711
712
|
end
|
712
713
|
end
|
713
714
|
|
714
|
-
# Set up the
|
715
|
-
# `
|
716
|
-
# used to update the
|
717
|
-
# process is the
|
715
|
+
# Set up the leader monitor. A one-time timer is used to run
|
716
|
+
# `request_leader_exection()` in 2 seconds. A periodic timer is
|
717
|
+
# used to update the leader lock timestamp if the current
|
718
|
+
# process is the leader, or to run `request_leader_election(),
|
718
719
|
# every 10 seconds. The timers are stored in the timers hash
|
719
720
|
# under `:run`.
|
720
|
-
def
|
721
|
+
def setup_leader_monitor
|
721
722
|
@timers[:run] << EM::Timer.new(2) do
|
722
|
-
|
723
|
+
request_leader_election
|
723
724
|
end
|
724
725
|
@timers[:run] << EM::PeriodicTimer.new(10) do
|
725
|
-
if @
|
726
|
-
|
727
|
-
|
726
|
+
if @is_leader
|
727
|
+
lock_timestamp = (Time.now.to_f * 1000).to_i
|
728
|
+
@redis.set("lock:leader", lock_timestamp) do
|
729
|
+
@logger.debug("updated leader lock timestamp")
|
728
730
|
end
|
729
731
|
else
|
730
|
-
|
732
|
+
request_leader_election
|
731
733
|
end
|
732
734
|
end
|
733
735
|
end
|
734
736
|
|
735
|
-
# Resign as
|
736
|
-
#
|
737
|
+
# Resign as leader, if the current process is the Sensu server
|
738
|
+
# leader. This method cancels and clears the leader timers,
|
737
739
|
# those with references stored in the timers hash under
|
738
|
-
# `:
|
739
|
-
def
|
740
|
-
if @
|
741
|
-
@logger.warn("resigning as
|
742
|
-
@timers[:
|
740
|
+
# `:leader`, and `@is_leader`is set to `false`.
|
741
|
+
def resign_as_leader
|
742
|
+
if @is_leader
|
743
|
+
@logger.warn("resigning as leader")
|
744
|
+
@timers[:leader].each do |timer|
|
743
745
|
timer.cancel
|
744
746
|
end
|
745
|
-
@timers[:
|
746
|
-
@
|
747
|
+
@timers[:leader].clear
|
748
|
+
@is_leader = false
|
747
749
|
else
|
748
|
-
@logger.debug("not currently
|
750
|
+
@logger.debug("not currently leader")
|
749
751
|
end
|
750
752
|
end
|
751
753
|
|
@@ -777,13 +779,13 @@ module Sensu
|
|
777
779
|
end
|
778
780
|
|
779
781
|
# Bootstrap the Sensu server process, setting up the keepalive
|
780
|
-
# and check result consumers, and attemping to become the
|
782
|
+
# and check result consumers, and attemping to become the leader
|
781
783
|
# to carry out its duties. This method sets the process/daemon
|
782
784
|
# `@state` to `:running`.
|
783
785
|
def bootstrap
|
784
786
|
setup_keepalives
|
785
787
|
setup_results
|
786
|
-
|
788
|
+
setup_leader_monitor
|
787
789
|
@state = :running
|
788
790
|
end
|
789
791
|
|
@@ -800,7 +802,7 @@ module Sensu
|
|
800
802
|
# set to `:pausing`, to indicate that it's in progress. All run
|
801
803
|
# timers are cancelled, and the references are cleared. The
|
802
804
|
# Sensu server will unsubscribe from all transport
|
803
|
-
# subscriptions, resign as
|
805
|
+
# subscriptions, resign as leader (if currently the leader),
|
804
806
|
# then set the process/daemon `@state` to `:paused`.
|
805
807
|
def pause
|
806
808
|
unless @state == :pausing || @state == :paused
|
@@ -810,7 +812,7 @@ module Sensu
|
|
810
812
|
end
|
811
813
|
@timers[:run].clear
|
812
814
|
unsubscribe
|
813
|
-
|
815
|
+
resign_as_leader
|
814
816
|
@state = :paused
|
815
817
|
end
|
816
818
|
end
|
data/sensu.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_dependency "eventmachine", "1.0.3"
|
20
20
|
s.add_dependency "sensu-em", "2.4.1"
|
21
21
|
s.add_dependency "sensu-logger", "1.0.0"
|
22
|
-
s.add_dependency "sensu-settings", "1.
|
22
|
+
s.add_dependency "sensu-settings", "1.7.0"
|
23
23
|
s.add_dependency "sensu-extension", "1.1.2"
|
24
24
|
s.add_dependency "sensu-extensions", "1.2.0"
|
25
25
|
s.add_dependency "sensu-transport", "2.4.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.0.beta
|
4
|
+
version: 0.18.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Porter
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-04-
|
12
|
+
date: 2015-04-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -87,14 +87,14 @@ dependencies:
|
|
87
87
|
requirements:
|
88
88
|
- - '='
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 1.
|
90
|
+
version: 1.7.0
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - '='
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 1.
|
97
|
+
version: 1.7.0
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: sensu-extension
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|