aspera-cli 4.4.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
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