aspera-cli 4.5.0 → 4.8.0
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
- checksums.yaml.gz.sig +1 -0
- data/README.md +1894 -1574
- data/bin/ascli +21 -1
- data/bin/asession +38 -34
- data/docs/test_env.conf +14 -3
- data/examples/aoc.rb +17 -15
- data/examples/dascli +26 -0
- data/examples/faspex4.rb +42 -35
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +38 -37
- data/lib/aspera/aoc.rb +245 -205
- data/lib/aspera/ascmd.rb +111 -90
- data/lib/aspera/ats_api.rb +16 -14
- data/lib/aspera/cli/basic_auth_plugin.rb +19 -18
- data/lib/aspera/cli/extended_value.rb +50 -39
- data/lib/aspera/cli/formater.rb +161 -135
- data/lib/aspera/cli/info.rb +18 -0
- data/lib/aspera/cli/listener/line_dump.rb +4 -2
- data/lib/aspera/cli/listener/logger.rb +3 -1
- data/lib/aspera/cli/listener/progress.rb +20 -21
- data/lib/aspera/cli/listener/progress_multi.rb +29 -31
- data/lib/aspera/cli/main.rb +194 -183
- data/lib/aspera/cli/manager.rb +213 -206
- data/lib/aspera/cli/plugin.rb +71 -49
- data/lib/aspera/cli/plugins/alee.rb +8 -7
- data/lib/aspera/cli/plugins/aoc.rb +675 -558
- data/lib/aspera/cli/plugins/ats.rb +116 -109
- data/lib/aspera/cli/plugins/bss.rb +35 -34
- data/lib/aspera/cli/plugins/config.rb +722 -542
- data/lib/aspera/cli/plugins/console.rb +28 -22
- data/lib/aspera/cli/plugins/cos.rb +28 -37
- data/lib/aspera/cli/plugins/faspex.rb +281 -227
- data/lib/aspera/cli/plugins/faspex5.rb +129 -84
- data/lib/aspera/cli/plugins/node.rb +426 -232
- data/lib/aspera/cli/plugins/orchestrator.rb +106 -98
- data/lib/aspera/cli/plugins/preview.rb +196 -191
- data/lib/aspera/cli/plugins/server.rb +131 -126
- data/lib/aspera/cli/plugins/shares.rb +49 -36
- data/lib/aspera/cli/plugins/sync.rb +27 -28
- data/lib/aspera/cli/transfer_agent.rb +84 -79
- data/lib/aspera/cli/version.rb +3 -1
- data/lib/aspera/colors.rb +37 -28
- data/lib/aspera/command_line_builder.rb +84 -63
- data/lib/aspera/cos_node.rb +68 -34
- data/lib/aspera/data_repository.rb +4 -2
- data/lib/aspera/environment.rb +61 -46
- data/lib/aspera/fasp/agent_base.rb +36 -31
- data/lib/aspera/fasp/agent_connect.rb +44 -37
- data/lib/aspera/fasp/agent_direct.rb +101 -104
- data/lib/aspera/fasp/agent_httpgw.rb +91 -90
- data/lib/aspera/fasp/agent_node.rb +36 -33
- data/lib/aspera/fasp/agent_trsdk.rb +28 -31
- data/lib/aspera/fasp/error.rb +3 -1
- data/lib/aspera/fasp/error_info.rb +81 -54
- data/lib/aspera/fasp/installation.rb +171 -151
- data/lib/aspera/fasp/listener.rb +2 -0
- data/lib/aspera/fasp/parameters.rb +105 -111
- data/lib/aspera/fasp/parameters.yaml +305 -249
- data/lib/aspera/fasp/resume_policy.rb +20 -20
- data/lib/aspera/fasp/transfer_spec.rb +27 -0
- data/lib/aspera/fasp/uri.rb +31 -29
- data/lib/aspera/faspex_gw.rb +95 -118
- data/lib/aspera/hash_ext.rb +12 -13
- data/lib/aspera/id_generator.rb +11 -9
- data/lib/aspera/keychain/encrypted_hash.rb +73 -57
- data/lib/aspera/keychain/macos_security.rb +27 -29
- data/lib/aspera/log.rb +40 -39
- data/lib/aspera/nagios.rb +24 -22
- data/lib/aspera/node.rb +38 -30
- data/lib/aspera/oauth.rb +217 -248
- data/lib/aspera/open_application.rb +9 -7
- data/lib/aspera/persistency_action_once.rb +15 -14
- data/lib/aspera/persistency_folder.rb +15 -18
- data/lib/aspera/preview/file_types.rb +266 -270
- data/lib/aspera/preview/generator.rb +94 -92
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +20 -17
- data/lib/aspera/preview/utils.rb +99 -102
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
- data/lib/aspera/proxy_auto_config.rb +114 -21
- data/lib/aspera/rest.rb +144 -142
- data/lib/aspera/rest_call_error.rb +3 -2
- data/lib/aspera/rest_error_analyzer.rb +31 -31
- data/lib/aspera/rest_errors_aspera.rb +18 -16
- data/lib/aspera/secret_hider.rb +68 -0
- data/lib/aspera/ssh.rb +20 -16
- data/lib/aspera/sync.rb +57 -54
- data/lib/aspera/temp_file_manager.rb +20 -14
- data/lib/aspera/timer_limiter.rb +10 -8
- data/lib/aspera/uri_reader.rb +14 -15
- data/lib/aspera/web_auth.rb +85 -80
- data.tar.gz.sig +0 -0
- metadata +169 -40
- metadata.gz.sig +2 -0
- data/bin/dascli +0 -13
- data/docs/Makefile +0 -63
- data/docs/README.erb.md +0 -4221
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/fasp/default.rb +0 -17
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# Aspera 2016
|
|
5
|
-
# Laurent Martin
|
|
6
|
-
#
|
|
7
|
-
##############################################################################
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'English'
|
|
8
4
|
require 'aspera/fasp/agent_base'
|
|
9
5
|
require 'aspera/fasp/error'
|
|
10
6
|
require 'aspera/fasp/parameters'
|
|
11
7
|
require 'aspera/fasp/installation'
|
|
12
8
|
require 'aspera/fasp/resume_policy'
|
|
13
|
-
require 'aspera/fasp/
|
|
9
|
+
require 'aspera/fasp/transfer_spec'
|
|
14
10
|
require 'aspera/log'
|
|
15
11
|
require 'socket'
|
|
16
12
|
require 'timeout'
|
|
17
13
|
require 'securerandom'
|
|
14
|
+
require 'shellwords'
|
|
18
15
|
|
|
19
16
|
module Aspera
|
|
20
17
|
module Fasp
|
|
@@ -27,8 +24,8 @@ module Aspera
|
|
|
27
24
|
wss: false,
|
|
28
25
|
multi_incr_udp: true,
|
|
29
26
|
resume: {},
|
|
30
|
-
quiet: true
|
|
31
|
-
}
|
|
27
|
+
quiet: true # by default no interactive progress bar
|
|
28
|
+
}.freeze
|
|
32
29
|
private_constant :DEFAULT_OPTIONS
|
|
33
30
|
|
|
34
31
|
# start ascp transfer (non blocking), single or multi-session
|
|
@@ -41,22 +38,23 @@ module Aspera
|
|
|
41
38
|
job_options[:resumer] ||= @resume_policy
|
|
42
39
|
job_options[:job_id] ||= SecureRandom.uuid
|
|
43
40
|
# clone transfer spec because we modify it (first level keys)
|
|
44
|
-
transfer_spec=transfer_spec.clone
|
|
41
|
+
transfer_spec = transfer_spec.clone
|
|
45
42
|
# if there is aspera tags
|
|
46
|
-
if transfer_spec['tags'].is_a?(Hash)
|
|
43
|
+
if transfer_spec['tags'].is_a?(Hash) && transfer_spec['tags']['aspera'].is_a?(Hash)
|
|
47
44
|
# TODO: what is this for ? only on local ascp ?
|
|
48
45
|
# NOTE: important: transfer id must be unique: generate random id
|
|
49
46
|
# using a non unique id results in discard of tags in AoC, and a package is never finalized
|
|
50
|
-
|
|
47
|
+
# all sessions in a multi-session transfer must have the same xfer_id (see admin manual)
|
|
48
|
+
transfer_spec['tags']['aspera']['xfer_id'] ||= SecureRandom.uuid
|
|
51
49
|
Log.log.debug("xfer id=#{transfer_spec['xfer_id']}")
|
|
52
50
|
# TODO: useful ? node only ?
|
|
53
|
-
transfer_spec['tags']['aspera']['xfer_retry']||=3600
|
|
51
|
+
transfer_spec['tags']['aspera']['xfer_retry'] ||= 3600
|
|
54
52
|
end
|
|
55
53
|
Log.dump('ts',transfer_spec)
|
|
56
54
|
|
|
57
55
|
# add bypass keys when authentication is token and no auth is provided
|
|
58
|
-
if transfer_spec.has_key?('token')
|
|
59
|
-
!transfer_spec.has_key?('remote_password')
|
|
56
|
+
if transfer_spec.has_key?('token') &&
|
|
57
|
+
!transfer_spec.has_key?('remote_password') &&
|
|
60
58
|
!transfer_spec.has_key?('EX_ssh_key_paths')
|
|
61
59
|
# transfer_spec['remote_password'] = Installation.instance.bypass_pass # not used
|
|
62
60
|
transfer_spec['EX_ssh_key_paths'] = Installation.instance.bypass_keys
|
|
@@ -64,35 +62,33 @@ module Aspera
|
|
|
64
62
|
|
|
65
63
|
# Compute this before using transfer spec because it potentially modifies the transfer spec
|
|
66
64
|
# (even if the var is not used in single session)
|
|
67
|
-
multi_session_info=nil
|
|
65
|
+
multi_session_info = nil
|
|
68
66
|
if transfer_spec.has_key?('multi_session')
|
|
69
|
-
multi_session_info={
|
|
70
|
-
count: transfer_spec['multi_session'].to_i
|
|
67
|
+
multi_session_info = {
|
|
68
|
+
count: transfer_spec['multi_session'].to_i
|
|
71
69
|
}
|
|
72
70
|
# Managed by multi-session, so delete from transfer spec
|
|
73
71
|
transfer_spec.delete('multi_session')
|
|
74
|
-
if multi_session_info[:count]
|
|
72
|
+
if multi_session_info[:count].negative?
|
|
75
73
|
Log.log.error("multi_session(#{transfer_spec['multi_session']}) shall be integer >= 0")
|
|
76
74
|
multi_session_info = nil
|
|
77
75
|
elsif multi_session_info[:count].eql?(0)
|
|
78
|
-
Log.log.debug(
|
|
76
|
+
Log.log.debug('multi_session count is zero: no multisession')
|
|
79
77
|
multi_session_info = nil
|
|
80
|
-
|
|
78
|
+
elsif @options[:multi_incr_udp] # multi_session_info[:count] > 0
|
|
81
79
|
# if option not true: keep default udp port for all sessions
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
transfer_spec.delete('fasp_port')
|
|
87
|
-
end
|
|
80
|
+
multi_session_info[:udp_base] = transfer_spec.has_key?('fasp_port') ? transfer_spec['fasp_port'] : TransferSpec::UDP_PORT
|
|
81
|
+
# delete from original transfer spec, as we will increment values
|
|
82
|
+
transfer_spec.delete('fasp_port')
|
|
83
|
+
# override if specified, else use default value
|
|
88
84
|
end
|
|
89
85
|
end
|
|
90
86
|
|
|
91
87
|
# compute known args
|
|
92
|
-
env_args=Parameters.ts_to_env_args(transfer_spec,wss: @options[:wss])
|
|
88
|
+
env_args = Parameters.ts_to_env_args(transfer_spec,wss: @options[:wss])
|
|
93
89
|
|
|
94
90
|
# add fallback cert and key as arguments if needed
|
|
95
|
-
if [
|
|
91
|
+
if %w[1 force].include?(transfer_spec['http_fallback'])
|
|
96
92
|
env_args[:args].unshift('-Y',Installation.instance.path(:fallback_key))
|
|
97
93
|
env_args[:args].unshift('-I',Installation.instance.path(:fallback_cert))
|
|
98
94
|
end
|
|
@@ -100,19 +96,19 @@ module Aspera
|
|
|
100
96
|
env_args[:args].unshift('-q') if @options[:quiet]
|
|
101
97
|
|
|
102
98
|
# transfer job can be multi session
|
|
103
|
-
xfer_job={
|
|
104
|
-
:
|
|
105
|
-
:
|
|
99
|
+
xfer_job = {
|
|
100
|
+
id: job_options[:job_id],
|
|
101
|
+
sessions: [] # all sessions as below
|
|
106
102
|
}
|
|
107
103
|
|
|
108
104
|
# generic session information
|
|
109
|
-
session={
|
|
110
|
-
:
|
|
111
|
-
:
|
|
112
|
-
:
|
|
113
|
-
:
|
|
114
|
-
:
|
|
115
|
-
:
|
|
105
|
+
session = {
|
|
106
|
+
thread: nil, # Thread object monitoring management port, not nil when pushed to :sessions
|
|
107
|
+
error: nil, # exception if failed
|
|
108
|
+
io: nil, # management port server socket
|
|
109
|
+
id: nil, # SessionId from INIT message in mgt port
|
|
110
|
+
env_args: env_args, # env vars and args to ascp (from transfer spec)
|
|
111
|
+
options: job_options # [Hash]
|
|
116
112
|
}
|
|
117
113
|
|
|
118
114
|
if multi_session_info.nil?
|
|
@@ -126,12 +122,12 @@ module Aspera
|
|
|
126
122
|
# do not delay the first session
|
|
127
123
|
sleep(@options[:spawn_delay_sec]) unless i.eql?(1)
|
|
128
124
|
# do deep copy (each thread has its own copy because it is modified here below and in thread)
|
|
129
|
-
this_session=session.clone
|
|
130
|
-
this_session[:env_args]=this_session[:env_args].clone
|
|
131
|
-
this_session[:env_args][:args]=this_session[:env_args][:args].clone
|
|
125
|
+
this_session = session.clone
|
|
126
|
+
this_session[:env_args] = this_session[:env_args].clone
|
|
127
|
+
this_session[:env_args][:args] = this_session[:env_args][:args].clone
|
|
132
128
|
this_session[:env_args][:args].unshift("-C#{i}:#{multi_session_info[:count]}")
|
|
133
129
|
# option: increment (default as per ascp manual) or not (cluster on other side ?)
|
|
134
|
-
this_session[:env_args][:args].unshift('-O',
|
|
130
|
+
this_session[:env_args][:args].unshift('-O',(multi_session_info[:udp_base] + i - 1).to_s) if @options[:multi_incr_udp]
|
|
135
131
|
this_session[:thread] = Thread.new(this_session) {|s|transfer_thread_entry(s)}
|
|
136
132
|
xfer_job[:sessions].push(this_session)
|
|
137
133
|
end
|
|
@@ -139,7 +135,7 @@ module Aspera
|
|
|
139
135
|
Log.log.debug('started session thread(s)')
|
|
140
136
|
|
|
141
137
|
# add job to list of jobs
|
|
142
|
-
@jobs[job_options[:job_id]]=xfer_job
|
|
138
|
+
@jobs[job_options[:job_id]] = xfer_job
|
|
143
139
|
Log.log.debug("jobs: #{@jobs.keys.count}")
|
|
144
140
|
|
|
145
141
|
return job_options[:job_id]
|
|
@@ -150,12 +146,12 @@ module Aspera
|
|
|
150
146
|
def wait_for_transfers_completion
|
|
151
147
|
Log.log.debug('wait_for_transfers_completion')
|
|
152
148
|
# set to non-nil to exit loop
|
|
153
|
-
result=[]
|
|
154
|
-
@jobs.each do |
|
|
149
|
+
result = []
|
|
150
|
+
@jobs.each do |_id,job|
|
|
155
151
|
job[:sessions].each do |session|
|
|
156
152
|
Log.log.debug("join #{session[:thread]}")
|
|
157
153
|
session[:thread].join
|
|
158
|
-
result.push(session[:error]
|
|
154
|
+
result.push(session[:error] || :success)
|
|
159
155
|
end
|
|
160
156
|
end
|
|
161
157
|
Log.log.debug('all transfers joined')
|
|
@@ -181,29 +177,36 @@ module Aspera
|
|
|
181
177
|
raise 'env_args must be Hash' unless env_args.is_a?(Hash)
|
|
182
178
|
raise 'session must be Hash' unless session.is_a?(Hash)
|
|
183
179
|
# by default we assume an exception will be raised (for ensure block)
|
|
184
|
-
exception_raised=true
|
|
180
|
+
exception_raised = true
|
|
185
181
|
begin
|
|
186
182
|
Log.log.debug("env_args=#{env_args.inspect}")
|
|
187
183
|
# get location of ascp executable
|
|
188
|
-
ascp_path
|
|
184
|
+
ascp_path = @mutex.synchronize do
|
|
189
185
|
Fasp::Installation.instance.path(env_args[:ascp_version])
|
|
190
186
|
end
|
|
191
187
|
# (optional) check it exists
|
|
192
|
-
raise Fasp::Error
|
|
188
|
+
raise Fasp::Error, "no such file: #{ascp_path}" unless File.exist?(ascp_path)
|
|
193
189
|
# open random local TCP port for listening for ascp management
|
|
194
190
|
mgt_sock = TCPServer.new('127.0.0.1',0)
|
|
195
191
|
# clone arguments as we eed to modify with mgt port
|
|
196
|
-
ascp_arguments=env_args[:args].clone
|
|
192
|
+
ascp_arguments = env_args[:args].clone
|
|
197
193
|
# add management port
|
|
198
194
|
ascp_arguments.unshift('-M', mgt_sock.addr[1].to_s)
|
|
199
195
|
# start ascp in sub process
|
|
200
|
-
Log.log.debug
|
|
196
|
+
Log.log.debug do
|
|
197
|
+
'execute: '+
|
|
198
|
+
env_args[:env].map{|k,v| "#{k}=#{Shellwords.shellescape(v)}"}.join(' ')+
|
|
199
|
+
' '+
|
|
200
|
+
Shellwords.shellescape(ascp_path)+
|
|
201
|
+
' '+
|
|
202
|
+
ascp_arguments.map{|a|Shellwords.shellescape(a)}.join(' ')
|
|
203
|
+
end
|
|
201
204
|
# start process
|
|
202
205
|
ascp_pid = Process.spawn(env_args[:env],[ascp_path,ascp_path],*ascp_arguments)
|
|
203
206
|
# in parent, wait for connection to socket max 3 seconds
|
|
204
207
|
Log.log.debug("before accept for pid (#{ascp_pid})")
|
|
205
208
|
# init management socket
|
|
206
|
-
ascp_mgt_io=nil
|
|
209
|
+
ascp_mgt_io = nil
|
|
207
210
|
Timeout.timeout(@options[:spawn_timeout_sec]) do
|
|
208
211
|
ascp_mgt_io = mgt_sock.accept
|
|
209
212
|
# management messages include file names which may be utf8
|
|
@@ -212,38 +215,38 @@ module Aspera
|
|
|
212
215
|
ascp_mgt_io.set_encoding(Encoding::UTF_8)
|
|
213
216
|
end
|
|
214
217
|
Log.log.debug("after accept (#{ascp_mgt_io})")
|
|
215
|
-
session[:io]=ascp_mgt_io
|
|
218
|
+
session[:io] = ascp_mgt_io
|
|
216
219
|
# exact text for event, with \n
|
|
217
|
-
current_event_text=''
|
|
220
|
+
current_event_text = ''
|
|
218
221
|
# parsed event (hash)
|
|
219
|
-
current_event_data=nil
|
|
222
|
+
current_event_data = nil
|
|
220
223
|
# this is the last full status
|
|
221
|
-
last_status_event=nil
|
|
224
|
+
last_status_event = nil
|
|
222
225
|
# read management port
|
|
223
226
|
loop do
|
|
224
227
|
# TODO: timeout here ?
|
|
225
228
|
line = ascp_mgt_io.gets
|
|
226
229
|
# nil when ascp process exits
|
|
227
230
|
break if line.nil?
|
|
228
|
-
current_event_text
|
|
231
|
+
current_event_text += line
|
|
229
232
|
line.chomp!
|
|
230
233
|
Log.log.debug("line=[#{line}]")
|
|
231
234
|
case line
|
|
232
235
|
when 'FASPMGR 2'
|
|
233
236
|
# begin event
|
|
234
|
-
current_event_data =
|
|
237
|
+
current_event_data = {}
|
|
235
238
|
current_event_text = ''
|
|
236
239
|
when /^([^:]+): (.*)$/
|
|
237
240
|
# event field
|
|
238
|
-
current_event_data[
|
|
241
|
+
current_event_data[Regexp.last_match(1)] = Regexp.last_match(2)
|
|
239
242
|
when ''
|
|
240
243
|
# empty line is separator to end event information
|
|
241
244
|
raise 'unexpected empty line' if current_event_data.nil?
|
|
242
|
-
current_event_data[AgentBase::LISTENER_SESSION_ID_B]=ascp_pid
|
|
245
|
+
current_event_data[AgentBase::LISTENER_SESSION_ID_B] = ascp_pid
|
|
243
246
|
notify_listeners(current_event_text,current_event_data)
|
|
244
247
|
case current_event_data['Type']
|
|
245
248
|
when 'INIT'
|
|
246
|
-
session[:id]=current_event_data['SessionId']
|
|
249
|
+
session[:id] = current_event_data['SessionId']
|
|
247
250
|
Log.log.debug("session id: #{session[:id]}")
|
|
248
251
|
when 'DONE','ERROR'
|
|
249
252
|
# TODO: check if this is always the last event
|
|
@@ -258,15 +261,15 @@ module Aspera
|
|
|
258
261
|
case last_status_event['Type']
|
|
259
262
|
when 'DONE'
|
|
260
263
|
# all went well
|
|
261
|
-
exception_raised=false
|
|
264
|
+
exception_raised = false
|
|
262
265
|
when 'ERROR'
|
|
263
266
|
Log.log.error("code: #{last_status_event['Code']}")
|
|
264
|
-
if last_status_event['Description']
|
|
267
|
+
if /bearer token/i.match?(last_status_event['Description'])
|
|
265
268
|
Log.log.error('need to regenerate token'.red)
|
|
266
|
-
if session[:options].is_a?(Hash)
|
|
269
|
+
if session[:options].is_a?(Hash) && session[:options].has_key?(:regenerate_token)
|
|
267
270
|
# regenerate token here, expired, or error on it
|
|
268
271
|
# Note: in multi-session, each session will have a different one.
|
|
269
|
-
env_args[:env]['ASPERA_SCP_TOKEN']=session[:options][:regenerate_token].call(true)
|
|
272
|
+
env_args[:env]['ASPERA_SCP_TOKEN'] = session[:options][:regenerate_token].call(true)
|
|
270
273
|
end
|
|
271
274
|
end
|
|
272
275
|
raise Fasp::Error.new(last_status_event['Description'],last_status_event['Code'].to_i)
|
|
@@ -274,32 +277,30 @@ module Aspera
|
|
|
274
277
|
raise "unexpected last event type: #{last_status_event['Type']}"
|
|
275
278
|
end
|
|
276
279
|
else
|
|
277
|
-
exception_raised=false
|
|
280
|
+
exception_raised = false
|
|
278
281
|
Log.log.debug('no status read from ascp mgt port')
|
|
279
282
|
end
|
|
280
283
|
rescue SystemCallError => e
|
|
281
284
|
# Process.spawn
|
|
282
|
-
raise Fasp::Error
|
|
283
|
-
rescue Timeout::Error
|
|
284
|
-
raise Fasp::Error
|
|
285
|
-
rescue Interrupt
|
|
286
|
-
raise Fasp::Error
|
|
285
|
+
raise Fasp::Error, e.message
|
|
286
|
+
rescue Timeout::Error
|
|
287
|
+
raise Fasp::Error, 'timeout waiting mgt port connect'
|
|
288
|
+
rescue Interrupt
|
|
289
|
+
raise Fasp::Error, 'transfer interrupted by user'
|
|
287
290
|
ensure
|
|
288
291
|
# if ascp was successfully started
|
|
289
292
|
unless ascp_pid.nil?
|
|
290
293
|
# "wait" for process to avoid zombie
|
|
291
294
|
Process.wait(ascp_pid)
|
|
292
|
-
status
|
|
293
|
-
ascp_pid=nil
|
|
295
|
+
status = $CHILD_STATUS
|
|
296
|
+
ascp_pid = nil
|
|
294
297
|
session.delete(:io)
|
|
295
298
|
if !status.success?
|
|
296
|
-
message="ascp failed with code #{status.exitstatus}"
|
|
297
|
-
if
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
raise Fasp::Error.new(message)
|
|
302
|
-
end
|
|
299
|
+
message = "ascp failed with code #{status.exitstatus}"
|
|
300
|
+
# raise error only if there was not already an exception
|
|
301
|
+
raise Fasp::Error, message unless exception_raised
|
|
302
|
+
# else just debug, as main exception is already here
|
|
303
|
+
Log.log.debug(message)
|
|
303
304
|
end
|
|
304
305
|
end
|
|
305
306
|
end # begin-ensure
|
|
@@ -312,18 +313,18 @@ module Aspera
|
|
|
312
313
|
# {'type'=>'START','source'=>_path_,'destination'=>_path_}
|
|
313
314
|
# {'type'=>'DONE'}
|
|
314
315
|
def send_command(job_id,session_index,data)
|
|
315
|
-
job
|
|
316
|
+
job = @jobs[job_id]
|
|
316
317
|
raise 'no such job' if job.nil?
|
|
317
|
-
session=job[:sessions][session_index]
|
|
318
|
+
session = job[:sessions][session_index]
|
|
318
319
|
raise 'no such session' if session.nil?
|
|
319
320
|
Log.log.debug("command: #{data}")
|
|
320
321
|
# build command
|
|
321
|
-
command=data.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
322
|
+
command = data.
|
|
323
|
+
keys.
|
|
324
|
+
map{|k|"#{k.capitalize}: #{data[k]}"}.
|
|
325
|
+
unshift('FASPMGR 2').
|
|
326
|
+
push('','').
|
|
327
|
+
join("\n")
|
|
327
328
|
session[:io].puts(command)
|
|
328
329
|
end
|
|
329
330
|
|
|
@@ -333,23 +334,20 @@ module Aspera
|
|
|
333
334
|
def initialize(options=nil)
|
|
334
335
|
super()
|
|
335
336
|
# all transfer jobs, key = SecureRandom.uuid, protected by mutex, condvar on change
|
|
336
|
-
@jobs={}
|
|
337
|
+
@jobs = {}
|
|
337
338
|
# mutex protects global data accessed by threads
|
|
338
|
-
@mutex=Mutex.new
|
|
339
|
+
@mutex = Mutex.new
|
|
339
340
|
# set default options and override if specified
|
|
340
|
-
@options=DEFAULT_OPTIONS.
|
|
341
|
+
@options = DEFAULT_OPTIONS.dup
|
|
341
342
|
if !options.nil?
|
|
342
343
|
raise "expecting Hash (or nil), but have #{options.class}" unless options.is_a?(Hash)
|
|
343
344
|
options.each do |k,v|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
else
|
|
347
|
-
raise "Unknown local agent parameter: #{k}, expect one of #{DEFAULT_OPTIONS.keys.map{|i|i.to_s}.join(",")}"
|
|
348
|
-
end
|
|
345
|
+
raise "Unknown local agent parameter: #{k}, expect one of #{DEFAULT_OPTIONS.keys.map(&:to_s).join(',')}" unless DEFAULT_OPTIONS.has_key?(k)
|
|
346
|
+
@options[k] = v
|
|
349
347
|
end
|
|
350
348
|
end
|
|
351
349
|
Log.log.debug("local options= #{options}")
|
|
352
|
-
@resume_policy=ResumePolicy.new(@options[:resume].symbolize_keys)
|
|
350
|
+
@resume_policy = ResumePolicy.new(@options[:resume].symbolize_keys)
|
|
353
351
|
end
|
|
354
352
|
|
|
355
353
|
# transfer thread entry
|
|
@@ -357,20 +355,19 @@ module Aspera
|
|
|
357
355
|
def transfer_thread_entry(session)
|
|
358
356
|
begin
|
|
359
357
|
# set name for logging
|
|
360
|
-
Thread.current[:name]='transfer'
|
|
358
|
+
Thread.current[:name] = 'transfer'
|
|
361
359
|
Log.log.debug("ENTER (#{Thread.current[:name]})")
|
|
362
360
|
# start transfer with selected resumer policy
|
|
363
|
-
session[:options][:resumer].
|
|
361
|
+
session[:options][:resumer].execute_with_resume do
|
|
364
362
|
start_transfer_with_args_env(session[:env_args],session)
|
|
365
363
|
end
|
|
366
364
|
Log.log.debug('transfer ok'.bg_green)
|
|
367
|
-
rescue => e
|
|
368
|
-
session[:error]=e
|
|
365
|
+
rescue StandardError => e
|
|
366
|
+
session[:error] = e
|
|
369
367
|
Log.log.error("Transfer thread error: #{e.class}:\n#{e.message}:\n#{e.backtrace.join("\n")}".red) if Log.instance.level.eql?(:debug)
|
|
370
368
|
end
|
|
371
369
|
Log.log.debug("EXIT (#{Thread.current[:name]})")
|
|
372
370
|
end
|
|
373
|
-
|
|
374
371
|
end # AgentDirect
|
|
375
372
|
end
|
|
376
373
|
end
|