flapjack 0.6.53 → 0.6.54

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/bin/flapjack +103 -19
  2. data/bin/flapjack-nagios-receiver +166 -52
  3. data/bin/flapper +107 -18
  4. data/etc/flapjack_config.yaml.example +16 -0
  5. data/features/events.feature +63 -0
  6. data/features/steps/events_steps.rb +5 -5
  7. data/features/steps/notifications_steps.rb +8 -6
  8. data/features/steps/time_travel_steps.rb +4 -4
  9. data/features/support/env.rb +1 -2
  10. data/flapjack.gemspec +1 -1
  11. data/lib/flapjack/configuration.rb +11 -13
  12. data/lib/flapjack/coordinator.rb +100 -220
  13. data/lib/flapjack/data/entity_check.rb +2 -2
  14. data/lib/flapjack/data/event.rb +3 -3
  15. data/lib/flapjack/executive.rb +30 -40
  16. data/lib/flapjack/filters/delays.rb +1 -1
  17. data/lib/flapjack/gateways/api.rb +6 -23
  18. data/lib/flapjack/gateways/email.rb +4 -10
  19. data/lib/flapjack/gateways/email/alert.html.haml +0 -5
  20. data/lib/flapjack/gateways/email/alert.text.erb +0 -1
  21. data/lib/flapjack/gateways/jabber.rb +80 -67
  22. data/lib/flapjack/gateways/oobetet.rb +29 -25
  23. data/lib/flapjack/gateways/pagerduty.rb +26 -45
  24. data/lib/flapjack/gateways/sms_messagenet.rb +10 -17
  25. data/lib/flapjack/gateways/web.rb +7 -21
  26. data/lib/flapjack/gateways/web/views/_css.haml +3 -0
  27. data/lib/flapjack/gateways/web/views/check.haml +1 -1
  28. data/lib/flapjack/logger.rb +57 -0
  29. data/lib/flapjack/patches.rb +0 -10
  30. data/lib/flapjack/pikelet.rb +214 -30
  31. data/lib/flapjack/redis_pool.rb +2 -17
  32. data/lib/flapjack/version.rb +1 -1
  33. data/spec/lib/flapjack/coordinator_spec.rb +116 -136
  34. data/spec/lib/flapjack/data/entity_check_spec.rb +3 -3
  35. data/spec/lib/flapjack/executive_spec.rb +33 -34
  36. data/spec/lib/flapjack/gateways/api_spec.rb +4 -2
  37. data/spec/lib/flapjack/gateways/jabber_spec.rb +39 -36
  38. data/spec/lib/flapjack/gateways/oobetet_spec.rb +14 -24
  39. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +43 -45
  40. data/spec/lib/flapjack/gateways/web_spec.rb +42 -35
  41. data/spec/lib/flapjack/logger_spec.rb +32 -0
  42. data/spec/lib/flapjack/pikelet_spec.rb +124 -15
  43. data/spec/lib/flapjack/redis_pool_spec.rb +1 -3
  44. data/spec/spec_helper.rb +34 -1
  45. data/tasks/events.rake +1 -0
  46. data/tmp/create_event_ok.rb +31 -0
  47. data/tmp/create_event_unknown.rb +31 -0
  48. data/tmp/create_events_ok.rb +1 -1
  49. metadata +10 -11
  50. data/bin/flapjack-nagios-receiver-control +0 -15
  51. data/bin/flapper-control +0 -15
  52. data/lib/flapjack/daemonizing.rb +0 -186
  53. data/lib/flapjack/gateways/base.rb +0 -38
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
- require 'ostruct'
5
-
6
3
  # add lib to the default include path
7
4
  unless $:.include?(File.dirname(__FILE__) + '/../lib/')
8
5
  $: << File.dirname(__FILE__) + '/../lib'
9
6
  end
10
7
 
8
+ require 'dante'
9
+ require 'optparse'
10
+ require 'ostruct'
11
+
11
12
  require 'flapjack/configuration'
12
13
 
13
14
  options = OpenStruct.new
@@ -15,7 +16,16 @@ options.config = File.join('etc', 'flapjack_config.yaml')
15
16
  options.daemonize = nil
16
17
 
17
18
  OptionParser.new do |opts|
18
- opts.banner = "Usage: flapjack [options]"
19
+ opts.banner = "Usage: flapjack COMMAND [OPTIONS]"
20
+
21
+ opts.separator ""
22
+ opts.separator "Commands"
23
+ opts.separator " start #{" " * 25} start flapjack"
24
+ opts.separator " stop #{" " * 26} stop flapjack"
25
+ opts.separator " restart #{" " * 23} (re)start flapjack"
26
+ opts.separator " reload #{" " * 24} reload flapjack configuration"
27
+ opts.separator ""
28
+ opts.separator "Options"
19
29
 
20
30
  opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
21
31
  options.config = c
@@ -29,6 +39,10 @@ OptionParser.new do |opts|
29
39
  options.pidfile = p
30
40
  end
31
41
 
42
+ opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
43
+ options.log_path = l
44
+ end
45
+
32
46
  end.parse!(ARGV)
33
47
 
34
48
  FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
@@ -42,25 +56,95 @@ if config_env.nil? || config_env.empty?
42
56
  exit(false)
43
57
  end
44
58
 
45
- if options.pidfile.nil?
46
- pid_file = (config_env['pid_file'] || 'tmp/pids/flapjack.pid')
47
- else
48
- pid_file = options.pidfile
49
- end
59
+ pidfile = options.pidfile.nil? ?
60
+ (config_env['pid_file'] || 'tmp/pids/flapjack.pid') :
61
+ options.pidfile
62
+
63
+ logfile = options.logfile.nil? ?
64
+ (config_env['log_file'] || 'log/flapjack.log') :
65
+ options.logfile
50
66
 
51
- # TODO Flapjack falls over when Redis restarted -- trap errors and attempt reconnect
67
+ daemonize = options.daemonize.nil? ?
68
+ !!config_env['daemonize'] :
69
+ options.daemonize
52
70
 
53
71
  require 'flapjack/coordinator'
54
72
 
55
- coordinator = Flapjack::Coordinator.new(config)
56
- coordinator.log_file = (config_env['log_file'] || 'log/flapjack.log')
57
- coordinator.pid_file = pid_file
73
+ flapjack_coord = Proc.new {
74
+ coordinator = Flapjack::Coordinator.new(config)
75
+ coordinator.start(:signals => true)
76
+ }
77
+
78
+ case ARGV[0]
79
+ when "start"
80
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
81
+ :log_path => logfile)
82
+
83
+ if runner.daemon_running?
84
+ puts "Flapjack is already running."
85
+ else
86
+ print "Flapjack starting..."
87
+ runner.execute(:daemonize => daemonize) {
88
+ flapjack_coord.call
89
+ }
90
+ puts " done."
91
+ end
92
+
93
+ when "stop"
94
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
95
+ :log_path => logfile)
96
+
97
+ if runner.daemon_running?
98
+ print "Flapjack stopping..."
99
+ runner.execute(:kill => true)
100
+ puts " done."
101
+ else
102
+ puts "Flapjack is not running."
103
+ end
104
+
105
+ when "restart"
106
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile,
107
+ :log_path => logfile)
108
+
109
+ print "Flapjack restarting..."
110
+ runner.execute(:daemonize => true, :restart => true) {
111
+ sleep 1 # get connection errors without this... -- might move this to
112
+ # be default behaviour when starting jabber gateway
113
+ flapjack_coord.call
114
+ }
115
+ puts " done."
116
+
117
+ when "reload"
118
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile, :log_path => logfile)
119
+
120
+ if runner.daemon_running?
121
+ print "Reloading Flapjack configuration..."
122
+ begin
123
+ pid = IO.read(pidfile).chomp.to_i
124
+ Process.kill('HUP', pid)
125
+ puts " sent HUP to pid #{pid}."
126
+ rescue => e
127
+ puts " couldn't send HUP to pid '#{pid}'."
128
+ end
129
+ else
130
+ puts "Flapjack is not running daemonized."
131
+ end
132
+
133
+ when "status"
134
+ runner = Dante::Runner.new('flapjack', :pid_path => pidfile, :log_path => logfile)
135
+
136
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
137
+ if runner.daemon_running?
138
+ puts "Flapjack is running: #{uptime}"
139
+ else
140
+ puts "Flapjack is not runninng"
141
+ end
58
142
 
59
- if options.daemonize.nil?
60
- daemonize = !!config_env['daemonize']
61
143
  else
62
- daemonize = options.daemonize
63
- end
144
+ if ARGV.nil? || ARGV.empty?
145
+ puts "No command provided"
146
+ else
147
+ puts "Unknown command provided: '#{ARGV[0]}'"
148
+ end
64
149
 
65
- puts "Daemonising ... " if daemonize
66
- coordinator.start(:daemonize => daemonize, :signals => true)
150
+ end
@@ -1,62 +1,27 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ unless $:.include?(File.dirname(__FILE__) + '/../lib/')
4
+ $: << File.dirname(__FILE__) + '/../lib'
5
+ end
6
+
3
7
  require 'optparse'
4
8
  require 'ostruct'
5
9
  require 'redis'
6
10
  require 'yajl/json_gem'
7
-
8
- # add lib to the default include path
9
- unless $:.include?(File.dirname(__FILE__) + '/../lib/')
10
- $: << File.dirname(__FILE__) + '/../lib'
11
- end
11
+ require 'dante'
12
12
 
13
13
  require 'flapjack/configuration'
14
14
 
15
- options = OpenStruct.new
16
- options.config = File.join('etc', 'flapjack_config.yaml')
17
- options.daemonize = nil
18
-
19
- OptionParser.new do |opts|
20
- opts.banner = "Usage: flapjack-nagios-receiver [options]"
21
-
22
- opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
23
- options.config = c
24
- end
25
-
26
- opts.on("-f", "--fifo FIFO", String, "Path to the nagios perfdata named pipe") do |f|
27
- options.fifo = f
28
- end
29
-
30
- end.parse!(ARGV)
31
-
32
- FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
33
-
34
- config = Flapjack::Configuration.new
35
- config.load(options.config)
36
- @config_env = config.all
37
- @redis_options = config.for_redis
38
-
39
- if @config_env.nil? || @config_env.empty?
40
- puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
41
- exit(false)
15
+ def pike(message)
16
+ puts "piking out: #{message}"
17
+ exit 1
42
18
  end
43
19
 
44
- if !options.fifo
45
- puts "You must specify a path to the nagios perfdata named pipe using the --fifo option"
46
- exit(false)
47
- end
48
-
49
- @fifo = File.new(options.fifo)
50
-
51
- # nagios.cfg contains the following templates for host and service data (modified from the default
52
- # to include hoststate / servicestate, and a fake service 'HOST' for hostperfdata, so that the
53
- # fields match up
54
- # host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
55
- # service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
56
-
57
- def process_input(redis)
20
+ def process_input(opts)
21
+ redis = opts[:redis]
22
+ fifo = File.new(opts[:fifo])
58
23
  begin
59
- while line = @fifo.gets
24
+ while line = fifo.gets
60
25
  skip unless line
61
26
  split_line = line.split("\t")
62
27
 
@@ -93,15 +58,164 @@ def process_input(redis)
93
58
  end
94
59
  end
95
60
 
96
- def main
97
- redis = Redis.new(@redis_options)
98
-
61
+ def main(opts)
62
+ fifo = opts[:fifo]
63
+ redis = Redis.new(opts[:redis_options])
99
64
  while true
100
- process_input(redis)
65
+ process_input(:redis => redis, :fifo => fifo)
101
66
  puts "Whoops, restarting main loop in 10 seconds"
102
67
  sleep 10
103
68
  end
104
69
  end
105
70
 
106
- main
71
+ options = OpenStruct.new
72
+ options.config = nil
73
+ options.daemonize = nil
74
+
75
+ exe = File.basename(__FILE__)
76
+
77
+ OptionParser.new do |opts|
78
+ opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
79
+
80
+ opts.separator ""
81
+ opts.separator "Commands"
82
+ opts.separator " start #{" " * 25} start #{exe}"
83
+ opts.separator " stop #{" " * 26} stop #{exe}"
84
+ opts.separator " restart #{" " * 23} (re)start #{exe}"
85
+ opts.separator ""
86
+ opts.separator "Options"
87
+
88
+ opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
89
+ options.config = c
90
+ end
91
+
92
+ opts.on("-f", "--fifo FIFO", String, "Path to the nagios perfdata named pipe") do |f|
93
+ options.fifo = f
94
+ end
95
+
96
+ opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
97
+ options.daemonize = d
98
+ end
99
+
100
+ opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |p|
101
+ options.pidfile = p
102
+ end
103
+
104
+ opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
105
+ options.log_path = l
106
+ end
107
+
108
+ end.parse!(ARGV)
109
+
110
+ FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
111
+
112
+ #runner = Dante::Runner.new('flapjack-nagios-receiver',
113
+ # :pid_path => '/var/run/flapjack/flapjack-nagios-receiver.pid',
114
+ # :log_path => '/var/log/flapjack/flapjack-nagios-receiver.log')
115
+
116
+
117
+ if options.config
118
+ config_file = options.config
119
+ pike "specified config file cannot be read" unless File.readable?(config_file)
120
+ else
121
+ [ 'etc/flapjack_config.yaml',
122
+ File.dirname(__FILE__) + 'etc/flapjack_config.yaml',
123
+ '/etc/flapjack/flapjack_config.yaml' ].each do |candidate|
124
+ if File.readable?(candidate)
125
+ config_file = candidate
126
+ break
127
+ else
128
+ puts "not found and/or not readable: #{candidate}"
129
+ end
130
+ end
131
+ pike "no config file specified and none found in default locations" unless config_file
132
+ end
133
+
134
+ config = Flapjack::Configuration.new
135
+ config.load(config_file)
136
+ config_env = config.all
137
+ redis_options = config.for_redis
138
+
139
+ if config_env.nil? || config_env.empty?
140
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
141
+ exit(false)
142
+ end
143
+
144
+ config_nr = config_env['nagios-receiver'] || {}
145
+
146
+ pidfile = options.pidfile.nil? ?
147
+ (config_nr['pid_file'] || "/var/run/flapjack/#{exe}.pid") :
148
+ options.pidfile
149
+
150
+ logfile = options.logfile.nil? ?
151
+ (config_nr['log_file'] || "/var/log/flapjack/#{exe}.log") :
152
+ options.logfile
153
+
154
+ fifo = options.fifo.nil? ?
155
+ (config_nr['fifo'] || '/var/cache/nagios3/event_stream.fifo') :
156
+ options.fifo
157
+
158
+ daemonize = options.daemonize.nil? ?
159
+ !!config_nr['daemonize'] :
160
+ options.daemonize
161
+
162
+
163
+ # nagios.cfg contains the following templates for host and service data (modified from the default
164
+ # to include hoststate / servicestate, and a fake service 'HOST' for hostperfdata, so that the
165
+ # fields match up
166
+ # host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
167
+ # service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
168
+
169
+
170
+ runner = Dante::Runner.new(exe, :pid_path => pidfile, :log_path => logfile)
171
+ case ARGV[0]
172
+ when "start", "restart"
173
+ pike "You must specify a path to the nagios perfdata named pipe using the --fifo option" unless fifo
174
+ end
175
+
176
+ case ARGV[0]
177
+ when "start"
178
+ if runner.daemon_running?
179
+ puts "#{exe} is already running."
180
+ else
181
+ print "#{exe} starting..."
182
+ runner.execute(:daemonize => daemonize) {
183
+ main(:redis_options => redis_options, :fifo => fifo)
184
+ }
185
+ puts " done."
186
+ end
187
+
188
+ when "stop"
189
+ if runner.daemon_running?
190
+ print "#{exe} stopping..."
191
+ runner.execute(:kill => true)
192
+ puts " done."
193
+ else
194
+ puts "#{exe} is not running."
195
+ end
196
+
197
+ when "restart"
198
+ print "#{exe} restarting..."
199
+ runner.execute(:daemonize => true, :restart => true) {
200
+ main(:redis_options => redis_options, :fifo => fifo)
201
+ }
202
+ puts " done."
203
+
204
+ when "status"
205
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
206
+ if runner.daemon_running?
207
+ puts "#{exe} is running: #{uptime}"
208
+ else
209
+ puts "#{exe} is not runninng"
210
+ end
211
+
212
+ else
213
+ if ARGV.nil? || ARGV.empty?
214
+ puts "No command provided"
215
+ else
216
+ puts "Unknown command provided: '#{ARGV[0]}'"
217
+ end
218
+
219
+ end
220
+
107
221
 
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'optparse'
4
+ require 'ostruct'
3
5
  require 'eventmachine'
4
6
  require 'socket'
7
+ require 'dante'
5
8
 
6
9
  module Flapper
7
-
8
10
  def receive_data data
9
11
  send_data ">>>you sent: #{data}"
10
12
  close_connection if data =~ /quit/i
11
13
  end
12
-
13
14
  end
14
15
 
15
16
  def local_ip
@@ -24,25 +25,113 @@ ensure
24
25
  Socket.do_not_reverse_lookup = orig
25
26
  end
26
27
 
27
- start_every = 120
28
- stop_after = 60
29
- bind_ip = local_ip
30
- bind_port = 12345
31
- EM.run {
32
-
33
- puts "#{Time.now}: starting server"
34
- server_init = EM.start_server bind_ip, bind_port, Flapper
35
- EM.add_timer(stop_after) do
36
- puts "#{Time.now}: stopping server"
37
- EM.stop_server(server_init)
38
- end
28
+ def main
29
+ start_every = 120
30
+ stop_after = 60
31
+ bind_ip = local_ip
32
+ bind_port = 12345
33
+ EM.run {
39
34
 
40
- EM.add_periodic_timer(start_every) do
41
35
  puts "#{Time.now}: starting server"
42
- server = EM.start_server bind_ip, bind_port, Flapper
36
+ server_init = EM.start_server bind_ip, bind_port, Flapper
43
37
  EM.add_timer(stop_after) do
44
38
  puts "#{Time.now}: stopping server"
45
- EM.stop_server(server)
39
+ EM.stop_server(server_init)
46
40
  end
41
+
42
+ EM.add_periodic_timer(start_every) do
43
+ puts "#{Time.now}: starting server"
44
+ server = EM.start_server bind_ip, bind_port, Flapper
45
+ EM.add_timer(stop_after) do
46
+ puts "#{Time.now}: stopping server"
47
+ EM.stop_server(server)
48
+ end
49
+ end
50
+ }
51
+ end
52
+
53
+ options = OpenStruct.new
54
+ options.daemonize = nil
55
+
56
+ exe = File.basename(__FILE__)
57
+
58
+ OptionParser.new do |opts|
59
+ opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
60
+
61
+ opts.separator ""
62
+ opts.separator "Commands"
63
+ opts.separator " start #{" " * 25} start #{exe}"
64
+ opts.separator " stop #{" " * 26} stop #{exe}"
65
+ opts.separator " restart #{" " * 23} (re)start #{exe}"
66
+ opts.separator ""
67
+ opts.separator "Options"
68
+
69
+ opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
70
+ options.daemonize = d
71
+ end
72
+
73
+ opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |p|
74
+ options.pidfile = p
75
+ end
76
+
77
+ opts.on("-l", "--logfile [PATH]", String, "PATH to the logfile to write to") do |l|
78
+ options.log_path = l
47
79
  end
48
- }
80
+ end.parse!(ARGV)
81
+
82
+ pidfile = options.pidfile.nil? ?
83
+ "/var/run/flapjack/#{exe}.pid" :
84
+ options.pidfile
85
+
86
+ logfile = options.logfile.nil? ?
87
+ "/var/log/flapjack/#{exe}.log" :
88
+ options.logfile
89
+
90
+ daemonize = options.daemonize.nil? ? true : options.daemonize
91
+
92
+ runner = Dante::Runner.new(exe, :pid_path => pidfile, :log_path => logfile)
93
+
94
+ case ARGV[0]
95
+ when "start"
96
+ if runner.daemon_running?
97
+ puts "#{exe} is already running."
98
+ else
99
+ print "#{exe} starting..."
100
+ runner.execute(:daemonize => daemonize) {
101
+ main
102
+ }
103
+ puts " done."
104
+ end
105
+
106
+ when "stop"
107
+ if runner.daemon_running?
108
+ print "#{exe} stopping..."
109
+ runner.execute(:kill => true)
110
+ puts " done."
111
+ else
112
+ puts "#{exe} is not running."
113
+ end
114
+
115
+ when "restart"
116
+ print "#{exe} restarting..."
117
+ runner.execute(:daemonize => true, :restart => true) {
118
+ main
119
+ }
120
+ puts " done."
121
+
122
+ when "status"
123
+ uptime = (runner.daemon_running?) ? Time.now - File.stat(pidfile).ctime : 0
124
+ if runner.daemon_running?
125
+ puts "#{exe} is running: #{uptime}"
126
+ else
127
+ puts "#{exe} is not runninng"
128
+ end
129
+
130
+ else
131
+ if ARGV.nil? || ARGV.empty?
132
+ puts "No command provided"
133
+ else
134
+ puts "Unknown command provided: '#{ARGV[0]}'"
135
+ end
136
+
137
+ end