scout-gear 10.9.0 → 10.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.vimproject +25 -0
- data/VERSION +1 -1
- data/bin/scout +4 -1
- data/lib/scout/knowledge_base/registry.rb +2 -3
- data/lib/scout/workflow/definition.rb +11 -0
- data/lib/scout/workflow/deployment/local.rb +288 -0
- data/lib/scout/workflow/deployment/orchestrator/batches.rb +130 -0
- data/lib/scout/workflow/deployment/orchestrator/chains.rb +104 -0
- data/lib/scout/workflow/deployment/orchestrator/rules.rb +256 -0
- data/lib/scout/workflow/deployment/orchestrator/workload.rb +67 -0
- data/lib/scout/workflow/deployment/scheduler/job.rb +740 -0
- data/lib/scout/workflow/deployment/scheduler/lfs.rb +125 -0
- data/lib/scout/workflow/deployment/scheduler/pbs.rb +176 -0
- data/lib/scout/workflow/deployment/scheduler/slurm.rb +158 -0
- data/lib/scout/workflow/deployment/scheduler.rb +73 -0
- data/lib/scout/workflow/deployment.rb +10 -1
- data/lib/scout/workflow/exceptions.rb +2 -0
- data/lib/scout/workflow/step/config.rb +3 -0
- data/lib/scout/workflow/step/info.rb +2 -2
- data/lib/scout/workflow/step/progress.rb +52 -0
- data/lib/scout/workflow/step.rb +30 -1
- data/lib/scout/workflow/task.rb +2 -0
- data/scout-gear.gemspec +23 -4
- data/scout_commands/batch/list +1 -1
- data/scout_commands/workflow/cmd +5 -13
- data/scout_commands/workflow/info +1 -1
- data/scout_commands/workflow/task +61 -25
- data/test/scout/workflow/deployment/orchestrator/test_batches.rb +138 -0
- data/test/scout/workflow/deployment/orchestrator/test_chains.rb +171 -0
- data/test/scout/workflow/deployment/orchestrator/test_rules.rb +219 -0
- data/test/scout/workflow/deployment/orchestrator/test_workload.rb +117 -0
- data/test/scout/workflow/deployment/scheduler/test_job.rb +31 -0
- data/test/scout/workflow/deployment/scheduler/test_lfs.rb +32 -0
- data/test/scout/workflow/deployment/scheduler/test_pbs.rb +32 -0
- data/test/scout/workflow/deployment/scheduler/test_slurm.rb +32 -0
- data/test/scout/workflow/deployment/{test_orchestrator.rb → test_local.rb} +161 -33
- data/test/scout/workflow/deployment/test_scheduler.rb +75 -0
- data/test/scout/workflow/deployment/test_trace.rb +1 -1
- data/test/scout/workflow/step/test_progress.rb +27 -0
- data/test/scout/workflow/task/test_inputs.rb +17 -0
- data/test/test_helper.rb +2 -1
- metadata +22 -3
- data/lib/scout/workflow/deployment/orchestrator.rb +0 -292
data/lib/scout/workflow/task.rb
CHANGED
|
@@ -42,6 +42,8 @@ module Task
|
|
|
42
42
|
memory_inputs = provided_inputs
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
memory_inputs = nil if Array === memory_inputs && memory_inputs.compact.empty?
|
|
46
|
+
memory_inputs = nil if Hash === memory_inputs && memory_inputs.empty?
|
|
45
47
|
Persist.memory("Task job #{self.name}", repo: Workflow.job_cache, other: {task: self.name, id: id, provided_inputs: memory_inputs}) do
|
|
46
48
|
provided_inputs, id = id, nil if (provided_inputs.nil? || provided_inputs.empty?) && (Hash === id || Array === id)
|
|
47
49
|
provided_inputs = {} if provided_inputs.nil?
|
data/scout-gear.gemspec
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: scout-gear 10.
|
|
5
|
+
# stub: scout-gear 10.10.1 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "scout-gear".freeze
|
|
9
|
-
s.version = "10.
|
|
9
|
+
s.version = "10.10.1".freeze
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib".freeze]
|
|
@@ -106,8 +106,17 @@ Gem::Specification.new do |s|
|
|
|
106
106
|
"lib/scout/workflow.rb",
|
|
107
107
|
"lib/scout/workflow/definition.rb",
|
|
108
108
|
"lib/scout/workflow/deployment.rb",
|
|
109
|
-
"lib/scout/workflow/deployment/
|
|
109
|
+
"lib/scout/workflow/deployment/local.rb",
|
|
110
|
+
"lib/scout/workflow/deployment/orchestrator/batches.rb",
|
|
111
|
+
"lib/scout/workflow/deployment/orchestrator/chains.rb",
|
|
112
|
+
"lib/scout/workflow/deployment/orchestrator/rules.rb",
|
|
113
|
+
"lib/scout/workflow/deployment/orchestrator/workload.rb",
|
|
110
114
|
"lib/scout/workflow/deployment/queue.rb",
|
|
115
|
+
"lib/scout/workflow/deployment/scheduler.rb",
|
|
116
|
+
"lib/scout/workflow/deployment/scheduler/job.rb",
|
|
117
|
+
"lib/scout/workflow/deployment/scheduler/lfs.rb",
|
|
118
|
+
"lib/scout/workflow/deployment/scheduler/pbs.rb",
|
|
119
|
+
"lib/scout/workflow/deployment/scheduler/slurm.rb",
|
|
111
120
|
"lib/scout/workflow/deployment/trace.rb",
|
|
112
121
|
"lib/scout/workflow/documentation.rb",
|
|
113
122
|
"lib/scout/workflow/entity.rb",
|
|
@@ -237,13 +246,23 @@ Gem::Specification.new do |s|
|
|
|
237
246
|
"test/scout/tsv/util/test_unzip.rb",
|
|
238
247
|
"test/scout/work_queue/test_socket.rb",
|
|
239
248
|
"test/scout/work_queue/test_worker.rb",
|
|
240
|
-
"test/scout/workflow/deployment/
|
|
249
|
+
"test/scout/workflow/deployment/orchestrator/test_batches.rb",
|
|
250
|
+
"test/scout/workflow/deployment/orchestrator/test_chains.rb",
|
|
251
|
+
"test/scout/workflow/deployment/orchestrator/test_rules.rb",
|
|
252
|
+
"test/scout/workflow/deployment/orchestrator/test_workload.rb",
|
|
253
|
+
"test/scout/workflow/deployment/scheduler/test_job.rb",
|
|
254
|
+
"test/scout/workflow/deployment/scheduler/test_lfs.rb",
|
|
255
|
+
"test/scout/workflow/deployment/scheduler/test_pbs.rb",
|
|
256
|
+
"test/scout/workflow/deployment/scheduler/test_slurm.rb",
|
|
257
|
+
"test/scout/workflow/deployment/test_local.rb",
|
|
258
|
+
"test/scout/workflow/deployment/test_scheduler.rb",
|
|
241
259
|
"test/scout/workflow/deployment/test_trace.rb",
|
|
242
260
|
"test/scout/workflow/step/test_archive.rb",
|
|
243
261
|
"test/scout/workflow/step/test_children.rb",
|
|
244
262
|
"test/scout/workflow/step/test_dependencies.rb",
|
|
245
263
|
"test/scout/workflow/step/test_info.rb",
|
|
246
264
|
"test/scout/workflow/step/test_load.rb",
|
|
265
|
+
"test/scout/workflow/step/test_progress.rb",
|
|
247
266
|
"test/scout/workflow/step/test_provenance.rb",
|
|
248
267
|
"test/scout/workflow/step/test_status.rb",
|
|
249
268
|
"test/scout/workflow/task/test_dependencies.rb",
|
data/scout_commands/batch/list
CHANGED
|
@@ -334,7 +334,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
|
334
334
|
step_path = step_line.split(": ").last.strip
|
|
335
335
|
step = Step.new step_path
|
|
336
336
|
has_bar = false
|
|
337
|
-
(step.rec_dependencies + [step]).reverse.each do |j|
|
|
337
|
+
(step.rec_dependencies.to_a + [step]).reverse.each do |j|
|
|
338
338
|
next if j.done?
|
|
339
339
|
if j.file(:progress).exists?
|
|
340
340
|
bar = Log::ProgressBar.new
|
data/scout_commands/workflow/cmd
CHANGED
|
@@ -12,20 +12,12 @@ $ #{$0} <workflow> <command> [<subcommands>] [<options>] [<arg> ...]
|
|
|
12
12
|
|
|
13
13
|
-h--help Print this help
|
|
14
14
|
EOF
|
|
15
|
-
if options[:help]
|
|
16
|
-
if defined? scout_usage
|
|
17
|
-
scout_usage
|
|
18
|
-
else
|
|
19
|
-
puts SOPT.doc
|
|
20
|
-
end
|
|
21
|
-
exit 0
|
|
22
|
-
end
|
|
23
15
|
|
|
24
16
|
workflow = ARGV.shift
|
|
25
17
|
|
|
26
18
|
if workflow == '-h'
|
|
27
19
|
if defined? scout_usage
|
|
28
|
-
scout_usage
|
|
20
|
+
scout_usage
|
|
29
21
|
else
|
|
30
22
|
puts SOPT.doc
|
|
31
23
|
end
|
|
@@ -99,11 +91,11 @@ puts
|
|
|
99
91
|
puts Log.color :magenta, "## COMMANDS"
|
|
100
92
|
puts
|
|
101
93
|
puts Log.color :magenta, "Command:"
|
|
102
|
-
puts
|
|
94
|
+
puts
|
|
103
95
|
puts " scout #{$previous_commands * " "} "
|
|
104
|
-
puts
|
|
96
|
+
puts
|
|
105
97
|
puts Log.color :magenta, "Subcommands:"
|
|
106
|
-
puts
|
|
98
|
+
puts
|
|
107
99
|
|
|
108
100
|
commands(prev).each do |command|
|
|
109
101
|
directory = File.directory? dir[command].find
|
|
@@ -113,4 +105,4 @@ commands(prev).each do |command|
|
|
|
113
105
|
puts " " << command
|
|
114
106
|
end
|
|
115
107
|
end
|
|
116
|
-
|
|
108
|
+
|
|
@@ -31,7 +31,7 @@ if options[:inputs]
|
|
|
31
31
|
names, values = step.info.values_at :input_names, :inputs
|
|
32
32
|
names.zip(values).each do |name,value|
|
|
33
33
|
puts [Log.color(:title, name), Log.fingerprint(value)] * " = "
|
|
34
|
-
end
|
|
34
|
+
end if names
|
|
35
35
|
elsif options[:recursive_inputs]
|
|
36
36
|
step.recursive_inputs.each do |name,value|
|
|
37
37
|
puts [Log.color(:title, name), Log.fingerprint(value)] * " = "
|
|
@@ -16,10 +16,13 @@ Run a workflow job
|
|
|
16
16
|
$ #{$0} [<options>] <workflow> <task>
|
|
17
17
|
|
|
18
18
|
-h--help Print this help
|
|
19
|
+
--workflows* Other workflows to load
|
|
19
20
|
--nostream Disable job streaming
|
|
20
21
|
--update Update jobs with newer dependencies
|
|
21
22
|
--deploy* Deploy mode: serial, local, queue, or SLURM (default 'serial')
|
|
23
|
+
--deploy_rules* Deployment rules; can be files of keywords
|
|
22
24
|
--fork Fork and return path
|
|
25
|
+
--exec Exec and return output
|
|
23
26
|
--load_inputs* Directory or file with inputs files to load
|
|
24
27
|
--save_inputs* Directory or tar.gz file path to store inputs
|
|
25
28
|
-jn--jobname* Name to use as job identifier
|
|
@@ -33,33 +36,45 @@ EOF
|
|
|
33
36
|
|
|
34
37
|
workflow_name, task_name = ARGV
|
|
35
38
|
|
|
39
|
+
|
|
40
|
+
help, workflows, provenance, clean, recursive_clean, clean_task, load_inputs, save_inputs, jobname, printpath, deploy, deploy_rules, override_deps, do_fork, do_exec = IndiferentHash.process_options options,
|
|
41
|
+
:help, :workflows, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :save_inputs, :jobname, :printpath, :deploy, :deploy_rules, :override_deps, :fork, :exec,
|
|
42
|
+
:deploy => 'serial'
|
|
43
|
+
|
|
36
44
|
raise MissingParameterException.new :workflow if workflow_name.nil?
|
|
37
45
|
|
|
38
46
|
workflow = Workflow.require_workflow workflow_name
|
|
47
|
+
|
|
48
|
+
workflows = workflows.split(/,\s*/) if workflows
|
|
49
|
+
workflows.each{|wf| Workflow.require_workflow wf } if workflows
|
|
50
|
+
|
|
39
51
|
task_name = task_name.to_sym if task_name
|
|
40
52
|
task = workflow.tasks[task_name.to_sym] if task_name
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
help, provenance, clean, recursive_clean, clean_task, load_inputs, save_inputs, jobname, printpath, deploy, override_deps, do_fork = IndiferentHash.process_options options,
|
|
45
|
-
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :save_inputs, :jobname, :printpath, :deploy, :override_deps, :fork,
|
|
46
|
-
:deploy => 'serial'
|
|
54
|
+
help = true if task.nil?
|
|
47
55
|
|
|
48
56
|
if help
|
|
49
57
|
if defined? scout_usage
|
|
50
|
-
scout_usage
|
|
58
|
+
scout_usage
|
|
51
59
|
else
|
|
52
60
|
puts SOPT.doc
|
|
53
61
|
end
|
|
54
62
|
|
|
55
63
|
puts workflow.usage(task) if workflow
|
|
56
|
-
|
|
64
|
+
|
|
65
|
+
if task_name && task.nil?
|
|
66
|
+
exit -1
|
|
67
|
+
else
|
|
68
|
+
exit 0
|
|
69
|
+
end
|
|
57
70
|
end
|
|
58
71
|
|
|
72
|
+
task = workflow.tasks[task_name]
|
|
73
|
+
|
|
59
74
|
job_inputs = task.get_SOPT
|
|
60
75
|
|
|
61
76
|
if load_inputs
|
|
62
|
-
job_inputs = job_inputs.merge(
|
|
77
|
+
job_inputs = job_inputs.merge(task.load_inputs(load_inputs))
|
|
63
78
|
end
|
|
64
79
|
|
|
65
80
|
if override_deps
|
|
@@ -99,10 +114,21 @@ elsif do_fork
|
|
|
99
114
|
job.fork
|
|
100
115
|
puts job.path
|
|
101
116
|
exit 0
|
|
117
|
+
elsif do_exec
|
|
118
|
+
puts job.exec
|
|
119
|
+
exit 0
|
|
102
120
|
elsif save_inputs
|
|
103
121
|
puts job.save_inputs(save_inputs)
|
|
104
122
|
exit 0
|
|
105
123
|
else
|
|
124
|
+
require 'scout/workflow/deployment'
|
|
125
|
+
|
|
126
|
+
if deploy_rules.nil?
|
|
127
|
+
rules = Workflow::Orchestrator.load_rules_for_job(job)
|
|
128
|
+
else
|
|
129
|
+
deploy_files = deploy_rules.split(/,\s*/)
|
|
130
|
+
rules = Workflow::Orchestrator.load_rules deploy_files
|
|
131
|
+
end
|
|
106
132
|
|
|
107
133
|
case deploy
|
|
108
134
|
when "queue"
|
|
@@ -112,28 +138,40 @@ else
|
|
|
112
138
|
puts save_inputs
|
|
113
139
|
exit
|
|
114
140
|
end
|
|
141
|
+
when 'dry', 'dryrun', 'debug'
|
|
142
|
+
batches = Workflow::Orchestrator.job_batches rules, job
|
|
143
|
+
batches.each do |batch|
|
|
144
|
+
top = batch[:top_level]
|
|
145
|
+
jobs = batch[:jobs]
|
|
146
|
+
puts Log.color :title, Log.fingerprint(top)
|
|
147
|
+
puts batch[:rules].to_yaml
|
|
148
|
+
deps = batch[:deps].collect{|dep| dep[:top_level] }
|
|
149
|
+
provided_inputs = jobs.inject({}){|acc,j| acc = IndiferentHash.add_defaults acc, j.provided_inputs }
|
|
150
|
+
provided_inputs.each do |i,v|
|
|
151
|
+
puts Log.color :green, "#{i}: " + Log.color(:blue, Log.fingerprint(v))
|
|
152
|
+
end
|
|
153
|
+
other = jobs - [top]
|
|
154
|
+
puts Log.color :subtitle, 'Other jobs: ' + Log.color(:blue, other.collect{|d| d.short_path}.uniq * ', ' ) if other.any?
|
|
155
|
+
puts Log.color :subtitle, 'Dependencies: ' + Log.color(:blue, deps.collect{|d| d.short_path}.uniq * ', ' ) if deps.any?
|
|
156
|
+
end
|
|
157
|
+
exit 0
|
|
115
158
|
when "serial"
|
|
116
159
|
job.run(true)
|
|
117
160
|
when "local"
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
job.grace
|
|
128
|
-
else
|
|
129
|
-
if deploy.end_with?('-slurm')
|
|
130
|
-
server = deploy.sub('-slurm','')
|
|
131
|
-
OffsiteStep.setup(job, server: server, slurm: true)
|
|
161
|
+
Workflow::LocalExecutor.produce job, rules
|
|
162
|
+
when 'batch', 'sched', 'cluster', "slurm", 'pbs', 'lsf'
|
|
163
|
+
Workflow::Scheduler.produce job, rules
|
|
164
|
+
exit 0
|
|
165
|
+
else
|
|
166
|
+
raise 'Use scout-camp instead of scout' unless defined? OffsiteStep
|
|
167
|
+
if deploy.end_with?('-batch')
|
|
168
|
+
server = deploy.sub('-batch','')
|
|
169
|
+
OffsiteStep.setup(job, server: server, batch: true)
|
|
132
170
|
else
|
|
133
171
|
OffsiteStep.setup(job, server: deploy)
|
|
134
172
|
end
|
|
135
173
|
|
|
136
|
-
job.run
|
|
174
|
+
job.run(true)
|
|
137
175
|
end unless job.done?
|
|
138
176
|
|
|
139
177
|
if printpath
|
|
@@ -147,5 +185,3 @@ else
|
|
|
147
185
|
end
|
|
148
186
|
end
|
|
149
187
|
end
|
|
150
|
-
|
|
151
|
-
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module TestWFA
|
|
6
|
+
extend Workflow
|
|
7
|
+
|
|
8
|
+
task :a1 => :string do self.task_name.to_s end
|
|
9
|
+
|
|
10
|
+
dep :a1
|
|
11
|
+
task :a2 => :string do self.task_name.to_s end
|
|
12
|
+
|
|
13
|
+
dep :a2
|
|
14
|
+
task :a3 => :string do self.task_name.to_s end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module TestWFB
|
|
18
|
+
extend Workflow
|
|
19
|
+
|
|
20
|
+
dep TestWFA, :a2
|
|
21
|
+
task :b1 => :string do self.task_name.to_s end
|
|
22
|
+
|
|
23
|
+
dep :b1
|
|
24
|
+
task :b2 => :string do self.task_name.to_s end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module TestWFC
|
|
28
|
+
extend Workflow
|
|
29
|
+
|
|
30
|
+
dep TestWFA, :a1
|
|
31
|
+
dep_task :c1, TestWFB, :b2
|
|
32
|
+
|
|
33
|
+
task :c2 => :string do self.task_name.to_s end
|
|
34
|
+
|
|
35
|
+
dep :c1
|
|
36
|
+
dep :c2
|
|
37
|
+
task :c3 => :string do self.task_name.to_s end
|
|
38
|
+
|
|
39
|
+
dep_task :c4, TestWFC, :c3
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module TestWFD
|
|
43
|
+
extend Workflow
|
|
44
|
+
|
|
45
|
+
dep TestWFC, :c3, :jobname => "First c3"
|
|
46
|
+
dep TestWFC, :c3, :jobname => "Second c3"
|
|
47
|
+
task :d1 => :string do self.task_name.to_s end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module TestDeepWF
|
|
51
|
+
extend Workflow
|
|
52
|
+
|
|
53
|
+
dep_task :deep1, TestWFD, :d1
|
|
54
|
+
|
|
55
|
+
input :size, :integer, "Number of dependencies", 100
|
|
56
|
+
dep :deep1 do |jobname,options|
|
|
57
|
+
options[:size].to_i.times.collect{|i|
|
|
58
|
+
{:jobname => "step-#{i}"}
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
task :suite => :array do
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class TestOrchestrateBatches < Test::Unit::TestCase
|
|
66
|
+
|
|
67
|
+
RULES = IndiferentHash.setup(YAML.load(<<-EOF))
|
|
68
|
+
---
|
|
69
|
+
defaults:
|
|
70
|
+
queue: first_queue
|
|
71
|
+
time: 1h
|
|
72
|
+
log: 2
|
|
73
|
+
config_keys: key1 value1 token1
|
|
74
|
+
chains:
|
|
75
|
+
chain_a_b:
|
|
76
|
+
tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1, TestWFA#a2
|
|
77
|
+
config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
|
|
78
|
+
chain_a:
|
|
79
|
+
workflow: TestWFA
|
|
80
|
+
tasks: a1, a2, a3
|
|
81
|
+
config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
|
|
82
|
+
chain_b:
|
|
83
|
+
workflow: TestWFB
|
|
84
|
+
tasks: b1, b2
|
|
85
|
+
chain_b2:
|
|
86
|
+
tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1
|
|
87
|
+
chain_d:
|
|
88
|
+
tasks: TestWFD#d1, TestWFC#c1, TestWFC#c2, TestWFC#c3
|
|
89
|
+
TestWFA:
|
|
90
|
+
defaults:
|
|
91
|
+
log: 4
|
|
92
|
+
config_keys: key4 value4 token4
|
|
93
|
+
time: 10min
|
|
94
|
+
a1:
|
|
95
|
+
cpus: 10
|
|
96
|
+
config_keys: key5 value5 token5
|
|
97
|
+
TestWFC:
|
|
98
|
+
defaults:
|
|
99
|
+
skip: true
|
|
100
|
+
log: 4
|
|
101
|
+
time: 10s
|
|
102
|
+
EOF
|
|
103
|
+
|
|
104
|
+
def test_chain_batches
|
|
105
|
+
job = TestWFD.job(:d1, nil)
|
|
106
|
+
job.recursive_clean
|
|
107
|
+
|
|
108
|
+
job_chains_map = Workflow::Orchestrator.job_chains(RULES, job)
|
|
109
|
+
workload = Workflow::Orchestrator.job_workload(job)
|
|
110
|
+
batches = Workflow::Orchestrator.chain_batches(RULES, job_chains_map, workload)
|
|
111
|
+
assert_equal 3, batches.length
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def test_job_batches_d
|
|
116
|
+
job = TestWFD.job(:d1, nil)
|
|
117
|
+
job.recursive_clean
|
|
118
|
+
|
|
119
|
+
batches = Workflow::Orchestrator.job_batches(RULES, [job])
|
|
120
|
+
assert_equal 3, batches.length
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_job_batches_c4
|
|
124
|
+
job = TestWFC.job(:c4, nil)
|
|
125
|
+
job.recursive_clean
|
|
126
|
+
|
|
127
|
+
batches = Workflow::Orchestrator.job_batches(RULES, job)
|
|
128
|
+
assert_equal 1, batches.length
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_job_batches_a2
|
|
132
|
+
job = TestWFA.job(:a2, nil)
|
|
133
|
+
job.recursive_clean
|
|
134
|
+
|
|
135
|
+
batches = Workflow::Orchestrator.job_batches({}, job)
|
|
136
|
+
assert_equal 2, batches.length
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
|
3
|
+
|
|
4
|
+
require 'scout/workflow'
|
|
5
|
+
|
|
6
|
+
module TestWFA
|
|
7
|
+
extend Workflow
|
|
8
|
+
|
|
9
|
+
task :a1 => :string do self.task_name.to_s end
|
|
10
|
+
|
|
11
|
+
dep :a1
|
|
12
|
+
task :a2 => :string do self.task_name.to_s end
|
|
13
|
+
|
|
14
|
+
dep :a2
|
|
15
|
+
task :a3 => :string do self.task_name.to_s end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module TestWFB
|
|
19
|
+
extend Workflow
|
|
20
|
+
|
|
21
|
+
dep TestWFA, :a2
|
|
22
|
+
task :b1 => :string do self.task_name.to_s end
|
|
23
|
+
|
|
24
|
+
dep :b1
|
|
25
|
+
task :b2 => :string do self.task_name.to_s end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module TestWFC
|
|
29
|
+
extend Workflow
|
|
30
|
+
|
|
31
|
+
dep TestWFA, :a1
|
|
32
|
+
dep_task :c1, TestWFB, :b2
|
|
33
|
+
|
|
34
|
+
task :c2 => :string do self.task_name.to_s end
|
|
35
|
+
|
|
36
|
+
dep :c1
|
|
37
|
+
dep :c2
|
|
38
|
+
task :c3 => :string do self.task_name.to_s end
|
|
39
|
+
|
|
40
|
+
dep_task :c4, TestWFC, :c3
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module TestWFD
|
|
44
|
+
extend Workflow
|
|
45
|
+
|
|
46
|
+
dep TestWFC, :c3, :jobname => "First c3"
|
|
47
|
+
dep TestWFC, :c3, :jobname => "Second c3"
|
|
48
|
+
task :d1 => :string do self.task_name.to_s end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
module TestDeepWF
|
|
52
|
+
extend Workflow
|
|
53
|
+
|
|
54
|
+
dep_task :deep1, TestWFD, :d1
|
|
55
|
+
|
|
56
|
+
input :size, :integer, "Number of dependencies", 100
|
|
57
|
+
dep :deep1 do |jobname,options|
|
|
58
|
+
options[:size].to_i.times.collect{|i|
|
|
59
|
+
{:jobname => "step-#{i}"}
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
task :suite => :array do
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class TestOrchestrateChains < Test::Unit::TestCase
|
|
67
|
+
|
|
68
|
+
RULES = IndiferentHash.setup(YAML.load(<<-EOF))
|
|
69
|
+
---
|
|
70
|
+
defaults:
|
|
71
|
+
queue: first_queue
|
|
72
|
+
time: 1h
|
|
73
|
+
log: 2
|
|
74
|
+
config_keys: key1 value1 token1
|
|
75
|
+
chains:
|
|
76
|
+
chain_a_b:
|
|
77
|
+
tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1, TestWFA#a2
|
|
78
|
+
comment: Should not include TestWFA#a1
|
|
79
|
+
chain_a:
|
|
80
|
+
workflow: TestWFA
|
|
81
|
+
tasks: a1, a2, a3
|
|
82
|
+
config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
|
|
83
|
+
chain_b:
|
|
84
|
+
workflow: TestWFB
|
|
85
|
+
tasks: b1, b2
|
|
86
|
+
chain_b2:
|
|
87
|
+
tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1
|
|
88
|
+
chain_d:
|
|
89
|
+
tasks: TestWFD#d1, TestWFC#c1, TestWFC#c2, TestWFC#c3
|
|
90
|
+
TestWFA:
|
|
91
|
+
defaults:
|
|
92
|
+
log: 4
|
|
93
|
+
config_keys: key4 value4 token4
|
|
94
|
+
a1:
|
|
95
|
+
cpus: 10
|
|
96
|
+
config_keys: key5 value5 token5
|
|
97
|
+
TestWFC:
|
|
98
|
+
defaults:
|
|
99
|
+
skip: true
|
|
100
|
+
log: 4
|
|
101
|
+
EOF
|
|
102
|
+
|
|
103
|
+
def test_parse_chains
|
|
104
|
+
chains = Workflow::Orchestrator.parse_chains RULES
|
|
105
|
+
assert chains[:chain_a][:tasks]["TestWFA"].include?("a1")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_job_chain_a
|
|
109
|
+
job = TestWFA.job(:a3, nil)
|
|
110
|
+
job.recursive_clean
|
|
111
|
+
|
|
112
|
+
job_chains = Workflow::Orchestrator.job_chains(RULES, job)
|
|
113
|
+
job_chains = NamedArray.setup(job_chains, job_chains.collect{|n,i| n })
|
|
114
|
+
|
|
115
|
+
assert_equal %w(chain_a_b chain_a), job_chains.fields
|
|
116
|
+
assert_equal 3, job_chains["chain_a"].last[:jobs].length
|
|
117
|
+
assert_equal job, job_chains["chain_a"].last[:top_level]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def test_job_chain_b
|
|
121
|
+
job = TestWFB.job(:b2, nil)
|
|
122
|
+
job.recursive_clean
|
|
123
|
+
|
|
124
|
+
job_chains = Workflow::Orchestrator.job_chains(RULES, job)
|
|
125
|
+
job_chains = NamedArray.setup(job_chains, job_chains.collect{|n,i| n })
|
|
126
|
+
|
|
127
|
+
assert_equal %w(chain_a chain_b chain_b2 chain_a_b).sort, job_chains.fields.sort
|
|
128
|
+
|
|
129
|
+
assert_equal 2, job_chains["chain_a"].last[:jobs].length
|
|
130
|
+
assert_equal job.step("a2"), job_chains["chain_a"].last[:top_level]
|
|
131
|
+
|
|
132
|
+
assert_equal 2, job_chains["chain_b"].last[:jobs].length
|
|
133
|
+
assert_equal job, job_chains["chain_b"].last[:top_level]
|
|
134
|
+
|
|
135
|
+
assert_equal 2, job_chains["chain_b2"].last[:jobs].length
|
|
136
|
+
assert_equal job, job_chains["chain_b2"].last[:top_level]
|
|
137
|
+
|
|
138
|
+
assert_equal 4, job_chains["chain_a_b"].last[:jobs].length
|
|
139
|
+
assert_equal job, job_chains["chain_a_b"].last[:top_level]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def test_job_chains_double
|
|
143
|
+
job = TestWFD.job(:d1, nil)
|
|
144
|
+
job.recursive_clean
|
|
145
|
+
|
|
146
|
+
job_chains = Workflow::Orchestrator.job_chains(RULES, job)
|
|
147
|
+
job_chains = NamedArray.setup(job_chains, job_chains.collect{|n,i| n })
|
|
148
|
+
|
|
149
|
+
assert_equal 2, job_chains.select{|n,i| n == 'chain_a' }.length
|
|
150
|
+
assert_equal ["First c3", "Second c3"].sort, job_chains.
|
|
151
|
+
select{|n,i| n == 'chain_a' }.
|
|
152
|
+
collect{|n,i| i[:top_level].name }.sort
|
|
153
|
+
|
|
154
|
+
assert_equal 1, job_chains.select{|n,i| n == 'chain_d' }.length
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def __test_benchmark
|
|
158
|
+
|
|
159
|
+
job = TestDeepWF.job(:suite, :size => 100)
|
|
160
|
+
job.recursive_clean
|
|
161
|
+
|
|
162
|
+
Misc.benchmark(10) do
|
|
163
|
+
Workflow::Orchestrator.job_chains(RULES, job)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
end
|
|
171
|
+
|