aspera-cli 4.16.0 → 4.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +50 -19
- data/CONTRIBUTING.md +3 -1
- data/README.md +965 -793
- data/bin/asession +29 -21
- data/lib/aspera/{fasp/agent_alpha.rb → agent/alpha.rb} +26 -25
- data/lib/aspera/{fasp/agent_base.rb → agent/base.rb} +15 -12
- data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
- data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +49 -53
- data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +20 -19
- data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +20 -33
- data/lib/aspera/{fasp/agent_trsdk.rb → agent/trsdk.rb} +11 -11
- data/lib/aspera/api/aoc.rb +586 -0
- data/lib/aspera/api/ats.rb +46 -0
- data/lib/aspera/api/cos_node.rb +95 -0
- data/lib/aspera/api/node.rb +344 -0
- data/lib/aspera/ascmd.rb +46 -10
- data/lib/aspera/{fasp → ascp}/installation.rb +5 -5
- data/lib/aspera/{fasp → ascp}/management.rb +3 -8
- data/lib/aspera/{fasp → ascp}/products.rb +1 -1
- data/lib/aspera/assert.rb +30 -30
- data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
- data/lib/aspera/cli/extended_value.rb +1 -1
- data/lib/aspera/cli/formatter.rb +13 -13
- data/lib/aspera/cli/hints.rb +5 -5
- data/lib/aspera/cli/main.rb +35 -28
- data/lib/aspera/cli/manager.rb +25 -24
- data/lib/aspera/cli/plugin.rb +22 -15
- data/lib/aspera/cli/plugin_factory.rb +61 -0
- data/lib/aspera/cli/plugins/alee.rb +7 -7
- data/lib/aspera/cli/plugins/aoc.rb +83 -77
- data/lib/aspera/cli/plugins/ats.rb +32 -33
- data/lib/aspera/cli/plugins/bss.rb +3 -4
- data/lib/aspera/cli/plugins/config.rb +169 -186
- data/lib/aspera/cli/plugins/console.rb +8 -6
- data/lib/aspera/cli/plugins/cos.rb +19 -18
- data/lib/aspera/cli/plugins/faspex.rb +61 -54
- data/lib/aspera/cli/plugins/faspex5.rb +150 -103
- data/lib/aspera/cli/plugins/node.rb +68 -73
- data/lib/aspera/cli/plugins/orchestrator.rb +34 -44
- data/lib/aspera/cli/plugins/preview.rb +31 -31
- data/lib/aspera/cli/plugins/server.rb +31 -33
- data/lib/aspera/cli/plugins/shares.rb +13 -11
- data/lib/aspera/cli/sync_actions.rb +8 -8
- data/lib/aspera/cli/transfer_agent.rb +32 -19
- data/lib/aspera/cli/transfer_progress.rb +1 -1
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +5 -0
- data/lib/aspera/command_line_builder.rb +14 -14
- data/lib/aspera/coverage.rb +1 -2
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +2 -3
- data/lib/aspera/faspex_gw.rb +5 -6
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/id_generator.rb +2 -2
- data/lib/aspera/json_rpc.rb +5 -5
- data/lib/aspera/keychain/encrypted_hash.rb +6 -6
- data/lib/aspera/keychain/macos_security.rb +27 -22
- data/lib/aspera/log.rb +2 -2
- data/lib/aspera/nagios.rb +3 -3
- data/lib/aspera/node_simulator.rb +5 -6
- data/lib/aspera/oauth/base.rb +143 -0
- data/lib/aspera/oauth/factory.rb +124 -0
- data/lib/aspera/oauth/generic.rb +34 -0
- data/lib/aspera/oauth/jwt.rb +51 -0
- data/lib/aspera/oauth/url_json.rb +31 -0
- data/lib/aspera/oauth/web.rb +50 -0
- data/lib/aspera/oauth.rb +5 -331
- data/lib/aspera/open_application.rb +7 -7
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +5 -5
- data/lib/aspera/preview/terminal.rb +3 -2
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +4 -4
- data/lib/aspera/rest.rb +175 -144
- data/lib/aspera/rest_errors_aspera.rb +3 -3
- data/lib/aspera/resumer.rb +77 -0
- data/lib/aspera/ssh.rb +6 -1
- data/lib/aspera/{fasp → transfer}/error.rb +3 -3
- data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
- data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
- data/lib/aspera/{fasp → transfer}/parameters.rb +58 -89
- data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +18 -16
- data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
- data/lib/aspera/{fasp → transfer}/sync.rb +32 -32
- data/lib/aspera/{fasp → transfer}/uri.rb +9 -8
- data/lib/aspera/web_server_simple.rb +11 -3
- data.tar.gz.sig +0 -0
- metadata +36 -63
- metadata.gz.sig +0 -0
- data/lib/aspera/aoc.rb +0 -601
- data/lib/aspera/ats_api.rb +0 -47
- data/lib/aspera/cos_node.rb +0 -94
- data/lib/aspera/fasp/resume_policy.rb +0 -79
- data/lib/aspera/node.rb +0 -339
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'aspera/
|
4
|
-
require 'aspera/
|
5
|
-
require 'aspera/
|
3
|
+
require 'aspera/agent/base'
|
4
|
+
require 'aspera/transfer/spec'
|
5
|
+
require 'aspera/transfer/faux_file'
|
6
6
|
require 'aspera/log'
|
7
7
|
require 'aspera/assert'
|
8
8
|
require 'aspera/rest'
|
@@ -12,7 +12,7 @@ require 'base64'
|
|
12
12
|
require 'json'
|
13
13
|
|
14
14
|
module Aspera
|
15
|
-
module
|
15
|
+
module Agent
|
16
16
|
# Start a transfer using Aspera HTTP Gateway, using web socket secure for uploads
|
17
17
|
# ref: https://api.ibm.com/explorer/catalog/aspera/product/ibm-aspera/api/http-gateway-api/doc/guides-toc
|
18
18
|
# https://developer.ibm.com/apis/catalog?search=%22aspera%20http%22
|
@@ -26,7 +26,7 @@ module Aspera
|
|
26
26
|
# 1 JSON.slice_upload File start "end_slice_upload" sent_v2_delimiter
|
27
27
|
# 2.. Binary File binary chunks "end upload" sent_general
|
28
28
|
# last JSON.slice_upload File end "end_slice_upload" sent_v2_delimiter
|
29
|
-
class
|
29
|
+
class Httpgw < Base
|
30
30
|
MSG_SEND_TRANSFER_SPEC = 'transfer_spec'
|
31
31
|
MSG_SEND_SLICE_UPLOAD = 'slice_upload'
|
32
32
|
MSG_RECV_DATA_RECEIVED_SIGNAL = 'end upload'
|
@@ -160,7 +160,7 @@ module Aspera
|
|
160
160
|
# modify transfer spec to be suitable for GW
|
161
161
|
transfer_spec['paths'].each do |item|
|
162
162
|
# save actual file location to be able read contents later
|
163
|
-
file_to_add = FauxFile.open(item['source'])
|
163
|
+
file_to_add = Transfer::FauxFile.open(item['source'])
|
164
164
|
if file_to_add
|
165
165
|
item['source'] = file_to_add.path
|
166
166
|
item['file_size'] = file_to_add.size
|
@@ -176,7 +176,8 @@ module Aspera
|
|
176
176
|
files_to_read.push(file_to_add)
|
177
177
|
total_bytes_to_transfer += item['file_size']
|
178
178
|
end
|
179
|
-
|
179
|
+
# TODO: check that this is available in endpoints: @api_info['endpoints']
|
180
|
+
upload_url = File.join(@gw_base_url, @options[:api_version], 'upload')
|
180
181
|
notify_progress(session_id: nil, type: :pre_start, info: 'connecting wss')
|
181
182
|
# open web socket to end point (equivalent to Net::HTTP.start)
|
182
183
|
http_session = Rest.start_http_session(upload_url)
|
@@ -186,7 +187,7 @@ module Aspera
|
|
186
187
|
@ws_io.write(@ws_handshake.to_s)
|
187
188
|
sleep(0.1)
|
188
189
|
@ws_handshake << @ws_io.readuntil("\r\n\r\n")
|
189
|
-
assert(@ws_handshake.finished?){'Error in websocket handshake'}
|
190
|
+
Aspera.assert(@ws_handshake.finished?){'Error in websocket handshake'}
|
190
191
|
Log.log.debug{"#{LOG_WS_SEND}handshake success"}
|
191
192
|
# start read thread after handshake
|
192
193
|
@ws_read_thread = Thread.new {process_read_thread}
|
@@ -227,7 +228,7 @@ module Aspera
|
|
227
228
|
fileIndex: file_index
|
228
229
|
}
|
229
230
|
file = files_to_read[file_index]
|
230
|
-
if file.is_a?(FauxFile)
|
231
|
+
if file.is_a?(Transfer::FauxFile)
|
231
232
|
slice_info[:name] = file.path
|
232
233
|
else
|
233
234
|
file = File.open(file)
|
@@ -295,7 +296,7 @@ module Aspera
|
|
295
296
|
end
|
296
297
|
creation = @gw_api.create('v1/download', {'transfer_spec' => transfer_spec})[:data]
|
297
298
|
transfer_uuid = creation['url'].split('/').last
|
298
|
-
|
299
|
+
file_name =
|
299
300
|
if transfer_spec['zip_required'] || transfer_spec['paths'].length > 1
|
300
301
|
# it is a zip file if zip is required or there is more than 1 file
|
301
302
|
transfer_spec['download_name'] + '.zip'
|
@@ -303,8 +304,8 @@ module Aspera
|
|
303
304
|
# it is a plain file if we don't require zip and there is only one file
|
304
305
|
File.basename(transfer_spec['paths'].first['source'])
|
305
306
|
end
|
306
|
-
|
307
|
-
@gw_api.call(
|
307
|
+
file_path = File.join(transfer_spec['destination_root'], file_name)
|
308
|
+
@gw_api.call(operation: 'GET', subpath: "v1/download/#{transfer_uuid}", save_to_file: file_path)
|
308
309
|
end
|
309
310
|
|
310
311
|
# start FASP transfer based on transfer spec (hash table)
|
@@ -312,14 +313,14 @@ module Aspera
|
|
312
313
|
# HTTP download only supports file list
|
313
314
|
def start_transfer(transfer_spec, token_regenerator: nil)
|
314
315
|
raise 'GW URL must be set' if @gw_api.nil?
|
315
|
-
assert_type(transfer_spec['paths'], Array){'paths'}
|
316
|
-
assert_type(transfer_spec['token'], String){'only token based transfer is supported in GW'}
|
316
|
+
Aspera.assert_type(transfer_spec['paths'], Array){'paths'}
|
317
|
+
Aspera.assert_type(transfer_spec['token'], String){'only token based transfer is supported in GW'}
|
317
318
|
Log.log.debug{Log.dump(:user_spec, transfer_spec)}
|
318
319
|
transfer_spec['authentication'] ||= 'token'
|
319
320
|
case transfer_spec['direction']
|
320
|
-
when
|
321
|
+
when Transfer::Spec::DIRECTION_SEND
|
321
322
|
upload(transfer_spec)
|
322
|
-
when
|
323
|
+
when Transfer::Spec::DIRECTION_RECEIVE
|
323
324
|
download(transfer_spec)
|
324
325
|
else
|
325
326
|
raise "unexpected direction: [#{transfer_spec['direction']}]"
|
@@ -340,10 +341,10 @@ module Aspera
|
|
340
341
|
|
341
342
|
def initialize(opts)
|
342
343
|
super(opts)
|
343
|
-
@options =
|
344
|
+
@options = Base.options(default: DEFAULT_OPTIONS, options: opts)
|
344
345
|
# remove /v1 from end of user-provided GW url: we need the base url only
|
345
|
-
@options[:url].gsub(%r{/v1/*$}, '')
|
346
|
-
@gw_api = Rest.new(
|
346
|
+
@gw_base_url = @options[:url].gsub(%r{/v1/*$}, '')
|
347
|
+
@gw_api = Rest.new(base_url: @gw_base_url)
|
347
348
|
@api_info = @gw_api.read('v1/info')[:data]
|
348
349
|
Log.log.debug{Log.dump(:api_info, @api_info)}
|
349
350
|
# web socket endpoint: by default use v2 (newer gateways), without base64 encoding
|
@@ -1,18 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# cspell:ignore precalc
|
4
|
-
require 'aspera/
|
5
|
-
require 'aspera/
|
6
|
-
require 'aspera/node'
|
4
|
+
require 'aspera/agent/base'
|
5
|
+
require 'aspera/transfer/spec'
|
6
|
+
require 'aspera/api/node'
|
7
7
|
require 'aspera/log'
|
8
8
|
require 'aspera/assert'
|
9
9
|
require 'aspera/oauth'
|
10
10
|
|
11
11
|
module Aspera
|
12
|
-
module
|
12
|
+
module Agent
|
13
13
|
# this singleton class is used by the CLI to provide a common interface to start a transfer
|
14
14
|
# before using it, the use must set the `node_api` member.
|
15
|
-
class
|
15
|
+
class Node < Base
|
16
16
|
DEFAULT_OPTIONS = {
|
17
17
|
url: :required,
|
18
18
|
username: :required,
|
@@ -23,15 +23,15 @@ module Aspera
|
|
23
23
|
# attr_writer :options
|
24
24
|
|
25
25
|
def initialize(opts)
|
26
|
-
assert_type(opts, Hash){'node agent options'}
|
26
|
+
Aspera.assert_type(opts, Hash){'node agent options'}
|
27
27
|
super(opts)
|
28
|
-
options =
|
28
|
+
options = Base.options(default: DEFAULT_OPTIONS, options: opts)
|
29
29
|
# root id is required for access key
|
30
30
|
@root_id = options[:root_id]
|
31
31
|
rest_params = { base_url: options[:url]}
|
32
|
-
if
|
33
|
-
|
34
|
-
rest_params[:headers] =
|
32
|
+
if OAuth::Factory.bearer?(options[:password])
|
33
|
+
Aspera.assert(!@root_id.nil?){'root_id not allowed for access key'}
|
34
|
+
rest_params[:headers] = Api::Node.bearer_headers(options[:password], access_key: options[:username])
|
35
35
|
else
|
36
36
|
rest_params[:auth] = {
|
37
37
|
type: :basic,
|
@@ -39,7 +39,7 @@ module Aspera
|
|
39
39
|
password: options[:password]
|
40
40
|
}
|
41
41
|
end
|
42
|
-
@node_api = Rest.new(rest_params)
|
42
|
+
@node_api = Rest.new(**rest_params)
|
43
43
|
# TODO: currently only supports one transfer. This is bad shortcut. but ok for CLI.
|
44
44
|
@transfer_id = nil
|
45
45
|
# Log.log.debug{Log.dump(:agent_options, @options)}
|
@@ -47,11 +47,9 @@ module Aspera
|
|
47
47
|
|
48
48
|
# used internally to ensure node api is set before using.
|
49
49
|
def node_api_
|
50
|
-
|
50
|
+
Aspera.assert(!@node_api.nil?){'Before using this object, set the node_api attribute to a Aspera::Rest object'}
|
51
51
|
return @node_api
|
52
52
|
end
|
53
|
-
# use this to read the node_api end point.
|
54
|
-
# attr_reader :node_api
|
55
53
|
|
56
54
|
# use this to set the node_api end point before using the class.
|
57
55
|
def node_api=(new_value)
|
@@ -66,30 +64,19 @@ module Aspera
|
|
66
64
|
# add root id if access key
|
67
65
|
if !@root_id.nil?
|
68
66
|
case transfer_spec['direction']
|
69
|
-
when
|
70
|
-
when
|
71
|
-
else error_unexpected_value(transfer_spec['direction'])
|
72
|
-
end
|
73
|
-
end
|
74
|
-
# manage special additional parameter
|
75
|
-
if transfer_spec.key?('EX_ssh_key_paths') && transfer_spec['EX_ssh_key_paths'].is_a?(Array) && !transfer_spec['EX_ssh_key_paths'].empty?
|
76
|
-
# not standard, so place standard field
|
77
|
-
if transfer_spec.key?('ssh_private_key')
|
78
|
-
Log.log.warn('Both ssh_private_key and EX_ssh_key_paths are present, using ssh_private_key')
|
79
|
-
else
|
80
|
-
Log.log.warn('EX_ssh_key_paths has multiple keys, using first one only') unless transfer_spec['EX_ssh_key_paths'].length.eql?(1)
|
81
|
-
transfer_spec['ssh_private_key'] = File.read(transfer_spec['EX_ssh_key_paths'].first)
|
82
|
-
transfer_spec.delete('EX_ssh_key_paths')
|
67
|
+
when Transfer::Spec::DIRECTION_SEND then transfer_spec['source_root_id'] = @root_id
|
68
|
+
when Transfer::Spec::DIRECTION_RECEIVE then transfer_spec['destination_root_id'] = @root_id
|
69
|
+
else Aspera.error_unexpected_value(transfer_spec['direction'])
|
83
70
|
end
|
84
71
|
end
|
85
72
|
# add mandatory retry parameter for node api
|
86
73
|
ts_tags = transfer_spec['tags']
|
87
|
-
if ts_tags.is_a?(Hash) && ts_tags[
|
88
|
-
ts_tags[
|
74
|
+
if ts_tags.is_a?(Hash) && ts_tags[Transfer::Spec::TAG_RESERVED].is_a?(Hash)
|
75
|
+
ts_tags[Transfer::Spec::TAG_RESERVED]['xfer_retry'] ||= 150
|
89
76
|
end
|
90
77
|
# Optimization in case of sending to the same node
|
91
78
|
# TODO: probably remove this, as /etc/hosts shall be used for that
|
92
|
-
if !transfer_spec['wss_enabled'] && transfer_spec['remote_host'].eql?(URI.parse(node_api_.
|
79
|
+
if !transfer_spec['wss_enabled'] && transfer_spec['remote_host'].eql?(URI.parse(node_api_.base_url).host)
|
93
80
|
transfer_spec['remote_host'] = '127.0.0.1'
|
94
81
|
end
|
95
82
|
resp = node_api_.create('ops/transfers', transfer_spec)[:data]
|
@@ -133,10 +120,10 @@ module Aspera
|
|
133
120
|
notify_progress(type: :end, session_id: @transfer_id)
|
134
121
|
# Bug in HSTS ? transfer is marked failed, but there is no reason
|
135
122
|
break if transfer_data['error_code'].eql?(0) && transfer_data['error_desc'].empty?
|
136
|
-
raise
|
123
|
+
raise Transfer::Error, "status: #{transfer_data['status']}. code: #{transfer_data['error_code']}. description: #{transfer_data['error_desc']}"
|
137
124
|
else
|
138
125
|
Log.log.warn{"transfer_data -> #{transfer_data}"}
|
139
|
-
raise
|
126
|
+
raise Transfer::Error, "status: #{transfer_data['status']}. code: #{transfer_data['error_code']}. description: #{transfer_data['error_desc']}"
|
140
127
|
end
|
141
128
|
sleep(1.0)
|
142
129
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'aspera/
|
4
|
-
require 'aspera/
|
3
|
+
require 'aspera/agent/base'
|
4
|
+
require 'aspera/ascp/installation'
|
5
5
|
require 'aspera/temp_file_manager'
|
6
6
|
require 'aspera/log'
|
7
7
|
require 'aspera/assert'
|
@@ -9,8 +9,8 @@ require 'json'
|
|
9
9
|
require 'uri'
|
10
10
|
|
11
11
|
module Aspera
|
12
|
-
module
|
13
|
-
class
|
12
|
+
module Agent
|
13
|
+
class Trsdk < Base
|
14
14
|
# see https://github.com/grpc/grpc/blob/master/doc/naming.md
|
15
15
|
# https://grpc.io/docs/guides/custom-name-resolution/
|
16
16
|
LOCAL_SOCKET_ADDR = '127.0.0.1'
|
@@ -47,12 +47,12 @@ module Aspera
|
|
47
47
|
# options come from transfer_info
|
48
48
|
def initialize(user_opts={})
|
49
49
|
super(user_opts)
|
50
|
-
@options =
|
50
|
+
@options = Base.options(default: DEFAULT_OPTIONS, options: user_opts)
|
51
51
|
is_local_auto_port = @options[:url].eql?(AUTO_LOCAL_TCP_PORT)
|
52
52
|
raise 'Cannot use options `keep` or `external` with port zero' if is_local_auto_port && (@options[:keep] || @options[:external])
|
53
53
|
Log.log.debug{Log.dump(:agent_options, @options)}
|
54
54
|
# load SDK stub class on demand, as it's an optional gem
|
55
|
-
$LOAD_PATH.unshift(Installation.instance.sdk_ruby_folder)
|
55
|
+
$LOAD_PATH.unshift(Ascp::Installation.instance.sdk_ruby_folder)
|
56
56
|
require 'transfer_services_pb'
|
57
57
|
# keep PID for optional shutdown
|
58
58
|
@daemon_pid = nil
|
@@ -73,13 +73,13 @@ module Aspera
|
|
73
73
|
# if transferd is external: do not start it, or other error
|
74
74
|
raise if @options[:external] || !e.message.include?('failed to connect')
|
75
75
|
# we already tried to start a daemon, but it failed
|
76
|
-
assert(@daemon_pid.nil?){"Daemon started with PID #{@daemon_pid}, but connection failed to #{daemon_endpoint}}"}
|
76
|
+
Aspera.assert(@daemon_pid.nil?){"Daemon started with PID #{@daemon_pid}, but connection failed to #{daemon_endpoint}}"}
|
77
77
|
Log.log.warn('no daemon present, starting daemon...') if @options[:external]
|
78
78
|
# location of daemon binary
|
79
|
-
sdk_folder = File.realpath(File.join(Installation.instance.sdk_ruby_folder, '..'))
|
79
|
+
sdk_folder = File.realpath(File.join(Ascp::Installation.instance.sdk_ruby_folder, '..'))
|
80
80
|
# transferd only supports local ip and port
|
81
81
|
daemon_uri = URI.parse("ipv4://#{daemon_endpoint}")
|
82
|
-
assert(daemon_uri.scheme.eql?('ipv4')){"Invalid scheme daemon URI #{daemon_endpoint}"}
|
82
|
+
Aspera.assert(daemon_uri.scheme.eql?('ipv4')){"Invalid scheme daemon URI #{daemon_endpoint}"}
|
83
83
|
# create a config file for daemon
|
84
84
|
config = {
|
85
85
|
address: daemon_uri.host,
|
@@ -99,7 +99,7 @@ module Aspera
|
|
99
99
|
log_stdout = "#{transferd_base_tmp}.out"
|
100
100
|
log_stderr = "#{transferd_base_tmp}.err"
|
101
101
|
File.write(conf_file, config.to_json)
|
102
|
-
@daemon_pid = Process.spawn(Installation.instance.path(:transferd), '--config', conf_file, out: log_stdout, err: log_stderr)
|
102
|
+
@daemon_pid = Process.spawn(Ascp::Installation.instance.path(:transferd), '--config', conf_file, out: log_stdout, err: log_stderr)
|
103
103
|
begin
|
104
104
|
# wait for process to initialize, max 2 seconds
|
105
105
|
Timeout.timeout(2.0) do
|
@@ -159,7 +159,7 @@ module Aspera
|
|
159
159
|
break
|
160
160
|
when :FAILED, :CANCELED
|
161
161
|
notify_progress(type: :end, session_id: @transfer_id)
|
162
|
-
raise
|
162
|
+
raise Transfer::Error, JSON.parse(response.message)['Description']
|
163
163
|
when :QUEUED, :UNKNOWN_STATUS, :PAUSED, :ORPHANED
|
164
164
|
notify_progress(session_id: nil, type: :pre_start, info: response.status.to_s.downcase)
|
165
165
|
else
|