rbbt-util 5.26.157 → 5.26.158

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,310 +0,0 @@
1
- module WorkflowRESTClient
2
- def self.encode(url)
3
- begin
4
- URI.encode(url)
5
- rescue
6
- Log.warn $!.message
7
- url
8
- end
9
- end
10
-
11
- def self.fix_hash(hash, fix_values = false)
12
- fixed = {}
13
- hash.each do |key, value|
14
- fixed[key.to_sym] = case value
15
- when TrueClass
16
- value
17
- when FalseClass
18
- value
19
- when Hash
20
- fix_hash(value)
21
- when (fix_values and String )
22
- value.to_sym
23
- when IO
24
- value.read
25
- when TSV::Dumper
26
- value.stream
27
- when Step
28
- stream = get_stream(value)
29
- stream || value.load
30
- else
31
- value
32
- end
33
- end
34
- fixed
35
- end
36
-
37
- def self.parse_exception(text)
38
- klass, message = text.split " => "
39
- begin
40
- klass = Kernel.const_get klass
41
- return klass.new message
42
- rescue
43
- message
44
- end
45
- end
46
-
47
- def self.capture_exception
48
- begin
49
- yield
50
- rescue Exception => e
51
- raise e unless e.respond_to? :response
52
- begin
53
- ne = parse_exception e.response.to_s
54
- case ne
55
- when String
56
- raise e.class, ne
57
- when Exception
58
- raise ne
59
- else
60
- raise
61
- end
62
- rescue
63
- raise e
64
- end
65
- raise $!
66
- end
67
- end
68
-
69
- def self.fix_params(params)
70
- new_params = {}
71
- params.each do |k,v|
72
- if Array === v and v.empty?
73
- new_params[k] = "EMPTY_ARRAY"
74
- else
75
- new_params[k] = v
76
- end
77
- end
78
- new_params
79
- end
80
-
81
- def self.clean_url(url, params = {})
82
- params = params.merge({ :_format => 'json', :update => 'clean' })
83
- params = fix_params params
84
- res = capture_exception do
85
- Misc.insist(2, 0.5) do
86
- Log.debug{ "RestClient clean: #{ url } - #{Misc.fingerprint params}" }
87
- res = begin
88
- RestClient.get(self.encode(url), :params => params)
89
- rescue RestClient::NotFound
90
- return nil
91
- end
92
- raise TryAgain if res.code == 202
93
- res
94
- end
95
- end
96
- res
97
- end
98
-
99
- def self.get_raw(url, params = {})
100
- params = params.merge({ :_format => 'raw' })
101
- params = fix_params params
102
- res = capture_exception do
103
- Misc.insist(2, 0.5) do
104
- raise "No url" if url.nil?
105
- Log.debug{ "RestClient get_raw: #{ url } - #{Misc.fingerprint params}" }
106
- res = RestClient.get(self.encode(url), :params => params)
107
- raise TryAgain if res.code == 202
108
- res.to_s
109
- end
110
- end
111
- res
112
- end
113
-
114
- def self.get_json(url, params = {})
115
- Log.debug{ "RestClient get_json: #{ url } - #{Misc.fingerprint params }" }
116
- params = params.merge({ :_format => 'json' })
117
- params = fix_params params
118
-
119
- res = capture_exception do
120
- Misc.insist(2, 0.5) do
121
- RestClient.get(self.encode(url), :params => params)
122
- end
123
- end
124
-
125
- begin
126
- JSON.parse(res)
127
- rescue
128
- res
129
- end
130
- end
131
-
132
- def self.post_jobname(url, params = {})
133
- Log.debug{ "RestClient post_jobname: #{ url } - #{Misc.fingerprint params}" }
134
- params = params.merge({ :_format => 'jobname' })
135
- params = fix_params params
136
-
137
- WorkflowRESTClient.__prepare_inputs_for_restclient(params)
138
- name = capture_exception do
139
- RestClient.post(self.encode(url), params)
140
- end
141
-
142
- Log.debug{ "RestClient jobname returned for #{ url } - #{Misc.fingerprint params}: #{name}" }
143
-
144
- name
145
- end
146
-
147
- def self.post_json(url, params = {})
148
- if url =~ /_cache_type=:exec/
149
- JSON.parse(Open.open(url, :nocache => true))
150
- else
151
- params = params.merge({ :_format => 'json' })
152
- params = fix_params params
153
-
154
- res = capture_exception do
155
- RestClient.post(self.encode(url), params)
156
- end
157
-
158
- begin
159
- JSON.parse(res)
160
- rescue
161
- res
162
- end
163
- end
164
- end
165
-
166
- def get
167
- params ||= {}
168
- params = params.merge(:_format => [:string, :boolean, :tsv, :annotations, :array].include?(result_type.to_sym) ? :raw : :json )
169
- @cache_result ||= Persist.persist("REST persist", :binary, :file => cache_file + "." + Misc.obj2digest(params)) do
170
- Misc.insist 3, rand(2) + 1 do
171
- begin
172
- init_job if url.nil?
173
- @adaptor.get_raw(url, params)
174
- rescue
175
- Log.exception $!
176
- raise $!
177
- end
178
- end
179
- end
180
- end
181
-
182
- def load
183
- params = {}
184
- join unless done? or streaming?
185
- raise get_exception if error? or aborted?
186
- load_res get
187
- end
188
-
189
- def exec_job
190
- res = _run_job(:exec)
191
- load_res res, result_type == :array ? :json : result_type
192
- end
193
-
194
- def abort
195
- return self if status == :done
196
- @adaptor.get_json(@url + '?_update=abort') if @url and @name
197
- self
198
- end
199
-
200
- def init_job(cache_type = nil, other_params = {})
201
- cache_type = :asynchronous if cache_type.nil? and not @is_exec
202
- cache_type = :exec if cache_type.nil?
203
- @last_info_time = nil
204
- @done = false
205
- get_streams
206
- @name ||= Persist.memory("RemoteSteps", :workflow => self, :task => task, :jobname => @name, :inputs => inputs, :cache_type => cache_type) do
207
- Misc.insist do
208
- @adaptor.post_jobname(File.join(base_url, task.to_s), inputs.merge(other_params).merge(:jobname => @name||@base_name, :_cache_type => cache_type))
209
- end
210
- end
211
- if Open.remote? @name
212
- @url = @name
213
- @name = File.basename(@name)
214
- else
215
- @url = File.join(base_url, task.to_s, @name)
216
- end
217
- self
218
- end
219
-
220
- def recursive_clean
221
- Log.warn "Not doing recursive cleans"
222
- return
223
- begin
224
- _restart
225
- params = {:_update => :recursive_clean}
226
- @adaptor.get_raw(url, params)
227
- rescue Exception
228
- Log.exception $!
229
- end
230
- self
231
- end
232
-
233
- def _clean
234
- begin
235
- _restart
236
- cache_files.each do |cache_file|
237
- Open.rm cache_file
238
- end
239
- params = {:_update => :clean}
240
- @adaptor.clean_url(url, params) if @url
241
- rescue Exception
242
- Log.exception $!
243
- end
244
- end
245
-
246
- def clean
247
- init_job
248
- _clean
249
- self
250
- end
251
-
252
- def stream_job(task_url, task_params, stream_input, cache_type = :exec)
253
- require 'rbbt/util/misc/multipart_payload'
254
- WorkflowRESTClient.capture_exception do
255
- @streaming = true
256
-
257
- Log.debug{ "RestClient stream #{Process.pid}: #{ task_url } #{stream_input} #{cache_type} - #{Misc.fingerprint task_params}" }
258
- res = RbbtMutiplartPayload.issue task_url, task_params, stream_input, nil, nil, true
259
- type = res.gets
260
-
261
- out = case type.strip
262
- when "LOCATION"
263
- @url = res.gets
264
- @url.sub!(/\?.*/,'')
265
- join
266
- WorkflowRESTClient.get_raw(@url)
267
- @done = true
268
- @streaming = false
269
- when /STREAM: (.*)/
270
- @url = $1.strip
271
- res.callback = Proc.new do
272
- Log.medium "Done streaming result from #{@url}"
273
- @done = true
274
- @streaming = false
275
- end
276
- res
277
- when "BULK"
278
- begin
279
- res.read
280
- ensure
281
- @done = true
282
- @streaming = false
283
- end
284
- else
285
- raise "What? " + type
286
- end
287
-
288
- ConcurrentStream.setup(out, :filename => @url)
289
-
290
- out
291
- end
292
- end
293
-
294
- def _run_job(cache_type = :async)
295
- get_streams
296
-
297
- task_url = URI.encode(File.join(base_url, task.to_s))
298
- @adaptor.__prepare_inputs_for_restclient(inputs)
299
- task_params = inputs.merge(:_cache_type => cache_type, :jobname => base_name, :_format => [:string, :boolean, :tsv, :annotations].include?(result_type) ? :raw : :json)
300
-
301
- if cache_type == :stream or cache_type == :exec and stream_input and inputs[stream_input]
302
- io = self.stream_job(task_url, task_params, stream_input, cache_type)
303
- return io
304
- else
305
- @adaptor.execute_job(base_url, task, task_params, cache_type)
306
- end
307
-
308
- end
309
-
310
- end
@@ -1,61 +0,0 @@
1
- require 'rbbt/workflow/remote/ssh/driver'
2
-
3
- module WorkflowSSHClient
4
- def workflow_description
5
- WorkflowSSHClient.get_raw(File.join(url, 'description'))
6
- end
7
-
8
- def documentation
9
- @documention ||= IndiferentHash.setup(WorkflowSSHClient.get_json(File.join(url, "documentation")))
10
- @documention
11
- end
12
-
13
- def task_info(task)
14
- @task_info ||= IndiferentHash.setup({})
15
-
16
- if @task_info[task].nil?
17
- task_info = WorkflowSSHClient.get_json(File.join(@base_url, task.to_s))
18
- task_info = WorkflowSSHClient.fix_hash(task_info)
19
-
20
- task_info[:result_type] = task_info[:result_type].to_sym if task_info[:result_type]
21
- task_info[:export] = task_info[:export].to_sym if task_info[:export]
22
- task_info[:input_types] = WorkflowSSHClient.fix_hash(task_info[:input_types], true)
23
- task_info[:inputs] = task_info[:inputs].collect{|input| input.to_sym }
24
-
25
- @task_info[task] = IndiferentHash.setup(task_info)
26
- end
27
-
28
- IndiferentHash.setup(@task_info[task])
29
- end
30
-
31
- def tasks
32
- @tasks ||= Hash.new do |hash,task_name|
33
- info = @task_info[task_name]
34
- task = Task.setup info do |*args|
35
- raise "This is a remote task"
36
- end
37
- task.name = task_name.to_sym
38
- hash[task_name] = task
39
- end
40
- end
41
-
42
- def load_tasks
43
- @task_info.keys.each{|name| tasks[name]}
44
- end
45
-
46
- def task_dependencies
47
- @task_dependencies ||= Hash.new do |hash,task|
48
- hash[task] = if exported_tasks.include? task
49
- WorkflowSSHClient.get_json(File.join(url, task.to_s, 'dependencies'))
50
- else
51
- []
52
- end
53
- end
54
- end
55
-
56
- def init_remote_tasks
57
- @task_info = IndiferentHash.setup(WorkflowSSHClient.get_json(url))
58
- @exec_exports = @stream_exports = @synchronous_exports = []
59
- @asynchronous_exports = @task_info.keys
60
- end
61
- end
@@ -1,147 +0,0 @@
1
- module SSHDriver
2
- def self.run(server, script)
3
- Log.debug "Run ssh script in #{server}:\n#{script}"
4
- CMD.cmd("ssh '#{server}' 'shopt -s expand_aliases; bash -l -i -c \"ruby\"' ", :in => script, :log => true).read
5
- end
6
-
7
- #def self.run_log(server, script)
8
- # Log.debug "Run and monitor ssh script in #{server}:\n#{script}"
9
- # CMD.cmd("ssh '#{server}' 'shopt -s expand_aliases; bash -ic \"ruby\"' ", :in => script, :log => true)
10
- #end
11
-
12
- def self.parse_url(url)
13
- m = url.match(/ssh:\/\/([^:]+):(.*)/)
14
- server = m.captures[0]
15
- path = m.captures[1]
16
- [server, path]
17
- end
18
-
19
- def self.path_script(path)
20
-
21
- workflow, task, job, *rest = path.split("/")
22
-
23
- script =<<-EOF
24
- require 'rbbt/workflow'
25
- wf = Workflow.require_workflow "#{workflow}"
26
- EOF
27
-
28
- case task
29
- when nil
30
- script +=<<-EOF
31
- task_info = {}
32
- wf.tasks.keys.each do |task|
33
- task_info[task] = wf.task_info(task)
34
- end
35
- res = task_info
36
- EOF
37
- when 'documentation'
38
- script +=<<-EOF
39
- res = documentation = wf.documentation
40
- EOF
41
- else
42
- if job.nil?
43
- script +=<<-EOF
44
- task = '#{task}'
45
- res = task_info = wf.task_info(task)
46
- EOF
47
- else
48
- case rest.first
49
- when nil
50
- script +=<<-EOF
51
- task = '#{task}'
52
- jobname = '#{job}'
53
- res = job = wf.fast_load_id(File.join(task, jobname))
54
- EOF
55
- when "info"
56
- script +=<<-EOF
57
- task = '#{task}'
58
- jobname = '#{job}'
59
- job = wf.fast_load_id(File.join(task, jobname))
60
- res = job_info = job.info
61
- EOF
62
- else
63
- raise "Unkown path: #{[path, rest].inspect}"
64
- end
65
- end
66
- end
67
- end
68
-
69
- def self.job_script(inputs_id, jobname = nil)
70
- script =<<-EOF
71
- jobname = #{jobname.nil? ? 'nil' : "'#{jobname}'"}
72
- path = File.join(ENV["HOME"], '.rbbt/tmp/tmp-ssh_job_inputs/#{inputs_id}')
73
- job_inputs = Workflow.load_inputs(path, task_info[:inputs], task_info[:input_types])
74
- job = wf.job(task, jobname, job_inputs)
75
- EOF
76
- script
77
- end
78
-
79
- def self.get_json(url, params)
80
- server, path = parse_url(url)
81
- script = path_script(path)
82
-
83
- script +=<<-EOF
84
- STDOUT.write res.to_json
85
- EOF
86
-
87
- JSON.parse(self.run(server, script))
88
- end
89
-
90
- def self.get_raw(url, params)
91
- server, path = parse_url(url)
92
- script = path_script(path)
93
-
94
- script +=<<-EOF
95
- STDOUT.write res
96
- EOF
97
-
98
- self.run(server, script)
99
- end
100
-
101
- def self.post_job(url, inputs_id, jobname = nil)
102
- server, path = parse_url(url)
103
-
104
- script = path_script(path)
105
- script += job_script(inputs_id, jobname)
106
- script +=<<-EOF
107
- job.init_info
108
- STDOUT.write job.name
109
- EOF
110
- @name = self.run(server, script)
111
- end
112
-
113
- def self.run_job(url, input_id, jobname = nil)
114
- server, path = parse_url(url)
115
-
116
- script = path_script(path)
117
- script += job_script(input_id, jobname)
118
- script +=<<-EOF
119
- job.produce
120
- STDOUT.write job.path
121
- EOF
122
- self.run(server, script)
123
- end
124
-
125
- def self.run_slurm_job(url, input_id, jobname = nil)
126
- server, path = parse_url(url)
127
-
128
- script = path_script(path)
129
- script += job_script(input_id, jobname)
130
- script +=<<-EOF
131
- job.produce
132
- STDOUT.write job.path
133
- EOF
134
- self.run(server, script)
135
- end
136
-
137
- def self.clean(url, input_id, jobname = nil)
138
- server, path = parse_url(url)
139
-
140
- script = path_script(path)
141
- script +=<<-EOF
142
- job.clean
143
- EOF
144
- self.run(server, script)
145
- end
146
-
147
- end
@@ -1,193 +0,0 @@
1
- module WorkflowSSHClient
2
- attr_accessor :override_dependencies
3
-
4
- def self.fix_hash(hash, fix_values = false)
5
- fixed = {}
6
- hash.each do |key, value|
7
- fixed[key.to_sym] = case value
8
- when TrueClass
9
- value
10
- when FalseClass
11
- value
12
- when Hash
13
- fix_hash(value)
14
- when (fix_values and String )
15
- value.to_sym
16
- when IO
17
- value.read
18
- when TSV::Dumper
19
- value.stream
20
- when Step
21
- stream = get_stream(value)
22
- stream || value.load
23
- else
24
- value
25
- end
26
- end
27
- fixed
28
- end
29
-
30
- def self.parse_exception(text)
31
- klass, message = text.split " => "
32
- begin
33
- klass = Kernel.const_get klass
34
- return klass.new message
35
- rescue
36
- message
37
- end
38
- end
39
-
40
- def self.capture_exception
41
- begin
42
- yield
43
- rescue Exception => e
44
- raise e unless e.respond_to? :response
45
- begin
46
- ne = parse_exception e.response.to_s
47
- case ne
48
- when String
49
- raise e.class, ne
50
- when Exception
51
- raise ne
52
- else
53
- raise
54
- end
55
- rescue
56
- raise e
57
- end
58
- raise $!
59
- end
60
- end
61
-
62
- def self.fix_params(params)
63
- new_params = {}
64
- params.each do |k,v|
65
- if Array === v and v.empty?
66
- new_params[k] = "EMPTY_ARRAY"
67
- else
68
- new_params[k] = v
69
- end
70
- end
71
- new_params
72
- end
73
-
74
- def self.get_json(url, params = {})
75
- Log.debug{ "SSHClient get_json: #{ url } - #{Misc.fingerprint params }" }
76
- params = params.merge({ :_format => 'json' })
77
- params = fix_params params
78
-
79
- res = capture_exception do
80
- Misc.insist(2, 0.5) do
81
- SSHDriver.get_json(url, :params => params)
82
- end
83
- end
84
-
85
- begin
86
- JSON.parse(res)
87
- rescue
88
- res
89
- end
90
- end
91
-
92
- def self.upload_inputs(server, inputs, input_types, input_id)
93
- TmpFile.with_file do |dir|
94
- if Step.save_inputs(inputs, input_types, dir)
95
- CMD.cmd("ssh '#{server}' mkdir -p .rbbt/tmp/tmp-ssh_job_inputs/; scp -r '#{dir}' #{server}:.rbbt/tmp/tmp-ssh_job_inputs/#{input_id}")
96
- end
97
- end
98
- end
99
-
100
- #{{{ RUN
101
-
102
-
103
- def init_job(cache_type = nil, other_params = {})
104
- cache_type = :asynchronous if cache_type.nil? and not @is_exec
105
- cache_type = :exec if cache_type.nil?
106
- @last_info_time = nil
107
- @done = false
108
- @server, @server_path = SSHDriver.parse_url base_url
109
- @input_id ||= "inputs-" << rand(100000).to_s
110
- @input_types = task_info(task)[:input_types]
111
-
112
- if override_dependencies
113
-
114
- if override_dependencies && override_dependencies.any?
115
- override_dependencies.each do |od|
116
- name, _sep, value = od.partition("=")
117
- inputs[name] = value
118
- end
119
- end
120
- iii inputs
121
-
122
- WorkflowSSHClient.upload_inputs(@server, inputs, @input_types, @input_id)
123
- else
124
- WorkflowSSHClient.upload_inputs(@server, inputs, @input_types, @input_id)
125
- end
126
-
127
- @name ||= Persist.memory("RemoteSteps", :workflow => self, :task => task, :jobname => @name, :inputs => inputs, :cache_type => cache_type) do
128
- Misc.insist do
129
- input_types = {}
130
- SSHDriver.post_job(File.join(base_url, task.to_s), @input_id, @base_name)
131
- end
132
- end
133
- if Open.remote? @name
134
- @url = @name
135
- @name = File.basename(@name)
136
- else
137
- @url = File.join(base_url, task.to_s, @name)
138
- end
139
- self
140
- end
141
-
142
- def path
143
- @server, @server_path = SSHDriver.parse_url @base_url
144
- "ssh://" + @server + ":" + @remote_path
145
- end
146
-
147
- def produce(*args)
148
- input_types = {}
149
- init_job
150
- @remote_path = SSHDriver.run_job(File.join(base_url, task.to_s), @input_id, @base_name)
151
- while ! done?
152
- sleep 1
153
- end
154
- end
155
-
156
- def load
157
- load_res Open.open(path)
158
- end
159
-
160
- def run(*args)
161
- produce(*args)
162
- self.load unless args.first
163
- end
164
-
165
- def clean
166
- init_job
167
- SSHDriver.clean(@url, @input_id, @base_name) if done?
168
- _restart
169
- end
170
-
171
- def self.relay(workflow, task, jobname, inputs, server, options = {})
172
- options = Misc.add_defaults options, :search_path => 'user'
173
- search_path = options[:search_path]
174
-
175
- job = workflow.job(task, jobname, inputs)
176
-
177
- job.dependencies.each do |dep|
178
- dep.produce
179
- end
180
-
181
- override_dependencies = job.dependencies.collect{|dep| [dep.workflow.to_s, dep.task_name.to_s] * "#" << "=" << Rbbt.identify(dep.path)}
182
-
183
- job.dependencies.each do |dep|
184
- Step.migrate(dep.path, search_path, :target => server)
185
- end
186
-
187
- remote = WorkflowRemoteClient.new("ssh://#{server}:#{workflow.to_s}", "#{workflow.to_s}")
188
- rjob = remote.job(task, jobname, {})
189
- rjob.override_dependencies = override_dependencies
190
- rjob.run
191
- end
192
-
193
- end