murakumo 0.3.1 → 0.3.2
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.
- 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.
|