flapjack 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'ostruct'
5
+ require 'optparse'
6
+
7
+ class WorkerManagerOptions
8
+ def self.parse(args)
9
+ options = OpenStruct.new
10
+ opts = OptionParser.new do |opts|
11
+ opts.banner = "Usage: flapjack-worker-manager <command> [options]"
12
+ opts.separator " "
13
+ opts.separator " where <command> is one of:"
14
+ opts.separator " start start a worker"
15
+ opts.separator " stop stop all workers"
16
+ opts.separator " restart restart workers"
17
+ opts.separator " "
18
+ opts.separator " and [options] are:"
19
+
20
+ opts.on('-w', '--workers N', 'number of workers to spin up') do |workers|
21
+ options.workers = workers.to_i
22
+ end
23
+ opts.on('-c', '--checks-directory DIR', 'sandboxed check directory') do |dir|
24
+ options.check_directory = dir
25
+ end
26
+ end
27
+
28
+ begin
29
+ opts.parse!(args)
30
+ rescue => e
31
+ puts e.message.capitalize + "\n\n"
32
+ puts opts
33
+ exit 1
34
+ end
35
+
36
+ options.workers ||= 5
37
+
38
+ unless %w(start stop restart).include?(args[0])
39
+ puts opts
40
+ exit 1
41
+ end
42
+
43
+ options
44
+ end
45
+ end
46
+
47
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dm-core'
4
+ require 'dm-validations'
5
+ require 'dm-types'
6
+ require 'dm-timestamps'
7
+
8
+ Dir.glob(File.join(File.dirname(__FILE__), 'models', '*.rb')).each do |model|
9
+ require model
10
+ end
@@ -0,0 +1,92 @@
1
+ class Check
2
+ include DataMapper::Resource
3
+
4
+ timestamps :at
5
+
6
+ has n, :related_checks, :child_key => [:child_id, :parent_id]
7
+ has n, :events
8
+
9
+ #has n, :parent_checks, :through => :related_checks,
10
+ # :child_key => :child_id, :class_name => "Check"
11
+ #has n, :child_checks, :through => :related_checks,
12
+ # :child_key => :parent_id, :class_name => "Check"
13
+
14
+ belongs_to :node
15
+ belongs_to :check_template
16
+
17
+ property :id, Serial, :key => true
18
+ property :command, Text, :nullable => false
19
+ property :params, Yaml
20
+ property :name, String, :nullable => false
21
+ property :enabled, Boolean, :default => false
22
+ property :status, Integer, :default => 0
23
+
24
+ # dm-timestamps
25
+ property :created_at, DateTime
26
+ property :updated_at, DateTime
27
+ property :deleted_at, ParanoidDateTime
28
+
29
+ # copy command onto check
30
+ before :valid? do
31
+ if self.check_template && self.command.blank?
32
+ self.command = self.check_template.command
33
+ self.name = self.check_template.name
34
+ self.params = (self.check_template.params || {})
35
+ end
36
+ end
37
+
38
+ def parameters_and_values
39
+ names = parameter_names_from_command
40
+ hash = {}
41
+ names.each { |name| hash[name] = params ? params[name] : "" }
42
+ hash["$FQDN"] = self.node_fqdn # pkey of node check belongs to
43
+ hash
44
+ end
45
+
46
+ def parameter_names_from_command
47
+ self.command.split.grep(/\$\w/)
48
+ end
49
+
50
+ def executed_command
51
+ c = self.command
52
+ parameters_and_values.each_pair do |param, value|
53
+ value = value.to_s
54
+ c.gsub!(param, value)
55
+ end
56
+ return c
57
+ end
58
+
59
+ # FIXME: this should work through related checks association, but doesn't
60
+ def parent_checks
61
+ RelatedCheck.all(:child_id => self.id).map {|rc| rc.parent_check}
62
+ end
63
+
64
+ def child_checks
65
+ RelatedCheck.all(:parent_id => self.id).map {|rc| rc.child_check}
66
+ end
67
+
68
+ def worst_parent_status
69
+ if parent_checks.size > 0
70
+ self.parent_checks.map { |parent| parent.status }.sort.pop
71
+ else
72
+ 0
73
+ end
74
+ end
75
+
76
+
77
+ GOOD = 0
78
+ BAD = 1
79
+ UGLY = 2
80
+
81
+ def pretty_print_status
82
+ case self.status
83
+ when GOOD
84
+ "good"
85
+ when BAD
86
+ "bad"
87
+ when UGLY
88
+ "ugly"
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,18 @@
1
+ class CheckTemplate
2
+ include DataMapper::Resource
3
+
4
+ has n, :checks
5
+
6
+ property :id, Serial
7
+ property :command, Text, :nullable => false
8
+ property :name, String, :nullable => false
9
+ property :params, Yaml
10
+
11
+ validates_is_unique :command, :name
12
+
13
+ def name_for_select
14
+ cmd = (self.command.size > 30 ? "#{self.command[0..50]}..." : self.command)
15
+ "#{self.name} (#{cmd})"
16
+ end
17
+
18
+ end
@@ -0,0 +1,16 @@
1
+ class Node
2
+ include DataMapper::Resource
3
+
4
+ has n, :checks
5
+
6
+ property :fqdn, String, :key => true
7
+
8
+ validates_is_unique :fqdn
9
+ validates_format :fqdn, :with => /^[0-9|a-z|A-Z|\-|\.]*$/,
10
+ :message => "not a RFC1035-formatted FQDN (see section 2.3.1)"
11
+
12
+ def hostname
13
+ self.fqdn.split('.').first
14
+ end
15
+
16
+ end
@@ -0,0 +1,13 @@
1
+ class RelatedCheck
2
+ include DataMapper::Resource
3
+
4
+ belongs_to :parent_check, :class_name => "Check", :child_key => [:parent_id]
5
+ belongs_to :child_check, :class_name => "Check", :child_key => [:child_id]
6
+
7
+ property :id, Serial, :key => true
8
+ #property :parent_check_id, Integer, :nullable => false
9
+ #property :child_check_id, Integer, :nullable => false
10
+
11
+
12
+
13
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ostruct'
4
+
5
+ module Flapjack
6
+ class Notifier
7
+
8
+ attr_reader :recipients, :log, :notifiers
9
+
10
+ def initialize(opts={})
11
+ @log = opts[:logger]
12
+ raise "you have to specify a logger" unless @log
13
+ @recipients = (opts[:recipients] || [])
14
+
15
+ @notifiers = []
16
+ if opts[:notifiers]
17
+ opts[:notifiers].each do |n|
18
+ @notifiers << n
19
+ @log.info("using the #{n.class.to_s.split("::").last} notifier")
20
+ end
21
+ else
22
+ @log.warning("there are no notifiers")
23
+ end
24
+ end
25
+
26
+ def notify!(result)
27
+ @notifiers.each do |n|
28
+ @recipients.each do |recipient|
29
+ @log.info("Notifying #{recipient.name} via #{n.class} about check #{result.id}")
30
+ n.notify(:result => result, :who => recipient)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), 'mailer')
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'net/smtp'
5
+ require 'mailfactory'
6
+
7
+ module Flapjack
8
+ module Notifiers
9
+
10
+ class Mailer
11
+
12
+ def initialize(opts={})
13
+ @from_address = opts[:from_address]
14
+ @website_uri = opts[:website_uri] ? opts[:website_uri].gsub(/\/$/, '') : "http://#{`hostname`}"
15
+ @log = opts[:logger]
16
+ @log ||= Log4r::Logger.new("notifier")
17
+ end
18
+
19
+ def notify(opts={})
20
+ raise unless (opts[:who] && opts[:result])
21
+
22
+ mail = MailFactory.new
23
+ mail.to = opts[:who].email
24
+ mail.from = @from_address
25
+ mail.subject = "Check: #{opts[:result].id}, Status: #{opts[:result].status}"
26
+ mail.text = <<-DESC
27
+ Check #{opts[:result].id} returned the status "#{opts[:result].status}".
28
+
29
+ Here was the output:
30
+ #{opts[:result].output}
31
+
32
+ You can respond to this issue at:
33
+ #{@website_uri}/issue/#{opts[:result].id}
34
+ DESC
35
+
36
+ begin
37
+ Net::SMTP.start('localhost') do |smtp|
38
+ smtp.sendmail(mail.to_s, mail.from, mail.to)
39
+ end
40
+ rescue Errno::ECONNREFUSED
41
+ @log.error("Couldn't establish connection to mail server!")
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), 'xmpp')
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'xmpp4r-simple'
4
+
5
+ module Flapjack
6
+ module Notifiers
7
+ class Xmpp
8
+
9
+ def initialize(opts={})
10
+
11
+ @jid = opts[:jid]
12
+ @password = opts[:password]
13
+ @log = opts[:logger]
14
+ unless @jid && @password
15
+ raise ArgumentError, "You have to provide a username and password"
16
+ end
17
+
18
+ begin
19
+ @xmpp = Jabber::Simple.new(@jid, @password)
20
+ rescue SocketError => e
21
+ @log.error("XMPP: #{e.message}")
22
+ end
23
+
24
+ end
25
+
26
+ def notify(opts={})
27
+
28
+ raise unless opts[:who] && opts[:result]
29
+
30
+ message = <<-DESC
31
+ Check #{opts[:result].id} returned the status "#{opts[:result].status}".
32
+ http://localhost:4000/checks/#{opts[:result].id}
33
+ DESC
34
+
35
+ @xmpp.deliver(opts[:who].jid, message)
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,26 @@
1
+ require 'ostruct'
2
+ require 'daemons'
3
+ require 'log4r'
4
+
5
+ class OpenStruct
6
+ def to_h
7
+ @table
8
+ end
9
+ end
10
+
11
+ module Daemons
12
+ class PidFile
13
+ # we override this method so creating pid files is fork-safe
14
+ def filename
15
+ File.join(@dir, "#{@progname}#{Process.pid}.pid")
16
+ end
17
+ end
18
+ end
19
+
20
+ module Log4r
21
+ class Logger
22
+ def error(args)
23
+ err(args)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ostruct'
4
+
5
+ ##
6
+ # Representation of a check result, as it's popped off the beanstalk.
7
+ #
8
+ # Provides several convience methods for querying the status of a result.
9
+ #
10
+ # Convenience methods are used by the Notifier to determine whether a
11
+ # notification needs to be sent out.
12
+ module Flapjack
13
+ class Result < OpenStruct
14
+
15
+ # Whether a check returns an ok status.
16
+ def ok?
17
+ self.retval == 0
18
+ end
19
+
20
+ # Whether a check has a warning status.
21
+ def warning?
22
+ self.retval == 1
23
+ end
24
+
25
+ # Whether a check has a critical status.
26
+ def critical?
27
+ self.retval == 2
28
+ end
29
+
30
+ # Human readable representation of the check's return value.
31
+ def status
32
+ case self.retval
33
+ when 0 ; "ok"
34
+ when 1 ; "warning"
35
+ when 2 ; "critical"
36
+ end
37
+ end
38
+
39
+ # The id of a check result.
40
+ def id
41
+ # openstruct won't respond, so we have to manually define it
42
+ @table[:id]
43
+ end
44
+
45
+ end
46
+ end
47
+
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flapjack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.10
5
+ platform: ruby
6
+ authors:
7
+ - Lindsay Holmwood
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-16 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: daemons
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.10
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: beanstalk-client
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.2
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: log4r
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.5
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: xmpp4r-simple
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.8
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: mailfactory
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 1.4.0
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: dm-core
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.9.11
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: dm-timestamps
77
+ type: :runtime
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 0.9.11
84
+ version:
85
+ - !ruby/object:Gem::Dependency
86
+ name: dm-types
87
+ type: :runtime
88
+ version_requirement:
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.11
94
+ version:
95
+ - !ruby/object:Gem::Dependency
96
+ name: dm-validations
97
+ type: :runtime
98
+ version_requirement:
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.11
104
+ version:
105
+ - !ruby/object:Gem::Dependency
106
+ name: data_objects
107
+ type: :runtime
108
+ version_requirement:
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: 0.9.12
114
+ version:
115
+ - !ruby/object:Gem::Dependency
116
+ name: do_sqlite3
117
+ type: :runtime
118
+ version_requirement:
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: 0.9.12
124
+ version:
125
+ description: Flapjack is highly scalable and distributed monitoring system. It understands the Nagios plugin format, and can easily be scaled from 1 server to 1000.
126
+ email: lindsay@holmwood.id.au
127
+ executables:
128
+ - flapjack-notifier
129
+ - flapjack-notifier-manager
130
+ - flapjack-stats
131
+ - flapjack-worker
132
+ - flapjack-worker-manager
133
+ - install-flapjack-systemwide
134
+ extensions: []
135
+
136
+ extra_rdoc_files: []
137
+
138
+ files:
139
+ - LICENCE
140
+ - README.md
141
+ - Rakefile
142
+ - TODO.md
143
+ - bin/flapjack-notifier
144
+ - bin/flapjack-notifier-manager
145
+ - bin/flapjack-stats
146
+ - bin/flapjack-worker
147
+ - bin/flapjack-worker-manager
148
+ - bin/install-flapjack-systemwide
149
+ - doc/CONFIGURING.md
150
+ - doc/DEVELOPING.md
151
+ - doc/INSTALL.md
152
+ - etc/default/flapjack-notifier
153
+ - etc/default/flapjack-workers
154
+ - etc/flapjack/flapjack-notifier.yaml.example
155
+ - etc/flapjack/recipients.yaml.example
156
+ - etc/init.d/flapjack-notifier
157
+ - etc/init.d/flapjack-workers
158
+ - flapjack.gemspec
159
+ - lib/flapjack/checks/http_content
160
+ - lib/flapjack/cli/notifier.rb
161
+ - lib/flapjack/cli/notifier_manager.rb
162
+ - lib/flapjack/cli/worker.rb
163
+ - lib/flapjack/cli/worker_manager.rb
164
+ - lib/flapjack/database.rb
165
+ - lib/flapjack/models/check.rb
166
+ - lib/flapjack/models/check_template.rb
167
+ - lib/flapjack/models/node.rb
168
+ - lib/flapjack/models/related_check.rb
169
+ - lib/flapjack/notifier.rb
170
+ - lib/flapjack/notifiers/mailer/init.rb
171
+ - lib/flapjack/notifiers/mailer/mailer.rb
172
+ - lib/flapjack/notifiers/xmpp/init.rb
173
+ - lib/flapjack/notifiers/xmpp/xmpp.rb
174
+ - lib/flapjack/patches.rb
175
+ - lib/flapjack/result.rb
176
+ has_rdoc: true
177
+ homepage: http://flapjack-project.com
178
+ licenses: []
179
+
180
+ post_install_message:
181
+ rdoc_options: []
182
+
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: "0"
190
+ version:
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: "0"
196
+ version:
197
+ requirements: []
198
+
199
+ rubyforge_project:
200
+ rubygems_version: 1.3.5
201
+ signing_key:
202
+ specification_version: 3
203
+ summary: a scalable and distributed monitoring system
204
+ test_files: []
205
+