aspera-cli 4.4.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1042 -787
  3. data/bin/ascli +1 -1
  4. data/bin/asession +3 -5
  5. data/docs/Makefile +4 -7
  6. data/docs/README.erb.md +988 -740
  7. data/examples/faspex4.rb +4 -6
  8. data/examples/transfer.rb +2 -2
  9. data/lib/aspera/aoc.rb +139 -118
  10. data/lib/aspera/cli/listener/progress_multi.rb +5 -5
  11. data/lib/aspera/cli/main.rb +64 -34
  12. data/lib/aspera/cli/manager.rb +19 -20
  13. data/lib/aspera/cli/plugin.rb +9 -1
  14. data/lib/aspera/cli/plugins/aoc.rb +156 -143
  15. data/lib/aspera/cli/plugins/ats.rb +11 -10
  16. data/lib/aspera/cli/plugins/bss.rb +2 -2
  17. data/lib/aspera/cli/plugins/config.rb +236 -112
  18. data/lib/aspera/cli/plugins/faspex.rb +29 -7
  19. data/lib/aspera/cli/plugins/faspex5.rb +21 -8
  20. data/lib/aspera/cli/plugins/node.rb +21 -9
  21. data/lib/aspera/cli/plugins/orchestrator.rb +5 -3
  22. data/lib/aspera/cli/plugins/preview.rb +2 -2
  23. data/lib/aspera/cli/plugins/server.rb +3 -3
  24. data/lib/aspera/cli/plugins/shares.rb +17 -0
  25. data/lib/aspera/cli/transfer_agent.rb +47 -85
  26. data/lib/aspera/cli/version.rb +1 -1
  27. data/lib/aspera/environment.rb +4 -4
  28. data/lib/aspera/fasp/{manager.rb → agent_base.rb} +7 -6
  29. data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +46 -39
  30. data/lib/aspera/fasp/{local.rb → agent_direct.rb} +14 -17
  31. data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +4 -4
  32. data/lib/aspera/fasp/{node.rb → agent_node.rb} +25 -8
  33. data/lib/aspera/fasp/agent_trsdk.rb +106 -0
  34. data/lib/aspera/fasp/default.rb +17 -0
  35. data/lib/aspera/fasp/installation.rb +64 -48
  36. data/lib/aspera/fasp/parameters.rb +7 -3
  37. data/lib/aspera/faspex_gw.rb +6 -6
  38. data/lib/aspera/keychain/encrypted_hash.rb +120 -0
  39. data/lib/aspera/keychain/macos_security.rb +94 -0
  40. data/lib/aspera/log.rb +45 -32
  41. data/lib/aspera/node.rb +3 -6
  42. data/lib/aspera/rest.rb +65 -49
  43. metadata +68 -27
  44. data/lib/aspera/api_detector.rb +0 -60
  45. data/lib/aspera/secrets.rb +0 -20
data/examples/faspex4.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
  # find Faspex API here: https://developer.ibm.com/apis/catalog/?search=faspex
3
3
  # this example makes use of class Aspera::Rest for REST calls, alternatively class RestClient of gem rest-client could be used
4
- # this example makes use of class Aspera::Fasp::Local for transfers, alternatively the official "Transfer SDK" could be used
4
+ # this example makes use of class Aspera::Fasp::AgentDirect for transfers, alternatively the official "Transfer SDK" could be used
5
5
  # Aspera SDK can be downloaded with: `ascli conf ascp install` , it installs in $HOME/.aspera/ascli/sdk
6
6
  require 'aspera/rest'
7
7
  require 'aspera/log'
8
- require 'aspera/fasp/local'
8
+ require 'aspera/fasp/agent_direct'
9
9
 
10
10
  tmpdir=ENV['tmp']||Dir.tmpdir || '.'
11
11
 
@@ -59,10 +59,8 @@ pkg_created=api_v3.create('send',package_create_params)[:data]
59
59
  transfer_spec=pkg_created['xfer_sessions'].first
60
60
  # set paths of files to send
61
61
  transfer_spec['paths']=[{'source'=>file_to_send}]
62
- # get the local agent (i.e. ascp)
63
- transfer_client=Aspera::Fasp::Local.new
64
- # disable ascp output on stdout (optional)
65
- transfer_client.quiet=true
62
+ # get local agent (ascp), disable ascp output on stdout to not mix with JSON events
63
+ transfer_client=Aspera::Fasp::AgentDirect.new({quiet: true})
66
64
  # start transfer (asynchronous)
67
65
  job_id=transfer_client.start_transfer(transfer_spec)
68
66
  # wait for all transfer completion (for the example)
data/examples/transfer.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  # Example: transfer a file using one of the provided transfer agents
3
3
  # location of ascp can be specified with env var "ascp"
4
4
  # temp folder can be specified with env var "tmp"
5
- require 'aspera/fasp/local'
5
+ require 'aspera/fasp/agent_direct'
6
6
  require 'aspera/fasp/listener'
7
7
  require 'aspera/fasp/installation'
8
8
  require 'aspera/log'
@@ -39,7 +39,7 @@ Aspera::Fasp::Installation.instance.ascp_path=ENV['ascp'] if ENV.has_key?('ascp'
39
39
  #
40
40
 
41
41
  # get FASP Manager singleton based on above ascp location
42
- fasp_manager=Aspera::Fasp::Local.new
42
+ fasp_manager=Aspera::Fasp::AgentDirect.new
43
43
 
44
44
  # Note that it would also be possible to start transfers using other agents
45
45
  #require 'aspera/fasp/connect'
data/lib/aspera/aoc.rb CHANGED
@@ -2,7 +2,7 @@ require 'aspera/log'
2
2
  require 'aspera/rest'
3
3
  require 'aspera/hash_ext'
4
4
  require 'aspera/data_repository'
5
- require 'aspera/node'
5
+ require 'aspera/fasp/default'
6
6
  require 'base64'
7
7
 
8
8
  module Aspera
@@ -18,19 +18,20 @@ module Aspera
18
18
  # to avoid infinite loop in pub link redirection
19
19
  MAX_REDIRECT=10
20
20
  CLIENT_APPS=['aspera.global-cli-client','aspera.drive']
21
+ # index offset in data repository of client app
21
22
  DATA_REPO_INDEX_START = 4
23
+ # cookie prefix so that console can decode identity
24
+ COOKIE_PREFIX='aspera.aoc'
22
25
 
23
26
  # path in URL of public links
24
- PATHS_PUBLIC_LINK=['/packages/public/receive','/packages/public/send','/files/public']
27
+ PUBLIC_LINK_PATHS=['/packages/public/receive','/packages/public/send','/files/public']
25
28
  JWT_AUDIENCE='https://api.asperafiles.com/api/v1/oauth2/token'
26
29
  OAUTH_API_SUBPATH='api/v1/oauth2'
27
- DEFAULT_TSPEC_INFO={
28
- 'remote_user' => Node::ACCESS_KEY_TRANSFER_USER,
29
- 'ssh_port' => Node::SSH_PORT_DEFAULT,
30
- 'fasp_port' => Node::UDP_PORT_DEFAULT
31
- }
30
+ # minimum fields for user info if retrieval fails
31
+ USER_INFO_FIELDS_MIN=['name','email','id','default_workspace_id','organization_id']
32
32
 
33
- private_constant :PRODUCT_NAME,:PROD_DOMAIN,:MAX_REDIRECT,:CLIENT_APPS,:PATHS_PUBLIC_LINK,:JWT_AUDIENCE,:OAUTH_API_SUBPATH,:DEFAULT_TSPEC_INFO
33
+ private_constant :PRODUCT_NAME,:PROD_DOMAIN,:MAX_REDIRECT,:CLIENT_APPS,:PUBLIC_LINK_PATHS,:JWT_AUDIENCE,
34
+ :OAUTH_API_SUBPATH,:COOKIE_PREFIX,:USER_INFO_FIELDS_MIN
34
35
 
35
36
  public
36
37
  # various API scopes supported
@@ -45,84 +46,119 @@ module Aspera
45
46
  FILES_APP='files'
46
47
  PACKAGES_APP='packages'
47
48
 
48
- def self.get_client_info(client_name=CLIENT_APPS.first)
49
- client_index=CLIENT_APPS.index(client_name)
50
- raise "no such pre-defined client: #{client_name}" if client_index.nil?
49
+ # class static methods
50
+ class << self
51
51
  # strings /Applications/Aspera\ Drive.app/Contents/MacOS/AsperaDrive|grep -E '.{100}==$'|base64 --decode
52
- return client_name,Base64.urlsafe_encode64(DataRepository.instance.get_bin(DATA_REPO_INDEX_START+client_index))
53
- end
52
+ def get_client_info(client_name=CLIENT_APPS.first)
53
+ client_index=CLIENT_APPS.index(client_name)
54
+ raise "no such pre-defined client: #{client_name}" if client_index.nil?
55
+ return client_name,Base64.urlsafe_encode64(DataRepository.instance.get_bin(DATA_REPO_INDEX_START+client_index))
56
+ end
54
57
 
55
- # @param url of AoC instance
56
- # @return organization id in url and AoC domain: ibmaspera.com, asperafiles.com or qa.asperafiles.com, etc...
57
- def self.parse_url(aoc_org_url)
58
- uri=URI.parse(aoc_org_url.gsub(/\/+$/,''))
59
- instance_fqdn=uri.host
60
- Log.log.debug("instance_fqdn=#{instance_fqdn}")
61
- raise "No host found in URL.Please check URL format: https://myorg.#{PROD_DOMAIN}" if instance_fqdn.nil?
62
- organization,instance_domain=instance_fqdn.split('.',2)
63
- Log.log.debug("instance_domain=#{instance_domain}")
64
- Log.log.debug("organization=#{organization}")
65
- raise "expecting a public FQDN for #{PRODUCT_NAME}" if instance_domain.nil?
66
- return organization,instance_domain
67
- end
58
+ # @param url of AoC instance
59
+ # @return organization id in url and AoC domain: ibmaspera.com, asperafiles.com or qa.asperafiles.com, etc...
60
+ def parse_url(aoc_org_url)
61
+ uri=URI.parse(aoc_org_url.gsub(/\/+$/,''))
62
+ instance_fqdn=uri.host
63
+ Log.log.debug("instance_fqdn=#{instance_fqdn}")
64
+ raise "No host found in URL.Please check URL format: https://myorg.#{PROD_DOMAIN}" if instance_fqdn.nil?
65
+ organization,instance_domain=instance_fqdn.split('.',2)
66
+ Log.log.debug("instance_domain=#{instance_domain}")
67
+ Log.log.debug("organization=#{organization}")
68
+ raise "expecting a public FQDN for #{PRODUCT_NAME}" if instance_domain.nil?
69
+ return organization,instance_domain
70
+ end
68
71
 
69
- # base API url depends on domain, which could be "qa.xxx"
70
- def self.api_base_url(api_domain=PROD_DOMAIN)
71
- return "https://api.#{api_domain}"
72
- end
72
+ # base API url depends on domain, which could be "qa.xxx"
73
+ def api_base_url(api_domain=PROD_DOMAIN)
74
+ return "https://api.#{api_domain}"
75
+ end
73
76
 
74
- def self.metering_api(entitlement_id,customer_id,api_domain=PROD_DOMAIN)
75
- return Rest.new({
76
- :base_url => "#{api_base_url(api_domain)}/metering/v1",
77
- :headers => {'X-Aspera-Entitlement-Authorization' => Rest.basic_creds(entitlement_id,customer_id)}
78
- })
79
- end
77
+ def metering_api(entitlement_id,customer_id,api_domain=PROD_DOMAIN)
78
+ return Rest.new({
79
+ :base_url => "#{api_base_url(api_domain)}/metering/v1",
80
+ :headers => {'X-Aspera-Entitlement-Authorization' => Rest.basic_creds(entitlement_id,customer_id)}
81
+ })
82
+ end
80
83
 
81
- # node API scopes
82
- def self.node_scope(access_key,scope)
83
- return 'node.'+access_key+':'+scope
84
- end
84
+ # node API scopes
85
+ def node_scope(access_key,scope)
86
+ return 'node.'+access_key+':'+scope
87
+ end
85
88
 
86
- def self.set_use_default_ports(val)
87
- @@use_standard_ports=val
88
- end
89
+ def set_use_default_ports(val)
90
+ @@use_standard_ports=val
91
+ end
89
92
 
90
- # check option "link"
91
- # if present try to get token value (resolve redirection if short links used)
92
- # then set options url/token/auth
93
- def self.resolve_pub_link(rest_opts,public_link_url)
94
- return if public_link_url.nil?
95
- # set to token if available after redirection
96
- url_param_token_pair=nil
97
- redirect_count=0
98
- loop do
99
- uri=URI.parse(public_link_url)
100
- if PATHS_PUBLIC_LINK.include?(uri.path)
101
- url_param_token_pair=URI::decode_www_form(uri.query).select{|e|e.first.eql?('token')}.first
102
- if url_param_token_pair.nil?
103
- raise ArgumentError,"link option must be URL with 'token' parameter"
93
+ # check option "link"
94
+ # if present try to get token value (resolve redirection if short links used)
95
+ # then set options url/token/auth
96
+ def resolve_pub_link(rest_opts,public_link_url)
97
+ return if public_link_url.nil?
98
+ # set to token if available after redirection
99
+ url_param_token_pair=nil
100
+ redirect_count=0
101
+ loop do
102
+ uri=URI.parse(public_link_url)
103
+ if PUBLIC_LINK_PATHS.include?(uri.path)
104
+ url_param_token_pair=URI::decode_www_form(uri.query).select{|e|e.first.eql?('token')}.first
105
+ if url_param_token_pair.nil?
106
+ raise ArgumentError,"link option must be URL with 'token' parameter"
107
+ end
108
+ # ok we get it !
109
+ rest_opts[:org_url]='https://'+uri.host
110
+ rest_opts[:auth][:grant]=:url_token
111
+ rest_opts[:auth][:url_token]=url_param_token_pair.last
112
+ return
104
113
  end
105
- # ok we get it !
106
- rest_opts[:org_url]='https://'+uri.host
107
- rest_opts[:auth][:grant]=:url_token
108
- rest_opts[:auth][:url_token]=url_param_token_pair.last
109
- return
110
- end
111
- Log.log.debug("no expected format: #{public_link_url}")
112
- raise "exceeded max redirection: #{MAX_REDIRECT}" if redirect_count > MAX_REDIRECT
113
- r = Net::HTTP.get_response(uri)
114
- if r.code.start_with?("3")
115
- public_link_url = r['location']
116
- raise "no location in redirection" if public_link_url.nil?
117
- Log.log.debug("redirect to: #{public_link_url}")
118
- else
119
- # not a redirection
120
- raise ArgumentError,'link option must be redirect or have token parameter'
114
+ Log.log.debug("no expected format: #{public_link_url}")
115
+ raise "exceeded max redirection: #{MAX_REDIRECT}" if redirect_count > MAX_REDIRECT
116
+ r = Net::HTTP.get_response(uri)
117
+ if r.code.start_with?("3")
118
+ public_link_url = r['location']
119
+ raise "no location in redirection" if public_link_url.nil?
120
+ Log.log.debug("redirect to: #{public_link_url}")
121
+ else
122
+ # not a redirection
123
+ raise ArgumentError,'link option must be redirect or have token parameter'
124
+ end
125
+ end # loop
126
+
127
+ raise RuntimeError,'too many redirections'
128
+ end
129
+
130
+ # additional transfer spec (tags) for package information
131
+ def package_tags(package_info,operation)
132
+ return {'tags'=>{'aspera'=>{'files'=>{
133
+ 'package_id' => package_info['id'],
134
+ 'package_name' => package_info['name'],
135
+ 'package_operation' => operation
136
+ }}}}
137
+ end
138
+
139
+ # add details to show in analytics
140
+ def analytics_ts(app,direction,ws_id,ws_name)
141
+ # translate transfer to operation
142
+ operation=case direction
143
+ when 'send'; 'upload'
144
+ when 'receive'; 'download'
145
+ else raise "ERROR: unexpected value: #{direction}"
121
146
  end
122
- end # loop
123
147
 
124
- raise RuntimeError,'too many redirections'
125
- end
148
+ return {
149
+ 'tags' => {
150
+ 'aspera' => {
151
+ 'usage_id' => "aspera.files.workspace.#{ws_id}", # activity tracking
152
+ 'files' => {
153
+ 'files_transfer_action' => "#{operation}_#{app.gsub(/s$/,'')}",
154
+ 'workspace_name' => ws_name, # activity tracking
155
+ 'workspace_id' => ws_id,
156
+ }
157
+ }
158
+ }
159
+ }
160
+ end
161
+ end # static methods
126
162
 
127
163
  # @param :link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:subpath,:password (for pub link)
128
164
  def initialize(opt)
@@ -130,6 +166,7 @@ module Aspera
130
166
  # key: access key
131
167
  # value: associated secret
132
168
  @key_chain=nil
169
+ @user_info=nil
133
170
 
134
171
  # init rest params
135
172
  aoc_rest_p={:auth=>{:type =>:oauth2}}
@@ -197,50 +234,28 @@ module Aspera
197
234
 
198
235
  def key_chain=(keychain)
199
236
  raise "keychain already set" unless @key_chain.nil?
237
+ raise "keychain must have get_secret" unless keychain.respond_to?(:get_secret)
200
238
  @key_chain=keychain
201
239
  nil
202
240
  end
203
241
 
204
- # additional transfer spec (tags) for package information
205
- def self.package_tags(package_info,operation)
206
- return {'tags'=>{'aspera'=>{'files'=>{
207
- 'package_id' => package_info['id'],
208
- 'package_name' => package_info['name'],
209
- 'package_operation' => operation
210
- }}}}
211
- end
212
-
213
- # add details to show in analytics
214
- def self.analytics_ts(app,direction,ws_id,ws_name)
215
- # translate transfer to operation
216
- operation=case direction
217
- when 'send'; 'upload'
218
- when 'receive'; 'download'
219
- else raise "ERROR: unexpected value: #{direction}"
242
+ # cached user information
243
+ def user_info
244
+ if @user_info.nil?
245
+ # get our user's default information
246
+ @user_info=self.read('self')[:data] rescue nil
247
+ @user_info=USER_INFO_FIELDS_MIN.inject({}){|m,f|m[f]=nil;m} if @user_info.nil?
248
+ USER_INFO_FIELDS_MIN.each{|f|@user_info[f]='unknown' if @user_info[f].nil?}
220
249
  end
221
-
222
- return {
223
- 'tags' => {
224
- 'aspera' => {
225
- 'usage_id' => "aspera.files.workspace.#{ws_id}", # activity tracking
226
- 'files' => {
227
- 'files_transfer_action' => "#{operation}_#{app.gsub(/s$/,'')}",
228
- 'workspace_name' => ws_name, # activity tracking
229
- 'workspace_id' => ws_id,
230
- }
231
- }
232
- }
233
- }
250
+ return @user_info
234
251
  end
235
252
 
236
253
  # build ts addon for IBM Aspera Console (cookie)
237
- def self.console_ts(app,user_name,user_email)
238
- elements=[app,user_name,user_email].map{|e|Base64.strict_encode64(e)}
239
- elements.unshift('aspera.aoc')
240
- #Log.dump('elem1'.bg_red,elements[1])
241
- return {
242
- 'cookie'=>elements.join(':')
243
- }
254
+ def console_ts(app)
255
+ # we are sure that fields are not nil
256
+ elements=[app,user_info['name'],user_info['email']].map{|e|Base64.strict_encode64(e)}
257
+ elements.unshift(COOKIE_PREFIX)
258
+ return {'cookie'=>elements.join(':')}
244
259
  end
245
260
 
246
261
  # build "transfer info", 2 elements array with:
@@ -248,12 +263,12 @@ module Aspera
248
263
  # - source and token regeneration method
249
264
  def tr_spec(app,direction,node_file,ts_add)
250
265
  # prepare the rest end point is used to generate the bearer token
251
- token_generation_method=lambda {|do_refresh|self.oauth_token(scope: self.class.node_scope(node_file[:node_info]['access_key'],SCOPE_NODE_USER), refresh: do_refresh)}
266
+ token_generation_lambda=lambda {|do_refresh|self.oauth_token(scope: self.class.node_scope(node_file[:node_info]['access_key'],SCOPE_NODE_USER), refresh: do_refresh)}
252
267
  # prepare transfer specification
253
268
  # note xfer_id and xfer_retry are set by the transfer agent itself
254
269
  transfer_spec={
255
270
  'direction' => direction,
256
- 'token' => token_generation_method.call(false), # first time, use cache
271
+ 'token' => token_generation_lambda.call(false), # first time, use cache
257
272
  'tags' => {
258
273
  'aspera' => {
259
274
  'app' => app,
@@ -270,8 +285,14 @@ module Aspera
270
285
  }
271
286
  # add remote host info
272
287
  if @@use_standard_ports
273
- transfer_spec.merge!(DEFAULT_TSPEC_INFO)
288
+ # get default TCP/UDP ports and transfer user
289
+ transfer_spec.merge!(Fasp::Default::AK_TSPEC_BASE)
290
+ # by default: same address as node API
274
291
  transfer_spec['remote_host']=node_file[:node_info]['host']
292
+ # 30 it's necessarily https scheme: webui does not allow anything else
293
+ if node_file[:node_info]['transfer_url'].is_a?(String) and !node_file[:node_info]['transfer_url'].empty?
294
+ transfer_spec['remote_host']=URI.parse(node_file[:node_info]['transfer_url']).host
295
+ end
275
296
  else
276
297
  # retrieve values from API
277
298
  std_t_spec=get_node_api(node_file[:node_info],scope: SCOPE_NODE_USER).create('files/download_setup',{:transfer_requests => [ { :transfer_request => {:paths => [ {"source"=>'/'} ] } } ] } )[:data]['transfer_specs'].first['transfer_spec']
@@ -282,7 +303,7 @@ module Aspera
282
303
  # additional information for transfer agent
283
304
  source_and_token_generator={
284
305
  :src => :node_gen4,
285
- :regenerate_token => token_generation_method
306
+ :regenerate_token => token_generation_lambda
286
307
  }
287
308
  return transfer_spec,source_and_token_generator
288
309
  end
@@ -292,10 +313,10 @@ module Aspera
292
313
  # no scope: requires secret
293
314
  # if secret provided beforehand: use it
294
315
  def get_node_api(node_info,options={})
295
- raise "INTERNAL ERROR: method parameters: options must ne hash" unless options.is_a?(Hash)
316
+ raise "INTERNAL ERROR: method parameters: options must be Hash" unless options.is_a?(Hash)
296
317
  options.keys.each {|k| raise "INTERNAL ERROR: not valid option: #{k}" unless [:scope,:use_secret].include?(k)}
297
318
  # get optional secret unless :use_secret is false (default is true)
298
- ak_secret=@key_chain.get_secret(node_info['access_key'],false) if !options.has_key?(:use_secret) or options[:use_secret]
319
+ ak_secret=@key_chain.get_secret(url: node_info['url'], username: node_info['access_key'], mandatory: false) if !@key_chain.nil? and ( !options.has_key?(:use_secret) or options[:use_secret] )
299
320
  if ak_secret.nil? and !options.has_key?(:scope)
300
321
  raise "There must be at least one of: 'secret' or 'scope' for access key #{node_info['access_key']}"
301
322
  end
@@ -1,5 +1,5 @@
1
1
  require 'aspera/fasp/listener'
2
- require 'aspera/fasp/manager'
2
+ require 'aspera/fasp/agent_base'
3
3
  require 'ruby-progressbar'
4
4
 
5
5
  module Aspera
@@ -43,13 +43,13 @@ module Aspera
43
43
  :title => '',
44
44
  :total => nil)
45
45
  end
46
- if !data.has_key?(Fasp::Manager::LISTENER_SESSION_ID_S)
47
- Log.log.error("Internal error: no #{Fasp::Manager::LISTENER_SESSION_ID_S} in event: #{data}")
46
+ if !data.has_key?(Fasp::AgentBase::LISTENER_SESSION_ID_S)
47
+ Log.log.error("Internal error: no #{Fasp::AgentBase::LISTENER_SESSION_ID_S} in event: #{data}")
48
48
  return
49
49
  end
50
50
  newtitle=@sessions.length < 2 ? '' : "multi=#{@sessions.length}"
51
51
  @progress_bar.title=newtitle unless @progress_bar.title.eql?(newtitle)
52
- session=@sessions[data[Fasp::Manager::LISTENER_SESSION_ID_S]]||={
52
+ session=@sessions[data[Fasp::AgentBase::LISTENER_SESSION_ID_S]]||={
53
53
  cumulative: 0,
54
54
  job_size: 0,
55
55
  current: 0
@@ -78,7 +78,7 @@ module Aspera
78
78
  # stop event when one file is completed
79
79
  session[:cumulative]=session[:cumulative]+data['size'].to_i
80
80
  when 'DONE' # end of session
81
- @sessions.delete(data[Fasp::Manager::LISTENER_SESSION_ID_S])
81
+ @sessions.delete(data[Fasp::AgentBase::LISTENER_SESSION_ID_S])
82
82
  update_progress
83
83
  update_total
84
84
  else