drbqs 0.0.15 → 0.0.16

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