drbqs 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/.document +3 -0
  2. data/README.md +137 -128
  3. data/VERSION +1 -1
  4. data/docs/FormatExecute.md +119 -0
  5. data/docs/GettingStarted.md +242 -0
  6. data/drbqs.gemspec +36 -13
  7. data/example/command/server_def.rb +4 -5
  8. data/example/execute/execute.rb +41 -0
  9. data/example/execute/server.rb +14 -0
  10. data/example/execute/task.rb +0 -0
  11. data/example/mandelbrot/README.md +15 -0
  12. data/example/mandelbrot/execute.rb +10 -0
  13. data/example/mandelbrot/mandelbrot.rb +56 -0
  14. data/example/mandelbrot/server.rb +49 -0
  15. data/example/server/server.rb +3 -6
  16. data/example/simple/README.md +18 -0
  17. data/example/simple/execute.rb +11 -0
  18. data/example/simple/server.rb +8 -0
  19. data/example/simple/task.rb +11 -0
  20. data/example/sum/server_def.rb +1 -1
  21. data/example/sum2/execute_def.rb +21 -8
  22. data/example/sum2/server_def.rb +8 -7
  23. data/example/transfer/file.rb +42 -8
  24. data/example/transfer/server_def.rb +43 -9
  25. data/lib/drbqs.rb +1 -1
  26. data/lib/drbqs/command_line/command_execute.rb +3 -3
  27. data/lib/drbqs/command_line/command_line.rb +1 -1
  28. data/lib/drbqs/execute/execute_node.rb +50 -0
  29. data/lib/drbqs/execute/process_define.rb +102 -54
  30. data/lib/drbqs/execute/register.rb +241 -87
  31. data/lib/drbqs/execute/server_define.rb +69 -58
  32. data/lib/drbqs/ext/task.rb +2 -0
  33. data/lib/drbqs/ext/task/command_task.rb +43 -0
  34. data/lib/drbqs/manage/manage.rb +5 -4
  35. data/lib/drbqs/manage/ssh_shell.rb +2 -8
  36. data/lib/drbqs/node/connection.rb +1 -1
  37. data/lib/drbqs/node/node.rb +8 -14
  38. data/lib/drbqs/node/task_client.rb +1 -1
  39. data/lib/drbqs/server/history.rb +5 -1
  40. data/lib/drbqs/server/message.rb +7 -34
  41. data/lib/drbqs/server/queue.rb +14 -2
  42. data/lib/drbqs/server/server.rb +86 -43
  43. data/lib/drbqs/server/server_hook.rb +3 -0
  44. data/lib/drbqs/server/test/node.rb +1 -1
  45. data/lib/drbqs/server/test/prof.rb +50 -0
  46. data/lib/drbqs/server/test/server.rb +2 -2
  47. data/lib/drbqs/server/transfer_setting.rb +23 -11
  48. data/lib/drbqs/setting/base.rb +15 -0
  49. data/lib/drbqs/setting/data_container.rb +1 -1
  50. data/lib/drbqs/setting/execute.rb +3 -3
  51. data/lib/drbqs/setting/node.rb +1 -1
  52. data/lib/drbqs/setting/server.rb +2 -2
  53. data/lib/drbqs/task/registrar.rb +39 -0
  54. data/lib/drbqs/task/task.rb +139 -59
  55. data/lib/drbqs/task/task_generator.rb +93 -116
  56. data/lib/drbqs/utility/misc.rb +15 -10
  57. data/lib/drbqs/utility/temporary.rb +7 -2
  58. data/lib/drbqs/utility/transfer/transfer.rb +81 -0
  59. data/lib/drbqs/utility/transfer/transfer_client.rb +68 -69
  60. data/lib/drbqs/utility/transfer/transfer_client_connect.rb +83 -0
  61. data/lib/drbqs/utility/transfer/transfer_file_list.rb +40 -0
  62. data/spec/execute/def/execute1.rb +4 -4
  63. data/spec/execute/def/execute2.rb +24 -0
  64. data/spec/execute/process_define_spec.rb +43 -6
  65. data/spec/execute/register_spec.rb +403 -9
  66. data/spec/execute/server_define_spec.rb +1 -1
  67. data/spec/ext/task/command_task_spec.rb +16 -0
  68. data/spec/integration_test/01_basic_usage_spec.rb +1 -1
  69. data/spec/integration_test/02_use_generator_spec.rb +2 -2
  70. data/spec/integration_test/04_use_unix_domain_spec.rb +1 -1
  71. data/spec/integration_test/05_server_exit_signal_spec.rb +1 -1
  72. data/spec/integration_test/06_node_exit_after_task_spec.rb +4 -4
  73. data/spec/integration_test/08_shutdown_unused_nodes_spec.rb +2 -2
  74. data/spec/integration_test/09_server_process_data_spec.rb +1 -1
  75. data/spec/integration_test/definition/server01.rb +4 -5
  76. data/spec/integration_test/definition/server02.rb +2 -4
  77. data/spec/node/node_spec.rb +34 -0
  78. data/spec/server/message_spec.rb +1 -1
  79. data/spec/server/queue_spec.rb +34 -7
  80. data/spec/server/server_spec.rb +21 -9
  81. data/spec/server/transfer_setting_spec.rb +59 -24
  82. data/spec/setting/base_spec.rb +11 -0
  83. data/spec/setting/data_container_spec.rb +8 -0
  84. data/spec/spec_helper.rb +1 -7
  85. data/spec/task/registrar_spec.rb +34 -0
  86. data/spec/task/task_generator_spec.rb +15 -15
  87. data/spec/task/task_spec.rb +132 -23
  88. data/spec/utility/misc_spec.rb +2 -2
  89. data/spec/utility/transfer/transfer_client_connect_spec.rb +90 -0
  90. data/spec/utility/transfer/transfer_file_list_spec.rb +27 -0
  91. data/spec/{task/file_transfer_spec.rb → utility/transfer/transfer_spec.rb} +24 -24
  92. metadata +66 -45
  93. data/lib/drbqs/manage/execute_node.rb +0 -50
  94. data/lib/drbqs/server/prof.rb +0 -48
  95. data/lib/drbqs/task/command_task.rb +0 -43
  96. data/lib/drbqs/utility/transfer/file_transfer.rb +0 -73
@@ -0,0 +1,50 @@
1
+ module DRbQS
2
+ class Execution
3
+ class ExecuteNode
4
+ attr_reader :pid
5
+
6
+ def initialize(uri, log_prefix, log_level, node_opts = {})
7
+ @uri = uri
8
+ @log_level = log_level
9
+ if log_prefix
10
+ @fname = FileName.new(log_prefix, :position => :suffix, :type => :time,
11
+ :add => :always, :directory => :parent,
12
+ :format => lambda { |t| t.strftime("%Y%m%d_%H%M_#{Process.pid}.log") })
13
+ else
14
+ @fname = nil
15
+ end
16
+ @pid = []
17
+ @node_opts = node_opts
18
+ end
19
+
20
+ def get_log_file
21
+ if @fname
22
+ return @fname.create
23
+ end
24
+ return STDOUT
25
+ end
26
+ private :get_log_file
27
+
28
+ def create_process
29
+ @pid << fork do
30
+ opts = @node_opts.merge({ :log_level => @log_level, :log_file => get_log_file })
31
+ node = DRbQS::Node.new(@uri, opts)
32
+ node.connect
33
+ node.calculate
34
+ end
35
+ end
36
+ private :create_process
37
+
38
+ def execute(process_num, interval = 0)
39
+ process_num.times do |i|
40
+ create_process
41
+ sleep(interval) if interval > 0
42
+ end
43
+ end
44
+
45
+ def wait
46
+ Process.waitall
47
+ end
48
+ end
49
+ end
50
+ end
@@ -2,11 +2,6 @@ require 'drbqs/execute/register'
2
2
 
3
3
  module DRbQS
4
4
  class ProcessDefinition
5
- class InvalidServerDefinition < StandardError
6
- end
7
-
8
- class InvalidNodeDefinition < StandardError
9
- end
10
5
 
11
6
  attr_reader :register
12
7
 
@@ -34,13 +29,19 @@ module DRbQS
34
29
  end
35
30
 
36
31
  def get_server_setting(name = nil)
37
- if data = (name ? @register.__server__.assoc(name.intern) : @register.__server__[0])
38
- { :name => data[0], :type => data[1][:type], :setting => data[1][:setting], :hostname => data[1][:args][0] }
39
- elsif name
40
- get_server_setting(nil)
41
- else
42
- nil
32
+ if !name
33
+ data = nil
34
+ @register.__server__.each do |server_data|
35
+ unless server_data[1][:template]
36
+ data = server_data
37
+ break
38
+ end
39
+ end
40
+ return nil unless data
41
+ elsif !(data = @register.__server__.assoc(name.intern))
42
+ return get_server_setting(nil)
43
43
  end
44
+ data
44
45
  end
45
46
  private :get_server_setting
46
47
 
@@ -54,16 +55,33 @@ module DRbQS
54
55
  private :get_node_data
55
56
 
56
57
  def each_node(names = nil, &block)
57
- if names
58
- names.each do |name|
59
- if data = get_node_data(name)
60
- yield(name, data)
58
+ if block_given?
59
+ if names
60
+ node_data = []
61
+ i = 0
62
+ while i < names.size
63
+ name = names[i]
64
+ if data = get_node_data(name)
65
+ if data[:template]
66
+ if :group == data[:type]
67
+ data[:args].each do |n|
68
+ names << n unless names.include?(n)
69
+ end
70
+ end
71
+ else
72
+ node_data << [name, data]
73
+ end
74
+ end
75
+ i += 1
76
+ end
77
+ node_data.each do |data|
78
+ yield(*data)
61
79
  end
80
+ else
81
+ each_node(@register.__node__.map { |name, data| name }, &block)
62
82
  end
63
83
  else
64
- @register.__node__.each do |name, data|
65
- yield(name, data)
66
- end
84
+ to_enum(:each_node, names)
67
85
  end
68
86
  end
69
87
  private :each_node
@@ -79,20 +97,24 @@ module DRbQS
79
97
  private :server_port
80
98
 
81
99
  def server_uri(name)
82
- data = get_server_setting(name)
83
- DRbQS::Misc.create_uri(:host => data[:hostname], :port => server_port)
100
+ if ary = get_server_setting(name)
101
+ DRbQS::Misc.create_uri(:host => ary[1][:args][0], :port => server_port)
102
+ else
103
+ nil
104
+ end
84
105
  end
85
106
  private :server_uri
86
107
 
87
108
  def execute_server(server_args)
88
- if data = get_server_setting(@server)
89
- name = data[:name].to_s
90
- puts_progress "Execute server '#{name}' (#{data[:type]})"
109
+ if ary = get_server_setting(@server)
110
+ name = ary[0].to_s
111
+ data = ary[1]
112
+ puts_progress "Execute server '#{name}' (#{data[:ssh] ? 'ssh' : 'local'})"
91
113
  setting = data[:setting]
92
- hostname = data[:hostname]
114
+ hostname = data[:args][0]
93
115
  type = data[:type]
94
- if type == :ssh
95
- setting.value.connect name
116
+ if data[:ssh]
117
+ setting.value.connect name unless setting.set?(:connect)
96
118
  server_setting = setting.mode_setting
97
119
  else
98
120
  server_setting = setting
@@ -104,7 +126,7 @@ module DRbQS
104
126
  server_setting.value.sftp_host hostname
105
127
  end
106
128
  setting.parse!
107
- unless type == :ssh
129
+ unless data[:ssh]
108
130
  server_setting.value.argument.each do |path|
109
131
  unless File.exist?(path)
110
132
  raise "File '#{path}' does not exist."
@@ -115,20 +137,23 @@ module DRbQS
115
137
  end
116
138
  rescue Exception => err
117
139
  puts_progress "Fail to execute server '#{data[:name].to_s}'"
118
- mes = "#{err.to_s} (#{err.class.to_s})"
119
- mes = "#{setting.string_for_shell}; " << mes if setting.respond_to?(:string_for_shell)
120
- new_err = InvalidServerDefinition.new(mes)
140
+ mes = "Invalid server definition: #{err.to_s} (#{err.class.to_s})"
141
+ begin
142
+ mes = "#{setting.string_for_shell}; " << mes if setting.respond_to?(:string_for_shell)
143
+ rescue
144
+ end
145
+ new_err = err.class.new(mes)
121
146
  new_err.set_backtrace(err.backtrace)
122
147
  raise new_err
123
148
  end
124
149
 
125
150
  def execute_one_node(name, data, uri)
126
- puts_progress "Execute node '#{name}' (#{data[:type]})"
151
+ puts_progress "Execute node '#{name}' (#{data[:ssh] ? 'ssh' : 'local'})"
127
152
  setting = data[:setting]
128
- node_setting = (data[:type] == :ssh ? setting.mode_setting : setting)
153
+ node_setting = (data[:ssh] ? setting.mode_setting : setting)
129
154
  node_setting.value.argument.clear
130
155
  node_setting.value.connect uri
131
- if data[:type] == :ssh
156
+ if data[:ssh]
132
157
  unless setting.set?(:connect)
133
158
  setting.value.connect name.to_s
134
159
  end
@@ -142,17 +167,25 @@ module DRbQS
142
167
  setting.exec
143
168
  rescue Exception => err
144
169
  puts_progress "Fail to execute node '#{name.to_s}'"
145
- mes = "#{err.to_s} (#{err.class.to_s})"
146
- mes = "#{setting.string_for_shell}; " << mes if setting.respond_to?(:string_for_shell)
147
- new_err = InvalidNodeDefinition.new(mes)
170
+ mes = "Invalid node definition: #{err.to_s} (#{err.class.to_s})"
171
+ begin
172
+ mes = "#{setting.string_for_shell}; " << mes if setting.respond_to?(:string_for_shell)
173
+ rescue
174
+ end
175
+ new_err = err.class.new(mes)
148
176
  new_err.set_backtrace(err.backtrace)
149
177
  raise new_err
150
178
  end
151
179
  private :execute_one_node
152
180
 
181
+ def each_node_to_execute(&block)
182
+ each_node(@node || @register.__default__[:node], &block)
183
+ end
184
+ private :each_node_to_execute
185
+
153
186
  def execute_node
154
187
  uri = server_uri(@server)
155
- each_node(@node) do |name, data|
188
+ each_node_to_execute do |name, data|
156
189
  execute_one_node(name, data, uri)
157
190
  end
158
191
  end
@@ -160,37 +193,52 @@ module DRbQS
160
193
  def information
161
194
  info = {}
162
195
  info[:server] = @register.__server__.map do |name, data|
163
- [name, data[:type]]
196
+ new_data = data.dup
197
+ new_data.delete(:setting)
198
+ [name, new_data]
164
199
  end
165
200
  info[:node] = @register.__node__.map do |name, data|
166
- [name, data[:type]]
201
+ new_data = data.dup
202
+ new_data.delete(:setting)
203
+ [name, new_data]
167
204
  end
168
- if data = get_server_setting(@server)
169
- default_server = data[:name]
205
+ if ary = get_server_setting(@server)
206
+ default_server = ary[0]
170
207
  else
171
208
  default_server = nil
172
209
  end
173
- info[:default] = {
174
- :server => default_server,
175
- :node => @node || info[:node].map { |ary| ary[0]},
176
- :port => server_port
177
- }
210
+ default_nodes = each_node_to_execute.map do |node_name, node_data|
211
+ node_name
212
+ end
213
+ info[:default] = { :server => default_server, :node => default_nodes, :port => server_port }
178
214
  info
179
215
  end
180
216
 
181
217
  def information_string
182
218
  info = information
183
219
  str = "Server:\n"
184
- info[:server].each do |name, type|
185
- s = sprintf("%- 16s %s\n", name, (type == :ssh ? 'ssh' : 'local'))
186
- str << (info[:default][:server] == name ? "* " : " ")
187
- str << s
220
+ ary = (info[:server] + info[:node]).map do |name, data|
221
+ name.size
222
+ end
223
+ string_name_size = ary.max
224
+ info[:server].each do |name, data|
225
+ prop = (data[:ssh] ? 'ssh' : 'local')
226
+ prop << ',template' if data[:template]
227
+ str << (data[:template] ? " - " : (info[:default][:server] == name ? " * " : " "))
228
+ str << sprintf("%- #{string_name_size}s %s\n", name, prop)
188
229
  end
189
230
  str << "Node:\n"
190
- info[:node].each do |name, type|
191
- s = sprintf("%- 16s %s\n", name, (type == :ssh ? 'ssh' : 'local'))
192
- str << (info[:default][:node].include?(name) ? " " : "- ")
193
- str << s
231
+ info[:node].each do |name, data|
232
+ if data[:type] == :group
233
+ prop = 'group: ' << data[:args].map(&:to_s).join(',')
234
+ else
235
+ prop = (data[:ssh] ? 'ssh' : 'local')
236
+ if data[:template]
237
+ prop << ',template'
238
+ end
239
+ end
240
+ str << (data[:template] ? " - " : (info[:default][:node].include?(name) ? " * " : " "))
241
+ str << sprintf("%- #{string_name_size}s %s\n", name, prop)
194
242
  end
195
243
  str << "Port: #{info[:default][:port]}"
196
244
  end
@@ -1,48 +1,86 @@
1
1
  module DRbQS
2
2
  class ProcessDefinition
3
3
  class Register
4
- attr_reader :__server__, :__node__, :__default__, :__usage__
4
+ # @return [Array] an array of pair [name symbol, definition hash]
5
+ # Keys of the hash are :type, :template, :ssh, :setting, and :args.
6
+ attr_reader :__server__, :__node__
7
+
8
+ # @return [Array] a hash of key and value
9
+ attr_reader :__default__, :__usage__
5
10
 
6
11
  def initialize
7
12
  @__server__ = []
8
13
  @__node__ = []
9
14
  @__default__ = {}
10
- @__usage__ = nil
15
+ @__usage__ = {}
11
16
  end
12
17
 
13
- def __register__(type, name, *args, &block)
14
- if block_given?
15
- type = type.intern
16
- case type
17
- when :server
18
- setting = DRbQS::Setting::Server.new
19
- when :node
20
- setting = DRbQS::Setting::Node.new
18
+ def __register__(type, setting, name, template, args, &block)
19
+ ary = [name.intern, { :type => type.intern, :template => template, :args => args }]
20
+ type = type.to_s
21
+ case block.arity
22
+ when 2
23
+ if DRbQS::Setting::SSH === setting
24
+ ssh_setting = setting
21
25
  else
22
- raise ArgumentError, "Invalid type of setting '#{type.to_s}'"
23
- end
24
- case block.arity
25
- when 2
26
26
  ssh_setting = DRbQS::Setting::SSH.new
27
27
  ssh_setting.value.argument << type.to_s
28
- yield(setting.value, ssh_setting.value)
29
28
  ssh_setting.mode_setting = setting
30
- unless ssh_setting.value.argument[0] == type.to_s
31
- ssh_setting.value.argument.unshift(type.to_s)
29
+ end
30
+ yield(ssh_setting.mode_setting.value, ssh_setting.value)
31
+ unless ssh_setting.value.argument[0] == type
32
+ ssh_setting.value.argument.unshift(type)
33
+ end
34
+ ary[1][:ssh] = true
35
+ ary[1][:setting] = ssh_setting
36
+ when 1
37
+ if DRbQS::Setting::SSH === setting
38
+ raise ArgumentError, "Inherited definition is over ssh."
39
+ end
40
+ yield(setting.value)
41
+ ary[1][:ssh] = false
42
+ ary[1][:setting] = setting
43
+ else
44
+ raise ArgumentError, "Block must take one or two arguments."
45
+ end
46
+ ary
47
+ end
48
+ private :__register__
49
+
50
+ def __register_server__(template, name, load_def, *args, &block)
51
+ if load_def
52
+ if DRbQS::Setting::Base === load_def
53
+ setting = load_def
54
+ elsif data = @__server__.assoc(load_def.intern)
55
+ setting = data[1][:setting].clone
56
+ else
57
+ raise ArgumentError, "Not registered definition '#{load_def}'."
58
+ end
59
+ else
60
+ setting = DRbQS::Setting::Server.new
61
+ end
62
+ @__server__ << __register__(:server, setting, name, template, args, &block)
63
+ end
64
+ private :__register_server__
65
+
66
+ def __register_node__(template, name, load_def, *args, &block)
67
+ if load_def
68
+ if DRbQS::Setting::Base === load_def
69
+ setting = load_def
70
+ elsif data = @__node__.assoc(load_def.intern)
71
+ if data[1][:type] == :group
72
+ raise ArgumentError, "Definition to inherit is group."
32
73
  end
33
- ary = [name.intern, { :type => :ssh, :setting => ssh_setting, :args => args }]
34
- when 1
35
- yield(setting.value)
36
- ary = [name.intern, { :type => type, :setting => setting, :args => args }]
74
+ setting = data[1][:setting].clone
37
75
  else
38
- raise ArgumentError, "Block must take one or two arguments."
76
+ raise ArgumentError, "Not registered definition '#{load_def}'."
39
77
  end
40
- instance_variable_get("@__#{type.to_s}__") << ary
41
78
  else
42
- raise ArgumentError, "Block to define settings is not given."
79
+ setting = DRbQS::Setting::Node.new
43
80
  end
81
+ @__node__ << __register__(:node, setting, name, template, args, &block)
44
82
  end
45
- private :__register__
83
+ private :__register_node__
46
84
 
47
85
  # To set properties of server we can use the similar options to the command 'drbqs-server'.
48
86
  # When we execute a server over ssh, we can use the similar options to the command 'drbqs-ssh'
@@ -51,34 +89,80 @@ module DRbQS
51
89
  # If we omit the 'connect' method then the program tries to connect
52
90
  # the name specified as first argument.
53
91
  #
54
- # * Example of a server on localhost
55
- # register_server(:server_local, "example.com") do |server|
56
- # server.load "server_definition.rb"
57
- # server.acl "/path/to/acl"
58
- # server.log_file "/path/to/log"
59
- # server.log_level Logger::ERROR
60
- # server.sftp_user "username"
61
- # server.sftp_host "example.com"
62
- # end
92
+ # @param [Symbol,String] name Server name
93
+ # @param [Hash] opts The options of server
94
+ # @option opts [true,false] :template Template for other servers to load, not actual server
95
+ # @option opts [Symbol] :load Inherit definition of other server
63
96
  #
64
- # * Example of a server over ssh
65
- # register_server(:server_ssh, "example.co.jp") do |server, ssh|
66
- # server.load "server_definition.rb"
67
- # server.acl "/path/to/acl"
68
- # server.log_level Logger::ERROR
69
- # server.sftp_user "username"
70
- # server.sftp_host "example.com"
97
+ # @example A server on localhost
98
+ # server :server_local, "example.com" do |srv|
99
+ # srv.load "server_definition.rb"
100
+ # srv.acl "/path/to/acl"
101
+ # srv.log_file "/path/to/log"
102
+ # srv.log_level Logger::ERROR
103
+ # srv.sftp_user "username"
104
+ # srv.sftp_host "example.com"
105
+ # end
71
106
  #
72
- # ssh.connect "hostname"
73
- # ssh.directory "/path/to/dir"
74
- # ssh.shell "bash"
75
- # ssh.rvm "ruby-head"
76
- # ssh.rvm_init "/path/to/scripts/rvm"
77
- # ssh.output "/path/to/output"
78
- # ssh.nice 10
79
- # end
80
- def register_server(name, hostname = nil, &block)
81
- __register__(:server, name, hostname || name.to_s, &block)
107
+ # @example A server over ssh
108
+ # server :server_ssh, "example.co.jp" do |srv, ssh|
109
+ # srv.load "server_definition.rb"
110
+ # srv.acl "/path/to/acl"
111
+ # srv.log_level Logger::ERROR
112
+ # srv.sftp_user "username"
113
+ # srv.sftp_host "example.com"
114
+ #
115
+ # ssh.connect "hostname"
116
+ # ssh.directory "/path/to/dir"
117
+ # ssh.shell "bash"
118
+ # ssh.rvm "ruby-head"
119
+ # ssh.rvm_init "/path/to/scripts/rvm"
120
+ # ssh.output "/path/to/output"
121
+ # ssh.nice 10
122
+ # end
123
+ def server(name, *args, &block)
124
+ name = name.intern
125
+ if ind = @__server__.index { |n, data| name == n }
126
+ old_data = @__server__.delete_at(ind)
127
+ else
128
+ old_data = nil
129
+ end
130
+ unless block_given?
131
+ raise ArgumentError, "Block to define settings is not given."
132
+ end
133
+ case args.size
134
+ when 2
135
+ hostname = args[0]
136
+ opts = args[1]
137
+ unless Hash === opts
138
+ raise ArgumentError, "Options must be hash."
139
+ end
140
+ when 1
141
+ if Hash === args[0]
142
+ hostname = nil
143
+ opts = args[0]
144
+ else
145
+ hostname = args[0]
146
+ opts = {}
147
+ end
148
+ else
149
+ unless old_data
150
+ raise ArgumentError, "Invalid argument size."
151
+ end
152
+ end
153
+ if old_data
154
+ if opts[:load]
155
+ raise ArgumentError, "Can not set both reconfiguring and loading."
156
+ end
157
+ load_def = old_data[1][:setting]
158
+ hostname = old_data[1][:args][0] if !hostname
159
+ else
160
+ load_def = opts[:load]
161
+ end
162
+ if !opts[:template] && !hostname
163
+ raise ArgumentError, "Definition of server '#{name}' needs hostname."
164
+ end
165
+ __register_server__(opts[:template], name, load_def, hostname, &block)
82
166
  end
83
167
 
84
168
  # To set properties of nodes we can use the similar options to the command 'drbqs-node'.
@@ -87,56 +171,126 @@ module DRbQS
87
171
  # If we omit the 'connect' method then the program tries to connect
88
172
  # the name specified as first argument.
89
173
  #
90
- # * Example of nodes on localhost
91
- # register_node(:node_local) do |node|
92
- # node.process 3
93
- # node.load "load_lib.rb"
94
- # node.log_prefix "/path/to/log"
95
- # node.log_level Logger::DEBUG
96
- # end
174
+ # @param [Symbol,String] name Node name
175
+ # @param [Hash] opts The options of node
176
+ # @option opts [true,false] :template Template for other nodes to load, not actual node
177
+ # @option opts [Symbol] :load Inherit definition of other node
178
+ # @option opts [true,false] :group Define the group of node
179
+ #
180
+ # @example Nodes on localhost
181
+ # node :node_local do |nd|
182
+ # nd.process 3
183
+ # nd.load "load_lib.rb"
184
+ # nd.log_prefix "/path/to/log"
185
+ # nd.log_level Logger::DEBUG
186
+ # end
97
187
  #
98
- # * Example of nodes over ssh
99
- # register_node(:node_ssh) do |node, ssh|
100
- # node.process 3
101
- # node.load "load_lib.rb"
102
- # node.log_level Logger::DEBUG
188
+ # @example Nodes over ssh
189
+ # node :node_ssh do |nd, ssh|
190
+ # nd.process 3
191
+ # nd.load "load_lib.rb"
192
+ # nd.log_level Logger::DEBUG
193
+ #
194
+ # ssh.connect "hostname"
195
+ # ssh.directory "/path/to/dir"
196
+ # ssh.shell "bash"
197
+ # ssh.rvm "ruby-head"
198
+ # ssh.rvm_init "/path/to/scripts/rvm"
199
+ # ssh.output "/path/to/output"
200
+ # ssh.nice 10
201
+ # end
103
202
  #
104
- # ssh.connect "hostname"
105
- # ssh.directory "/path/to/dir"
106
- # ssh.shell "bash"
107
- # ssh.rvm "ruby-head"
108
- # ssh.rvm_init "/path/to/scripts/rvm"
109
- # ssh.output "/path/to/output"
110
- # ssh.nice 10
111
- # end
112
- def register_node(name, &block)
113
- __register__(:node, name, &block)
203
+ # @example Node group
204
+ # node :node_group, :group => [:node_local, :node_ssh]
205
+ def node(name, opts = {}, &block)
206
+ name = name.intern
207
+ load_def = opts[:load]
208
+ if ind = @__node__.index { |n, data| name == n }
209
+ old_data = @__node__.delete_at(ind)
210
+ if (opts[:group] && old_data[1][:type] != :group) ||
211
+ (!opts[:group] && old_data[1][:type] == :group)
212
+ raise ArgumentError, "Change type of definition on reconfiguring."
213
+ elsif (!opts[:group] && load_def)
214
+ raise ArgumentError, "Can not set both reconfiguring and loading."
215
+ end
216
+ load_def = old_data[1][:setting]
217
+ else
218
+ old_data = nil
219
+ end
220
+ if opts[:group]
221
+ unless Array === opts[:group]
222
+ raise ":group must be an array of node names."
223
+ end
224
+ data = {
225
+ :type => :group, :template => true, :ssh => nil, :setting => nil,
226
+ :args => opts[:group].map(&:intern)
227
+ }
228
+ @__node__ << [name, data]
229
+ elsif block_given?
230
+ __register_node__(opts[:template], name, load_def, &block)
231
+ else
232
+ raise ArgumentError, "Block to define settings is not given."
233
+ end
234
+ end
235
+
236
+ # @param [Array] *args Symbols of servers
237
+ # @example Clear server definitions
238
+ # clear_server :server1, :server2
239
+ def clear_server(*args)
240
+ args.each do |arg|
241
+ @__server__.delete_if do |name, data|
242
+ name == arg.intern
243
+ end
244
+ end
245
+ end
246
+
247
+ # @param [Array] *args Symbols of nodes
248
+ # @example Clear node definitions
249
+ # clear_node :node1, :node2
250
+ def clear_node(*args)
251
+ args.each do |arg|
252
+ @__node__.delete_if do |name, data|
253
+ name == arg.intern
254
+ end
255
+ end
114
256
  end
115
257
 
116
258
  # We can set default server, default port, and default directory to output log.
117
- # * Example of usage
118
- # default :port => 13456, :server => :server_local, :log => "/tmp/drbqs_execute_log"
259
+ # @param [Hash] val the pair of key and value
260
+ # @option val [Fixnum] :port Port number of a server
261
+ # @option val [Symbol] :server Server executed by default
262
+ # @option val [String] :log Path of log of a server and nods on localhost
263
+ # @example Set default value
264
+ # default :port => 13456, :server => :server_local, :log => "/tmp/drbqs_execute_log"
119
265
  def default(val = {})
120
266
  val.delete_if { |key, v| !v }
121
- @__default__.merge!(val)
122
- if @__default__[:server]
123
- @__default__[:server] = @__default__[:server].intern
267
+ if val[:server]
268
+ val[:server] = val[:server].intern
124
269
  end
125
- if @__default__[:port]
126
- @__default__[:port] = @__default__[:port].to_i
270
+ if val[:port]
271
+ val[:port] = val[:port].to_i
127
272
  end
273
+ raise "Invalid default value for :node." if val.has_key?(:node) && !(Array === val[:node])
274
+ raise "Invalid default value for :log." if val.has_key?(:log) && !(String === val[:log])
275
+ @__default__.merge!(val)
128
276
  end
129
277
 
130
- def default_clear(key)
131
- @__default__.delete(key)
278
+ # @example Clear default value
279
+ # default_clear :port, :server, :log
280
+ def default_clear(*keys)
281
+ keys.each do |key|
282
+ @__default__.delete(key)
283
+ end
132
284
  end
133
285
 
134
- # We can set messages of usage and path of definition file of server
135
- # to output help of server on showing help.
136
- # * Example of usage
137
- # usage(:message => 'Calculate some value', :server => 'server.rb')
286
+ # We can set some messages shown by drbqs-execute -h.
287
+ # @param [Hash] opts
288
+ # @option opts [String] :message Simple message strings
289
+ # @option opts [String] :server Path of server definition to output as help of server
290
+ # @example Set usage
291
+ # usage :message => 'Calculate some value', :server => 'server.rb'
138
292
  def usage(opts = {})
139
- @__usage__ = opts
293
+ @__usage__.merge!(opts)
140
294
  end
141
295
 
142
296
  def __load__(path)