murakumo 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module Murakumo
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
 
4
4
  # Priority
5
5
  MASTER = 1
@@ -19,18 +19,21 @@ module Murakumo
19
19
  s = TCPSocket.new(host, port)
20
20
  s.close
21
21
  return true
22
- rescue Exception
22
+ rescue => e
23
+ @logger.debug("#{@name}: #{e.message}")
23
24
  return false
24
25
  end
25
26
 
26
27
  # HTTPチェッカー
27
28
  def http_get(path, statuses = [200], host = '127.0.0.1', port = 80)
28
29
  res = Net::HTTP.start('127.0.0.1', 80) do |http|
30
+ http.read_timeout = @options['timeout']
29
31
  http.get(path)
30
32
  end
31
33
 
32
34
  statuses.include?(res.code.to_i)
33
- rescue Exception
35
+ rescue => e
36
+ @logger.debug("#{@name}: #{e.message}")
34
37
  return false
35
38
  end
36
39
 
@@ -53,7 +56,7 @@ module Murakumo
53
56
  my = Mysql.new(host, user, passwd, db, port, sock)
54
57
  !!(my.respond_to?(:ping) ? my.ping : my.stat)
55
58
  rescue => e
56
- @logger.debug(e.message)
59
+ @logger.debug("#{@name}: #{e.message}")
57
60
  return false
58
61
  ensure
59
62
  my.close if my
@@ -80,7 +83,7 @@ module Murakumo
80
83
  my = Mysql2::Client.new(opts)
81
84
  my.ping
82
85
  rescue => e
83
- @logger.debug(e.message)
86
+ @logger.debug("#{@name}: #{e.message}")
84
87
  return false
85
88
  ensure
86
89
  my.close if my
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: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 0
10
- version: 0.3.0
9
+ - 1
10
+ version: 0.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - winebarrel
@@ -93,11 +93,8 @@ extra_rdoc_files: []
93
93
 
94
94
  files:
95
95
  - README
96
- - bin/murakumo.orig
97
96
  - bin/murakumo
98
- - bin/murakumo-install-init-script.orig
99
97
  - bin/murakumo-install-init-script
100
- - bin/mrkmctl.orig
101
98
  - bin/mrkmctl
102
99
  - lib/cli/mrkmctl.rb
103
100
  - lib/cli/murakumo.rb
@@ -105,13 +102,10 @@ files:
105
102
  - lib/cli/mrkmctl_options.rb
106
103
  - lib/misc/murakumo_const.rb
107
104
  - lib/srv/murakumo_server.rb
108
- - lib/srv/murakumo_cloud.rb.orig
109
105
  - lib/srv/murakumo_health_checker_context.rb
110
- - lib/srv/murakumo_server.rb.orig
111
106
  - lib/srv/murakumo_health_checker.rb
112
107
  - lib/srv/murakumo_cloud.rb
113
108
  - etc/murakumo.server
114
- - etc/murakumo-update-config-for-ec2.orig
115
109
  - etc/murakumo.yml.example
116
110
  - etc/gai.conf.example
117
111
  - etc/murakumo-update-config-for-ec2
data/bin/mrkmctl.orig DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
-
4
- require 'rubygems'
5
- require 'cli/mrkmctl'
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
-
4
- require 'misc/murakumo_const'
5
-
6
- INIT_D_DIR = '/etc/init.d'
7
-
8
- begin
9
- require 'rbconfig'
10
- require 'rubygems'
11
- rescue LoadError
12
- end
13
-
14
- gem_dir = nil
15
-
16
- if defined?(Gem)
17
- gem_dir = "#{Gem.dir}/gems"
18
- elsif defined?(RbConfig)
19
- gem_dir = RbConfig::CONFIG["rubylibdir"].sub(/\d+\.\d+\Z/) {|m| "gems/#{m}/gems"}
20
- else
21
- $stderr.puts 'error: gem dir is not found.'
22
- exit 1
23
- end
24
-
25
- bin_dir = ((RbConfig::CONFIG['bindir'] rescue nil) || '').strip
26
-
27
- `cp -i #{gem_dir}/murakumo-#{Murakumo::VERSION}/etc/murakumo.server #{INIT_D_DIR}/murakumo`
28
- `chmod 755 #{INIT_D_DIR}/murakumo`
29
-
30
- unless bin_dir.empty?
31
- `sed -i -r 's|^# processname:.*|# processname: #{bin_dir}/murakumo|' #{INIT_D_DIR}/murakumo`
32
- `sed -i -r 's|^prog=.*|prog=#{bin_dir}/murakumo|' #{INIT_D_DIR}/murakumo`
33
- `sed -i -r 's|^ctlprog=.*|ctlprog=#{bin_dir}/mrkmctl|' #{INIT_D_DIR}/murakumo`
34
- end
data/bin/murakumo.orig DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
-
4
- require 'rubygems'
5
- require 'cli/murakumo'
@@ -1,33 +0,0 @@
1
- #!/bin/sh
2
- CURL='curl --retry 3 --retry-delay 0 --silent --fail'
3
- IP_ADDR=`$CURL http://169.254.169.254/1.0/meta-data/local-ipv4`
4
- CONF=/etc/murakumo.yml
5
-
6
- if [ $? -ne 0 -o -z "$IP_ADDR" ]; then
7
- exit 1
8
- fi
9
-
10
- if [ `grep ^host $CONF | egrep "host: $IP_ADDR\b" | wc -l` -eq 1 ]; then
11
- exit
12
- fi
13
-
14
- ## gets a host name from user data.
15
- #HOSTNAME=`$CURL http://169.254.169.254/1.0/user-data`
16
-
17
- ## gets a host name from name tag.
18
- #export JAVA_HOME=/usr/java/default
19
- #export EC2_HOME=/opt/ec2-api-tools
20
- #EC2_PRIVATE_KEY=
21
- #EC2_CERT=
22
- #REGION=ap-northeast-1
23
- #EC2DIN=$EC2_HOME/bin/ec2-describe-instances
24
- #HOSTNAME=`$EC2DIN -K $EC2_PRIVATE_KEY -C $EC2_CERT --region $REGION -F "private-ip-address=$IP_ADDR" | awk -F'\t' '$1 == "TAG" && $4 == "Name" {print $5}'`
25
-
26
- ## gets a host name from meta data.
27
- HOSTNAME=`$CURL http://169.254.169.254/1.0/meta-data/hostname`
28
-
29
- if [ $? -ne 0 -o -z "$HOSTNAME" ]; then
30
- exit 1
31
- fi
32
-
33
- sed -i.bak -r "s|^host:.*|host: $IP_ADDR, $HOSTNAME|" /etc/murakumo.yml
@@ -1,532 +0,0 @@
1
- require 'forwardable'
2
- require 'rgossip2'
3
- require 'sqlite3'
4
-
5
- require 'srv/murakumo_health_checker'
6
- require 'misc/murakumo_const'
7
-
8
- module Murakumo
9
-
10
- class Cloud
11
- extend Forwardable
12
-
13
- attr_reader :address
14
- attr_reader :gossip
15
- attr_reader :db
16
- attr_reader :hostname
17
-
18
- def initialize(options)
19
- # オプションはインスタンス変数に保存
20
- @options = options
21
-
22
- # リソースレコードからホストのアドレスとデータを取り出す
23
- host_data = options[:host]
24
- @address = host_data.shift
25
- host_data.concat [ORIGIN, ACTIVE]
26
- alias_datas = options[:aliases].map {|r| r + [ACTIVE] }
27
- @logger = options[:logger]
28
-
29
- # 名前は小文字に変換
30
- datas = ([host_data] + alias_datas).map do |i|
31
- name, ttl, priority, activity = i
32
- name = name.downcase
33
- [name, ttl, priority, activity]
34
- end
35
-
36
- # データベースを作成してレコードを更新
37
- create_database
38
- update(@address, datas)
39
-
40
- # updateの後にホスト名をセットすること
41
- @hostname = host_data.first
42
-
43
- # ゴシップオブジェクトを生成
44
- @gossip = RGossip2.client({
45
- :initial_nodes => options[:initial_nodes],
46
- :address => @address,
47
- :data => datas,
48
- :auth_key => options[:auth_key],
49
- :port => options[:gossip_port],
50
- :node_lifetime => options[:gossip_node_lifetime],
51
- :gossip_interval => options[:gossip_send_interval],
52
- :receive_timeout => options[:gossip_receive_timeout],
53
- :logger => @logger,
54
- })
55
-
56
- # ノードの更新をフック
57
- @gossip.context.callback_handler = lambda do |act, addr, ts, dt, old_dt|
58
- case act
59
- when :add, :comeback
60
- # 追加・復帰の時は無条件に更新
61
- update(addr, dt)
62
- when :update
63
- # 更新の時はデータが更新されたときのみ更新
64
- update(addr, dt) if dt != old_dt
65
- when :delete
66
- delete(addr)
67
- end
68
- end
69
-
70
- # ヘルスチェック
71
- @health_checkers = {}
72
-
73
- if options.config_file and options.config_file['health-check']
74
- health_check = options.config_file['health-check']
75
-
76
- if health_check.kind_of?(Hash)
77
- health_check.each do |name, conf|
78
- name = name.downcase
79
-
80
- if datas.any? {|i| i[0] == name }
81
- checker = HealthChecker.new(name, self, @logger, conf)
82
- @health_checkers[name] = checker
83
- # ヘルスチェックはまだ起動しない
84
- else
85
- # ホスト名になかったら警告
86
- @logger.warn("host for a health check is not found: #{name}")
87
- end
88
- end
89
- else
90
- @logger.warn('configuration of a health check is not right')
91
- end
92
- end
93
-
94
- # キャッシュ
95
- @cache = {}
96
- end
97
-
98
- # Control of service
99
- def_delegators :@gossip, :stop, :clear_dead_list
100
-
101
- def start
102
- # デーモン化すると子プロセスはすぐ死ぬので
103
- # このタイミングでヘルスチェックを起動
104
- @health_checkers.each do |name, checker|
105
- checker.start
106
- end
107
-
108
- @gossip.start
109
- end
110
-
111
- def to_hash
112
- keys = {
113
- :auth_key => 'auth-key',
114
- :dns_address => 'address',
115
- :dns_port => 'port',
116
- :initial_nodes => lambda {|v| ['initial-nodes', v.join(',')] },
117
- :resolver => lambda {|v| [
118
- 'resolver',
119
- v.instance_variable_get(:@config).instance_variable_get(:@config_info)[:nameserver].join(',')
120
- ]},
121
- :socket => 'socket',
122
- :max_ip_num => 'max-ip-num',
123
- :domain => 'domain',
124
- :log_path => 'log-path',
125
- :log_level => 'log-level',
126
- :gossip_port => 'gossip-port',
127
- :gossip_node_lifetime => lambda {|v| [
128
- 'gossip-node-lifetime',
129
- @gossip.context.node_lifetime
130
- ]},
131
- :gossip_send_interval => lambda {|v| [
132
- 'gossip-send-interval',
133
- @gossip.context.gossip_interval
134
- ]},
135
- :gossip_receive_timeout => lambda {|v| [
136
- 'gossip-receive-timeout',
137
- @gossip.context.receive_timeout
138
- ]},
139
- }
140
-
141
- hash = {}
142
-
143
- keys.each do |k, name|
144
- value = @options[k]
145
-
146
- if value and name.respond_to?(:call)
147
- name, value = name.call(value)
148
- end
149
-
150
- if value and (not value.kind_of?(String) or not value.empty?)
151
- hash[name] = value
152
- end
153
- end
154
-
155
- records = list_records
156
-
157
- hash['host'] = records.find {|r| r[3] == ORIGIN }[0..2].join(',')
158
-
159
- aliases = records.select {|r| r[3] != ORIGIN }.map do |r|
160
- [r[1], r[2], (r[3] == MASTER ? 'master' : 'backup')].join(',')
161
- end
162
-
163
- hash['alias'] = aliases unless aliases.empty?
164
-
165
- if @options.config_file and @options.config_file['health-check']
166
- hash['health-check'] = @options.config_file['health-check']
167
- end
168
-
169
- return hash
170
- end
171
-
172
- def list_records
173
- columns = %w(ip_address name ttl priority activity)
174
-
175
- @db.execute(<<-EOS).map {|i| i.values_at(*columns) }
176
- SELECT #{columns.join(', ')} FROM records ORDER BY ip_address, name
177
- EOS
178
- end
179
-
180
- def add_or_rplace_records(records)
181
- errmsg = nil
182
-
183
- # 名前は小文字に変換
184
- records = records.map do |i|
185
- name, ttl, priority = i
186
- name = name.downcase
187
- [name, ttl, priority]
188
- end
189
-
190
- @gossip.transaction do
191
-
192
- # 既存のホスト名は削除
193
- @gossip.data.reject! do |d|
194
- if records.any? {|r| r[0] == d[0] }
195
- # オリジンのPriorityは変更不可
196
- if d[2] == ORIGIN
197
- records.each {|r| r[2] = ORIGIN if r[0] == d[0] }
198
- end
199
-
200
- true
201
- end
202
- end
203
-
204
- # データを更新
205
- records = records.map {|r| r + [ACTIVE] }
206
- @gossip.data.concat(records)
207
- end # transaction
208
-
209
- # データベースを更新
210
- update(@address, records, true)
211
-
212
- # ヘルスチェックがあれば開始
213
- records.map {|i| i.first }.each do |name|
214
- checker = @health_checkers[name]
215
-
216
- if checker and not checker.alive?
217
- checker.start
218
- end
219
- end
220
-
221
- return [!errmsg, errmsg]
222
- end
223
-
224
- def delete_records(names)
225
- errmsg = nil
226
-
227
- # 名前は小文字に変換
228
- names = names.map {|i| i.downcase }
229
-
230
- @gossip.transaction do
231
- # データを削除
232
- @gossip.data.reject! do |d|
233
- if names.any? {|n| n == d[0] }
234
- if d[2] == ORIGIN
235
- # オリジンは削除不可
236
- errmsg = 'original host name cannot be deleted'
237
- names.reject! {|n| n == d[0] }
238
- false
239
- else
240
- true
241
- end
242
- end
243
- end
244
- end # transaction
245
-
246
- # データベースを更新
247
- delete_by_names(@address, names)
248
-
249
- # ヘルスチェックがあれば停止
250
- names.each do |name|
251
- checker = @health_checkers[name]
252
- checker.stop if checker
253
- end
254
-
255
- return [!errmsg, errmsg]
256
- end
257
-
258
- def add_nodes(nodes)
259
- errmsg = nil
260
-
261
- nodes.each do |i|
262
- @gossip.add_node(i)
263
- end
264
-
265
- return [!errmsg, errmsg]
266
- end
267
-
268
- def delete_nodes(nodes)
269
- errmsg = nil
270
-
271
- nodes.each do |i|
272
- @gossip.delete_node(i)
273
- end
274
-
275
- return [!errmsg, errmsg]
276
- end
277
-
278
- def get_attr(name)
279
- return unless ATTRIBUTES.has_key?(name)
280
-
281
- if name == :log_level
282
- if @gossip.logger
283
- %w(debug info warn error fatal)[@gossip.logger.level]
284
- else
285
- nil
286
- end
287
- else
288
- attr, conv = ATTRIBUTES[name]
289
- @gossip.context.send(attr).to_s
290
- end
291
- end
292
-
293
- def set_attr(name, value)
294
- return unless ATTRIBUTES.has_key?(name)
295
-
296
- errmsg = nil
297
-
298
- if name == :log_level
299
- if @gossip.logger
300
- @gossip.logger.level = %w(debug info warn error fatal).index(value.to_s)
301
- end
302
- else
303
- attr, conv = ATTRIBUTES[name]
304
- @gossip.context.send("#{attr}=", value.send(conv)).to_s
305
- end
306
-
307
- return [!errmsg, errmsg]
308
- end
309
-
310
- def close
311
- # データベースをクローズ
312
- @db.close
313
- end
314
-
315
- # Operation of storage
316
-
317
- def update(address, datas, update_only = false)
318
- return unless datas
319
-
320
- datas.each do |i|
321
- name, ttl, priority, activity = i
322
-
323
- # 名前は小文字に変換
324
- name = name.downcase
325
-
326
- # ホスト名と同じなら警告
327
- if name == @hostname
328
- @logger.warn('same hostname as origin was found')
329
- end
330
-
331
- @db.execute(<<-EOS, address, name, ttl, priority, activity)
332
- REPLACE INTO records (ip_address, name, ttl, priority, activity)
333
- VALUES (?, ?, ?, ?, ?)
334
- EOS
335
- end
336
-
337
- # データにないレコードは消す
338
- unless update_only
339
- names = datas.map {|i| "'#{i.first.downcase}'" }.join(',')
340
-
341
- @db.execute(<<-EOS, address)
342
- DELETE FROM records
343
- WHERE ip_address = ? AND name NOT IN (#{names})
344
- EOS
345
- end
346
- end
347
-
348
- def delete(address)
349
- @db.execute('DELETE FROM records WHERE ip_address = ?', address)
350
- end
351
-
352
- def delete_by_names(address, names)
353
- names = names.map {|i| "'#{i.downcase}'" }.join(',')
354
-
355
- @db.execute(<<-EOS, address)
356
- DELETE FROM records
357
- WHERE ip_address = ? AND name IN (#{names})
358
- EOS
359
- end
360
-
361
- # Search of records
362
-
363
- def address_exist?(name)
364
- # 名前は小文字に変換
365
- name = name.downcase
366
-
367
- # ドメインが指定されていたら削除
368
- name.sub!(/\.#{Regexp.escape(@options[:domain])}\Z/i, '') if @options[:domain]
369
-
370
- # キャッシュを検索
371
- @address_records, cache_time = @cache[name]
372
- now = Time.now
373
-
374
- unless @address_records and now <= cache_time
375
- # キャッシュがない場合
376
-
377
- # シングルスレッドェ…
378
- @address_records = @db.execute(<<-EOS, name, ACTIVE)
379
- SELECT ip_address, ttl, priority FROM records
380
- WHERE name = ? AND activity = ?
381
- EOS
382
-
383
- # レコードがあればキャッシュに入れる
384
- if @address_records.empty?
385
- # ネガティブキャッシュはしない
386
- @cache.delete(name)
387
- else
388
- min_ttl = nil
389
-
390
- # レコードはハッシュに変換する
391
- cache_records = @address_records.map do |i|
392
- ip_address, ttl, priority = i.values_at('ip_address', 'ttl', 'priority')
393
-
394
- if min_ttl.nil? or ttl < min_ttl
395
- min_ttl = ttl
396
- end
397
-
398
- {'ip_address' => ip_address, 'ttl' => ttl, 'priority' => priority}
399
- end
400
-
401
- expire_time = now + min_ttl
402
- @cache[name] = [cache_records, expire_time]
403
- end
404
- end
405
-
406
- @address_records.length.nonzero?
407
- end
408
-
409
- def lookup_addresses(name)
410
- records = nil
411
-
412
- #if @address_records.length == 1
413
- # # レコードが一件ならそれを返す
414
- # return @address_records.map {|i| i.values_at('ip_address', 'ttl') }
415
- #end
416
- @address_record
417
-
418
- # 優先度の高いレコードを検索
419
- #records = @address_records #.select {|i| i['priority'] == MASTER }
420
-
421
- # 次に優先度の高いレコードを検索
422
- #records.concat(shuffle_records(@address_records.select {|i| i['priority'] == SECONDARY }))
423
-
424
- # レコードが見つからなかった場合はバックアップを選択
425
- #if records.empty?
426
- # records = shuffle_records(@address_records.select {|i| i['priority'] == BACKUP })
427
- #end
428
-
429
- # それでもレコードが見つからなかった場合はオリジンを選択
430
- # ※このパスは通らない
431
- #records = @address_records if records.empty?
432
-
433
- # IPアドレス、TTLを返す
434
- #records.map {|i| i.values_at('ip_address', 'ttl') }
435
- ensure
436
- # エラー検出のため、一応クリア
437
- @address_records = nil
438
- end
439
-
440
- def name_exist?(address)
441
- address = x_ip_addr(address)
442
-
443
- # シングルスレッドェ…
444
- @name_records = @db.execute(<<-EOS, address, ACTIVE)
445
- SELECT name, ttl, priority FROM records
446
- WHERE ip_address = ? AND activity = ?
447
- EOS
448
-
449
- @name_records.length.nonzero?
450
- end
451
-
452
- def lookup_name(address)
453
- record = nil
454
-
455
- if @name_records.length == 1
456
- # レコードが一件ならそれを返す
457
- record = @name_records.first
458
- else
459
- # オリジンを検索
460
- record = @name_records.find {|i| i['priority'] == ORIGIN }
461
-
462
- # レコードが見つからなかった場合は優先度の高いレコード選択
463
- unless record
464
- record = @name_records.find {|i| i['priority'] == ACTIVE }
465
- end
466
-
467
- # それでもレコードが見つからなかった場合は優先度の低いレコードを選択
468
- record = @name_records.first unless record
469
- end
470
-
471
- # ホスト名、TTLを返す
472
- return record.values_at('name', 'ttl')
473
- ensure
474
- # エラー検出のため、一応クリア
475
- @name_records = nil
476
- end
477
-
478
- private
479
-
480
- # 乱数でレコードをシャッフルする
481
- def shuffle_records(records)
482
- # レコードが一件の時はそのまま返す
483
- return records if records.length == 1
484
-
485
- # 先頭のAレコードを決定
486
- max_ip_num = [records.length, @options[:max_ip_num]].min
487
- first_index = rand(records.length)
488
-
489
- # Aレコードを返す
490
- (records + records).slice(first_index, max_ip_num)
491
- end
492
-
493
- # リソースレコードのデータベース作成
494
- # もう少し並列処理に強いストレージに変えたいが…
495
- def create_database
496
- @db = SQLite3::Database.new(':memory:')
497
- @db.type_translation = true
498
- @db.results_as_hash = true
499
-
500
- # リソースレコード用のテーブル
501
- # (Typeは必要?)
502
- @db.execute(<<-EOS)
503
- CREATE TABLE records (
504
- ip_address TEXT NOT NULL,
505
- name TEXT NOT NULL,
506
- ttl INTEGER NOT NULL,
507
- priority INTEGER NOT NULL, /* MASTER:1, BACKUP:0, ORIGIN:-1 */
508
- activity INTEGER NOT NULL, /* Active:1, Inactive:0 */
509
- PRIMARY KEY (ip_address, name)
510
- )
511
- EOS
512
-
513
- # インデックスを作成(必要?)
514
- @db.execute(<<-EOS)
515
- CREATE INDEX idx_name_act
516
- ON records (name, activity)
517
- EOS
518
-
519
- @db.execute(<<-EOS)
520
- CREATE INDEX idx_ip_act
521
- ON records (ip_address, activity)
522
- EOS
523
- end
524
-
525
- # 逆引き名の変換
526
- def x_ip_addr(name)
527
- name.sub(/\.in-addr\.arpa\Z/, '').split('.').reverse.join('.')
528
- end
529
-
530
- end # Cloud
531
-
532
- end # Murakumo
@@ -1,101 +0,0 @@
1
- require 'drb/drb'
2
- require 'fileutils'
3
- require 'rexec'
4
- require 'rexec/daemon'
5
- require 'rubydns'
6
- require 'socket'
7
-
8
- require 'srv/murakumo_cloud'
9
-
10
- BasicSocket.do_not_reverse_lookup = true
11
-
12
- module Murakumo
13
-
14
- # RExecに依存しているのでこんな設計に…
15
- class Server < RExec::Daemon::Base
16
-
17
- # クラスメソッドを定義
18
- class << self
19
-
20
- def init(options)
21
- # クラスインスタンス変数を使わないこと
22
- @@options = options
23
- @@cloud = Cloud.new(options)
24
- end
25
-
26
- def pid_directory=(path)
27
- @@pid_directory = path
28
- end
29
-
30
- def run
31
- RubyDNS.run_server(:listen => [[:udp, @@options[:dns_address], @@options[:dns_port]]]) do
32
- # RubyDNS::Serverのコンテキスト
33
- @logger = @@options[:logger] if @@options[:logger]
34
-
35
- on(:start) do
36
- if @@options[:socket]
37
- # 既存のソケットファイルは削除
38
- FileUtils.rm_f(@@options[:socket])
39
-
40
- # ServerクラスをDRuby化
41
- DRb.start_service("drbunix:#{@@options[:socket]}", @@cloud)
42
- at_exit { FileUtils.rm_f(@@options[:socket]) }
43
- end
44
-
45
- # HUPでログをローテート
46
- if @@options[:logger]
47
- trap(:HUP) do
48
- if logger = @@options[:logger]
49
- logdev = logger.instance_variable_get(:@logdev)
50
-
51
- if (dev = logdev.dev).kind_of?(File)
52
- path = dev.path
53
- mutex = logdev.instance_variable_get(:@mutex)
54
-
55
- mutex.synchronize do
56
- dev.reopen(path, 'a')
57
- dev.sync = true
58
- end
59
- end
60
- end
61
- end
62
- end
63
-
64
- # ゴシッププロトコルを開始
65
- @@cloud.start
66
- end
67
-
68
- # look up A record
69
- match(@@cloud.method(:address_exist?), :A) do |transaction|
70
- transaction.append!(Resolv::DNS::Resource::IN::A.new('10.158.59.165'), Resolv::DNS::Resource::IN::A.new('10.148.150.17'))
71
- #records = @@cloud.lookup_addresses(transaction.name)
72
-
73
- #records.each do |r|
74
- # address, ttl = r.values_at('ip_address', 'ttl')
75
- # transaction.respond!(address, :ttl => ttl)
76
- #end
77
- end # match
78
-
79
- # look up PTR record
80
- match(@@cloud.method(:name_exist?), :PTR) do |transaction|
81
- name, ttl = @@cloud.lookup_name(transaction.name)
82
- transaction.respond!(Resolv::DNS::Name.create("#{name}."), :ttl => ttl)
83
- end
84
-
85
- if @@options[:resolver]
86
- otherwise do |transaction|
87
- transaction.passthrough!(@@options[:resolver])
88
- end
89
- end
90
- end # RubyDNS.run_server
91
- end # run
92
-
93
- def shutdown
94
- @@cloud.stop
95
- end
96
-
97
- end # class << self
98
-
99
- end # Server
100
-
101
- end # Murakumo