flapjack 1.0.0rc3 → 1.0.0rc5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.ruby-version +1 -0
- data/CHANGELOG.md +20 -0
- data/CONTRIBUTING.md +2 -2
- data/Gemfile +1 -1
- data/README.md +6 -16
- data/build.sh +13 -1
- data/etc/flapjack_config.yaml.example +98 -12
- data/features/cli.feature +8 -8
- data/features/cli_flapjack-nagios-receiver.feature +29 -37
- data/features/cli_flapper.feature +24 -12
- data/features/cli_simulate-failed-check.feature +2 -2
- data/features/notifications.feature +18 -1
- data/features/steps/cli_steps.rb +2 -2
- data/features/steps/notifications_steps.rb +71 -0
- data/features/support/env.rb +7 -6
- data/flapjack.gemspec +3 -1
- data/lib/flapjack/cli/flapper.rb +74 -25
- data/lib/flapjack/cli/import.rb +3 -4
- data/lib/flapjack/cli/maintenance.rb +182 -0
- data/lib/flapjack/cli/receiver.rb +110 -121
- data/lib/flapjack/cli/server.rb +30 -26
- data/lib/flapjack/cli/simulate.rb +2 -3
- data/lib/flapjack/data/contact.rb +1 -1
- data/lib/flapjack/data/entity.rb +425 -32
- data/lib/flapjack/data/entity_check.rb +212 -14
- data/lib/flapjack/data/event.rb +1 -1
- data/lib/flapjack/gateways/aws_sns.rb +134 -0
- data/lib/flapjack/gateways/aws_sns/alert.text.erb +5 -0
- data/lib/flapjack/gateways/aws_sns/rollup.text.erb +2 -0
- data/lib/flapjack/gateways/jabber.rb +2 -2
- data/lib/flapjack/gateways/jsonapi/check_methods.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/contact_methods.rb +1 -1
- data/lib/flapjack/gateways/jsonapi/entity_methods.rb +15 -1
- data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +4 -3
- data/lib/flapjack/gateways/jsonapi/report_methods.rb +1 -1
- data/lib/flapjack/gateways/web.rb +35 -16
- data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -16
- data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +1 -1
- data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -45
- data/lib/flapjack/gateways/web/public/js/modules/contact.js +2 -2
- data/lib/flapjack/gateways/web/public/js/modules/entity.js +2 -2
- data/lib/flapjack/gateways/web/public/js/modules/medium.js +4 -4
- data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -1
- data/lib/flapjack/gateways/web/views/check.html.erb +10 -10
- data/lib/flapjack/gateways/web/views/checks.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/contact.html.erb +5 -1
- data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +3 -4
- data/lib/flapjack/gateways/web/views/entities.html.erb +1 -1
- data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
- data/lib/flapjack/gateways/web/views/layout.erb +3 -3
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +5 -6
- data/lib/flapjack/notifier.rb +4 -1
- data/lib/flapjack/patches.rb +8 -2
- data/lib/flapjack/pikelet.rb +3 -1
- data/lib/flapjack/version.rb +1 -1
- data/libexec/httpbroker.go +1 -1
- data/spec/lib/flapjack/coordinator_spec.rb +3 -3
- data/spec/lib/flapjack/data/contact_spec.rb +2 -2
- data/spec/lib/flapjack/data/entity_check_spec.rb +805 -53
- data/spec/lib/flapjack/data/entity_spec.rb +661 -0
- data/spec/lib/flapjack/gateways/aws_sns_spec.rb +123 -0
- data/spec/lib/flapjack/gateways/jabber_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +2 -2
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +1 -1
- data/spec/lib/flapjack/gateways/web_spec.rb +11 -11
- data/spec/support/profile_all_formatter.rb +10 -10
- data/spec/support/uncolored_doc_formatter.rb +66 -4
- data/src/flapjack/event.go +1 -1
- data/tasks/benchmarks.rake +24 -20
- data/tasks/entities.rake +148 -0
- data/tmp/dummy_contacts.json +43 -0
- data/tmp/dummy_entities.json +37 -1
- metadata +43 -7
- data/tmp/test_entities.json +0 -1
data/lib/flapjack/cli/flapper.rb
CHANGED
@@ -23,14 +23,40 @@ module Flapjack
|
|
23
23
|
def initialize(global_options, options)
|
24
24
|
@global_options = global_options
|
25
25
|
@options = options
|
26
|
+
|
27
|
+
@config = Flapjack::Configuration.new
|
28
|
+
@config.load(global_options[:config])
|
29
|
+
@config_env = @config.all
|
30
|
+
|
31
|
+
if @config_env.nil? || @config_env.empty?
|
32
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
33
|
+
end
|
34
|
+
|
35
|
+
@pidfile = case
|
36
|
+
when !@options[:pidfile].nil?
|
37
|
+
@options[:pidfile]
|
38
|
+
when !@config_env['pid_dir'].nil?
|
39
|
+
@config_env['pid_dir'] + 'flapper.pid'
|
40
|
+
else
|
41
|
+
"/var/run/flapjack/flapper.pid"
|
42
|
+
end
|
43
|
+
|
44
|
+
@logfile = case
|
45
|
+
when !@options[:logfile].nil?
|
46
|
+
@options[:logfile]
|
47
|
+
when !@config_env['log_dir'].nil?
|
48
|
+
@config_env['log_dir'] + 'flapper.log'
|
49
|
+
else
|
50
|
+
"/var/run/flapjack/flapper.log"
|
51
|
+
end
|
26
52
|
end
|
27
53
|
|
28
54
|
def start
|
29
55
|
if runner.daemon_running?
|
30
56
|
puts "flapper is already running."
|
31
|
-
exit 1
|
32
57
|
else
|
33
58
|
print "flapper starting..."
|
59
|
+
print "\n" unless @options[:daemonize]
|
34
60
|
runner.execute(:daemonize => @options[:daemonize]) do
|
35
61
|
main(@options['bind-ip'], @options['bind-port'].to_i, @options[:frequency])
|
36
62
|
end
|
@@ -39,14 +65,15 @@ module Flapjack
|
|
39
65
|
end
|
40
66
|
|
41
67
|
def stop
|
68
|
+
pid = get_pid
|
42
69
|
if runner.daemon_running?
|
43
70
|
print "flapper stopping..."
|
44
71
|
runner.execute(:kill => true)
|
45
72
|
puts " done."
|
46
73
|
else
|
47
74
|
puts "flapper is not running."
|
48
|
-
exit 1
|
49
75
|
end
|
76
|
+
exit_now! unless wait_pid_gone(pid)
|
50
77
|
end
|
51
78
|
|
52
79
|
def restart
|
@@ -58,12 +85,12 @@ module Flapjack
|
|
58
85
|
end
|
59
86
|
|
60
87
|
def status
|
61
|
-
uptime = (runner.daemon_running?) ? (Time.now - File.stat(@options[:pidfile]).ctime) : 0
|
62
88
|
if runner.daemon_running?
|
63
|
-
|
89
|
+
pid = get_pid
|
90
|
+
uptime = Time.now - File.stat(@pidfile).ctime
|
91
|
+
puts "flapper is running: pid #{pid}, uptime #{uptime}"
|
64
92
|
else
|
65
|
-
|
66
|
-
exit 3
|
93
|
+
exit_now! "flapper is not running"
|
67
94
|
end
|
68
95
|
end
|
69
96
|
|
@@ -79,8 +106,8 @@ module Flapjack
|
|
79
106
|
def runner
|
80
107
|
return @runner if @runner
|
81
108
|
|
82
|
-
@runner = Dante::Runner.new('flapper', :pid_path => @
|
83
|
-
:log_path => @
|
109
|
+
@runner = Dante::Runner.new('flapper', :pid_path => @pidfile,
|
110
|
+
:log_path => @logfile)
|
84
111
|
@runner
|
85
112
|
end
|
86
113
|
|
@@ -109,12 +136,42 @@ module Flapjack
|
|
109
136
|
end
|
110
137
|
end
|
111
138
|
|
139
|
+
def process_exists(pid)
|
140
|
+
return unless pid
|
141
|
+
begin
|
142
|
+
Process.kill(0, pid)
|
143
|
+
return true
|
144
|
+
rescue Errno::ESRCH
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# wait until the specified pid no longer exists, or until a timeout is reached
|
150
|
+
def wait_pid_gone(pid, timeout = 30)
|
151
|
+
print "waiting for a max of #{timeout} seconds for process #{pid} to exit" if process_exists(pid)
|
152
|
+
started_at = Time.now.to_i
|
153
|
+
while process_exists(pid)
|
154
|
+
break unless (Time.now.to_i - started_at < timeout)
|
155
|
+
print '.'
|
156
|
+
sleep 1
|
157
|
+
end
|
158
|
+
puts ''
|
159
|
+
!process_exists(pid)
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_pid
|
163
|
+
IO.read(@pidfile).chomp.to_i
|
164
|
+
rescue StandardError
|
165
|
+
pid = nil
|
166
|
+
end
|
167
|
+
|
168
|
+
|
112
169
|
end
|
113
170
|
end
|
114
171
|
end
|
115
172
|
|
116
173
|
|
117
|
-
desc 'Artificial service that oscillates up and down'
|
174
|
+
desc 'Artificial service that oscillates up and down, for use in http://flapjack.io/docs/1.0/usage/oobetet'
|
118
175
|
command :flapper do |flapper|
|
119
176
|
|
120
177
|
flapper.desc 'start flapper'
|
@@ -123,11 +180,9 @@ command :flapper do |flapper|
|
|
123
180
|
start.switch [:d, 'daemonize'], :desc => 'Daemonize',
|
124
181
|
:default_value => true
|
125
182
|
|
126
|
-
start.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
127
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
183
|
+
start.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
128
184
|
|
129
|
-
start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
130
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
185
|
+
start.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
131
186
|
|
132
187
|
start.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to',
|
133
188
|
:default_value => Flapjack::CLI::Flapper.local_ip
|
@@ -147,11 +202,9 @@ command :flapper do |flapper|
|
|
147
202
|
flapper.desc 'stop flapper'
|
148
203
|
flapper.command :stop do |stop|
|
149
204
|
|
150
|
-
stop.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
151
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
205
|
+
stop.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
152
206
|
|
153
|
-
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
154
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
207
|
+
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
155
208
|
|
156
209
|
stop.action do |global_options, options, args|
|
157
210
|
cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
|
@@ -162,11 +215,9 @@ command :flapper do |flapper|
|
|
162
215
|
flapper.desc 'restart flapper'
|
163
216
|
flapper.command :restart do |restart|
|
164
217
|
|
165
|
-
restart.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
166
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
218
|
+
restart.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
167
219
|
|
168
|
-
restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
169
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
220
|
+
restart.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
170
221
|
|
171
222
|
restart.flag [:b, 'bind-ip'], :desc => 'ADDRESS (IPv4 or IPv6) for flapper to bind to',
|
172
223
|
:default_value => Flapjack::CLI::Flapper.local_ip
|
@@ -186,11 +237,9 @@ command :flapper do |flapper|
|
|
186
237
|
flapper.desc 'flapper status'
|
187
238
|
flapper.command :status do |status|
|
188
239
|
|
189
|
-
status.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
190
|
-
:default_value => "/var/run/flapjack/flapper.pid"
|
240
|
+
status.flag [:p, 'pidfile'], :desc => 'PATH of the pidfile to write to'
|
191
241
|
|
192
|
-
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
193
|
-
:default_value => "/var/log/flapjack/flapper.log"
|
242
|
+
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
194
243
|
|
195
244
|
status.action do |global_options, options, args|
|
196
245
|
cli_flapper = Flapjack::CLI::Flapper.new(global_options, options)
|
data/lib/flapjack/cli/import.rb
CHANGED
@@ -22,8 +22,7 @@ module Flapjack
|
|
22
22
|
@config_env = config.all
|
23
23
|
|
24
24
|
if @config_env.nil? || @config_env.empty?
|
25
|
-
|
26
|
-
exit 1
|
25
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
27
26
|
end
|
28
27
|
|
29
28
|
@redis_options = config.for_redis
|
@@ -65,14 +64,14 @@ module Flapjack
|
|
65
64
|
private
|
66
65
|
|
67
66
|
def redis
|
68
|
-
@redis ||= Redis.new(@redis_options)
|
67
|
+
@redis ||= Redis.new(@redis_options.merge(:driver => :ruby))
|
69
68
|
end
|
70
69
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
end
|
74
73
|
|
75
|
-
desc 'Bulk import data from an external source'
|
74
|
+
desc 'Bulk import data from an external source, reading from JSON formatted data files'
|
76
75
|
command :import do |import|
|
77
76
|
|
78
77
|
import.desc 'Import contacts'
|
@@ -0,0 +1,182 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'em-synchrony'
|
5
|
+
require 'redis'
|
6
|
+
require 'redis/connection/synchrony'
|
7
|
+
|
8
|
+
require 'flapjack/configuration'
|
9
|
+
require 'flapjack/data/event'
|
10
|
+
require 'flapjack/data/entity_check'
|
11
|
+
require 'terminal-table'
|
12
|
+
|
13
|
+
module Flapjack
|
14
|
+
module CLI
|
15
|
+
class Maintenance
|
16
|
+
|
17
|
+
def initialize(global_options, options)
|
18
|
+
@global_options = global_options
|
19
|
+
@options = options
|
20
|
+
|
21
|
+
config = Flapjack::Configuration.new
|
22
|
+
config.load(global_options[:config])
|
23
|
+
@config_env = config.all
|
24
|
+
|
25
|
+
if @config_env.nil? || @config_env.empty?
|
26
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
27
|
+
end
|
28
|
+
|
29
|
+
@redis_options = config.for_redis.merge(:driver => :ruby)
|
30
|
+
@options[:redis] = redis
|
31
|
+
end
|
32
|
+
|
33
|
+
def show
|
34
|
+
exit_now!("state must be one of 'ok', 'warning', 'critical', 'unknown'") unless @options[:state].nil? || %w(ok warning critical unknown).include?(@options[:state].downcase)
|
35
|
+
exit_now!("type must be one of 'scheduled', 'unscheduled'") unless %w(scheduled unscheduled).include?(@options[:type].downcase)
|
36
|
+
%w(started finishing).each do |time|
|
37
|
+
exit_now!("#{time.capitalize} time must start with 'more than', 'less than', 'on', 'before', 'after' or between") if @options[time] && !@options[time].downcase.start_with?('more than', 'less than', 'on', 'before', 'after', 'between')
|
38
|
+
end
|
39
|
+
@options[:finishing] ||= 'after now'
|
40
|
+
maintenances = Flapjack::Data::EntityCheck.find_maintenance(@options)
|
41
|
+
rows = []
|
42
|
+
maintenances.each do |m|
|
43
|
+
row = []
|
44
|
+
# Convert the unix timestamps of the start and end time back into readable times
|
45
|
+
m.each { |k, v| row.push(k.to_s.end_with?('time') ? Time.at(v) : v) }
|
46
|
+
rows.push(row)
|
47
|
+
end
|
48
|
+
puts Terminal::Table.new :headings => ['Entity', 'Check', 'State', 'Start', 'Duration (s)', 'Reason', 'End'], :rows => rows
|
49
|
+
maintenances
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete
|
53
|
+
maintenances = show
|
54
|
+
exit_now!('The following maintenances would be deleted. Run this command again with --apply true to remove them.') unless @options[:apply]
|
55
|
+
errors = Flapjack::Data::EntityCheck.delete_maintenance(@options)
|
56
|
+
(errors.each { |k, v| puts "#{k}: #{v}" }; exit_now!('Failed to delete maintenances')) if errors.length > 0
|
57
|
+
puts "The maintenances above have been deleted"
|
58
|
+
end
|
59
|
+
|
60
|
+
def create
|
61
|
+
exit_now!("Entity & check must be supplied to create a maintenance period") if @options[:entity].nil? || @options[:check].nil?
|
62
|
+
errors = Flapjack::Data::EntityCheck.create_maintenance(@options)
|
63
|
+
(errors.each { |k, v| puts "#{k}: #{v}" }; exit_now!('Failed to create maintenances')) if errors.length > 0
|
64
|
+
puts "The maintenances specified have been created"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def redis
|
70
|
+
@redis ||= Redis.new(@redis_options)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Show, create and delete maintenance windows'
|
78
|
+
command :maintenance do |maintenance|
|
79
|
+
|
80
|
+
|
81
|
+
maintenance.desc 'Show maintenance windows according to criteria (default: all ongoing maintenance)'
|
82
|
+
maintenance.command :show do |show|
|
83
|
+
|
84
|
+
show.flag [:e, 'entity'],
|
85
|
+
:desc => 'The entity for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'db*\' or \'[[:lower:]]\''
|
86
|
+
|
87
|
+
show.flag [:c, 'check'],
|
88
|
+
:desc => 'The check for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'http*\' or \'[[:lower:]]\''
|
89
|
+
|
90
|
+
show.flag [:r, 'reason'],
|
91
|
+
:desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\''
|
92
|
+
|
93
|
+
show.flag [:s, 'start', 'started', 'starting'],
|
94
|
+
:desc => 'The start time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between times and time"'
|
95
|
+
|
96
|
+
show.flag [:d, 'duration'],
|
97
|
+
:desc => 'The total duration of the maintenance window. This should be prefixed with "more than", "less than", "before, "after" or "equal to", or or of the form "between 3 and 4 hours". This should be an interval'
|
98
|
+
|
99
|
+
show.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'],
|
100
|
+
:desc => 'The finishing time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between time and time"'
|
101
|
+
|
102
|
+
show.flag [:st, 'state'],
|
103
|
+
:desc => 'The state that the check is currently in'
|
104
|
+
|
105
|
+
show.flag [:t, 'type'],
|
106
|
+
:desc => 'The type of maintenance scheduled',
|
107
|
+
:default_value => 'scheduled'
|
108
|
+
|
109
|
+
show.action do |global_options,options,args|
|
110
|
+
maintenance = Flapjack::CLI::Maintenance.new(global_options, options)
|
111
|
+
maintenance.show
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
maintenance.desc 'Delete maintenance windows according to criteria (default: all ongoing maintenance)'
|
116
|
+
maintenance.command :delete do |delete|
|
117
|
+
|
118
|
+
delete.flag [:a, 'apply'],
|
119
|
+
:desc => 'Whether this deletion should occur',
|
120
|
+
:default_value => false
|
121
|
+
|
122
|
+
delete.flag [:e, 'entity'],
|
123
|
+
:desc => 'The entity for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'db*\' or \'[[:lower:]]\''
|
124
|
+
|
125
|
+
delete.flag [:c, 'check'],
|
126
|
+
:desc => 'The check for the maintenance window to occur on. This can be a string, or a ruby regex of the form \'http*\' or \'[[:lower:]]\''
|
127
|
+
|
128
|
+
delete.flag [:r, 'reason'],
|
129
|
+
:desc => 'The reason for the maintenance window to occur. This can be a string, or a ruby regex of the form \'Downtime for *\' or \'[[:lower:]]\''
|
130
|
+
|
131
|
+
delete.flag [:s, 'start', 'started', 'starting'],
|
132
|
+
:desc => 'The start time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between times and time"'
|
133
|
+
|
134
|
+
delete.flag [:d, 'duration'],
|
135
|
+
:desc => 'The total duration of the maintenance window. This should be prefixed with "more than", "less than", "before, "after" or "equal to", or or of the form "between 3 and 4 hours". This should be an interval'
|
136
|
+
|
137
|
+
delete.flag [:f, 'finish', 'finished', 'finishing', 'remain', 'remained', 'remaining', 'end'],
|
138
|
+
:desc => 'The finishing time for the maintenance window. This should be prefixed with "more than", "less than", "on", "before", or "after", or of the form "between time and time"'
|
139
|
+
|
140
|
+
delete.flag [:st, 'state'],
|
141
|
+
:desc => 'The state that the check is currently in'
|
142
|
+
|
143
|
+
delete.flag [:t, 'type'],
|
144
|
+
:desc => 'The type of maintenance scheduled',
|
145
|
+
:default_value => 'scheduled'
|
146
|
+
|
147
|
+
delete.action do |global_options,options,args|
|
148
|
+
maintenance = Flapjack::CLI::Maintenance.new(global_options, options)
|
149
|
+
maintenance.delete
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
maintenance.desc 'Create a maintenance window'
|
154
|
+
maintenance.command :create do |create|
|
155
|
+
|
156
|
+
create.flag [:e, 'entity'],
|
157
|
+
:desc => 'The entity for the maintenance window to occur on. This can be a comma separated list',
|
158
|
+
:type => Array
|
159
|
+
|
160
|
+
create.flag [:c, 'check'],
|
161
|
+
:desc => 'The check for the maintenance window to occur on. This can be a comma separated list',
|
162
|
+
:type => Array
|
163
|
+
|
164
|
+
create.flag [:r, 'reason'],
|
165
|
+
:desc => 'The reason for the maintenance window to occur'
|
166
|
+
|
167
|
+
create.flag [:s, 'start', 'started', 'starting'],
|
168
|
+
:desc => 'The start time for the maintenance window'
|
169
|
+
|
170
|
+
create.flag [:d, 'duration'],
|
171
|
+
:desc => 'The total duration of the maintenance window. This should be an interval'
|
172
|
+
|
173
|
+
create.flag [:t, 'type'],
|
174
|
+
:desc => 'The type of maintenance scheduled ("scheduled")',
|
175
|
+
:default_value => 'scheduled'
|
176
|
+
|
177
|
+
create.action do |global_options,options,args|
|
178
|
+
maintenance = Flapjack::CLI::Maintenance.new(global_options, options)
|
179
|
+
maintenance.create
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -20,123 +20,87 @@ module Flapjack
|
|
20
20
|
@global_options = global_options
|
21
21
|
@options = options
|
22
22
|
|
23
|
-
config = Flapjack::Configuration.new
|
24
|
-
config.load(global_options[:config])
|
25
|
-
@config_env = config.all
|
23
|
+
@config = Flapjack::Configuration.new
|
24
|
+
@config.load(global_options[:config])
|
25
|
+
@config_env = @config.all
|
26
26
|
|
27
27
|
if @config_env.nil? || @config_env.empty?
|
28
|
-
|
29
|
-
exit 1
|
28
|
+
exit_now! "No config data for environment '#{FLAPJACK_ENV}' found in '#{global_options[:config]}'"
|
30
29
|
end
|
31
30
|
|
32
|
-
@
|
33
|
-
end
|
31
|
+
@config_runner = @config_env["#{@options[:type]}-receiver"] || {}
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#
|
41
|
-
# host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
|
42
|
-
#
|
43
|
-
# service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
|
44
|
-
#
|
45
|
-
|
46
|
-
def nagios_start
|
47
|
-
if runner('nagios').daemon_running?
|
48
|
-
puts "nagios-receiver is already running."
|
49
|
-
exit 1
|
33
|
+
@pidfile = case
|
34
|
+
when !@options[:pidfile].nil?
|
35
|
+
@options[:pidfile]
|
36
|
+
when !@config_env['pid_dir'].nil?
|
37
|
+
@config_env['pid_dir'] + "#{@options[:type]}-receiver.pid"
|
50
38
|
else
|
51
|
-
|
52
|
-
runner('nagios').execute(:daemonize => @options[:daemonize]) do
|
53
|
-
begin
|
54
|
-
main(:fifo => @options[:fifo], :nagios => true)
|
55
|
-
rescue Exception => e
|
56
|
-
p e.message
|
57
|
-
puts e.backtrace.join("\n")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
puts " done."
|
39
|
+
"/var/run/flapjack/#{@options[:type]}-receiver.pid"
|
61
40
|
end
|
62
|
-
end
|
63
41
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
42
|
+
@logfile = case
|
43
|
+
when !@options[:logfile].nil?
|
44
|
+
@options[:logfile]
|
45
|
+
when !@config_env['log_dir'].nil?
|
46
|
+
@config_env['log_dir'] + "#{@options[:type]}-receiver.log"
|
69
47
|
else
|
70
|
-
|
71
|
-
exit 1
|
48
|
+
"/var/run/flapjack/#{@options[:type]}-receiver.log"
|
72
49
|
end
|
73
|
-
end
|
74
50
|
|
75
|
-
|
76
|
-
print "nagios-receiver restarting..."
|
77
|
-
runner('nagios').execute(:daemonize => true, :restart => true) do
|
78
|
-
main(:fifo => @options[:fifo], :nagios => true)
|
79
|
-
end
|
80
|
-
puts " done."
|
51
|
+
@redis_options = @config.for_redis
|
81
52
|
end
|
82
53
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
"/var/run/flapjack/nagios-receiver.pid"
|
87
|
-
uptime = (runner('nagios').daemon_running?) ? (Time.now - File.stat(pidfile).ctime) : 0
|
88
|
-
if runner('nagios').daemon_running?
|
89
|
-
puts "nagios-receiver is running: #{uptime}"
|
54
|
+
def start
|
55
|
+
if runner(@options[:type]).daemon_running?
|
56
|
+
puts "#{@options[:type]}-receiver is already running."
|
90
57
|
else
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
print "nsca-receiver starting..."
|
102
|
-
runner('nsca').execute(:daemonize => @options[:daemonize]) do
|
103
|
-
main(:fifo => @options[:fifo], :nsca => true)
|
58
|
+
print "#{@options[:type]}-receiver starting..."
|
59
|
+
print "\n" unless @options[:daemonize]
|
60
|
+
runner(@options[:type]).execute(:daemonize => @options[:daemonize]) do
|
61
|
+
begin
|
62
|
+
main(:fifo => @options[:fifo], :type => @options[:type])
|
63
|
+
rescue Exception => e
|
64
|
+
p e.message
|
65
|
+
puts e.backtrace.join("\n")
|
66
|
+
end
|
104
67
|
end
|
105
68
|
puts " done."
|
106
69
|
end
|
107
70
|
end
|
108
71
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
72
|
+
def stop
|
73
|
+
pid = get_pid
|
74
|
+
if runner(@options[:type]).daemon_running?
|
75
|
+
print "#{@options[:type]}-receiver stopping..."
|
76
|
+
runner(@options[:type]).execute(:kill => true)
|
113
77
|
puts " done."
|
114
78
|
else
|
115
|
-
puts "
|
116
|
-
exit 1
|
79
|
+
puts "#{@options[:type]}-receiver is not running."
|
117
80
|
end
|
81
|
+
exit_now! unless wait_pid_gone(pid)
|
118
82
|
end
|
119
83
|
|
120
|
-
def
|
121
|
-
print "
|
122
|
-
runner(
|
123
|
-
|
84
|
+
def restart
|
85
|
+
print "#{@options[:type]}-receiver restarting..."
|
86
|
+
runner(@options[:type]).execute(:daemonize => true, :restart => true) do
|
87
|
+
begin
|
88
|
+
main(:fifo => @options[:fifo], :type => @options[:type])
|
89
|
+
rescue Exception => e
|
90
|
+
p e.message
|
91
|
+
puts e.backtrace.join("\n")
|
92
|
+
end
|
124
93
|
end
|
125
94
|
puts " done."
|
126
95
|
end
|
127
96
|
|
128
|
-
def
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
"
|
133
|
-
|
134
|
-
uptime = (runner('nsca').daemon_running?) ? (Time.now - File.stat(pidfile).ctime) : 0
|
135
|
-
if runner('nsca').daemon_running?
|
136
|
-
puts "nsca-receiver is running: #{uptime}"
|
97
|
+
def status
|
98
|
+
if runner(@options[:type]).daemon_running?
|
99
|
+
pid = get_pid
|
100
|
+
uptime = Time.now - File.stat(@pidfile).ctime
|
101
|
+
puts "#{@options[:type]}-receiver is running: pid #{pid}, uptime #{uptime}"
|
137
102
|
else
|
138
|
-
|
139
|
-
exit 3
|
103
|
+
exit_now! "#{@options[:type]}-receiver is not running"
|
140
104
|
end
|
141
105
|
end
|
142
106
|
|
@@ -159,25 +123,16 @@ module Flapjack
|
|
159
123
|
def runner(type)
|
160
124
|
return @runner if @runner
|
161
125
|
|
162
|
-
|
163
|
-
|
164
|
-
pidfile = @options[:pidfile].nil? ?
|
165
|
-
(config_runner['pid_file'] || "/var/run/flapjack/#{type}-receiver.pid") :
|
166
|
-
@options[:pidfile]
|
167
|
-
|
168
|
-
logfile = @options[:logfile].nil? ?
|
169
|
-
(config_runner['log_file'] || "/var/log/flapjack/#{type}-receiver.log") :
|
170
|
-
@options[:logfile]
|
171
|
-
|
172
|
-
@runner = Dante::Runner.new("#{type}-receiver", :pid_path => pidfile,
|
173
|
-
:log_path => logfile)
|
126
|
+
@runner = Dante::Runner.new("#{@options[:type]}-receiver", :pid_path => @pidfile,
|
127
|
+
:log_path => @logfile)
|
174
128
|
@runner
|
175
129
|
end
|
176
130
|
|
177
131
|
def process_input(opts)
|
178
|
-
config_rec =
|
132
|
+
config_rec = case opts[:type]
|
133
|
+
when /nagios/
|
179
134
|
@config_env['nagios-receiver'] || {}
|
180
|
-
|
135
|
+
when /nsca/
|
181
136
|
@config_env['nsca-receiver'] || {}
|
182
137
|
else
|
183
138
|
raise "Unknown receiver type"
|
@@ -204,8 +159,8 @@ module Flapjack
|
|
204
159
|
check_latency, check_output, check_perfdata, check_long_output =
|
205
160
|
[nil] * 10
|
206
161
|
|
207
|
-
|
208
|
-
|
162
|
+
case opts[:type]
|
163
|
+
when /nagios/
|
209
164
|
object_type, timestamp, entity, check, state, check_time,
|
210
165
|
check_latency, check_output, check_perfdata, check_long_output = split_line
|
211
166
|
|
@@ -221,7 +176,7 @@ module Flapjack
|
|
221
176
|
next
|
222
177
|
end
|
223
178
|
|
224
|
-
|
179
|
+
when /nsca/
|
225
180
|
|
226
181
|
timestamp, passivecheck = split_line
|
227
182
|
split_passive = passivecheck.split(";")
|
@@ -269,12 +224,40 @@ module Flapjack
|
|
269
224
|
def main(opts)
|
270
225
|
fifo = opts[:fifo]
|
271
226
|
while true
|
272
|
-
process_input(:fifo => fifo, :
|
227
|
+
process_input(:fifo => fifo, :type => opts[:type])
|
273
228
|
puts "Whoops with the fifo, restarting main loop in 10 seconds"
|
274
229
|
sleep 10
|
275
230
|
end
|
276
231
|
end
|
277
232
|
|
233
|
+
def process_exists(pid)
|
234
|
+
return unless pid
|
235
|
+
begin
|
236
|
+
Process.kill(0, pid)
|
237
|
+
return true
|
238
|
+
rescue Errno::ESRCH
|
239
|
+
return false
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# wait until the specified pid no longer exists, or until a timeout is reached
|
244
|
+
def wait_pid_gone(pid, timeout = 30)
|
245
|
+
print "waiting for a max of #{timeout} seconds for process #{pid} to exit" if process_exists(pid)
|
246
|
+
started_at = Time.now.to_i
|
247
|
+
while process_exists(pid)
|
248
|
+
break unless (Time.now.to_i - started_at < timeout)
|
249
|
+
print '.'
|
250
|
+
sleep 1
|
251
|
+
end
|
252
|
+
puts ''
|
253
|
+
!process_exists(pid)
|
254
|
+
end
|
255
|
+
|
256
|
+
def get_pid
|
257
|
+
IO.read(@pidfile).chomp.to_i
|
258
|
+
rescue StandardError
|
259
|
+
pid = nil
|
260
|
+
end
|
278
261
|
|
279
262
|
class EventFeedHandler < Oj::ScHandler
|
280
263
|
|
@@ -319,8 +302,7 @@ module Flapjack
|
|
319
302
|
input = if opts[:from]
|
320
303
|
File.open(opts[:from]) # Explodes if file does not exist.
|
321
304
|
elsif $stdin.tty?
|
322
|
-
|
323
|
-
exit(1)
|
305
|
+
exit_now! "No file provided, and STDIN is from terminal! Exiting..."
|
324
306
|
else
|
325
307
|
$stdin
|
326
308
|
end
|
@@ -349,8 +331,7 @@ module Flapjack
|
|
349
331
|
|
350
332
|
def mirror_receive(opts)
|
351
333
|
unless opts[:follow] || opts[:all]
|
352
|
-
|
353
|
-
exit 1
|
334
|
+
exit_now! "one or both of --follow or --all is required"
|
354
335
|
end
|
355
336
|
|
356
337
|
source_redis = Redis.new(:url => opts[:source])
|
@@ -422,7 +403,7 @@ module Flapjack
|
|
422
403
|
end
|
423
404
|
end
|
424
405
|
|
425
|
-
desc 'Receive events from external systems and
|
406
|
+
desc 'Receive events from external systems and sends them to Flapjack'
|
426
407
|
arg_name 'receiver'
|
427
408
|
command :receiver do |receiver|
|
428
409
|
|
@@ -453,7 +434,7 @@ command :receiver do |receiver|
|
|
453
434
|
# host_perfdata_file_mode=p
|
454
435
|
# service_perfdata_file_mode=p
|
455
436
|
|
456
|
-
# Details on the wiki:
|
437
|
+
# Details on the wiki: http://flapjack.io/docs/1.0/usage/USING#configuring-nagios
|
457
438
|
# '
|
458
439
|
|
459
440
|
nagios.command :start do |start|
|
@@ -468,8 +449,9 @@ command :receiver do |receiver|
|
|
468
449
|
start.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
469
450
|
|
470
451
|
start.action do |global_options,options,args|
|
452
|
+
options.merge!(:type => 'nagios')
|
471
453
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
472
|
-
receiver.
|
454
|
+
receiver.start
|
473
455
|
end
|
474
456
|
end
|
475
457
|
|
@@ -480,8 +462,9 @@ command :receiver do |receiver|
|
|
480
462
|
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
481
463
|
|
482
464
|
stop.action do |global_options,options,args|
|
465
|
+
options.merge!(:type => 'nagios')
|
483
466
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
484
|
-
receiver.
|
467
|
+
receiver.stop
|
485
468
|
end
|
486
469
|
end
|
487
470
|
|
@@ -494,8 +477,9 @@ command :receiver do |receiver|
|
|
494
477
|
restart.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
495
478
|
|
496
479
|
restart.action do |global_options,options,args|
|
480
|
+
options.merge!(:type => 'nagios')
|
497
481
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
498
|
-
receiver.
|
482
|
+
receiver.restart
|
499
483
|
end
|
500
484
|
end
|
501
485
|
|
@@ -506,8 +490,9 @@ command :receiver do |receiver|
|
|
506
490
|
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
507
491
|
|
508
492
|
status.action do |global_options,options,args|
|
493
|
+
options.merge!(:type => 'nagios')
|
509
494
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
510
|
-
receiver.
|
495
|
+
receiver.status
|
511
496
|
end
|
512
497
|
end
|
513
498
|
|
@@ -535,7 +520,7 @@ command :receiver do |receiver|
|
|
535
520
|
# The Nsca daemon is optionally writing to a tempfile if the named pipe does
|
536
521
|
# not exist.
|
537
522
|
|
538
|
-
# Details on the wiki:
|
523
|
+
# Details on the wiki: http://flapjack.io/docs/1.0/usage/USING#XXX
|
539
524
|
# '
|
540
525
|
|
541
526
|
start.switch [:d, 'daemonize'], :desc => 'Daemonize',
|
@@ -548,8 +533,9 @@ command :receiver do |receiver|
|
|
548
533
|
start.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
549
534
|
|
550
535
|
start.action do |global_options,options,args|
|
536
|
+
options.merge!(:type => 'nsca')
|
551
537
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
552
|
-
receiver.
|
538
|
+
receiver.start
|
553
539
|
end
|
554
540
|
end
|
555
541
|
|
@@ -560,8 +546,9 @@ command :receiver do |receiver|
|
|
560
546
|
stop.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
561
547
|
|
562
548
|
stop.action do |global_options,options,args|
|
549
|
+
options.merge!(:type => 'nsca')
|
563
550
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
564
|
-
receiver.
|
551
|
+
receiver.stop
|
565
552
|
end
|
566
553
|
end
|
567
554
|
|
@@ -574,8 +561,9 @@ command :receiver do |receiver|
|
|
574
561
|
restart.flag [:f, 'fifo'], :desc => 'PATH of the nagios perfdata named pipe'
|
575
562
|
|
576
563
|
restart.action do |global_options,options,args|
|
564
|
+
options.merge!(:type => 'nsca')
|
577
565
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
578
|
-
receiver.
|
566
|
+
receiver.restart
|
579
567
|
end
|
580
568
|
end
|
581
569
|
|
@@ -586,8 +574,9 @@ command :receiver do |receiver|
|
|
586
574
|
status.flag [:l, 'logfile'], :desc => 'PATH of the logfile to write to'
|
587
575
|
|
588
576
|
status.action do |global_options,options,args|
|
577
|
+
options.merge!(:type => 'nsca')
|
589
578
|
receiver = Flapjack::CLI::Receiver.new(global_options, options)
|
590
|
-
receiver.
|
579
|
+
receiver.status
|
591
580
|
end
|
592
581
|
end
|
593
582
|
|