flapjack 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
data/LICENCE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Lindsay Holmwood
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,205 @@
1
+ Flapjack
2
+ ========
3
+
4
+ Flapjack is highly scalable and distributed monitoring system.
5
+
6
+ It understands the Nagios plugin format, and can easily be scaled
7
+ from 1 server to 1000.
8
+
9
+
10
+
11
+ Setup dependencies (Ubuntu Hardy)
12
+ ---------------------------------
13
+
14
+ Add the following lines to `/etc/apt/sources.list`
15
+
16
+ deb http://ppa.launchpad.net/ubuntu-ruby-backports/ubuntu hardy main
17
+ deb http://ppa.launchpad.net/auxesis/ppa/ubuntu hardy main
18
+
19
+ Add GPG keys for the repos:
20
+
21
+ sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 288BA53BCB7DA731
22
+
23
+ Update your package list:
24
+
25
+ sudo apt-get update
26
+
27
+ Install Ruby dependencies:
28
+
29
+ sudo apt-get install build-essential libsqlite3-dev
30
+
31
+ Install rubygems + beanstalkd:
32
+
33
+ sudo apt-get install rubygems beanstalkd
34
+
35
+ Set `ENABLED=1` in `/etc/default/beanstalkd`.
36
+
37
+ Start beanstalkd:
38
+
39
+ sudo /etc/init.d/beanstalkd start
40
+
41
+
42
+ Setup dependencies (everyone else)
43
+ ----------------------------------
44
+
45
+ Install the following software through your package manager or from source:
46
+
47
+ - beanstalkd (from http://xph.us/software/beanstalkd/)
48
+ - libevent (from http://monkey.org/~provos/libevent/)
49
+
50
+
51
+ Installation
52
+ ------------
53
+
54
+ Add GitHub's RubyGems server to your Gem sources:
55
+
56
+ sudo gem sources -a http://gems.github.com
57
+
58
+ Install the Flapjack gem:
59
+
60
+ sudo gem install auxesis-flapjack
61
+
62
+ Then run the magic configuration script to set up init scripts:
63
+
64
+ sudo install-flapjack-systemwide
65
+
66
+ The script will prompt you if it wants to do anything destructive.
67
+
68
+
69
+ Running
70
+ -------
71
+
72
+ Make sure beanstalkd is running.
73
+
74
+ You'll want to set up `/etc/flapjack/recipients.yaml` so notifications can be sent via
75
+ `flapjack-notifier`:
76
+
77
+ ---
78
+ - :name: Jane Doe
79
+ :email: "jane@doe.com"
80
+ :phone: "+61 444 222 111"
81
+ :pager: "61444222111"
82
+ :jid: "jane@doe.com"
83
+
84
+ You also need to set up `/etc/flapjack/flapjack-notifier.yaml`:
85
+
86
+ ---
87
+ :notifiers:
88
+ :mailer:
89
+ :from_address: notifications@my-domain.com
90
+ :xmpp:
91
+ :jid: notifications@my-domain.com
92
+ :password: foo
93
+ :database_uri: "sqlite3:///var/lib/flapjack/flapjack.db"
94
+
95
+ Start up a cluster of workers:
96
+
97
+ flapjack-worker-manager start
98
+
99
+ This will spin up 5 workers in the background. You can specify how many workers
100
+ to start:
101
+
102
+ flapjack-worker-manager start --workers=10
103
+
104
+ Each of the `flapjack-worker`s will output to syslog (check in /var/log/messages).
105
+
106
+ Start up the notifier:
107
+
108
+ flapjack-notifier-manager start --recipients /etc/flapjack/recipients.yaml
109
+
110
+ Currently there are email and XMPP notifiers.
111
+
112
+ You'll want to get a copy of (http://github.com/auxesis/flapjack-admin/)[flapjack-admin]
113
+ to set up some checks, then run its' populator to get them into Flapjack.
114
+
115
+ What things do
116
+ --------------
117
+
118
+ * `flapjack-worker` => executes checks, reports results
119
+ * `flapjack-worker-manager` => starts/stops a cluster of `flapjack-worker`
120
+ * `flapjack-notifier` => gets results, notifies people if necessary
121
+ * `flapjack-stats` => gets stats from beanstalkd tubes (useful for benchmarks + performance analysis)
122
+
123
+
124
+ init scripts
125
+ ------------
126
+
127
+ You can use the provided init scripts to start Flapjack on boot.
128
+
129
+ To start:
130
+
131
+ /etc/init.d/flapjack-workers start
132
+ /etc/init.d/flapjack-notifier start
133
+
134
+ To set Flapjack to start on boot (Ubuntu):
135
+
136
+ sudo update-rc.d flapjack-workers defaults
137
+ sudo update-rc.d flapjack-notifier defaults
138
+
139
+ Config for the init scripts can be found in `/etc/defaults`.
140
+
141
+
142
+
143
+ Developing
144
+ ----------
145
+
146
+ You can write your own notifiers and place them in `lib/flapjack/notifiers/`.
147
+
148
+ Your notifier just needs to implement the `notify` method, and take in a hash:
149
+
150
+ class Sms
151
+ def initialize(opts={})
152
+ # you may want to set from address here
153
+ end
154
+
155
+ def notify(opts={})
156
+ who = opts[:who]
157
+ result = opts[:result]
158
+ # sms to your hearts content
159
+ end
160
+ end
161
+
162
+
163
+ Testing
164
+ -------
165
+
166
+ Tests are in `spec/`.
167
+
168
+ To run tests:
169
+
170
+ $ rake spec
171
+
172
+
173
+ Architecture
174
+ ------------
175
+
176
+ -------------------
177
+ | web interface / |
178
+ | dsl / flat file |
179
+ -------------------
180
+ /
181
+ |
182
+ |
183
+ ------------- ------------
184
+ | populator |--- -----| notifier |
185
+ ------------- | | ------------
186
+ | |
187
+ --------------
188
+ | beanstalkd |
189
+ --------------
190
+ |
191
+ -----------------------------------
192
+ | | |
193
+ ---------- ---------- ----------
194
+ | worker | | worker | | worker |
195
+ ---------- ---------- ----------
196
+
197
+
198
+ - populator determines checks that need to occur, and puts checks onto `jobs` tube
199
+ - populator fetches jobs from a database
200
+ - populator can be swapped out to get checks from a dsl or flat files
201
+ - workers pop a check off the beanstalk, perform check, put result onto `results` tube,
202
+ re-add check to `jobs` tube with a delay.
203
+ - notifier pops results off `results` tube, notifies as necessary
204
+
205
+
data/Rakefile ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'fileutils'
5
+ require 'spec/rake/spectask'
6
+
7
+ # integration tests for cli utils
8
+ begin
9
+ require 'cucumber/rake/task'
10
+
11
+ Cucumber::Rake::Task.new do |task|
12
+ task.cucumber_opts = "--require features/"
13
+ end
14
+ rescue LoadError
15
+ end
16
+
17
+ Spec::Rake::SpecTask.new do |t|
18
+ t.spec_opts = ["--options", "spec/spec.opts"]
19
+ end
20
+
21
+
22
+ desc "freeze deps"
23
+ task :deps do
24
+
25
+ deps = {'beanstalk-client' => ">= 1.0.2",
26
+ 'log4r' => ">= 1.0.5",
27
+ 'xmpp4r-simple' => ">= 0.8.8",
28
+ 'mailfactory' => ">= 1.4.0"}
29
+
30
+ puts "\ninstalling dependencies. this will take a few minutes."
31
+
32
+ deps.each_pair do |dep, version|
33
+ puts "\ninstalling #{dep} (#{version})"
34
+ system("gem install #{dep} --version '#{version}' -i gems --no-rdoc --no-ri")
35
+ end
36
+
37
+ end
38
+
39
+ desc "generate list of files for gemspec"
40
+ task "gengemfiles" do
41
+ executables = `git ls-files bin/*`.split.map {|bin| bin.gsub(/^bin\//, '')}
42
+ files = `git ls-files`.split.delete_if {|file| file =~ /^(spec\/|\.gitignore)/}
43
+ puts
44
+ puts "Copy and paste into flapjack.gemspec:"
45
+ puts
46
+ puts " s.executables = #{executables.inspect}"
47
+ puts " s.files = #{files.inspect}"
48
+ puts
49
+ puts
50
+ end
51
+
52
+ desc "build gem"
53
+ task :build do
54
+ system("gem build flapjack.gemspec")
55
+
56
+ FileUtils.mkdir_p('pkg')
57
+ puts
58
+ puts "Flapjack gems:"
59
+ Dir.glob("flapjack-*.gem").each do |gem|
60
+ dest = File.join('pkg', gem)
61
+ FileUtils.mv gem, dest
62
+ puts " " + dest
63
+ end
64
+ end
65
+
66
+
67
+ if require 'yard'
68
+
69
+ YARD::Rake::YardocTask.new do |t|
70
+ t.files = ['lib/**/*.rb']
71
+ t.options = ['--output-dir=doc/', '--readme=README.md']
72
+ end
73
+
74
+ end
75
+
76
+ desc "display FIXMEs in the codebase"
77
+ task :fixmes do
78
+ output = `grep -nR FIXME lib/* spec/* bin/`
79
+ output.split("\n").each do |line|
80
+ parts = line.split(':')
81
+ puts "#{parts[0].strip} +#{parts[1].strip}"
82
+ puts " - #{parts[3].strip}"
83
+ end
84
+ end
data/TODO.md ADDED
@@ -0,0 +1,26 @@
1
+ * create events for failed checks
2
+ * build option to specify notifier(s) directory
3
+ * documentation!
4
+ * user
5
+ * developer
6
+ * step-by-step install guide
7
+ * scaling guide
8
+ * integrating with collectd guide
9
+ * writing custom populators guide
10
+ * build benchmarks for flapjack-{worker,notifier}
11
+ * write puppet manifests
12
+ * package with pallet
13
+ * generate .deb/.rpms
14
+ * build packages for gem dependencies
15
+ * sandbox flapjack-worker
16
+ * provide config option for specifying sandbox dir
17
+ * provide common interface for loading checks into beanstalk (extract from populator)
18
+ * write check generator
19
+ * include a collection of common functions
20
+ (logging to rrd, retreiving values, executing check)
21
+ * write zeroconf/avahi notifier
22
+ * write growl notifier
23
+ * write way to customise notifier messages (email body, xmpp format)
24
+ * write sms notifier
25
+ * patch beanstalk-client to recognise DRAINING status
26
+ * http://www.kitchensoap.com/2009/10/05/meanwhile-more-meta-metrics/
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__) + '/../lib' unless $:.include?(File.dirname(__FILE__) + '/../lib/')
4
+
5
+ require 'rubygems'
6
+ require 'beanstalk-client'
7
+ require 'ostruct'
8
+ require 'optparse'
9
+ require 'log4r'
10
+ require 'log4r/outputter/syslogoutputter'
11
+ require 'flapjack/result'
12
+ require 'flapjack/notifier'
13
+ require 'daemons'
14
+ require 'flapjack/patches'
15
+
16
+ # command line options are in here
17
+ require 'flapjack/cli/notifier'
18
+
19
+ # boot up the notifier
20
+ @options = Flapjack::NotifierOptions.parse(ARGV)
21
+
22
+ ncli = Flapjack::NotifierCLI.new
23
+ ncli.setup_loggers
24
+ ncli.setup_recipients(:filename => @options.recipients)
25
+ ncli.setup_config(:filename => @options.config_filename)
26
+ ncli.setup_notifier
27
+ ncli.setup_database(:database_uri => @options.database_uri)
28
+
29
+ begin
30
+
31
+ ncli.results_queue = Beanstalk::Pool.new(["#{@options.host}:#{@options.port}"], 'results')
32
+ ncli.log.info("established connection to beanstalkd on #{@options.host}...")
33
+
34
+ # process results
35
+ ncli.process_loop
36
+
37
+ rescue Beanstalk::NotConnected
38
+ ncli.log.error("Couldn't connect to the Beanstalk!")
39
+
40
+ timeout = 5
41
+ ncli.log.error("Retrying in #{timeout} seconds.")
42
+ sleep timeout
43
+
44
+ ncli.log.error("Retrying...")
45
+ retry
46
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__) + '/../lib' unless $:.include?(File.dirname(__FILE__) + '/../lib/')
4
+
5
+ require 'rubygems'
6
+ require 'daemons'
7
+ require 'fileutils'
8
+ require 'flapjack/cli/notifier_manager'
9
+ require 'flapjack/patches' # for Daemons
10
+
11
+ # reassign ARGV so we don't mess with it directly
12
+ args = ARGV
13
+ args << '--help' if args.size == 0
14
+ options = Flapjack::NotifierManagerOptions.parse(args)
15
+
16
+ worker_path = File.join(File.dirname(__FILE__), 'flapjack-notifier')
17
+
18
+ # set up pid dir
19
+ pid_dir = "/var/run/flapjack/"
20
+ unless File.exists?(pid_dir)
21
+ puts "#{pid_dir} doesn't exist."
22
+ exit 2
23
+ end
24
+
25
+ unless File.writable?(pid_dir)
26
+ puts "Can't write to #{pid_dir} - check permissions?"
27
+ exit 2
28
+ end
29
+
30
+ # construct arguments
31
+ daemon_args = args
32
+ if args.first != "stop"
33
+ # if we're not stopping the daemon, pass options to it
34
+ daemon_args += ['--', '--beanstalk', options.host,
35
+ '--port', options.port.to_s,
36
+ '--recipients', options.recipients,
37
+ '--config', File.expand_path(options.config_filename)]
38
+ end
39
+
40
+ # boot
41
+ Daemons.run(worker_path, :ARGV => daemon_args,
42
+ :multiple => false,
43
+ :dir_mode => :normal,
44
+ :dir => pid_dir)
45
+
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'beanstalk-client'
5
+
6
+ begin
7
+ beanstalk = Beanstalk::Pool.new(['localhost:11300'])
8
+ loop do
9
+ time = Time.now
10
+ beanstalk.list_tubes['localhost:11300'].each do |tube_name|
11
+ next if tube_name == 'default'
12
+ stats = beanstalk.stats_tube(tube_name)
13
+ puts "#{time.to_i} [#{tube_name}] total: #{stats['total-jobs']}, waiting: #{stats['current-waiting']}, ready: #{stats['current-jobs-ready']}"
14
+ end
15
+ sleep 1
16
+ end
17
+ rescue Beanstalk::NotConnected
18
+ puts "beanstalk isn't up!"
19
+ exit 2
20
+ end
21
+
22
+