aspera-cli 4.19.0 → 4.21.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +46 -0
  4. data/CONTRIBUTING.md +18 -4
  5. data/README.md +886 -510
  6. data/bin/asession +27 -20
  7. data/examples/build_exec +65 -76
  8. data/examples/build_exec_rubyc +40 -0
  9. data/examples/get_proto_file.rb +7 -0
  10. data/lib/aspera/agent/alpha.rb +18 -24
  11. data/lib/aspera/agent/base.rb +2 -18
  12. data/lib/aspera/agent/connect.rb +34 -15
  13. data/lib/aspera/agent/direct.rb +44 -54
  14. data/lib/aspera/agent/httpgw.rb +2 -3
  15. data/lib/aspera/agent/node.rb +11 -21
  16. data/lib/aspera/agent/{trsdk.rb → transferd.rb} +27 -51
  17. data/lib/aspera/api/alee.rb +15 -0
  18. data/lib/aspera/api/aoc.rb +139 -105
  19. data/lib/aspera/api/ats.rb +1 -1
  20. data/lib/aspera/api/cos_node.rb +1 -1
  21. data/lib/aspera/api/httpgw.rb +15 -10
  22. data/lib/aspera/api/node.rb +70 -32
  23. data/lib/aspera/ascmd.rb +56 -48
  24. data/lib/aspera/ascp/installation.rb +166 -70
  25. data/lib/aspera/ascp/management.rb +30 -8
  26. data/lib/aspera/assert.rb +10 -5
  27. data/lib/aspera/cli/formatter.rb +166 -162
  28. data/lib/aspera/cli/hints.rb +2 -1
  29. data/lib/aspera/cli/info.rb +12 -10
  30. data/lib/aspera/cli/main.rb +28 -13
  31. data/lib/aspera/cli/manager.rb +7 -2
  32. data/lib/aspera/cli/plugin.rb +17 -31
  33. data/lib/aspera/cli/plugins/alee.rb +3 -3
  34. data/lib/aspera/cli/plugins/aoc.rb +246 -208
  35. data/lib/aspera/cli/plugins/ats.rb +16 -14
  36. data/lib/aspera/cli/plugins/config.rb +154 -94
  37. data/lib/aspera/cli/plugins/console.rb +3 -3
  38. data/lib/aspera/cli/plugins/cos.rb +1 -0
  39. data/lib/aspera/cli/plugins/faspex.rb +15 -23
  40. data/lib/aspera/cli/plugins/faspex5.rb +64 -50
  41. data/lib/aspera/cli/plugins/faspio.rb +2 -2
  42. data/lib/aspera/cli/plugins/httpgw.rb +1 -1
  43. data/lib/aspera/cli/plugins/node.rb +174 -109
  44. data/lib/aspera/cli/plugins/orchestrator.rb +14 -13
  45. data/lib/aspera/cli/plugins/preview.rb +8 -9
  46. data/lib/aspera/cli/plugins/server.rb +5 -9
  47. data/lib/aspera/cli/plugins/shares.rb +2 -2
  48. data/lib/aspera/cli/sync_actions.rb +2 -2
  49. data/lib/aspera/cli/transfer_agent.rb +12 -14
  50. data/lib/aspera/cli/transfer_progress.rb +37 -17
  51. data/lib/aspera/cli/version.rb +1 -1
  52. data/lib/aspera/command_line_builder.rb +4 -5
  53. data/lib/aspera/coverage.rb +13 -1
  54. data/lib/aspera/environment.rb +75 -25
  55. data/lib/aspera/faspex_gw.rb +2 -2
  56. data/lib/aspera/json_rpc.rb +1 -1
  57. data/lib/aspera/keychain/macos_security.rb +7 -12
  58. data/lib/aspera/log.rb +3 -4
  59. data/lib/aspera/node_simulator.rb +230 -112
  60. data/lib/aspera/oauth/base.rb +64 -83
  61. data/lib/aspera/oauth/factory.rb +52 -6
  62. data/lib/aspera/oauth/generic.rb +4 -8
  63. data/lib/aspera/oauth/jwt.rb +6 -3
  64. data/lib/aspera/oauth/url_json.rb +1 -2
  65. data/lib/aspera/oauth/web.rb +5 -2
  66. data/lib/aspera/persistency_action_once.rb +16 -8
  67. data/lib/aspera/persistency_folder.rb +20 -2
  68. data/lib/aspera/preview/generator.rb +1 -1
  69. data/lib/aspera/preview/utils.rb +11 -17
  70. data/lib/aspera/products/alpha.rb +30 -0
  71. data/lib/aspera/products/connect.rb +48 -0
  72. data/lib/aspera/products/other.rb +82 -0
  73. data/lib/aspera/products/transferd.rb +54 -0
  74. data/lib/aspera/rest.rb +116 -87
  75. data/lib/aspera/secret_hider.rb +2 -2
  76. data/lib/aspera/ssh.rb +31 -24
  77. data/lib/aspera/transfer/faux_file.rb +4 -4
  78. data/lib/aspera/transfer/parameters.rb +16 -17
  79. data/lib/aspera/transfer/spec.rb +12 -12
  80. data/lib/aspera/transfer/spec.yaml +22 -20
  81. data/lib/aspera/transfer/sync.rb +2 -10
  82. data/lib/aspera/transfer/uri.rb +3 -3
  83. data/lib/aspera/uri_reader.rb +1 -1
  84. data/lib/aspera/web_auth.rb +166 -17
  85. data/lib/aspera/web_server_simple.rb +4 -3
  86. data/lib/transferd_pb.rb +86 -0
  87. data/lib/transferd_services_pb.rb +84 -0
  88. data.tar.gz.sig +0 -0
  89. metadata +58 -22
  90. metadata.gz.sig +0 -0
  91. data/lib/aspera/ascp/products.rb +0 -156
@@ -72,7 +72,7 @@ module Aspera
72
72
  session = {
73
73
  id: nil, # SessionId from INIT message in mgt port
74
74
  job_id: SecureRandom.uuid, # job id (regroup sessions)
75
- ts: transfer_spec, # transfer spec
75
+ ts: transfer_spec, # global transfer spec
76
76
  thread: nil, # Thread object monitoring management port, not nil when pushed to :sessions
77
77
  error: nil, # exception if failed
78
78
  io: nil, # management port server socket
@@ -84,7 +84,7 @@ module Aspera
84
84
  if multi_session_info.nil?
85
85
  Log.log.debug('Starting single session thread')
86
86
  # single session for transfer : simple
87
- session[:thread] = Thread.new(session) {|session_info|transfer_thread_entry(session_info)}
87
+ session[:thread] = Thread.new {transfer_thread_entry(session)}
88
88
  @sessions.push(session)
89
89
  else
90
90
  Log.log.debug('Starting multi session threads')
@@ -101,7 +101,7 @@ module Aspera
101
101
  # option: increment (default as per ascp manual) or not (cluster on other side ?)
102
102
  args.unshift('-O', (multi_session_info[:udp_base] + i - 1).to_s) if @multi_incr_udp
103
103
  # finally start the thread
104
- this_session[:thread] = Thread.new(this_session) {|session_info|transfer_thread_entry(session_info)}
104
+ this_session[:thread] = Thread.new {transfer_thread_entry(this_session)}
105
105
  @sessions.push(this_session)
106
106
  end
107
107
  end
@@ -132,18 +132,18 @@ module Aspera
132
132
 
133
133
  # @return [Array] list of sessions for a job
134
134
  def sessions_by_job(job_id)
135
- @sessions.select{|session_info| session_info[:job_id].eql?(job_id)}
135
+ @sessions.select{|session| session[:job_id].eql?(job_id)}
136
136
  end
137
137
 
138
- # This is the low level method to start the transfer process
138
+ # This is the low level method to start the transfer process.
139
+ # Typically started in a thread.
139
140
  # Start process with management port.
140
- # returns
141
- # raises FaspError on error
142
141
  # @param session this session information, keys :io and :token_regenerator
143
- # @param env [Hash] environment variables
144
- # @param name [Symbol] name of executable: :ascp, :ascp4 or :async
145
- # @param args [Array] command line arguments
142
+ # @param env [Hash] environment variables (comes from ascp_args)
143
+ # @param name [Symbol] name of executable: :ascp, :ascp4 or :async (comes from ascp_args)
144
+ # @param args [Array] command line arguments (comes from ascp_args)
146
145
  # @return [nil] when process has exited
146
+ # @throw FaspError on error
147
147
  def start_and_monitor_process(
148
148
  session:,
149
149
  env:,
@@ -151,7 +151,7 @@ module Aspera
151
151
  args:
152
152
  )
153
153
  Aspera.assert_type(session, Hash)
154
- notify_progress(session_id: nil, type: :pre_start, info: 'starting')
154
+ notify_progress(:pre_start, session_id: nil, info: 'starting')
155
155
  begin
156
156
  command_pid = nil
157
157
  # we use Socket directly, instead of TCPServer, as it gives access to lower level options
@@ -159,6 +159,8 @@ module Aspera
159
159
  mgt_server_socket = socket_class.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
160
160
  # open any available (0) local TCP port for use as management port
161
161
  mgt_server_socket.bind(Addrinfo.tcp(LISTEN_LOCAL_ADDRESS, SELECT_AVAILABLE_PORT))
162
+ # make port ready to accept connections, before starting ascp
163
+ mgt_server_socket.listen(1)
162
164
  # build arguments and add mgt port
163
165
  command_arguments = if name.eql?(:async)
164
166
  ["--exclusive-mgmt-port=#{mgt_server_socket.local_address.ip_port}"]
@@ -169,9 +171,9 @@ module Aspera
169
171
  # get location of command executable (ascp, async)
170
172
  command_path = Ascp::Installation.instance.path(name)
171
173
  command_pid = Environment.secure_spawn(env: env, exec: command_path, args: command_arguments)
172
- notify_progress(session_id: nil, type: :pre_start, info: "waiting for #{name} to start")
173
- mgt_server_socket.listen(1)
174
+ notify_progress(:pre_start, session_id: nil, info: "waiting for #{name} to start")
174
175
  # TODO: timeout does not work when Process.spawn is used... until process exits, then it works
176
+ # So we use select to detect that anything happens on the socket (connection)
175
177
  Log.log.debug{"before select, timeout: #{@spawn_timeout_sec}"}
176
178
  readable, _, _ = IO.select([mgt_server_socket], nil, nil, @spawn_timeout_sec)
177
179
  Log.log.debug('after select, before accept')
@@ -192,29 +194,30 @@ module Aspera
192
194
  next unless event
193
195
  # event is ready
194
196
  Log.log.trace1{Log.dump(:management_port, event)}
197
+ # store latest event by type
198
+ session[:id] = event['SessionId'] if event['Type'].eql?('INIT')
195
199
  @management_cb&.call(event)
196
200
  process_progress(event)
197
- Log.log.error((event['Description']).to_s) if event['Type'].eql?('FILEERROR') # cspell:disable-line
201
+ Log.log.error(event['Description'].to_s) if event['Type'].eql?('FILEERROR') # cspell:disable-line
198
202
  end
199
203
  Log.log.debug('management io closed')
200
- last_event = processor.last_event
201
204
  # check that last status was received before process exit
202
- if last_event.is_a?(Hash)
203
- case last_event['Type']
204
- when 'ERROR'
205
- if /bearer token/i.match?(last_event['Description']) &&
206
- session[:token_regenerator].respond_to?(:refreshed_transfer_token)
207
- # regenerate token here, expired, or error on it
208
- # Note: in multi-session, each session will have a different one.
209
- Log.log.warn('Regenerating token for transfer')
210
- env['ASPERA_SCP_TOKEN'] = session[:token_regenerator].refreshed_transfer_token
211
- end
212
- raise Transfer::Error.new(last_event['Description'], last_event['Code'].to_i)
213
- when 'DONE'
214
- nil
215
- else
216
- raise "unexpected last event type: #{last_event['Type']}"
205
+ last_event = processor.last_event
206
+ raise Transfer::Error, "internal: no management event (#{last_event.class})" unless last_event.is_a?(Hash)
207
+ case last_event['Type']
208
+ when 'ERROR'
209
+ if /bearer token/i.match?(last_event['Description']) &&
210
+ session[:token_regenerator].respond_to?(:refreshed_transfer_token)
211
+ # regenerate token here, expired, or error on it
212
+ # Note: in multi-session, each session will have a different one.
213
+ Log.log.warn('Regenerating token for transfer')
214
+ env['ASPERA_SCP_TOKEN'] = session[:token_regenerator].refreshed_transfer_token
217
215
  end
216
+ raise Transfer::Error.new(last_event['Description'], last_event['Code'].to_i)
217
+ when 'DONE'
218
+ nil
219
+ else
220
+ raise Transfer::Error, "unexpected last event type: #{last_event['Type']}, #{last_event['Description']}"
218
221
  end
219
222
  rescue SystemCallError => e
220
223
  # Process.spawn failed, or socket error
@@ -243,34 +246,37 @@ module Aspera
243
246
  nil
244
247
  end
245
248
 
249
+ attr_reader :sessions
250
+
246
251
  private
247
252
 
248
253
  # notify progress to callback
249
254
  # @param event management port event
255
+ # @param session sessin object
250
256
  def process_progress(event)
251
257
  session_id = event['SessionId']
252
258
  case event['Type']
253
259
  when 'INIT'
254
260
  @pre_calc_sent = false
255
261
  @pre_calc_last_size = nil
256
- notify_progress(session_id: session_id, type: :session_start)
262
+ notify_progress(:session_start, session_id: session_id)
257
263
  when 'NOTIFICATION' # sent from remote
258
264
  if event.key?('PreTransferBytes')
259
265
  @pre_calc_sent = true
260
- notify_progress(session_id: session_id, type: :session_size, info: event['PreTransferBytes'])
266
+ notify_progress(:session_size, session_id: session_id, info: event['PreTransferBytes'])
261
267
  end
262
268
  when 'STATS' # during transfer
263
269
  @pre_calc_last_size = event['TransferBytes'].to_i + event['StartByte'].to_i
264
- notify_progress(session_id: session_id, type: :transfer, info: @pre_calc_last_size)
270
+ notify_progress(:transfer, session_id: session_id, info: @pre_calc_last_size)
265
271
  when 'DONE', 'ERROR' # end of session
266
272
  total_size = event['TransferBytes'].to_i + event['StartByte'].to_i
267
273
  if !@pre_calc_sent && !total_size.zero?
268
- notify_progress(session_id: session_id, type: :session_size, info: total_size)
274
+ notify_progress(:session_size, session_id: session_id, info: total_size)
269
275
  end
270
276
  if @pre_calc_last_size != total_size
271
- notify_progress(session_id: session_id, type: :transfer, info: total_size)
277
+ notify_progress(:transfer, session_id: session_id, info: total_size)
272
278
  end
273
- notify_progress(session_id: session_id, type: :end)
279
+ notify_progress(:end, session_id: session_id)
274
280
  # cspell:disable
275
281
  when 'SESSION'
276
282
  when 'ARGSTOP'
@@ -283,14 +289,6 @@ module Aspera
283
289
  end
284
290
  end
285
291
 
286
- # @return [Hash] session information
287
- def session_by_id(id)
288
- matches = @sessions.select{|session_info| session_info[:id].eql?(id)}
289
- raise 'no such session' if matches.empty?
290
- raise 'more than one session' if matches.length > 1
291
- return matches.first
292
- end
293
-
294
292
  # send command to management port of command (used in `asession)
295
293
  # @param job_id identified transfer process
296
294
  # @param session_index index of session (for multi session)
@@ -298,18 +296,10 @@ module Aspera
298
296
  # {'type'=>'START','source'=>_path_,'destination'=>_path_}
299
297
  # {'type'=>'DONE'}
300
298
  def send_command(job_id, data)
301
- session = session_by_id(job_id)
299
+ session = @sessions.find{|session| session[:job_id].eql?(job_id)}
302
300
  Log.log.debug{"command: #{data}"}
303
- # build command
304
- command = data
305
- .keys
306
- .map{|k|"#{k.capitalize}: #{data[k]}"}
307
- .unshift(MGT_HEADER)
308
- .push('', '')
309
- .join("\n")
310
- session[:io].puts(command)
301
+ session[:io].puts(Ascp::Management.command_to_stream(data))
311
302
  end
312
- attr_reader :sessions
313
303
 
314
304
  # options for initialize (same as values in option transfer_info)
315
305
  # @param ascp_args [Array] additional arguments to ascp
@@ -23,8 +23,7 @@ module Aspera
23
23
  @gw_api.upload(transfer_spec)
24
24
  when Transfer::Spec::DIRECTION_RECEIVE
25
25
  @gw_api.download(transfer_spec)
26
- else
27
- raise "unexpected direction: [#{transfer_spec['direction']}]"
26
+ else Aspera.error_unexpected_value(transfer_spec['direction']){'direction'}
28
27
  end
29
28
  end
30
29
 
@@ -54,7 +53,7 @@ module Aspera
54
53
  api_version: api_version,
55
54
  upload_chunk_size: upload_chunk_size,
56
55
  synchronous: synchronous,
57
- notify_cb: ->(**event) { notify_progress(**event) }
56
+ notify_cb: ->(*pa, **ka) { notify_progress(*pa, **ka) }
58
57
  )
59
58
  end
60
59
  end
@@ -50,14 +50,6 @@ module Aspera
50
50
  return @node_api
51
51
  end
52
52
 
53
- # use this to set the node_api end point before using the class.
54
- def node_api=(new_value)
55
- if !@node_api.nil? && !new_value.nil?
56
- Log.log.warn('overriding existing node api value')
57
- end
58
- @node_api = new_value
59
- end
60
-
61
53
  # generic method
62
54
  def start_transfer(transfer_spec, token_regenerator: nil)
63
55
  # add root id if access key
@@ -78,7 +70,7 @@ module Aspera
78
70
  if !transfer_spec['wss_enabled'] && transfer_spec['remote_host'].eql?(URI.parse(node_api_.base_url).host)
79
71
  transfer_spec['remote_host'] = '127.0.0.1'
80
72
  end
81
- resp = node_api_.create('ops/transfers', transfer_spec)[:data]
73
+ resp = node_api_.create('ops/transfers', transfer_spec)
82
74
  @transfer_id = resp['id']
83
75
  Log.log.debug{"tr_id=#{@transfer_id}"}
84
76
  return @transfer_id
@@ -92,37 +84,35 @@ module Aspera
92
84
  # lets emulate management events to display progress bar
93
85
  loop do
94
86
  # status is empty sometimes with status 200...
95
- transfer_data = node_api_.read("ops/transfers/#{@transfer_id}")[:data] || {'status' => 'unknown'} rescue {'status' => 'waiting(api error)'}
87
+ transfer_data = node_api_.read("ops/transfers/#{@transfer_id}") || {'status' => 'unknown'} rescue {'status' => 'waiting(api error)'}
96
88
  case transfer_data['status']
97
89
  when 'waiting', 'partially_completed', 'unknown', 'waiting(read error)'
98
- notify_progress(session_id: nil, type: :pre_start, info: transfer_data['status'])
90
+ notify_progress(:pre_start, session_id: nil, info: transfer_data['status'])
99
91
  when 'running'
100
92
  if !session_started
101
- notify_progress(session_id: @transfer_id, type: :session_start)
93
+ notify_progress(:session_start, session_id: @transfer_id)
102
94
  session_started = true
103
95
  end
104
96
  message = transfer_data['status']
105
97
  message = "#{message} (#{transfer_data['error_desc']})" if !transfer_data['error_desc']&.empty?
106
- notify_progress(session_id: nil, type: :pre_start, info: message)
98
+ notify_progress(:pre_start, session_id: nil, info: message)
107
99
  if bytes_expected.nil? &&
108
100
  transfer_data['precalc'].is_a?(Hash) &&
109
101
  transfer_data['precalc']['status'].eql?('ready')
110
102
  bytes_expected = transfer_data['precalc']['bytes_expected']
111
- notify_progress(type: :session_size, session_id: @transfer_id, info: bytes_expected)
103
+ notify_progress(:session_size, session_id: @transfer_id, info: bytes_expected)
112
104
  end
113
- notify_progress(type: :transfer, session_id: @transfer_id, info: transfer_data['bytes_transferred'])
105
+ notify_progress(:transfer, session_id: @transfer_id, info: transfer_data['bytes_transferred'])
114
106
  when 'completed'
115
- notify_progress(type: :transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
116
- notify_progress(type: :end, session_id: @transfer_id)
107
+ notify_progress(:transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
108
+ notify_progress(:end, session_id: @transfer_id)
117
109
  break
118
110
  when 'failed'
119
- notify_progress(type: :end, session_id: @transfer_id)
111
+ notify_progress(:end, session_id: @transfer_id)
120
112
  # Bug in HSTS ? transfer is marked failed, but there is no reason
121
113
  break if transfer_data['error_code'].eql?(0) && transfer_data['error_desc'].empty?
122
114
  raise Transfer::Error, "status: #{transfer_data['status']}. code: #{transfer_data['error_code']}. description: #{transfer_data['error_desc']}"
123
- else
124
- Log.log.warn{"transfer_data -> #{transfer_data}"}
125
- raise Transfer::Error, "status: #{transfer_data['status']}. code: #{transfer_data['error_code']}. description: #{transfer_data['error_desc']}"
115
+ else Aspera.error_unexpected_value(transfer_data['status']){"transfer_data -> #{transfer_data}"}
126
116
  end
127
117
  sleep(1.0)
128
118
  end
@@ -1,41 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aspera/agent/base'
4
- require 'aspera/ascp/installation'
4
+ require 'aspera/products/transferd'
5
5
  require 'aspera/temp_file_manager'
6
- require 'aspera/log'
7
- require 'aspera/assert'
8
6
  require 'json'
9
7
  require 'uri'
8
+ require 'transferd_services_pb'
10
9
 
11
10
  module Aspera
12
11
  module Agent
13
- class Trsdk < Base
14
- # see https://github.com/grpc/grpc/blob/master/doc/naming.md
12
+ class Transferd < Base
13
+ # https://github.com/grpc/grpc/blob/master/doc/naming.md
15
14
  # https://grpc.io/docs/guides/custom-name-resolution/
16
15
  LOCAL_SOCKET_ADDR = '127.0.0.1'
17
16
  PORT_SEP = ':'
18
17
  # port zero means select a random available high port
19
18
  AUTO_LOCAL_TCP_PORT = "#{PORT_SEP}0"
20
- class << self
21
- # Well, the port number is only in log file
22
- def daemon_port_from_log(log_file)
23
- result = nil
24
- # if port is zero, a dynamic port was created, get it
25
- File.open(log_file, 'r') do |file|
26
- file.each_line do |line|
27
- # Well, it's tricky to depend on log
28
- if (m = line.match(/Info: API Server: Listening on ([^:]+):(\d+) /))
29
- result = m[2].to_i
30
- # no "break" , need to read last matching log line
31
- end
32
- end
33
- end
34
- raise 'Port not found in daemon logs' if result.nil?
35
- Log.log.debug{"Got port #{result} from log"}
36
- return result
37
- end
38
- end
39
19
 
40
20
  # @param url [String] URL of the transfer manager daemon
41
21
  # @param external [Boolean] if true, expect that an external daemon is already running
@@ -48,34 +28,30 @@ module Aspera
48
28
  **base_options
49
29
  )
50
30
  super(**base_options)
51
- is_local_auto_port = @url.eql?(AUTO_LOCAL_TCP_PORT)
52
- raise 'Cannot use options `keep` or `external` with port zero' if is_local_auto_port && (@keep || @external)
53
- # load SDK stub class on demand, as it's an optional gem
54
- $LOAD_PATH.unshift(Ascp::Installation.instance.sdk_ruby_folder)
55
- require 'transfer_services_pb'
31
+ @keep = keep
32
+ is_local_auto_port = url.eql?(AUTO_LOCAL_TCP_PORT)
33
+ raise 'Cannot use options `keep` or `external` with port zero' if is_local_auto_port && (@keep || external)
56
34
  # keep PID for optional shutdown
57
35
  @daemon_pid = nil
58
- daemon_endpoint = @url
36
+ daemon_endpoint = url
59
37
  Log.log.debug{Log.dump(:daemon_endpoint, daemon_endpoint)}
60
38
  # retry loop
61
39
  begin
62
40
  # no address: local bind
63
41
  daemon_endpoint = "#{LOCAL_SOCKET_ADDR}#{daemon_endpoint}" if daemon_endpoint.match?(/^#{PORT_SEP}[0-9]+$/o)
64
42
  # Create stub (without credentials)
65
- @transfer_client = Transfersdk::TransferService::Stub.new(daemon_endpoint, :this_channel_is_insecure)
43
+ @transfer_client = ::Transferd::Api::TransferService::Stub.new(daemon_endpoint, :this_channel_is_insecure)
66
44
  # Initiate actual connection
67
- get_info_response = @transfer_client.get_info(Transfersdk::InstanceInfoRequest.new)
45
+ get_info_response = @transfer_client.get_info(::Transferd::Api::InstanceInfoRequest.new)
68
46
  Log.log.debug{"Daemon info: #{get_info_response}"}
69
- Log.log.warn{'Attached to existing daemon'} unless @daemon_pid || @external || @keep
47
+ Log.log.warn{'Attached to existing daemon'} unless @daemon_pid || external || @keep
70
48
  at_exit{shutdown}
71
49
  rescue GRPC::Unavailable => e
72
50
  # if transferd is external: do not start it, or other error
73
- raise if @external || !e.message.include?('failed to connect')
51
+ raise if external || !e.message.include?('failed to connect')
74
52
  # we already tried to start a daemon, but it failed
75
53
  Aspera.assert(@daemon_pid.nil?){"Daemon started with PID #{@daemon_pid}, but connection failed to #{daemon_endpoint}}"}
76
- Log.log.warn('no daemon present, starting daemon...') if @external
77
- # location of daemon binary
78
- sdk_folder = File.realpath(File.join(Ascp::Installation.instance.sdk_ruby_folder, '..'))
54
+ Log.log.warn('no daemon present, starting daemon...') if external
79
55
  # transferd only supports local ip and port
80
56
  daemon_uri = URI.parse("ipv4://#{daemon_endpoint}")
81
57
  Aspera.assert(daemon_uri.scheme.eql?('ipv4')){"Invalid scheme daemon URI #{daemon_endpoint}"}
@@ -86,8 +62,8 @@ module Aspera
86
62
  fasp_runtime: {
87
63
  use_embedded: false,
88
64
  user_defined: {
89
- bin: sdk_folder,
90
- etc: sdk_folder
65
+ bin: Products::Transferd.sdk_directory,
66
+ etc: Products::Transferd.sdk_directory
91
67
  }
92
68
  }
93
69
  }
@@ -113,7 +89,7 @@ module Aspera
113
89
  Process.detach(@daemon_pid) if @keep
114
90
  at_exit {shutdown}
115
91
  # update port for next connection attempt (if auto high port was requested)
116
- daemon_endpoint = "#{LOCAL_SOCKET_ADDR}#{PORT_SEP}#{self.class.daemon_port_from_log(log_stdout)}" if is_local_auto_port
92
+ daemon_endpoint = "#{LOCAL_SOCKET_ADDR}#{PORT_SEP}#{Products::Transferd.daemon_port_from_log(log_stdout)}" if is_local_auto_port
117
93
  # local daemon started, try again
118
94
  retry
119
95
  end
@@ -121,9 +97,9 @@ module Aspera
121
97
 
122
98
  def start_transfer(transfer_spec, token_regenerator: nil)
123
99
  # create a transfer request
124
- transfer_request = Transfersdk::TransferRequest.new(
125
- transferType: Transfersdk::TransferType::FILE_REGULAR, # transfer type (file/stream)
126
- config: Transfersdk::TransferConfig.new, # transfer configuration
100
+ transfer_request = ::Transferd::Api::TransferRequest.new(
101
+ transferType: ::Transferd::Api::TransferType::FILE_REGULAR, # transfer type (file/stream)
102
+ config: ::Transferd::Api::TransferConfig.new, # transfer configuration
127
103
  transferSpec: transfer_spec.to_json) # transfer definition
128
104
  # send start transfer request to the transfer manager daemon
129
105
  start_transfer_response = @transfer_client.start_transfer(transfer_request)
@@ -137,30 +113,30 @@ module Aspera
137
113
  session_started = false
138
114
  bytes_expected = nil
139
115
  # monitor transfer status
140
- @transfer_client.monitor_transfers(Transfersdk::RegistrationRequest.new(transferId: [@transfer_id])) do |response|
116
+ @transfer_client.monitor_transfers(::Transferd::Api::RegistrationRequest.new(transferId: [@transfer_id])) do |response|
141
117
  Log.log.debug{Log.dump(:response, response.to_h)}
142
118
  # Log.log.debug{"#{response.sessionInfo.preTransferBytes} #{response.transferInfo.bytesTransferred}"}
143
119
  case response.status
144
120
  when :RUNNING
145
121
  if !session_started
146
- notify_progress(session_id: @transfer_id, type: :session_start)
122
+ notify_progress(:session_start, session_id: @transfer_id)
147
123
  session_started = true
148
124
  end
149
125
  if bytes_expected.nil? &&
150
126
  !response.sessionInfo.preTransferBytes.eql?(0)
151
127
  bytes_expected = response.sessionInfo.preTransferBytes
152
- notify_progress(type: :session_size, session_id: @transfer_id, info: bytes_expected)
128
+ notify_progress(:session_size, session_id: @transfer_id, info: bytes_expected)
153
129
  end
154
- notify_progress(type: :transfer, session_id: @transfer_id, info: response.transferInfo.bytesTransferred)
130
+ notify_progress(:transfer, session_id: @transfer_id, info: response.transferInfo.bytesTransferred)
155
131
  when :COMPLETED
156
- notify_progress(type: :transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
157
- notify_progress(type: :end, session_id: @transfer_id)
132
+ notify_progress(:transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
133
+ notify_progress(:end, session_id: @transfer_id)
158
134
  break
159
135
  when :FAILED, :CANCELED
160
- notify_progress(type: :end, session_id: @transfer_id)
136
+ notify_progress(:end, session_id: @transfer_id)
161
137
  raise Transfer::Error, JSON.parse(response.message)['Description']
162
138
  when :QUEUED, :UNKNOWN_STATUS, :PAUSED, :ORPHANED
163
- notify_progress(session_id: nil, type: :pre_start, info: response.status.to_s.downcase)
139
+ notify_progress(:pre_start, session_id: nil, info: response.status.to_s.downcase)
164
140
  else
165
141
  Log.log.error{"unknown status#{response.status}"}
166
142
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aspera/api/aoc.rb'
4
+ module Aspera
5
+ module Api
6
+ class Alee < Aspera::Rest
7
+ def initialize(entitlement_id, customer_id, api_domain: AoC::SAAS_DOMAIN_PROD, version: 'v1')
8
+ super(
9
+ base_url: "https://api.#{api_domain}/metering/#{version}",
10
+ headers: {'X-Aspera-Entitlement-Authorization' => Rest.basic_token(entitlement_id, customer_id)}
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end