aspera-cli 4.4.0 → 4.7.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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2095 -1503
  3. data/bin/ascli +2 -1
  4. data/bin/asession +4 -5
  5. data/docs/test_env.conf +3 -0
  6. data/examples/aoc.rb +4 -3
  7. data/examples/faspex4.rb +25 -25
  8. data/examples/proxy.pac +1 -1
  9. data/examples/transfer.rb +17 -17
  10. data/lib/aspera/aoc.rb +238 -185
  11. data/lib/aspera/ascmd.rb +93 -83
  12. data/lib/aspera/ats_api.rb +11 -10
  13. data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
  14. data/lib/aspera/cli/extended_value.rb +42 -33
  15. data/lib/aspera/cli/formater.rb +142 -108
  16. data/lib/aspera/cli/info.rb +17 -0
  17. data/lib/aspera/cli/listener/line_dump.rb +3 -2
  18. data/lib/aspera/cli/listener/logger.rb +2 -1
  19. data/lib/aspera/cli/listener/progress.rb +16 -18
  20. data/lib/aspera/cli/listener/progress_multi.rb +18 -21
  21. data/lib/aspera/cli/main.rb +173 -149
  22. data/lib/aspera/cli/manager.rb +163 -168
  23. data/lib/aspera/cli/plugin.rb +43 -31
  24. data/lib/aspera/cli/plugins/alee.rb +6 -6
  25. data/lib/aspera/cli/plugins/aoc.rb +405 -370
  26. data/lib/aspera/cli/plugins/ats.rb +86 -79
  27. data/lib/aspera/cli/plugins/bss.rb +14 -16
  28. data/lib/aspera/cli/plugins/config.rb +580 -362
  29. data/lib/aspera/cli/plugins/console.rb +23 -19
  30. data/lib/aspera/cli/plugins/cos.rb +18 -18
  31. data/lib/aspera/cli/plugins/faspex.rb +201 -158
  32. data/lib/aspera/cli/plugins/faspex5.rb +80 -57
  33. data/lib/aspera/cli/plugins/node.rb +183 -166
  34. data/lib/aspera/cli/plugins/orchestrator.rb +71 -67
  35. data/lib/aspera/cli/plugins/preview.rb +92 -96
  36. data/lib/aspera/cli/plugins/server.rb +79 -75
  37. data/lib/aspera/cli/plugins/shares.rb +35 -19
  38. data/lib/aspera/cli/plugins/sync.rb +20 -22
  39. data/lib/aspera/cli/transfer_agent.rb +76 -113
  40. data/lib/aspera/cli/version.rb +2 -1
  41. data/lib/aspera/colors.rb +35 -27
  42. data/lib/aspera/command_line_builder.rb +48 -34
  43. data/lib/aspera/cos_node.rb +29 -21
  44. data/lib/aspera/data_repository.rb +3 -2
  45. data/lib/aspera/environment.rb +50 -45
  46. data/lib/aspera/fasp/{manager.rb → agent_base.rb} +28 -25
  47. data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +52 -43
  48. data/lib/aspera/fasp/{local.rb → agent_direct.rb} +58 -72
  49. data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +37 -43
  50. data/lib/aspera/fasp/{node.rb → agent_node.rb} +35 -16
  51. data/lib/aspera/fasp/agent_trsdk.rb +104 -0
  52. data/lib/aspera/fasp/error.rb +2 -1
  53. data/lib/aspera/fasp/error_info.rb +68 -52
  54. data/lib/aspera/fasp/installation.rb +152 -124
  55. data/lib/aspera/fasp/listener.rb +1 -0
  56. data/lib/aspera/fasp/parameters.rb +87 -92
  57. data/lib/aspera/fasp/parameters.yaml +305 -249
  58. data/lib/aspera/fasp/resume_policy.rb +11 -14
  59. data/lib/aspera/fasp/transfer_spec.rb +26 -0
  60. data/lib/aspera/fasp/uri.rb +22 -21
  61. data/lib/aspera/faspex_gw.rb +55 -89
  62. data/lib/aspera/hash_ext.rb +4 -3
  63. data/lib/aspera/id_generator.rb +8 -7
  64. data/lib/aspera/keychain/encrypted_hash.rb +121 -0
  65. data/lib/aspera/keychain/macos_security.rb +90 -0
  66. data/lib/aspera/log.rb +55 -37
  67. data/lib/aspera/nagios.rb +13 -12
  68. data/lib/aspera/node.rb +30 -25
  69. data/lib/aspera/oauth.rb +175 -226
  70. data/lib/aspera/open_application.rb +4 -3
  71. data/lib/aspera/persistency_action_once.rb +6 -6
  72. data/lib/aspera/persistency_folder.rb +5 -9
  73. data/lib/aspera/preview/file_types.rb +6 -5
  74. data/lib/aspera/preview/generator.rb +25 -24
  75. data/lib/aspera/preview/options.rb +16 -14
  76. data/lib/aspera/preview/utils.rb +98 -98
  77. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  78. data/lib/aspera/proxy_auto_config.rb +111 -20
  79. data/lib/aspera/rest.rb +154 -135
  80. data/lib/aspera/rest_call_error.rb +2 -2
  81. data/lib/aspera/rest_error_analyzer.rb +23 -25
  82. data/lib/aspera/rest_errors_aspera.rb +15 -14
  83. data/lib/aspera/ssh.rb +12 -10
  84. data/lib/aspera/sync.rb +42 -41
  85. data/lib/aspera/temp_file_manager.rb +18 -14
  86. data/lib/aspera/timer_limiter.rb +2 -1
  87. data/lib/aspera/uri_reader.rb +7 -5
  88. data/lib/aspera/web_auth.rb +79 -76
  89. metadata +116 -29
  90. data/docs/Makefile +0 -66
  91. data/docs/README.erb.md +0 -3973
  92. data/docs/README.md +0 -13
  93. data/docs/diagrams.txt +0 -49
  94. data/docs/doc_tools.rb +0 -58
  95. data/lib/aspera/api_detector.rb +0 -60
  96. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  97. data/lib/aspera/secrets.rb +0 -20
@@ -1,66 +1,71 @@
1
+ # frozen_string_literal: true
1
2
  require 'aspera/log'
2
3
  require 'rbconfig'
3
4
 
4
5
  module Aspera
5
- # detect OS, architecture, and OS specific stuff
6
+ # detect OS, architecture, and specific stuff
6
7
  class Environment
7
8
  OS_WINDOWS = :windows
8
9
  OS_X = :osx
9
10
  OS_LINUX = :linux
10
11
  OS_AIX = :aix
11
- OS_LIST=[OS_WINDOWS,OS_X,OS_LINUX,OS_AIX]
12
-
13
- def self.os
14
- case RbConfig::CONFIG['host_os']
15
- when /mswin/,/msys/,/mingw/,/cygwin/,/bccwin/,/wince/,/emc/
16
- return OS_WINDOWS
17
- when /darwin/,/mac os/
18
- return OS_X
19
- when /linux/
20
- return OS_LINUX
21
- when /aix/
22
- return OS_AIX
23
- else
24
- raise "Unknown OS: #{RbConfig::CONFIG['host_os']}"
25
- end
26
- end
27
- CPU_X86_64=:x86_64
12
+ OS_LIST=[OS_WINDOWS,OS_X,OS_LINUX,OS_AIX].freeze
13
+ CPU_X86_64=:x86_64 # rubocop:disable Naming/VariableNumber
28
14
  CPU_PPC64=:ppc64
29
15
  CPU_PPC64LE=:ppc64le
30
16
  CPU_S390=:s390
31
- CPU_LIST=[CPU_X86_64,CPU_PPC64,CPU_PPC64LE,CPU_S390]
17
+ CPU_LIST=[CPU_X86_64,CPU_PPC64,CPU_PPC64LE,CPU_S390].freeze
32
18
 
33
- def self.cpu
34
- case RbConfig::CONFIG['host_cpu']
35
- when /x86_64/,/x64/
36
- return :x86_64
37
- when /powerpc/
38
- return :ppc64le if os.eql?(OS_LINUX)
39
- return :ppc64
40
- when /s390/
41
- return :s390
42
- else # other
43
- raise "Unknown CPU: #{RbConfig::CONFIG['host_cpu']}"
19
+ class<<self
20
+ def ruby_version
21
+ return RbConfig::CONFIG['RUBY_PROGRAM_VERSION']
44
22
  end
45
- end
46
23
 
47
- def self.architecture
48
- return "#{os}-#{cpu}"
49
- end
50
-
51
- def self.exe_extension
52
- return '.exe' if os.eql?(OS_WINDOWS)
53
- return ''
54
- end
24
+ def os
25
+ case RbConfig::CONFIG['host_os']
26
+ when /mswin/,/msys/,/mingw/,/cygwin/,/bccwin/,/wince/,/emc/
27
+ return OS_WINDOWS
28
+ when /darwin/,/mac os/
29
+ return OS_X
30
+ when /linux/
31
+ return OS_LINUX
32
+ when /aix/
33
+ return OS_AIX
34
+ else
35
+ raise "Unknown OS: #{RbConfig::CONFIG['host_os']}"
36
+ end
37
+ end
55
38
 
56
- # on Windows, the env var %USERPROFILE% provides the path to user's home more reliably than %HOMEDRIVE%%HOMEPATH%
57
- def self.fix_home
58
- if os.eql?(OS_WINDOWS)
59
- if ENV.has_key?('USERPROFILE') and Dir.exist?(ENV['USERPROFILE'])
60
- ENV['HOME']=ENV['USERPROFILE']
61
- Log.log.debug("Windows: set home to USERPROFILE: #{ENV['HOME']}")
39
+ def cpu
40
+ case RbConfig::CONFIG['host_cpu']
41
+ when /x86_64/,/x64/
42
+ return CPU_X86_64
43
+ when /powerpc/,/ppc64/
44
+ return CPU_PPC64LE if os.eql?(OS_LINUX)
45
+ return CPU_PPC64
46
+ when /s390/
47
+ return CPU_S390
48
+ else # other
49
+ raise "Unknown CPU: #{RbConfig::CONFIG['host_cpu']}"
62
50
  end
63
51
  end
52
+
53
+ def architecture
54
+ return "#{os}-#{cpu}"
55
+ end
56
+
57
+ def exe_extension
58
+ return '.exe' if os.eql?(OS_WINDOWS)
59
+ return ''
60
+ end
61
+
62
+ # on Windows, the env var %USERPROFILE% provides the path to user's home more reliably than %HOMEDRIVE%%HOMEPATH%
63
+ # so, tell Ruby the right way
64
+ def fix_home
65
+ return unless os.eql?(OS_WINDOWS) && ENV.has_key?('USERPROFILE') && Dir.exist?(ENV['USERPROFILE'])
66
+ ENV['HOME']=ENV['USERPROFILE']
67
+ Log.log.debug("Windows: set home to USERPROFILE: #{ENV['HOME']}")
68
+ end
64
69
  end
65
70
  end
66
71
  end
@@ -1,30 +1,32 @@
1
+ # frozen_string_literal: true
1
2
  module Aspera
2
3
  module Fasp
3
4
  # Base class for FASP transfer agents
4
5
  # sub classes shall implement start_transfer and shutdown
5
- class Manager
6
+ class AgentBase
7
+ # fields description for JSON generation
8
+ INTEGER_FIELDS=%w[Bytescont FaspFileArgIndex StartByte Rate MinRate Port Priority RateCap MinRateCap TCPPort CreatePolicy TimePolicy DatagramSize XoptFlags VLinkVersion
9
+ PeerVLinkVersion DSPipelineDepth PeerDSPipelineDepth ReadBlockSize WriteBlockSize ClusterNumNodes ClusterNodeId Size Written Loss FileBytes PreTransferBytes TransferBytes PMTU Elapsedusec ArgScansAttempted ArgScansCompleted PathScansAttempted FileScansCompleted TransfersAttempted TransfersPassed Delay].freeze
10
+ BOOLEAN_FIELDS=%w[Encryption Remote RateLock MinRateLock PolicyLock FilesEncrypt FilesDecrypt VLinkLocalEnabled VLinkRemoteEnabled MoveRange Keepalive TestLogin UseProxy
11
+ Precalc RTTAutocorrect].freeze
12
+ EXPECTED_METHODS=%i[text struct enhanced].freeze
13
+ private_constant :INTEGER_FIELDS,:BOOLEAN_FIELDS,:EXPECTED_METHODS
6
14
 
7
15
  private
8
16
 
9
- # fields description for JSON generation
10
- IntegerFields=['Bytescont','FaspFileArgIndex','StartByte','Rate','MinRate','Port','Priority','RateCap','MinRateCap','TCPPort','CreatePolicy','TimePolicy','DatagramSize','XoptFlags','VLinkVersion','PeerVLinkVersion','DSPipelineDepth','PeerDSPipelineDepth','ReadBlockSize','WriteBlockSize','ClusterNumNodes','ClusterNodeId','Size','Written','Loss','FileBytes','PreTransferBytes','TransferBytes','PMTU','Elapsedusec','ArgScansAttempted','ArgScansCompleted','PathScansAttempted','FileScansCompleted','TransfersAttempted','TransfersPassed','Delay']
11
- BooleanFields=['Encryption','Remote','RateLock','MinRateLock','PolicyLock','FilesEncrypt','FilesDecrypt','VLinkLocalEnabled','VLinkRemoteEnabled','MoveRange','Keepalive','TestLogin','UseProxy','Precalc','RTTAutocorrect']
12
- ExpectedMethod=[:text,:struct,:enhanced]
13
-
14
17
  # translates legacy event into enhanced (JSON) event
15
18
  def enhanced_event_format(event)
16
- return event.keys.inject({}) do |h,e|
19
+ return event.keys.each_with_object({}) do |e,h|
17
20
  # capital_to_snake_case
18
21
  new_name=e.
19
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
20
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
21
- gsub(/([a-z\d])(usec)$/,'\1_\2').
22
- downcase
22
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
23
+ gsub(/([a-z\d])(usec)$/,'\1_\2').
24
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
25
+ downcase
23
26
  value=event[e]
24
- value=value.to_i if IntegerFields.include?(e)
25
- value=value.eql?('Yes') ? true : false if BooleanFields.include?(e)
27
+ value=value.to_i if INTEGER_FIELDS.include?(e)
28
+ value=value.eql?('Yes') if BOOLEAN_FIELDS.include?(e)
26
29
  h[new_name]=value
27
- h
28
30
  end
29
31
  end
30
32
 
@@ -33,14 +35,14 @@ module Aspera
33
35
  end
34
36
 
35
37
  def notify_listeners(current_event_text,current_event_data)
36
- Log.log.debug("send event to listeners")
38
+ Log.log.debug('send event to listeners')
37
39
  enhanced_event=nil
38
40
  @listeners.each do |listener|
39
- listener.send(:event_text,current_event_text) if listener.respond_to?(:event_text)
40
- listener.send(:event_struct,current_event_data) if listener.respond_to?(:event_struct)
41
+ listener.event_text(current_event_text) if listener.respond_to?(:event_text)
42
+ listener.event_struct(current_event_data) if listener.respond_to?(:event_struct)
41
43
  if listener.respond_to?(:event_enhanced)
42
44
  enhanced_event=enhanced_event_format(current_event_data) if enhanced_event.nil?
43
- listener.send(:event_enhanced,enhanced_event)
45
+ listener.event_enhanced(enhanced_event)
44
46
  end
45
47
  end
46
48
  end # notify_listeners
@@ -58,27 +60,28 @@ module Aspera
58
60
  end
59
61
 
60
62
  public
63
+
61
64
  LISTENER_SESSION_ID_B='ListenerSessionId'
62
65
  LISTENER_SESSION_ID_S='listener_session_id'
63
66
 
64
67
  # listener receives events
65
68
  def add_listener(listener)
66
- raise "expect one of #{ExpectedMethod}" if ExpectedMethod.inject(0){|m,e|m+=listener.respond_to?("event_#{e}")?1:0;m}.eql?(0)
69
+ raise "expect one of #{EXPECTED_METHODS}" if EXPECTED_METHODS.inject(0){|m,e|m+=listener.respond_to?("event_#{e}")?1:0;m}.eql?(0)
67
70
  @listeners.push(listener)
68
71
  self
69
72
  end
70
73
 
71
- # the following methods must be implemented by subclass:
72
- # start_transfer(transfer_spec,options) : start and wait for completion
73
- # wait_for_transfers_completion : wait for termination of all transfers, @return list of : :success or error message
74
- # optional: shutdown
75
-
76
74
  # This checks the validity of the value returned by wait_for_transfers_completion
77
75
  # it must be a list of :success or exception
78
76
  def self.validate_status_list(statuses)
79
77
  raise "internal error: bad statuses type: #{statuses.class}" unless statuses.is_a?(Array)
80
- raise "internal error: bad statuses content: #{statuses}" unless statuses.select{|i|!i.eql?(:success) and !i.is_a?(StandardError)}.empty?
78
+ raise "internal error: bad statuses content: #{statuses}" unless statuses.select{|i|!i.eql?(:success) && !i.is_a?(StandardError)}.empty?
81
79
  end
80
+
81
+ # the following methods must be implemented by subclass:
82
+ # start_transfer(transfer_spec,options) : start and wait for completion
83
+ # wait_for_transfers_completion : wait for termination of all transfers, @return list of : :success or error message
84
+ # optional: shutdown
82
85
  end
83
86
  end
84
87
  end
@@ -1,4 +1,5 @@
1
- require 'aspera/fasp/manager'
1
+ # frozen_string_literal: true
2
+ require 'aspera/fasp/agent_base'
2
3
  require 'aspera/rest'
3
4
  require 'aspera/open_application'
4
5
  require 'securerandom'
@@ -6,19 +7,15 @@ require 'tty-spinner'
6
7
 
7
8
  module Aspera
8
9
  module Fasp
9
- class Connect < Manager
10
+ class AgentConnect < AgentBase
10
11
  MAX_CONNECT_START_RETRY=3
11
12
  SLEEP_SEC_BETWEEN_RETRY=2
12
13
  private_constant :MAX_CONNECT_START_RETRY,:SLEEP_SEC_BETWEEN_RETRY
13
- def initialize
14
- super
14
+ def initialize(_options)
15
+ super()
15
16
  @connect_settings={
16
17
  'app_id' => SecureRandom.uuid
17
18
  }
18
- # TODO: start here and create monitor
19
- end
20
-
21
- def start_transfer(transfer_spec,options=nil)
22
19
  raise 'Using connect requires a graphical environment' if !OpenApplication.default_gui_mode.eql?(:graphical)
23
20
  trynumber=0
24
21
  begin
@@ -26,7 +23,8 @@ module Aspera
26
23
  Log.log.debug("found: #{connect_url}")
27
24
  @connect_api=Rest.new({base_url: "#{connect_url}/v5/connect",headers: {'Origin'=>Rest.user_agent}}) # could use v6 also now
28
25
  cinfo=@connect_api.read('info/version')[:data]
29
- rescue => e # Errno::ECONNREFUSED
26
+ Log.dump(:connect_version,cinfo)
27
+ rescue StandardError => e # Errno::ECONNREFUSED
30
28
  raise StandardError,"Unable to start connect after #{trynumber} try" if trynumber >= MAX_CONNECT_START_RETRY
31
29
  Log.log.warn("connect is not started. Retry ##{trynumber}, err=#{e}")
32
30
  trynumber+=1
@@ -37,24 +35,27 @@ module Aspera
37
35
  sleep(SLEEP_SEC_BETWEEN_RETRY)
38
36
  retry
39
37
  end
38
+ end
39
+
40
+ def start_transfer(transfer_spec,_options=nil)
40
41
  if transfer_spec['direction'] == 'send'
41
42
  Log.log.warn("Connect requires upload selection using GUI, ignoring #{transfer_spec['paths']}".red)
42
43
  transfer_spec.delete('paths')
43
- resdata=@connect_api.create('windows/select-open-file-dialog/',{'aspera_connect_settings'=>@connect_settings,'title'=>'Select Files','suggestedName'=>'','allowMultipleSelection'=>true,'allowedFileTypes'=>''})[:data]
44
+ resdata=@connect_api.create('windows/select-open-file-dialog/',
45
+ {'aspera_connect_settings'=>@connect_settings,'title'=>'Select Files','suggestedName'=>'','allowMultipleSelection'=>true,'allowedFileTypes'=>''})[:data]
44
46
  transfer_spec['paths']=resdata['dataTransfer']['files'].map { |i| {'source'=>i['name']}}
45
47
  end
46
48
  @request_id=SecureRandom.uuid
47
49
  # if there is a token, we ask connect client to use well known ssh private keys
48
50
  # instead of asking password
49
51
  transfer_spec['authentication']='token' if transfer_spec.has_key?('token')
50
- connect_settings=
51
52
  connect_transfer_args={
52
53
  'aspera_connect_settings'=>@connect_settings.merge({
53
54
  'request_id' =>@request_id,
54
- 'allow_dialogs' =>true,
55
+ 'allow_dialogs' =>true
55
56
  }),
56
57
  'transfer_specs' =>[{
57
- 'transfer_spec' =>transfer_spec,
58
+ 'transfer_spec' =>transfer_spec
58
59
  }]}
59
60
  # asynchronous anyway
60
61
  res=@connect_api.create('transfers/start',connect_transfer_args)[:data]
@@ -65,42 +66,50 @@ module Aspera
65
66
  connect_activity_args={'aspera_connect_settings'=>@connect_settings}
66
67
  started=false
67
68
  spinner=nil
68
- loop do
69
- tr_info=@connect_api.create("transfers/info/#{@xfer_id}",connect_activity_args)[:data]
70
- if tr_info['transfer_info'].is_a?(Hash)
71
- trdata=tr_info['transfer_info']
72
- if trdata.nil?
73
- Log.log.warn("no session in Connect")
74
- break
75
- end
76
- # TODO: get session id
77
- case trdata['status']
78
- when 'completed'
79
- notify_end(@connect_settings['app_id'])
80
- break
81
- when 'initiating','queued'
82
- if spinner.nil?
83
- spinner = TTY::Spinner.new('[:spinner] :title', format: :classic)
84
- spinner.start
69
+ begin
70
+ loop do
71
+ tr_info=@connect_api.create("transfers/info/#{@xfer_id}",connect_activity_args)[:data]
72
+ if tr_info['transfer_info'].is_a?(Hash)
73
+ trdata=tr_info['transfer_info']
74
+ if trdata.nil?
75
+ Log.log.warn('no session in Connect')
76
+ break
85
77
  end
86
- spinner.update(title: trdata['status'])
87
- spinner.spin
88
- when 'running'
89
- #puts "running: sessions:#{trdata['sessions'].length}, #{trdata['sessions'].map{|i| i['bytes_transferred']}.join(',')}"
90
- if !started and trdata['bytes_expected'] != 0
91
- notify_begin(@connect_settings['app_id'],trdata['bytes_expected'])
92
- started=true
78
+ # TODO: get session id
79
+ case trdata['status']
80
+ when 'completed'
81
+ notify_end(@connect_settings['app_id'])
82
+ break
83
+ when 'initiating','queued'
84
+ if spinner.nil?
85
+ spinner = TTY::Spinner.new('[:spinner] :title', format: :classic)
86
+ spinner.start
87
+ end
88
+ spinner.update(title: trdata['status'])
89
+ spinner.spin
90
+ when 'running'
91
+ #puts "running: sessions:#{trdata['sessions'].length}, #{trdata['sessions'].map{|i| i['bytes_transferred']}.join(',')}"
92
+ if !started && (trdata['bytes_expected'] != 0)
93
+ spinner.success unless spinner.nil?
94
+ notify_begin(@connect_settings['app_id'],trdata['bytes_expected'])
95
+ started=true
96
+ else
97
+ notify_progress(@connect_settings['app_id'],trdata['bytes_written'])
98
+ end
99
+ when 'failed'
100
+ spinner.error unless spinner.nil?
101
+ raise Fasp::Error, trdata['error_desc']
93
102
  else
94
- notify_progress(@connect_settings['app_id'],trdata['bytes_written'])
103
+ raise Fasp::Error, "unknown status: #{trdata['status']}: #{trdata['error_desc']}"
95
104
  end
96
- else
97
- raise Fasp::Error.new("unknown status: #{trdata['status']}: #{trdata['error_desc']}")
98
105
  end
106
+ sleep 1
99
107
  end
100
- sleep 1
108
+ rescue StandardError => e
109
+ return [e]
101
110
  end
102
- return [] #TODO
111
+ return [:success]
103
112
  end # wait
104
- end # Connect
113
+ end # AgentConnect
105
114
  end
106
115
  end