autoflow 0.3.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/autoflow.gemspec CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_runtime_dependency 'net-ssh', '>= 2.8.0'
22
+ spec.add_runtime_dependency 'win32console', '>= 1.3.2' if !ENV['OS'].nil? && ENV['OS'].downcase.include?('windows')
23
+ spec.add_runtime_dependency 'colorize', '~> 0.7.3'
22
24
  spec.add_development_dependency "bundler", "~> 1.3"
23
25
  spec.add_development_dependency "rake"
24
26
  end
data/bin/AutoFlow CHANGED
@@ -9,6 +9,62 @@ require 'optparse'
9
9
  require 'autoflow'
10
10
  require 'io/console'
11
11
  require 'net/ssh'
12
+ require 'queue_manager'
13
+ require 'fileutils'
14
+
15
+ #################################################################################################
16
+ # METHODS
17
+ #################################################################################################
18
+ def get_templates(string_template)
19
+ templates = string_template.split(',')
20
+ return templates
21
+ end
22
+
23
+ def get_repositories
24
+ directories = []
25
+ directories = ENV['WORKFLOW_REPOSITORY'].split(':') if !ENV['WORKFLOW_REPOSITORY'].nil?
26
+ return directories
27
+ end
28
+
29
+ def exit_exec(message)
30
+ puts message
31
+ Process.exit(-1)
32
+ end
33
+
34
+ def list_repository_templates
35
+ templates = []
36
+ if !ENV['WORKFLOW_REPOSITORY']. nil?
37
+ directories = get_repositories
38
+ directories.each do |dir|
39
+ templates.concat(Dir.entries(dir))
40
+ end
41
+ end
42
+ templates.delete('.')
43
+ templates.delete('..')
44
+ return templates
45
+ end
46
+
47
+ def get_template_path(template)
48
+ path = nil
49
+ directories = get_repositories
50
+ directories.each do |dir|
51
+ if Dir.entries(dir).include?(template)
52
+ path = File.join(dir, template)
53
+ break
54
+ end
55
+ end
56
+ return path
57
+ end
58
+
59
+ def get_description(path)
60
+ File.open(path).each do |line|
61
+ line.chomp!
62
+ if line =~ /^#=/
63
+ line.gsub!('#=','')
64
+ puts line
65
+ end
66
+ end
67
+ end
12
68
 
13
69
  #################################################################################################
14
70
  # INPUT PARSING
@@ -16,6 +72,11 @@ require 'net/ssh'
16
72
  options = {}
17
73
  template_file = ''
18
74
  optparse = OptionParser.new do |opts|
75
+ options[:add] = nil
76
+ opts.on( '-a', '--add STRING', 'Puts a copy of a selected workflow template in repository' ) do |add|
77
+ options[:add] = add
78
+ end
79
+
19
80
  options[:batch] = FALSE
20
81
  opts.on( '-b', '--batch', 'Workflow execution using batch' ) do
21
82
  options[:batch] = TRUE
@@ -31,21 +92,26 @@ optparse = OptionParser.new do |opts|
31
92
  options[:external_dependencies] = external_dependencies.split(',')
32
93
  end
33
94
 
34
- options[:exp_cpu] = 0
35
- opts.on( '-e', '--exp_cpu INTEGER', 'Exponent of cpu assigment series' ) do |exp_cpu|
36
- options[:exp_cpu] = exp_cpu.to_i
37
- end
38
-
39
95
  options[:retry] = FALSE
40
96
  opts.on( '-f', '--force', 'Execute all jobs, included the jobs commented with %' ) do
41
97
  options[:retry] = TRUE
42
98
  end
43
99
 
44
100
  options[:graph] = nil
45
- opts.on( '-g', '--graph STRING', 'Draw the template. t for use tag like names or f for use folders names instead' ) do |graph|
101
+ opts.on( '-g', '--graph STRING', 'Draw the template. t for use tag like names or f for use folders names instead. This option cancel the workflow launching' ) do |graph|
46
102
  options[:graph] = graph
47
103
  end
48
104
 
105
+ options[:identifier] = FALSE
106
+ opts.on( '-i', '--job_identifier STRING', 'Identifier tag for each launching script' ) do |identifier|
107
+ options[:identifier] = identifier
108
+ end
109
+
110
+ options[:list] = nil
111
+ opts.on( 'l', '--list_repository STRING', 'List template names in repository') do |name|
112
+ options[:list] = name
113
+ end
114
+
49
115
  options[:memory] = '4gb'
50
116
  opts.on( '-m', '--memory STRING', 'Max memory can be used in a task' ) do |mem|
51
117
  options[:memory] = mem
@@ -61,6 +127,11 @@ optparse = OptionParser.new do |opts|
61
127
  options[:output] = output
62
128
  end
63
129
 
130
+ options[:pull] = nil
131
+ opts.on( '-p', '--pull STRING', 'Get a copy of a workflow template in repository.' ) do |pull|
132
+ options[:pull] = pull
133
+ end
134
+
64
135
  options[:remote] = FALSE
65
136
  opts.on( '-r', '--remote', 'Connect with remote machine and launch the workflow' ) do
66
137
  options[:remote] = TRUE
@@ -74,8 +145,13 @@ optparse = OptionParser.new do |opts|
74
145
  puts options[:ssh].exec!('hostname')
75
146
  end
76
147
 
148
+ options[:use_ntasks] = FALSE
149
+ opts.on( '-s', '--use_ntasks', 'Use -ntasks flag with sh' ) do
150
+ options[:use_ntasks] = TRUE
151
+ end
152
+
77
153
  options[:time] = '20:00:00'
78
- opts.on( '-t', '--time STRING', 'Max time that can be needed in a task' ) do |time|
154
+ opts.on( '-t', '--time STRING', 'Max time that can be needed in a task. Format: dd-hh:mm:ss' ) do |time|
79
155
  options[:time] = time
80
156
  end
81
157
 
@@ -84,10 +160,6 @@ optparse = OptionParser.new do |opts|
84
160
  options[:use_multinode] = use_multinode.to_i
85
161
  end
86
162
 
87
- options[:use_ntasks] = FALSE
88
- opts.on( '-s', '--use_ntasks', 'Use -ntasks flag with sh' ) do
89
- options[:use_ntasks] = TRUE
90
- end
91
163
 
92
164
  options[:verbose] = FALSE
93
165
  opts.on( '-v', '--verbose', 'Show info without launch jobs' ) do
@@ -95,8 +167,8 @@ optparse = OptionParser.new do |opts|
95
167
  end
96
168
 
97
169
  options[:Variables] = nil
98
- opts.on( '-V', '--Variables STRING', 'Variables to be parsed on template. Format: \'$variable_name1=value1;$variable_name2=value2;...\'' ) do |mem|
99
- options[:Variables] = mem.split(';')
170
+ opts.on( '-V', '--Variables STRING', 'Variables to be parsed on template. Format: \'$variable_name1=value1,$variable_name2=value2,...\'' ) do |mem|
171
+ options[:Variables] = [mem]
100
172
  end
101
173
 
102
174
  options[:workflow] = FALSE
@@ -105,10 +177,6 @@ optparse = OptionParser.new do |opts|
105
177
  template_file = workflow
106
178
  end
107
179
 
108
- options[:identifier] = FALSE
109
- opts.on( '-i', '--job_identifier STRING', 'Identifier tag for each launching script' ) do |identifier|
110
- options[:identifier] = identifier
111
- end
112
180
 
113
181
  # Set a banner, displayed at the top of the help screen.
114
182
  opts.banner = "Usage: AutoFlow.rb -w worflow_file -c n_cpus \n\n"
@@ -124,23 +192,85 @@ end # End opts
124
192
  # parse options and remove from ARGV
125
193
  optparse.parse!
126
194
 
127
- if !options[:workflow] || !File.exists?(options[:workflow])
128
- puts 'Workflow file not especified or not exists'
129
- Process.exit(-1)
130
- else
131
- options[:identifier] = "#{options[:workflow]}_#{Time.new.to_i}" if !options[:identifier]
132
- options[:workflow] = File.open(options[:workflow]).read
133
- end
134
-
135
195
  #################################################################################################
136
196
  # MAIN
137
197
  #################################################################################################
198
+
199
+ # List templates
200
+ templates_rep_names = list_repository_templates
201
+ if !options[:list].nil?
202
+ if options[:list] == 'all'
203
+ puts templates_rep_names
204
+ else
205
+ path = get_template_path(options[:list])
206
+ get_description(path) if !path.nil?
207
+ end
208
+ exit_exec('')
209
+ end
210
+
211
+ # Get a template
212
+ if !options[:pull].nil?
213
+ path = get_template_path(options[:pull])
214
+ if !path.nil?
215
+ FileUtils.cp(path, Dir.pwd)
216
+ else
217
+ exit_exec("Template not found: #{options[:pull]}")
218
+ end
219
+ exit_exec('')
220
+ end
221
+
222
+ # Upload a template
223
+ if !options[:add].nil? && File.exists?(options[:add])
224
+ directories = get_repositories
225
+ writable_dirs = []
226
+ directories.each_with_index do |dir, i|
227
+ if File.directory?(dir) && File.writable?(dir)
228
+ puts "#{i}\t#{dir}"
229
+ writable_dirs << dir
230
+ end
231
+ end
232
+ if !writable_dirs.empty?
233
+ msg = ''
234
+ puts "Select a directory"
235
+ select = gets.chomp.to_i
236
+ FileUtils.cp(options[:add], writable_dirs[select])
237
+ else
238
+ msg = "You don't have a writable directory"
239
+ end
240
+ exit_exec(msg)
241
+ end
242
+
243
+ # Merge templates
244
+ templates = get_templates(options[:workflow])
245
+ options[:workflow] = ''
246
+ options[:identifier] = "#{File.basename(templates.first)}_#{Time.new.to_i}" if !options[:identifier]
247
+
248
+ if !options[:workflow]
249
+ exit_exec('Workflow not especified')
250
+ else
251
+ templates.each do |template|
252
+ if !File.exists?(template) && !templates_rep_names.empty? && !templates_rep_names.include?(template)
253
+ exit_exec("Workflow not found: #{template}")
254
+ Process.exit(-1)
255
+ else
256
+ if File.exists?(template)
257
+ path = template
258
+ else
259
+ path = get_template_path(template)
260
+ end
261
+ options[:workflow] += File.open(path).read+"\n"
262
+ end
263
+ end
264
+ end
265
+
266
+ # Set local or remote execution
138
267
  if options[:remote]
139
268
  main_path = options[:ssh].exec!('pwd').chomp
140
269
  else
141
270
  main_path = Dir.pwd
142
271
  end
143
272
 
273
+ # Set output directory
144
274
  if options[:output] == 'exec'
145
275
  exec_folder = File.join(main_path,'exec')
146
276
  else
@@ -151,17 +281,16 @@ end
151
281
  #--------------------------------------------------------------------------------
152
282
  # Flow parse
153
283
  #--------------------------------------------------------------------------------
154
- stack=Stack.new(exec_folder, options)
155
- stack.draw(template_file, options[:graph]) if !options[:graph].nil?
156
-
284
+ stack = Stack.new(exec_folder, options)
285
+ manager = QueueManager.select_queue_manager(stack, options)
286
+
157
287
  #--------------------------------------------------------------------------------
158
288
  # Flow exec
159
289
  #--------------------------------------------------------------------------------
160
- if options[:verbose]
161
- stack.inspect
162
- stack.send
163
- elsif options[:graph].nil?
164
- stack.send
290
+ if !options[:graph].nil?
291
+ stack.draw(template_file, options[:graph])
292
+ else
293
+ stack.inspect if options[:verbose]
294
+ manager.exec
165
295
  end
166
296
  options[:ssh].close if options[:remote]
167
-
@@ -0,0 +1,342 @@
1
+ class Batch
2
+ attr_accessor :name, :iterator, :dependencies, :init, :main_command, :attrib, :id, :jobs, :parent
3
+
4
+ @@all_batch = {}
5
+ @@all_jobs_relations = {}
6
+ @@batch_iterator_relations = {}
7
+ @@state_iterations = {}
8
+ @@general_computation_attrib = {
9
+ :cpu => nil,
10
+ :mem => nil,
11
+ :time => nil,
12
+ :node => nil,
13
+ :multinode => nil,
14
+ :ntask => nil
15
+ }
16
+
17
+ def self.set_general_attrib(attrib_hash)
18
+ @@general_computation_attrib = attrib_hash
19
+ end
20
+
21
+ def self.get_job_relations
22
+ return @@all_jobs_relations
23
+ end
24
+
25
+ def initialize(tag, init, main_command, id, exec_folder)
26
+ @name = nil
27
+ @id = id
28
+ @iterator = [nil]
29
+ @parent = nil
30
+ @dependencies = [] # [batch_name, dependency_type, keyword2replace]
31
+ # nil => There isn't dependecies,
32
+ # 'simple' => One job needs a previous job,
33
+ # '1to1' => A job in a batch needs another job in other batch,
34
+ # '*to1' => A job need a previous full batch of jobs
35
+ # 'local' => A simple job needs one job of a batch
36
+ @initialization = init
37
+ @main_command = main_command
38
+ @attrib = {
39
+ :done => FALSE,
40
+ :folder => TRUE,
41
+ :buffer => FALSE,
42
+ :exec_folder => exec_folder,
43
+ :cpu_asign => nil # number, list or mono
44
+ }.merge(@@general_computation_attrib)
45
+ get_name_and_iterators_and_modifiers(tag)
46
+ set_execution_attrib
47
+ set_cpu
48
+ @jobs = []
49
+ @@all_batch[@name] = self
50
+ end
51
+
52
+ def has_jobs?
53
+ res = !@jobs.empty?
54
+ return res
55
+ end
56
+
57
+ def get_name_and_iterators_and_modifiers(tag)
58
+ tag =~ /(^.+)\[([^\]]+)/
59
+ name = $1
60
+ if $1.nil?
61
+ tag =~ /(^.+)\)/
62
+ name = $1
63
+ end
64
+ @name , @attrib[:done], @attrib[:folder], @attrib[:buffer] = check_execution_modifiers(name)
65
+ if !$2.nil?
66
+ @iterator = []
67
+ $2.split(';').map{|interval|
68
+ if interval.include?('-')
69
+ limits = interval.split('-')
70
+ @iterator.concat((limits.first..limits.last).to_a.map{|n| n.to_s})
71
+ else
72
+ @iterator << interval
73
+ end
74
+ }
75
+ end
76
+ end
77
+
78
+ def check_execution_modifiers(name)
79
+ done = FALSE
80
+ folder = TRUE
81
+ buffer = FALSE
82
+ done = TRUE if name.include?('%')
83
+ folder = FALSE if name.include?('!')
84
+ buffer = TRUE if name.include?('&')
85
+ name.gsub!(/&|\!|\%|\)/,'')# Delete function characters
86
+ return name, done, folder, buffer
87
+ end
88
+
89
+ def set_execution_attrib
90
+ @initialization = scan_resources(@initialization) if !@initialization.nil?
91
+ @main_command = scan_resources(@main_command) if @main_command.class.to_s == 'String'
92
+ end
93
+
94
+ def scan_resources(command)
95
+ resources_line = nil
96
+ command.each_line do |line|
97
+ if line.include?('resources:')
98
+ resources_line = line
99
+ fields = line.split(' ')
100
+ fields.each_with_index do |field, index|
101
+ if field == '-c'
102
+ @attrib[:cpu] = fields[index+1].to_i
103
+ elsif field == '-m'
104
+ @attrib[:mem] = fields[index+1]
105
+ elsif field == '-n'
106
+ @attrib[:node] = fields[index+1]
107
+ elsif field == '-t'
108
+ @attrib[:time] = fields[index+1]
109
+ elsif field == '-u'
110
+ @attrib[:multinode] = fields[index+1].to_i
111
+ end
112
+ end
113
+ if fields.include?('-s')
114
+ @attrib[:ntask] = TRUE
115
+ else
116
+ @attrib[:ntask] = FALSE
117
+ end
118
+ end
119
+ end
120
+ command.gsub!(resources_line, '') if !resources_line.nil?
121
+ return command
122
+ end
123
+
124
+ def set_cpu
125
+ @initialization = scan_cpu(@initialization) if !@initialization.nil?
126
+ @main_command = scan_cpu(@main_command) if @main_command.class.to_s == 'String'
127
+ @attrib[:cpu] = 1 if @attrib[:cpu_asign] == 'mono'
128
+ end
129
+
130
+ def scan_cpu(command)
131
+ if command.include?('[cpu]')
132
+ command.gsub!('[cpu]', @attrib[:cpu].to_s)
133
+ @attrib[:cpu_asign] = 'number'
134
+ elsif command.include?('[lcpu]')
135
+ command.gsub!('[lcpu]', 'workers')
136
+ @attrib[:cpu_asign] = 'list'
137
+ elsif @attrib[:cpu_asign].nil?
138
+ @attrib[:cpu_asign] = 'mono'
139
+ end
140
+ return command
141
+ end
142
+
143
+
144
+ def asign_folder(local_command = nil)
145
+ if local_command.nil? #we check a simple job
146
+ command = @main_command
147
+ else #we check a cloned job
148
+ command = local_command
149
+ end
150
+ if command.class.to_s == 'Array'
151
+ folder = nil
152
+ elsif @attrib[:folder]
153
+ program = File.join(@attrib[:exec_folder], command.split(' ', 2).first)
154
+ count = 0
155
+ folder = program + "_#{"%04d" % count}"
156
+ while @@all_jobs_relations.values.include?(folder)
157
+ folder = program + "_#{"%04d" % count}"
158
+ count += 1
159
+ end
160
+ else
161
+ folder = @attrib[:exec_folder]
162
+ end
163
+ return folder
164
+ end
165
+
166
+ def duplicate_job(tmp_j, sufix_name = '')
167
+ new_job = tmp_j.clone
168
+ new_job.name = tmp_j.name+'_'+sufix_name
169
+ new_job.attrib = tmp_j.attrib.clone
170
+ new_job.dependencies = tmp_j.dependencies.clone
171
+ new_job.initialization = tmp_j.initialization.clone
172
+ new_job.parameters = tmp_j.parameters.clone
173
+ new_job.attrib[:exec_folder] = asign_folder(new_job.parameters)
174
+ return new_job
175
+ end
176
+
177
+ def delete_jobs(jobs2delete, job_array)
178
+ jobs2delete.uniq!
179
+ jobs2delete.sort{|s1, s2| s2 <=> s1}.each do |index|
180
+ job_array.delete_at(index)
181
+ end
182
+ return job_array
183
+ end
184
+
185
+ def get_jobs
186
+ jobs = []
187
+ @@batch_iterator_relations[@name] = @iterator
188
+ if @main_command.class.to_s == 'Array' # There are nested batchs
189
+ temp_jobs = []
190
+ @main_command.each do |batch|
191
+ temp_jobs.concat(batch.get_jobs)
192
+ end
193
+ jobs2delete = []
194
+ @iterator.each_with_index do |iter, i|
195
+ temp_jobs.each_with_index do |tmp_j, tmp_i|
196
+ new_job = duplicate_job(tmp_j, iter)
197
+ check_dependencies(new_job, iter, temp_jobs)
198
+ parse_iter(iter, @name, new_job)
199
+ jobs << new_job
200
+ @jobs << new_job
201
+ @@all_jobs_relations[new_job.name] = new_job.attrib[:exec_folder]
202
+ jobs2delete << tmp_i
203
+ end
204
+ end
205
+ temp_jobs = delete_jobs(jobs2delete, temp_jobs) #Remove temporal jobs
206
+ else
207
+ @iterator.each_with_index do |iter, num|
208
+ job_attrib = @attrib.dup
209
+ if !iter.nil?
210
+ iter, done, job_attrib[:folder], job_attrib[:buffer] = check_execution_modifiers(iter)
211
+ job_attrib[:done] = done if !@attrib[:done] # To keep attrib priority in batch on job
212
+ end
213
+ name = "#{@name}#{iter}"
214
+ job_attrib[:exec_folder] = asign_folder if @parent.nil? #Don't asign folder to nested batches (iterative batchs)
215
+ job_dependencies = []
216
+ initialization = replace_dependencies(@initialization, job_dependencies, iter, num)
217
+ parameters = replace_dependencies(@main_command, job_dependencies, iter, num)
218
+ job = Program.new(name, initialization, parameters, job_dependencies, job_attrib)
219
+ job.batch = @name
220
+ jobs << job
221
+ @jobs << job
222
+ @@all_jobs_relations[name] = job_attrib[:exec_folder]
223
+ end
224
+ end
225
+ return jobs
226
+ end
227
+
228
+ #tmp_j => job to set dependencies in iteration
229
+ #iter => sufix of current iteration
230
+ #jobs => array of jobs which has the job dependency
231
+ def check_dependencies(tmp_j, iter, jobs)
232
+ jobs_names = jobs.map{|job| job.name}
233
+ deps = {}
234
+ tmp_j.dependencies.each_with_index do |dep, i|
235
+ deps[dep] = i if jobs_names.include?(dep)
236
+ end
237
+ deps.each do |name, index|
238
+ dep = name+'_'+iter
239
+ tmp_j.initialization.gsub!(name+')', dep+')')
240
+ tmp_j.parameters.gsub!(name+')', dep+')')
241
+ tmp_j.dependencies[index] = dep
242
+ end
243
+ end
244
+
245
+ def parse_iter(iter, name, job)
246
+ job.parameters = set_iter(name, iter, job.parameters)
247
+ job.initialization = set_iter(name, iter, job.initialization)
248
+ end
249
+
250
+ def set_iter(name, iter, string)
251
+ string = string.gsub(name+'(+)', iter)
252
+ return string
253
+ end
254
+
255
+ def replace_dependencies(command, job_dependencies, iter, num)
256
+ if !command.nil?
257
+ @dependencies.each do |batch_name, dep_type, dep_keyword2replace, dep_info|
258
+ if dep_type == 'simple'
259
+ if @@all_batch[batch_name].parent.nil?
260
+ new_string = @@all_jobs_relations[batch_name]
261
+ end
262
+ job_dependencies << batch_name
263
+ elsif dep_type == '1to1'
264
+ if @@all_batch[batch_name].parent.nil? || !@parent.nil?
265
+ dep_name = "#{batch_name}#{@@batch_iterator_relations[batch_name][num]}"
266
+ else
267
+ root_batch = get_root(batch_name)
268
+ selected_jobs = root_batch.get_jobs_by_batch_name(batch_name)
269
+ dep_name = selected_jobs[num].name
270
+ end
271
+ job_dependencies << dep_name
272
+ if !@parent.nil? && !@@all_batch[batch_name].parent.nil?
273
+ new_string = dep_name + ')'
274
+ else
275
+ new_string = @@all_jobs_relations[dep_name]
276
+ end
277
+ elsif dep_type == '*to1'
278
+ if @@all_batch[batch_name].parent.nil?
279
+ new_string = @@batch_iterator_relations[batch_name].map{|iter|
280
+ dep_name = batch_name + iter
281
+ job_dependencies << dep_name
282
+ "#{@@all_jobs_relations[dep_name]}#{dep_info}"
283
+ }.join(' ')
284
+ dep_keyword2replace = "#{dep_keyword2replace}#{dep_info}"
285
+ elsif !@parent.nil?
286
+ new_string = @@batch_iterator_relations[batch_name].map{|iter|
287
+ dep_name = batch_name + iter
288
+ job_dependencies << dep_name
289
+ "#{dep_name})#{dep_info}"
290
+ }.join(' ')
291
+ dep_keyword2replace = "#{dep_keyword2replace}#{dep_info}"
292
+ else
293
+ root_batch = get_root(batch_name)
294
+ selected_jobs = root_batch.get_jobs_by_batch_name(batch_name)
295
+ new_string = selected_jobs.map{|j|
296
+ job_dependencies << j.name
297
+ "#{@@all_jobs_relations[j.name]}#{dep_info}"
298
+ }.join(' ')
299
+ dep_keyword2replace = "#{dep_keyword2replace}#{dep_info}"
300
+ end
301
+ elsif dep_type == 'local'
302
+ if @@all_batch[batch_name].parent.nil? || !@parent.nil?
303
+ if @@batch_iterator_relations[batch_name].include?(dep_info) #This avoids cross dependencies by similar names
304
+ dep_name = batch_name + dep_info
305
+ job_dependencies << dep_name
306
+ if !@parent.nil? && !@@all_batch[batch_name].parent.nil?
307
+ new_string = dep_name + ')'
308
+ else
309
+ new_string = @@all_jobs_relations[dep_name]
310
+ end
311
+ end
312
+ else
313
+ dep_name = dep_keyword2replace.gsub(')','') #This avoids cross dependencies by similar names
314
+ if !@@all_jobs_relations[dep_name].nil?
315
+ job_dependencies << dep_name
316
+ new_string = @@all_jobs_relations[dep_name]
317
+ end
318
+ end
319
+ elsif dep_type == 'DinVar'
320
+ job_dependencies << batch_name if batch_name != @name # This condition avoids autodependencies
321
+ end
322
+ job_dependencies.uniq!
323
+ command = command.gsub(dep_keyword2replace, new_string) if dep_type != 'DinVar' && !dep_keyword2replace.nil? && !new_string.nil?
324
+ end
325
+
326
+ command = command.gsub('(*)', "#{iter}") if command.class.to_s == 'String'
327
+ end
328
+ return command
329
+ end
330
+
331
+ def get_root(batch_name)
332
+ root_batch = @@all_batch[batch_name]
333
+ root_batch = root_batch.get_root(root_batch.parent) if !root_batch.nil? && !root_batch.parent.nil?
334
+ return root_batch
335
+ end
336
+
337
+ def get_jobs_by_batch_name(batch_name)
338
+ jobs = @jobs.select{|j| j.batch == batch_name}
339
+ return jobs
340
+ end
341
+
342
+ end
@@ -1,22 +1,25 @@
1
1
  class Program
2
- attr_accessor :name, :exec_folder_program, :parameters, :initialization, :queue_id, :done, :dependencies, :monocpu, :no_buffer_node,:cloned_id
3
- def initialize(name, parameters, initialization, exec_folder_program, dependencies, done, no_buffer_node)
4
- @name=name
5
- @parameters=parameters
6
- @initialization=initialization
7
- @exec_folder_program=exec_folder_program
8
- @queue_id=nil
9
- @done=done
10
- @dependencies=dependencies
11
- @no_buffer_node=no_buffer_node
12
- @monocpu=TRUE
13
- @cloned_id = nil
14
- if @parameters =~ /\[cpu|lcpu\]/ #||@parameters =~ /\[lcpu\]/
15
- @monocpu=FALSE
16
- end
2
+ attr_accessor :name, :initialization, :parameters, :dependencies, :attrib, :queue_id, :batch
3
+
4
+ def initialize(name, initialization, parameters, dependencies, job_attrib)
5
+ @name = name
6
+ @initialization = initialization
7
+ @parameters = parameters
8
+ @dependencies = dependencies
9
+ @attrib = job_attrib
10
+ @queue_id = nil
11
+ @batch = nil
17
12
  end
18
13
 
19
14
  def inspect
20
- string="\e[31m#{@name}\e[0m\n\t\e[33m#{@parameters.gsub("\n","\n\t")}\e[0m\t\e[34m#{@exec_folder_program}\e[0m"
15
+ if @parameters.class.to_s == 'String'
16
+ program = @parameters.split(' ').first
17
+ command = @parameters.gsub("\n","\n\t")
18
+ else
19
+ program = 'iterative_job'
20
+ command = @parameters.map{|b| b}.join(' ')
21
+ end
22
+ string="\e[31m#{program}\n\e[0m\t\e[33m#{command}\e[0m\e[34m#{@attrib[:exec_folder]}\e[0m"
21
23
  end
24
+
22
25
  end