murakumo 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/etc/murakumo.server +17 -0
- data/etc/murakumo.yml.example +16 -1
- data/lib/cli/murakumo_options.rb +53 -3
- data/lib/misc/murakumo_const.rb +1 -1
- data/lib/srv/murakumo_cloud.rb +9 -1
- data/lib/srv/{murakumo_health_checker_context.rb → murakumo_health_check_context.rb} +11 -2
- data/lib/srv/murakumo_health_check_notifier.rb +56 -0
- data/lib/srv/murakumo_health_checker.rb +40 -3
- metadata +14 -13
data/etc/murakumo.server
CHANGED
@@ -72,8 +72,23 @@ max-ip-num: 8
|
|
72
72
|
#domain: ap-northeast-1.compute.internal
|
73
73
|
#enable-cache: true
|
74
74
|
|
75
|
+
#notification:
|
76
|
+
# host: my.smtp.server
|
77
|
+
# #port: 25
|
78
|
+
# sender: sender@mail.from
|
79
|
+
# recipients:
|
80
|
+
# - recipient1@mail.to
|
81
|
+
# - recipient2@mail.to
|
82
|
+
# #helo: my.domain
|
83
|
+
# #account: my_name
|
84
|
+
# #password: my_password
|
85
|
+
# #open_timeout: 30
|
86
|
+
# #read_timeout: 60
|
87
|
+
|
88
|
+
# Ip address, hostname, ttl
|
75
89
|
host: $ip_addr, $hostname, 60
|
76
90
|
|
91
|
+
# alias hostname, ttl, master/secondary/backup
|
77
92
|
#alias:
|
78
93
|
# - foo,60,master
|
79
94
|
# - bar,60,backup
|
@@ -84,6 +99,8 @@ host: $ip_addr, $hostname, 60
|
|
84
99
|
# timeout: 5
|
85
100
|
# healthy: 2
|
86
101
|
# unhealthy: 2
|
102
|
+
# #on_activate: /foo/bar/zoo.sh # args: address name status
|
103
|
+
# #on_inactivate: /foo/bar/zoo.sh # args: address name status
|
87
104
|
# script: |
|
88
105
|
# tcp_check 80
|
89
106
|
# bar:
|
data/etc/murakumo.yml.example
CHANGED
@@ -12,10 +12,23 @@ max-ip-num: 8
|
|
12
12
|
#domain: ap-northeast-1.compute.internal
|
13
13
|
#enable-cache: true
|
14
14
|
|
15
|
+
#notification:
|
16
|
+
# host: my.smtp.server
|
17
|
+
# #port: 25
|
18
|
+
# sender: sender@mail.from
|
19
|
+
# recipients:
|
20
|
+
# - recipient1@mail.to
|
21
|
+
# - recipient2@mail.to
|
22
|
+
# #helo: my.domain
|
23
|
+
# #account: my_name
|
24
|
+
# #password: my_password
|
25
|
+
# #open_timeout: 30
|
26
|
+
# #read_timeout: 60
|
27
|
+
|
15
28
|
# Ip address, hostname, ttl
|
16
29
|
host: 10.11.12.13, my-host, 60
|
17
30
|
|
18
|
-
# alias hostname, ttl, master/backup
|
31
|
+
# alias hostname, ttl, master/secondary/backup
|
19
32
|
alias:
|
20
33
|
- foo,60,master
|
21
34
|
- bar,60,master
|
@@ -26,6 +39,8 @@ health-check:
|
|
26
39
|
timeout: 5
|
27
40
|
healthy: 2
|
28
41
|
unhealthy: 2
|
42
|
+
#on_activate: /foo/bar/zoo.sh # args: address name status
|
43
|
+
#on_inactivate: /foo/bar/zoo.sh # args: address name status
|
29
44
|
script: |
|
30
45
|
tcp_check 80
|
31
46
|
bar:
|
data/lib/cli/murakumo_options.rb
CHANGED
@@ -183,14 +183,64 @@ def murakumo_parse_args
|
|
183
183
|
hostnames = [options[:host][0].downcase] + options[:aliases].map {|i| i[0].downcase }
|
184
184
|
|
185
185
|
if hostnames.length != hostnames.uniq.length
|
186
|
-
|
186
|
+
parse_error('same hostname was found')
|
187
187
|
end
|
188
188
|
|
189
189
|
# health check
|
190
190
|
if options.config_file and (health_check = options.config_file['health-check'])
|
191
|
-
|
192
|
-
|
191
|
+
health_check.kind_of?(Hash) or parse_error('configuration of a health check is not right')
|
192
|
+
|
193
|
+
health_check.each do |name, conf|
|
194
|
+
if (conf['script'] || '').empty?
|
195
|
+
parse_error('configuration of a health check is not right', "#{name}/script")
|
196
|
+
end
|
197
|
+
|
198
|
+
%w(on_activate on_inactivate).each do |key|
|
199
|
+
next unless conf[key]
|
200
|
+
path = conf[key] = conf[key].strip
|
201
|
+
|
202
|
+
if FileTest.directory?(path) or not FileTest.executable?(path)
|
203
|
+
parse_error('configuration of a health check is not right', "#{name}/#{key}")
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# notification
|
210
|
+
if options.config_file and (ntfc = options.config_file['notification'])
|
211
|
+
ntfc.kind_of?(Hash) or parse_error('configuration of a notification is not right')
|
212
|
+
|
213
|
+
if (ntfc['host'] || '').empty?
|
214
|
+
parse_error('configuration of a notification is not right', 'host')
|
215
|
+
end
|
216
|
+
|
217
|
+
unless ntfc['recipients']
|
218
|
+
parse_error('configuration of a notification is not right', 'recipients')
|
193
219
|
end
|
220
|
+
|
221
|
+
%w(port open_timeout read_timeout).each do |key|
|
222
|
+
if ntfc[key] and /\A\d+\Z/ !~ ntfc[key].to_s
|
223
|
+
parse_error('configuration of a notification is not right', key)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
ntfc_args = [ntfc['host']]
|
228
|
+
ntfc_args << ntfc['port'].to_i if ntfc['port']
|
229
|
+
ntfc_args << ntfc['account'] if ntfc['account']
|
230
|
+
ntfc_args << ntfc['password'] if ntfc['password']
|
231
|
+
|
232
|
+
options[:notification] = ntfc_h = {:args => ntfc_args}
|
233
|
+
|
234
|
+
ntfc_h[:sender] = ntfc['sender'] || 'murakumo@localhost.localdomain'
|
235
|
+
|
236
|
+
if ntfc['recipients'].kind_of?(Array)
|
237
|
+
ntfc_h[:recipients] = ntfc['recipients']
|
238
|
+
else
|
239
|
+
ntfc_h[:recipients] = ntfc['recipients'].to_s.split(/\s*,\s*/).select {|i| not i.empty? }
|
240
|
+
end
|
241
|
+
|
242
|
+
ntfc_h[:open_timeout] = ntfc['open_timeout'].to_i if ntfc['open_timeout']
|
243
|
+
ntfc_h[:read_timeout] = ntfc['read_timeout'].to_i if ntfc['read_timeout']
|
194
244
|
end
|
195
245
|
end
|
196
246
|
|
data/lib/misc/murakumo_const.rb
CHANGED
data/lib/srv/murakumo_cloud.rb
CHANGED
@@ -77,8 +77,12 @@ module Murakumo
|
|
77
77
|
health_check.each do |name, conf|
|
78
78
|
name = name.downcase
|
79
79
|
|
80
|
+
if options[:notification]
|
81
|
+
conf = conf.merge(:notification => options[:notification])
|
82
|
+
end
|
83
|
+
|
80
84
|
if datas.any? {|i| i[0] == name }
|
81
|
-
checker = HealthChecker.new(name, self, @logger, conf)
|
85
|
+
checker = HealthChecker.new(@address, name, self, @logger, conf)
|
82
86
|
@health_checkers[name] = checker
|
83
87
|
# ヘルスチェックはまだ起動しない
|
84
88
|
else
|
@@ -167,6 +171,10 @@ module Murakumo
|
|
167
171
|
hash['health-check'] = @options.config_file['health-check']
|
168
172
|
end
|
169
173
|
|
174
|
+
if @options.config_file and @options.config_file['notification']
|
175
|
+
hash['notification'] = @options.config_file['notification']
|
176
|
+
end
|
177
|
+
|
170
178
|
return hash
|
171
179
|
end
|
172
180
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'net/http'
|
2
|
+
require 'net/smtp'
|
2
3
|
require 'socket'
|
3
4
|
|
4
5
|
require 'misc/murakumo_const'
|
@@ -6,7 +7,7 @@ require 'misc/murakumo_const'
|
|
6
7
|
module Murakumo
|
7
8
|
|
8
9
|
# ヘルスチェックのコンテキスト
|
9
|
-
class
|
10
|
+
class HealthCheckContext
|
10
11
|
|
11
12
|
def initialize(vars = {})
|
12
13
|
vars.each do |name, val|
|
@@ -37,6 +38,14 @@ module Murakumo
|
|
37
38
|
return false
|
38
39
|
end
|
39
40
|
|
41
|
+
# SMTPチェッカー
|
42
|
+
def smtp_check(*args)
|
43
|
+
Net::SMTP.start(*args) {|smtp| true }
|
44
|
+
rescue => e
|
45
|
+
@logger.debug("#{@name}: #{e.message}")
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
40
49
|
# MySQLのドライバがあれば、MySQLチェッカーを定義
|
41
50
|
mysql_class = nil
|
42
51
|
|
@@ -91,6 +100,6 @@ module Murakumo
|
|
91
100
|
rescue LoadError
|
92
101
|
end
|
93
102
|
|
94
|
-
end #
|
103
|
+
end # HealthCheckContext
|
95
104
|
|
96
105
|
end # Murakumo
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
require 'resolv-replace'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module Murakumo
|
6
|
+
|
7
|
+
class HealthCheckNotifier
|
8
|
+
|
9
|
+
def initialize(address, name, logger, options)
|
10
|
+
@address = address
|
11
|
+
@name = name
|
12
|
+
@logger = logger
|
13
|
+
@args = options[:args]
|
14
|
+
@sender = options[:sender]
|
15
|
+
@recipients = options[:recipients]
|
16
|
+
@open_timeout = options[:open_timeout]
|
17
|
+
@read_timeout = options[:read_timeout]
|
18
|
+
end
|
19
|
+
|
20
|
+
def notify_active
|
21
|
+
notify('Active', "#{@name} changed into the activity status.")
|
22
|
+
end
|
23
|
+
|
24
|
+
def notify_inactive
|
25
|
+
notify('Inactive', "#{@name} changed into the inactivity status.")
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def notify(status, body)
|
30
|
+
Net::SMTP.start(*@args) do |smtp|
|
31
|
+
smtp.open_timeout = @open_timeout if @open_timeout
|
32
|
+
smtp.read_timeout = @read_timeout if @read_timeout
|
33
|
+
|
34
|
+
smtp.send_mail(<<-EOS, @sender, *@recipients)
|
35
|
+
From: Murakumo Notifier <#{@sender}>
|
36
|
+
To: #{@recipients.join(', ')}
|
37
|
+
Subject: #{@name}/#{@address} => #{status}
|
38
|
+
Date: #{Time.now.rfc2822}
|
39
|
+
|
40
|
+
Address: #{@address}
|
41
|
+
Name: #{@name}
|
42
|
+
Status: #{status}
|
43
|
+
|
44
|
+
#{body.strip}
|
45
|
+
EOS
|
46
|
+
end
|
47
|
+
|
48
|
+
@logger.info("sent the notice: #{status}")
|
49
|
+
rescue Exception => e
|
50
|
+
message = (["#{e.class}: #{e.message}"] + (e.backtrace || [])).join("\n\tfrom ")
|
51
|
+
@logger.error("healthcheck failed: #{@name}: #{message}")
|
52
|
+
end
|
53
|
+
|
54
|
+
end # HealthCheckNotifier
|
55
|
+
|
56
|
+
end # Murakumo
|
@@ -1,14 +1,17 @@
|
|
1
1
|
require 'timeout'
|
2
|
+
require 'open3'
|
2
3
|
require 'resolv-replace'
|
3
4
|
|
4
|
-
require 'srv/
|
5
|
+
require 'srv/murakumo_health_check_context'
|
6
|
+
require 'srv/murakumo_health_check_notifier'
|
5
7
|
require 'misc/murakumo_const'
|
6
8
|
|
7
9
|
module Murakumo
|
8
10
|
|
9
11
|
class HealthChecker
|
10
12
|
|
11
|
-
def initialize(name, cloud, logger, options)
|
13
|
+
def initialize(address, name, cloud, logger, options)
|
14
|
+
@address = address
|
12
15
|
@name = name
|
13
16
|
@cloud = cloud
|
14
17
|
@logger = logger
|
@@ -32,6 +35,15 @@ module Murakumo
|
|
32
35
|
@script = options['script']
|
33
36
|
raise "health check script of #{@name} is not found" unless @script
|
34
37
|
@script = File.read(script) if File.exists?(@script)
|
38
|
+
|
39
|
+
# 通知オブジェクトの設定
|
40
|
+
if options[:notification]
|
41
|
+
@notifier = HealthCheckNotifier.new(@address, @name, @logger, options[:notification])
|
42
|
+
end
|
43
|
+
|
44
|
+
# イベントハンドラの設定
|
45
|
+
@on_activate = options['on_activate']
|
46
|
+
@on_inactivate = options['on_inactivate']
|
35
47
|
end
|
36
48
|
|
37
49
|
def good
|
@@ -71,6 +83,15 @@ module Murakumo
|
|
71
83
|
|
72
84
|
status = @normal_health ? 'healthy' : 'unhealthy'
|
73
85
|
@logger.info("health condition changed: #{@name}: #{status}")
|
86
|
+
|
87
|
+
case activity
|
88
|
+
when ACTIVE
|
89
|
+
@notifier.notify_active if @notifier
|
90
|
+
handle_event(@on_activate, 'Active') if @on_activate
|
91
|
+
when INACTIVE
|
92
|
+
@notifier.notify_inactive if @notifier
|
93
|
+
handle_event(@on_inactivate, 'Inactive') if @on_inactivate
|
94
|
+
end
|
74
95
|
end
|
75
96
|
|
76
97
|
def start
|
@@ -98,7 +119,7 @@ module Murakumo
|
|
98
119
|
|
99
120
|
begin
|
100
121
|
retval = timeout(@timeout) {
|
101
|
-
|
122
|
+
HealthCheckContext.new(:name => @name, :logger => @logger, :options => @options).instance_eval(@script)
|
102
123
|
}
|
103
124
|
rescue Timeout::Error
|
104
125
|
retval = false
|
@@ -133,6 +154,22 @@ module Murakumo
|
|
133
154
|
def alive?
|
134
155
|
@alive
|
135
156
|
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def handle_event(handler, status)
|
161
|
+
Open3.popen3("#{@on_activate} '#{@address}' '#{@name}' '#{status}'") do |stdin, stdout, stderr|
|
162
|
+
out = stdout.read.strip
|
163
|
+
@logger.info(out) unless out.empty?
|
164
|
+
|
165
|
+
err = stderr.read.strip
|
166
|
+
@logger.error(err) unless err.empty?
|
167
|
+
end
|
168
|
+
rescue Exception => e
|
169
|
+
message = (["#{e.class}: #{e.message}"] + (e.backtrace || [])).join("\n\tfrom ")
|
170
|
+
@logger.error("#{@name}: #{message}")
|
171
|
+
end
|
172
|
+
|
136
173
|
end # HealthChecker
|
137
174
|
|
138
175
|
end # Murakumo
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: murakumo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 2
|
10
|
+
version: 0.3.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- winebarrel
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-11-
|
18
|
+
date: 2011-11-26 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rubydns
|
@@ -93,23 +93,24 @@ extra_rdoc_files: []
|
|
93
93
|
|
94
94
|
files:
|
95
95
|
- README
|
96
|
-
- bin/murakumo
|
97
96
|
- bin/murakumo-install-init-script
|
98
97
|
- bin/mrkmctl
|
99
|
-
-
|
100
|
-
- lib/cli/murakumo.rb
|
98
|
+
- bin/murakumo
|
101
99
|
- lib/cli/murakumo_options.rb
|
100
|
+
- lib/cli/mrkmctl.rb
|
102
101
|
- lib/cli/mrkmctl_options.rb
|
103
|
-
- lib/
|
102
|
+
- lib/cli/murakumo.rb
|
103
|
+
- lib/srv/murakumo_health_check_notifier.rb
|
104
104
|
- lib/srv/murakumo_server.rb
|
105
|
-
- lib/srv/murakumo_health_checker_context.rb
|
106
105
|
- lib/srv/murakumo_health_checker.rb
|
107
106
|
- lib/srv/murakumo_cloud.rb
|
108
|
-
-
|
109
|
-
-
|
110
|
-
- etc/gai.conf.example
|
107
|
+
- lib/srv/murakumo_health_check_context.rb
|
108
|
+
- lib/misc/murakumo_const.rb
|
111
109
|
- etc/murakumo-update-config-for-ec2
|
110
|
+
- etc/gai.conf.example
|
111
|
+
- etc/murakumo.yml.example
|
112
112
|
- etc/dhclient-script.patch
|
113
|
+
- etc/murakumo.server
|
113
114
|
homepage: https://bitbucket.org/winebarrel/murakumo
|
114
115
|
licenses: []
|
115
116
|
|
@@ -139,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
140
|
requirements: []
|
140
141
|
|
141
142
|
rubyforge_project:
|
142
|
-
rubygems_version: 1.8.
|
143
|
+
rubygems_version: 1.8.1
|
143
144
|
signing_key:
|
144
145
|
specification_version: 3
|
145
146
|
summary: Murakumo is the internal DNS server which manages name information using a gossip protocol.
|