murakumo 0.3.0 → 0.3.1

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.
@@ -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