flapjack 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+