flare-tools 0.1.4 → 0.4.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/.gemtest +0 -0
  2. data/Flare-tools.txt +0 -0
  3. data/History.txt +114 -2
  4. data/LICENSE +21 -0
  5. data/Manifest.txt +65 -8
  6. data/README.txt +356 -0
  7. data/Rakefile +90 -25
  8. data/Tutorial.txt +370 -0
  9. data/bin/flare-admin +6 -0
  10. data/bin/flare-argv0 +6 -0
  11. data/bin/flare-deploy +6 -0
  12. data/bin/flare-keychecker +6 -0
  13. data/bin/flare-part +6 -0
  14. data/bin/flare-ping +6 -0
  15. data/bin/flare-stats +4 -10
  16. data/bin/flare-zkadmin +6 -0
  17. data/lib/flare/net/connection.rb +98 -0
  18. data/lib/flare/test/cluster.rb +140 -0
  19. data/lib/flare/test/daemon.rb +144 -0
  20. data/lib/flare/test/node.rb +62 -0
  21. data/lib/flare/tools.rb +18 -16
  22. data/lib/flare/tools/cli.rb +32 -0
  23. data/lib/flare/tools/cli/activate.rb +106 -0
  24. data/lib/flare/tools/cli/balance.rb +83 -0
  25. data/lib/flare/tools/cli/cli_util.rb +77 -0
  26. data/lib/flare/tools/cli/deploy.rb +170 -0
  27. data/lib/flare/tools/cli/down.rb +85 -0
  28. data/lib/flare/tools/cli/dump.rb +219 -0
  29. data/lib/flare/tools/cli/dumpkey.rb +117 -0
  30. data/lib/flare/tools/cli/flare_admin.rb +81 -0
  31. data/lib/flare/tools/cli/flare_argv0.rb +60 -0
  32. data/lib/flare/tools/cli/flare_keychecker.rb +106 -0
  33. data/lib/flare/tools/cli/flare_zkadmin.rb +226 -0
  34. data/lib/flare/tools/cli/index.rb +54 -0
  35. data/lib/flare/tools/cli/list.rb +93 -0
  36. data/lib/flare/tools/cli/master.rb +143 -0
  37. data/lib/flare/tools/cli/part.rb +100 -0
  38. data/lib/flare/tools/cli/ping.rb +81 -0
  39. data/lib/flare/tools/cli/reconstruct.rb +164 -0
  40. data/lib/flare/tools/cli/remove.rb +119 -0
  41. data/lib/flare/tools/cli/restore.rb +180 -0
  42. data/lib/flare/tools/cli/slave.rb +125 -0
  43. data/lib/flare/tools/cli/stats.rb +229 -122
  44. data/lib/flare/tools/cli/sub_command.rb +73 -0
  45. data/lib/flare/tools/cli/summary.rb +97 -0
  46. data/lib/flare/tools/cli/threads.rb +78 -0
  47. data/lib/flare/tools/cli/verify.rb +202 -0
  48. data/lib/flare/tools/client.rb +267 -0
  49. data/lib/flare/tools/cluster.rb +319 -0
  50. data/lib/flare/tools/common.rb +196 -0
  51. data/lib/flare/tools/index_server.rb +51 -0
  52. data/lib/flare/tools/node.rb +162 -0
  53. data/lib/flare/tools/stats.rb +75 -0
  54. data/lib/flare/tools/zk_util.rb +28 -0
  55. data/lib/flare/util.rb +34 -0
  56. data/lib/flare/util/bwlimit.rb +132 -0
  57. data/lib/flare/util/command_line.rb +79 -0
  58. data/lib/flare/util/conf.rb +71 -0
  59. data/lib/flare/util/constant.rb +25 -0
  60. data/lib/flare/util/conversion.rb +26 -0
  61. data/lib/flare/util/default_logger.rb +52 -0
  62. data/lib/flare/util/exception.rb +19 -0
  63. data/lib/flare/util/filesystem.rb +30 -0
  64. data/lib/flare/util/flared_conf.rb +33 -0
  65. data/lib/flare/util/flarei_conf.rb +32 -0
  66. data/lib/flare/util/hash_function.rb +32 -0
  67. data/lib/flare/util/interruption.rb +70 -0
  68. data/lib/flare/util/key_resolver.rb +67 -0
  69. data/lib/flare/util/log4r_logger.rb +79 -0
  70. data/lib/flare/util/logger.rb +40 -0
  71. data/lib/flare/util/logging.rb +84 -0
  72. data/lib/flare/util/result.rb +53 -0
  73. data/test/test/experimental/cache_test.rb +113 -0
  74. data/test/test/experimental/key_distribution_test.rb +38 -0
  75. data/test/test/experimental/keychecker_test.rb +60 -0
  76. data/test/test/experimental/list_test.rb +108 -0
  77. data/test/test/extra/replication_test.rb +184 -0
  78. data/test/test/integration/cli_test.rb +348 -0
  79. data/test/test/integration/dump_expired_test.rb +103 -0
  80. data/test/test/integration/dump_test.rb +128 -0
  81. data/test/test/integration/index_server_test.rb +35 -0
  82. data/test/test/integration/node_test.rb +78 -0
  83. data/test/test/integration/partition_test.rb +235 -0
  84. data/test/test/integration/proxy_test.rb +54 -0
  85. data/test/test/integration/stats_test.rb +79 -0
  86. data/test/test/system/flare_admin_test.rb +191 -0
  87. data/test/test/unit/bwlimit_test.rb +52 -0
  88. data/test/test/unit/cluster_test.rb +96 -0
  89. data/test/test/unit/daemon_test.rb +30 -0
  90. data/test/test/unit/logger_test.rb +46 -0
  91. data/test/test/unit/tools_test.rb +25 -0
  92. data/test/test/unit/util_test.rb +70 -0
  93. metadata +239 -84
  94. data/README.rdoc +0 -83
  95. data/bin/flare-partition-setting +0 -12
  96. data/lib/flare/tools/cli/partition_setting.rb +0 -86
  97. data/lib/flare/tools/core.rb +0 -189
  98. data/lib/flare/tools/logger.rb +0 -31
  99. data/test/test_flare-tools.rb +0 -11
  100. data/test/test_helper.rb +0 -3
@@ -0,0 +1,93 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/index_server'
7
+ require 'flare/tools/cluster'
8
+ require 'flare/tools/common'
9
+ require 'flare/util/conversion'
10
+ require 'flare/tools/cli/sub_command'
11
+
12
+ #
13
+ module Flare
14
+ module Tools
15
+ module Cli
16
+
17
+ # == Description
18
+ #
19
+ class List < SubCommand
20
+ include Flare::Util::Conversion
21
+ include Flare::Tools::Common
22
+
23
+ myname :list
24
+ desc "show the list of nodes in a flare cluster."
25
+ usage "list"
26
+
27
+ HeaderConfig = [ ['%-32s', 'node'],
28
+ ['%9s', 'partition'],
29
+ ['%6s', 'role'],
30
+ ['%6s', 'state'],
31
+ ['%7s', 'balance'] ]
32
+
33
+ def setup(opt)
34
+ opt.on('--numeric-hosts', "show numerical host addresses") {@numeric_hosts = true}
35
+ end
36
+
37
+ def initialize
38
+ super
39
+ @numeric_hosts = false
40
+ @format = HeaderConfig.map {|x| x[0]}.join(' ')
41
+ @cout = STDOUT
42
+ end
43
+
44
+ def print_header
45
+ @cout.puts @format % HeaderConfig.map{|x| x[1]}.flatten
46
+ nil
47
+ end
48
+
49
+ def print_node *args
50
+ @cout.puts @format % args
51
+ nil
52
+ end
53
+
54
+ def get_address_or_remain hostname
55
+ begin
56
+ Resolv.getaddress(hostname)
57
+ rescue Resolv::ResolvError
58
+ hostname
59
+ end
60
+ end
61
+
62
+ def execute(config, *args)
63
+ if args.size > 0
64
+ error "invalid arguments: "+args.join(' ')
65
+ return S_NG
66
+ end
67
+
68
+ cluster = Flare::Tools::IndexServer.open(config[:index_server_hostname],
69
+ config[:index_server_port], config[:timeout]) do |s|
70
+ Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
71
+ end
72
+
73
+ if cluster.nil?
74
+ error "Invalid index server."
75
+ return S_NG
76
+ end
77
+
78
+ print_header
79
+ cluster.nodekeys.each do |nodekey|
80
+ data = cluster.node_stat(nodekey)
81
+ hostname, port = nodekey.split(":", 2)
82
+ hostname = get_address_or_remain(hostname) if @numeric_hosts
83
+ partition = (data.partition == -1) ? "-" : data.partition
84
+ print_node nodekey_of(hostname, port), partition, data.role, data.state, data.balance
85
+ end
86
+
87
+ S_OK
88
+ end
89
+
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/stats'
7
+ require 'flare/tools/index_server'
8
+ require 'flare/tools/common'
9
+ require 'flare/tools/cluster'
10
+ require 'flare/util/conversion'
11
+ require 'flare/util/constant'
12
+ require 'flare/tools/cli/sub_command'
13
+
14
+ module Flare
15
+ module Tools
16
+ module Cli
17
+ class Master < SubCommand
18
+ include Flare::Util::Conversion
19
+ include Flare::Util::Constant
20
+ include Flare::Tools::Common
21
+
22
+ myname :master
23
+ desc "construct a partition with a proxy node for master role."
24
+ usage "master [hostname:port:balance:partition] ..."
25
+
26
+ def setup(opt)
27
+ opt.on('--force', "commit changes without confirmation" ) {@force = true}
28
+ opt.on('--retry=COUNT', "specify retry count (default:#{@retry})" ) {|v| @retry = v.to_i}
29
+ opt.on('--activate', "change node's state from ready to active") {@activate = true}
30
+ end
31
+
32
+ def initialize
33
+ @force = false
34
+ @retry = 10
35
+ @activate = false
36
+ end
37
+
38
+ def execute(config, *args)
39
+ status = S_OK
40
+
41
+ return S_NG if args.empty?
42
+ hosts = args.map {|x| x.to_s.split(':')}
43
+ hosts.each do |x|
44
+ if x.size != 4
45
+ error "invalid argument '#{x.join(':')}'."
46
+ return S_NG
47
+ end
48
+ if x[2].to_i <= 0
49
+ error "invalid balance '#{x.join(':')}'."
50
+ return S_NG
51
+ end
52
+ if nodekey_of(x[0..1]).nil?
53
+ error "invalid nodekey '#{x.join(':')}'."
54
+ return S_NG
55
+ end
56
+ end
57
+ hosts = hosts.sort_by{|hostname,port,balance,partition| [partition]}
58
+
59
+ Flare::Tools::IndexServer.open(config[:index_server_hostname], config[:index_server_port], config[:timeout]) do |s|
60
+ cluster = Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
61
+
62
+ hosts.each do |hostname,port,balance,partition|
63
+ role = 'master'
64
+ nodekey = nodekey_of hostname, port
65
+ ipaddr = address_of_hostname(hostname)
66
+
67
+ unless cluster.has_nodekey? nodekey
68
+ error "unknown host: #{nodekey}"
69
+ # return S_NG
70
+ end
71
+
72
+ node = cluster.node_stat(nodekey)
73
+
74
+ partition = if partition == '' then node['partition'].to_i else partition.to_i end
75
+ balance = if balance == '' then node['balance'] else balance.to_i end
76
+ existing_master = cluster.master_in_partition(partition)
77
+
78
+ exec = false
79
+ if @force
80
+ exec = true
81
+ elsif node['role'] == role
82
+ info "no need to change the role of #{ipaddr}:#{port}."
83
+ elsif existing_master
84
+ info "the partiton already has a master #{existing_master}."
85
+ else
86
+ STDERR.print "making the node master (node=#{ipaddr}:#{port}, role=#{node['role']} -> #{role}) (y/n): "
87
+ exec = interruptible {(gets.chomp.upcase == "Y")}
88
+ end
89
+ if exec && !config[:dry_run]
90
+ nretry = 0
91
+ resp = false
92
+ while resp == false && nretry < @retry
93
+ resp = s.set_role(hostname, port, role, balance, partition)
94
+ if resp
95
+ info "started constructing the master node..."
96
+ else
97
+ nretry += 1
98
+ info "waiting #{nretry} sec..."
99
+ sleep nretry
100
+ info "retrying..."
101
+ end
102
+ end
103
+ if resp
104
+ state = wait_for_master_construction(s, nodekey, config[:timeout])
105
+ if state == 'ready' && @activate
106
+ unless @force
107
+ node = s.stats_nodes[nodekey]
108
+ STDERR.print "changing node's state (node=#{ipaddr}:#{port}, state=#{node['state']} -> active) (y/n): "
109
+ exec = interruptible {
110
+ (gets.chomp.upcase == "Y")
111
+ }
112
+ end
113
+ if exec
114
+ begin
115
+ resp = s.set_state(hostname, port, 'active')
116
+ unless resp
117
+ error "failed to activate #{nodekey}"
118
+ status = S_NG
119
+ end
120
+ rescue Timeout::Error
121
+ error "failed to activate #{nodekey} (timeout)"
122
+ status = S_NG
123
+ end
124
+ end
125
+ end
126
+ else
127
+ error "failed to change the state."
128
+ status = S_NG
129
+ end
130
+ end
131
+ end
132
+
133
+ break if status == S_NG
134
+ STDOUT.puts string_of_nodelist(s.stats_nodes, hosts.map {|x| "#{x[0]}:#{x[1]}"})
135
+ end
136
+
137
+ status
138
+ end # execute()
139
+
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,100 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/stats'
7
+ require 'flare/tools/index_server'
8
+ require 'flare/tools/common'
9
+ require 'flare/util/conversion'
10
+ require 'flare/util/constant'
11
+ require 'flare/tools/cli/sub_command'
12
+ require 'flare/tools/cli/slave'
13
+ require 'flare/tools/cli/master'
14
+
15
+ module Flare
16
+ module Tools
17
+ module Cli
18
+ class Part < SubCommand
19
+ include Flare::Util::Conversion
20
+ include Flare::Util::Constant
21
+ include Flare::Tools::Common
22
+
23
+ myname :part
24
+ desc "set the master of a partition."
25
+ usage "master [hostname:port:balance:partition] ..."
26
+
27
+ def setup(opt)
28
+ opt.on('--force', "commits changes without confirmation") {@force = true}
29
+ opt.on('--retry=COUNT', "retry count" ) {|v| @retry = v.to_i}
30
+ end
31
+
32
+ def initialize
33
+ super
34
+ @force = false
35
+ @retry = nil
36
+ end
37
+
38
+ def execute(config, *args)
39
+ return S_NG if args.size < 1
40
+
41
+ hosts = args.map {|x| x.to_s.split(':')}
42
+ hosts.each do |x|
43
+ if x.size != 4
44
+ puts "invalid argument '#{x.join(':')}'."
45
+ return S_NG
46
+ end
47
+ end
48
+
49
+ masters = []
50
+ slaves = []
51
+
52
+ Flare::Tools::IndexServer.open(config[:index_server_hostname], config[:index_server_port], config[:timeout]) do |s|
53
+ cluster = Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
54
+
55
+ partitions = {}
56
+ hosts.each do |hostname,port,balance,partition|
57
+ partitions[partition] = [] unless partitions.has_key? partition
58
+ partitions[partition] << "#{hostname}:#{port}:#{balance}:#{partition}"
59
+ end
60
+
61
+ partitions.sort_by {|p,nodes| p.to_i }.each do |p,nodes|
62
+ masters << nodes.shift
63
+ end
64
+
65
+ partitions.each do |p,nodes|
66
+ slaves.concat nodes
67
+ end
68
+ end
69
+
70
+ puts "master:"
71
+ begin
72
+ opt = OptionParser.new
73
+ subc = Flare::Tools::Cli::Master.new
74
+ subc.setup(opt)
75
+ args = masters
76
+ args << "--force" if @force
77
+ args << "--activate"
78
+ opt.parse!(args)
79
+ subc.execute(config, *args)
80
+ end
81
+
82
+ puts "slaves:"
83
+ begin
84
+ opt = OptionParser.new
85
+ subc = Flare::Tools::Cli::Slave.new
86
+ subc.setup(opt)
87
+ args = slaves
88
+ args << "--force" if @force
89
+ args << "--retry=#{@retry}" unless @retry.nil?
90
+ opt.parse!(args)
91
+ subc.execute(config, *args)
92
+ end
93
+
94
+ S_OK
95
+ end # execute()
96
+
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,81 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/index_server'
7
+ require 'flare/util/conversion'
8
+ require 'flare/util/logging'
9
+ require 'flare/tools/cli/sub_command'
10
+
11
+ #
12
+ module Flare
13
+ module Tools
14
+
15
+ # == Description
16
+ #
17
+ module Cli
18
+ class Ping < SubCommand
19
+ include Flare::Util::Conversion
20
+ include Flare::Util::Logging
21
+
22
+ myname :ping
23
+ desc "ping"
24
+ usage "ping [hostname:port] ..."
25
+
26
+ def setup(opt)
27
+ opt.on('--wait', "wait for OK responses from nodes") {@wait = true}
28
+ end
29
+
30
+ def initialize
31
+ super
32
+ @wait = false
33
+ end
34
+
35
+ def execute(config, *args)
36
+
37
+ hosts = args.map do |arg|
38
+ hostname, port, rest = arg.split(':', 3)
39
+ if !rest.nil? || hostname.nil? || hostname.empty? || port.nil? || port.empty?
40
+ error "invalid argument '#{arg}'. it must be hostname:port."
41
+ return S_NG
42
+ end
43
+ begin
44
+ ipaddr = Resolv.getaddress(hostname)
45
+ rescue Resolv::ResolvError
46
+ error "unknown host '#{hostname}'"
47
+ return S_NG
48
+ end
49
+ [hostname, port]
50
+ end
51
+
52
+ hosts.each do |hostname, port|
53
+ resp = nil
54
+ until resp
55
+ begin
56
+ debug "trying..."
57
+ interruptible do
58
+ Flare::Tools::Stats.open(hostname, port, config[:timeout]) do |s|
59
+ resp = s.ping
60
+ end
61
+ end
62
+ rescue IOError
63
+ return S_NG
64
+ rescue
65
+ unless @wait
66
+ puts "#{hostname}:#{port} is down"
67
+ return S_NG
68
+ end
69
+ interruptible {sleep 1}
70
+ end
71
+ end
72
+ end
73
+
74
+ puts "alive"
75
+ S_OK
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,164 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/stats'
7
+ require 'flare/tools/node'
8
+ require 'flare/tools/index_server'
9
+ require 'flare/tools/cluster'
10
+ require 'flare/tools/common'
11
+ require 'flare/util/conversion'
12
+ require 'flare/util/constant'
13
+ require 'flare/tools/cli/sub_command'
14
+
15
+ module Flare
16
+ module Tools
17
+ module Cli
18
+ class Reconstruct < SubCommand
19
+ include Flare::Util::Conversion
20
+ include Flare::Util::Constant
21
+ include Flare::Tools::Common
22
+
23
+ myname :reconstruct
24
+ desc "reconstruct the database of nodes by copying."
25
+ usage "reconstruct [hostname:port] ..."
26
+
27
+ def setup(opt)
28
+ opt.on('--force', "commit changes without confirmation" ) {@force = true}
29
+ opt.on('--safe', "reconstruct a node safely" ) {@safe = true}
30
+ opt.on('--retry=COUNT', "specify retry count (default:#{@retry})") {|v| @retry = v.to_i}
31
+ opt.on('--all', "reconstruct all nodes" ) {@all = true}
32
+ end
33
+
34
+ def initialize
35
+ super
36
+ @force = false
37
+ @safe = false
38
+ @retry = 10
39
+ @all = false
40
+ end
41
+
42
+ def execute(config, *args)
43
+ if @all
44
+ unless args.empty?
45
+ puts "don't specify any nodes with --all option."
46
+ return S_NG
47
+ else
48
+ Flare::Tools::IndexServer.open(config[:index_server_hostname], config[:index_server_port], config[:timeout]) do |s|
49
+ cluster = Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
50
+ args = cluster.master_and_slave_nodekeys
51
+ end
52
+ end
53
+ else
54
+ return S_NG if args.size == 0
55
+ end
56
+
57
+ hosts = args.map {|x| x.to_s.split(':')}
58
+ hosts.each do |x|
59
+ if x.size != 2
60
+ puts "invalid argument '#{x.join(':')}'. it must be hostname:port."
61
+ return S_NG
62
+ end
63
+ end
64
+
65
+ status = S_OK
66
+
67
+ Flare::Tools::IndexServer.open(config[:index_server_hostname], config[:index_server_port], config[:timeout]) do |s|
68
+ puts string_of_nodelist(s.stats_nodes, hosts.map {|x| nodekey_of(x[0], x[1])})
69
+
70
+ hosts.each do |hostname,port|
71
+ nodekey = nodekey_of hostname, port
72
+ cluster = Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
73
+
74
+ unless node = cluster.node_stat(nodekey)
75
+ puts "#{nodekey} is not found in this cluster."
76
+ return S_NG
77
+ end
78
+ unless cluster.reconstructable? nodekey
79
+ puts "#{nodekey} is not reconstructable."
80
+ status = S_NG
81
+ next
82
+ end
83
+ is_safe = cluster.safely_reconstructable? nodekey
84
+ if @safe && !is_safe
85
+ puts "The partition needs one more slave to reconstruct #{nodekey} safely."
86
+ status = S_NG
87
+ next
88
+ end
89
+
90
+ exec = @force
91
+ unless exec
92
+ puts "you are trying to reconstruct #{nodekey} without redanduncy." unless is_safe
93
+ input = nil
94
+ while input.nil?
95
+ STDERR.print "reconstructing node (node=#{nodekey}, role=#{node['role']}) (y/n/a/q/h:help): "
96
+ input = interruptible do
97
+ gets.chomp.upcase
98
+ end
99
+ case input
100
+ when "A"
101
+ @force = true
102
+ exec = true
103
+ when "N"
104
+ when "Q"
105
+ return S_OK
106
+ when "Y"
107
+ exec = true
108
+ else
109
+ puts "y: execute, n: skip, a: execute all the left nodes, q: quit, h: help"
110
+ input = nil
111
+ end
112
+ end
113
+ end
114
+ if exec && !config[:dry_run]
115
+ puts "turning down..."
116
+ s.set_state(hostname, port, 'down')
117
+
118
+ puts "waiting for node to be active again..."
119
+ sleep 3
120
+
121
+ Flare::Tools::Node.open(hostname, port, config[:timeout]) do |n|
122
+ n.flush_all
123
+ end
124
+
125
+ nretry = 0
126
+ resp = false
127
+ while resp == false && nretry < @retry
128
+ resp = s.set_role(hostname, port, 'slave', 0, node['partition'])
129
+ if resp
130
+ puts "started constructing node..."
131
+ else
132
+ nretry += 1
133
+ puts "waiting #{nretry} sec..."
134
+ sleep nretry
135
+ puts "retrying..."
136
+ end
137
+ end
138
+ balance = node['balance']
139
+ if resp
140
+ wait_for_slave_construction(s, nodekey, config[:timeout])
141
+ unless @force
142
+ print "changing node's balance (node=#{nodekey}, balance=0 -> #{balance}) (y/n): "
143
+ exec = interruptible {(gets.chomp.upcase == "Y")}
144
+ end
145
+ s.set_role(hostname, port, 'slave', node['balance'], node['partition']) if exec
146
+ puts "done."
147
+ else
148
+ error "failed to change the state."
149
+ status = S_NG
150
+ end
151
+ end
152
+ @force = false if interrupted?
153
+ end
154
+
155
+ puts string_of_nodelist(s.stats_nodes, hosts.map {|x| "#{x[0]}:#{x[1]}"})
156
+ end # open
157
+
158
+ status
159
+ end # execute()
160
+
161
+ end
162
+ end
163
+ end
164
+ end