aspera-cli 4.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3592 -0
  3. data/bin/ascli +7 -0
  4. data/bin/asession +89 -0
  5. data/docs/Makefile +59 -0
  6. data/docs/README.erb.md +3012 -0
  7. data/docs/README.md +13 -0
  8. data/docs/diagrams.txt +49 -0
  9. data/docs/secrets.make +38 -0
  10. data/docs/test_env.conf +117 -0
  11. data/docs/transfer_spec.html +99 -0
  12. data/examples/aoc.rb +17 -0
  13. data/examples/proxy.pac +60 -0
  14. data/examples/transfer.rb +115 -0
  15. data/lib/aspera/api_detector.rb +60 -0
  16. data/lib/aspera/ascmd.rb +151 -0
  17. data/lib/aspera/ats_api.rb +43 -0
  18. data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
  19. data/lib/aspera/cli/extended_value.rb +88 -0
  20. data/lib/aspera/cli/formater.rb +238 -0
  21. data/lib/aspera/cli/listener/line_dump.rb +17 -0
  22. data/lib/aspera/cli/listener/logger.rb +20 -0
  23. data/lib/aspera/cli/listener/progress.rb +52 -0
  24. data/lib/aspera/cli/listener/progress_multi.rb +91 -0
  25. data/lib/aspera/cli/main.rb +304 -0
  26. data/lib/aspera/cli/manager.rb +440 -0
  27. data/lib/aspera/cli/plugin.rb +90 -0
  28. data/lib/aspera/cli/plugins/alee.rb +24 -0
  29. data/lib/aspera/cli/plugins/ats.rb +231 -0
  30. data/lib/aspera/cli/plugins/bss.rb +71 -0
  31. data/lib/aspera/cli/plugins/config.rb +806 -0
  32. data/lib/aspera/cli/plugins/console.rb +62 -0
  33. data/lib/aspera/cli/plugins/cos.rb +106 -0
  34. data/lib/aspera/cli/plugins/faspex.rb +377 -0
  35. data/lib/aspera/cli/plugins/faspex5.rb +93 -0
  36. data/lib/aspera/cli/plugins/node.rb +438 -0
  37. data/lib/aspera/cli/plugins/oncloud.rb +937 -0
  38. data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
  39. data/lib/aspera/cli/plugins/preview.rb +464 -0
  40. data/lib/aspera/cli/plugins/server.rb +216 -0
  41. data/lib/aspera/cli/plugins/shares.rb +63 -0
  42. data/lib/aspera/cli/plugins/shares2.rb +114 -0
  43. data/lib/aspera/cli/plugins/sync.rb +65 -0
  44. data/lib/aspera/cli/plugins/xnode.rb +115 -0
  45. data/lib/aspera/cli/transfer_agent.rb +251 -0
  46. data/lib/aspera/cli/version.rb +5 -0
  47. data/lib/aspera/colors.rb +39 -0
  48. data/lib/aspera/command_line_builder.rb +137 -0
  49. data/lib/aspera/fasp/aoc.rb +24 -0
  50. data/lib/aspera/fasp/connect.rb +99 -0
  51. data/lib/aspera/fasp/error.rb +21 -0
  52. data/lib/aspera/fasp/error_info.rb +60 -0
  53. data/lib/aspera/fasp/http_gw.rb +81 -0
  54. data/lib/aspera/fasp/installation.rb +240 -0
  55. data/lib/aspera/fasp/listener.rb +11 -0
  56. data/lib/aspera/fasp/local.rb +377 -0
  57. data/lib/aspera/fasp/manager.rb +69 -0
  58. data/lib/aspera/fasp/node.rb +88 -0
  59. data/lib/aspera/fasp/parameters.rb +235 -0
  60. data/lib/aspera/fasp/resume_policy.rb +76 -0
  61. data/lib/aspera/fasp/uri.rb +51 -0
  62. data/lib/aspera/faspex_gw.rb +196 -0
  63. data/lib/aspera/hash_ext.rb +28 -0
  64. data/lib/aspera/log.rb +80 -0
  65. data/lib/aspera/nagios.rb +71 -0
  66. data/lib/aspera/node.rb +14 -0
  67. data/lib/aspera/oauth.rb +319 -0
  68. data/lib/aspera/on_cloud.rb +421 -0
  69. data/lib/aspera/open_application.rb +72 -0
  70. data/lib/aspera/persistency_action_once.rb +42 -0
  71. data/lib/aspera/persistency_folder.rb +91 -0
  72. data/lib/aspera/preview/file_types.rb +300 -0
  73. data/lib/aspera/preview/generator.rb +258 -0
  74. data/lib/aspera/preview/image_error.png +0 -0
  75. data/lib/aspera/preview/options.rb +35 -0
  76. data/lib/aspera/preview/utils.rb +131 -0
  77. data/lib/aspera/preview/video_error.png +0 -0
  78. data/lib/aspera/proxy_auto_config.erb.js +287 -0
  79. data/lib/aspera/proxy_auto_config.rb +34 -0
  80. data/lib/aspera/rest.rb +296 -0
  81. data/lib/aspera/rest_call_error.rb +13 -0
  82. data/lib/aspera/rest_error_analyzer.rb +98 -0
  83. data/lib/aspera/rest_errors_aspera.rb +58 -0
  84. data/lib/aspera/ssh.rb +53 -0
  85. data/lib/aspera/sync.rb +82 -0
  86. data/lib/aspera/temp_file_manager.rb +37 -0
  87. data/lib/aspera/uri_reader.rb +25 -0
  88. metadata +288 -0
@@ -0,0 +1,93 @@
1
+ require 'aspera/cli/basic_auth_plugin'
2
+ require 'aspera/persistency_action_once'
3
+
4
+ module Aspera
5
+ module Cli
6
+ module Plugins
7
+ class Faspex5 < BasicAuthPlugin
8
+ VAL_ALL='ALL'
9
+ def initialize(env)
10
+ super(env)
11
+ #self.options.add_opt_simple(:delivery_info,'package delivery information (extended value)')
12
+ #self.options.parse_options!
13
+ end
14
+ ACTIONS=[ :node, :package ]
15
+
16
+ # http://apie-next-ui-shell-dev.mybluemix.net/explorer/catalog/aspera/product/ibm-aspera/api/faspex5-api/spec/openapi
17
+ def execute_action
18
+ # get parameters
19
+ faxpex5_api_base_url=self.options.get_option(:url,:mandatory)
20
+ faxpex5_username=self.options.get_option(:username,:mandatory)
21
+ faxpex5_password=self.options.get_option(:password,:mandatory)
22
+ faxpex5_api_base_url+='/api/v5'
23
+ # create object for REST calls to Shares2
24
+ api_v5=Rest.new({
25
+ :base_url => faxpex5_api_base_url,
26
+ :auth => {
27
+ :type => :oauth2,
28
+ :base_url => faxpex5_api_base_url,
29
+ :grant => :body_data,
30
+ :token_field =>'auth_token',
31
+ :path_token => 'authenticate',
32
+ :path_authorize => :unused,
33
+ :userpass_body => {name: faxpex5_username,password: faxpex5_password}
34
+ }})
35
+ command=self.options.get_next_command(ACTIONS)
36
+ case command
37
+ when :node
38
+ return self.entity_action(api_v5,'nodes',nil,:id,nil,true)
39
+ when :package
40
+ command=self.options.get_next_command([:list,:show,:send,:receive])
41
+ case command
42
+ when :list
43
+ parameters=self.options.get_option(:value,:optional)
44
+ return {:type => :object_list, :data=>api_v5.read('packages',parameters)[:data]['packages']}
45
+ when :show
46
+ id=self.options.get_option(:id,:mandatory)
47
+ return {:type => :single_object, :data=>api_v5.read("packages/#{id}")[:data]}
48
+ when :send
49
+ parameters=self.options.get_option(:value,:mandatory)
50
+ raise CliBadArgument,'package value must be hash, refer to API' unless parameters.is_a?(Hash)
51
+ package=api_v5.create('packages',parameters)[:data]
52
+ transfer_spec=api_v5.create("packages/#{package['id']}/transfer_spec/upload",{transfer_type: 'Connect'})[:data]
53
+ transfer_spec.delete('authentication')
54
+ return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
55
+ when :receive
56
+ pkg_type='received'
57
+ pack_id=self.options.get_option(:id,:mandatory)
58
+ package_ids=[pack_id]
59
+ skip_ids_data=[]
60
+ skip_ids_persistency=nil
61
+ if self.options.get_option(:once_only,:mandatory)
62
+ skip_ids_persistency=PersistencyActionOnce.new(
63
+ manager: @agents[:persistency],
64
+ data: skip_ids_data,
65
+ ids: ['faspex_recv',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),pkg_type])
66
+ end
67
+ if pack_id.eql?(VAL_ALL)
68
+ # todo: if packages have same name, they will overwrite
69
+ parameters=self.options.get_option(:value,:optional)
70
+ parameters||={"type"=>"received","subtype"=>"mypackages","limit"=>1000}
71
+ raise CliBadArgument,'value filter must be hash (API GET)' unless parameters.is_a?(Hash)
72
+ package_ids=api_v5.read('packages',parameters)[:data]['packages'].map{|p|p['id']}
73
+ package_ids.select!{|i|!skip_ids_data.include?(i)}
74
+ end
75
+ result_transfer=[]
76
+ package_ids.each do |id|
77
+ # TODO: allow from sent as well ?
78
+ transfer_spec=api_v5.create("packages/#{id}/transfer_spec/download",{transfer_type: 'Connect', type: pkg_type})[:data]
79
+ transfer_spec.delete('authentication')
80
+ statuses=self.transfer.start(transfer_spec,{:src=>:node_gen3})
81
+ result_transfer.push({'package'=>id,'status'=>statuses.map{|i|i.to_s}.join(',')})
82
+ # skip only if all sessions completed
83
+ skip_ids_data.push(id) if TransferAgent.session_status(statuses).eql?(:success)
84
+ end
85
+ skip_ids_persistency.save unless skip_ids_persistency.nil?
86
+ return {:type=>:object_list,:data=>result_transfer}
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end # Plugins
92
+ end # Cli
93
+ end # Aspera
@@ -0,0 +1,438 @@
1
+ require 'aspera/cli/basic_auth_plugin'
2
+ require 'aspera/nagios'
3
+ require 'aspera/hash_ext'
4
+ require 'base64'
5
+ require 'zlib'
6
+
7
+ module Aspera
8
+ module Cli
9
+ module Plugins
10
+ class Node < BasicAuthPlugin
11
+ SAMPLE_SOAP_CALL='<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="urn:Aspera:XML:FASPSessionNET:2009/11:Types"><soapenv:Header></soapenv:Header><soapenv:Body><typ:GetSessionInfoRequest><SessionFilter><SessionStatus>running</SessionStatus></SessionFilter></typ:GetSessionInfoRequest></soapenv:Body></soapenv:Envelope>'
12
+ private_constant :SAMPLE_SOAP_CALL
13
+ def initialize(env)
14
+ super(env)
15
+ # this is added to some requests , for instance to add tags
16
+ @add_request_param = env[:add_request_param] || {}
17
+ unless env[:skip_basic_auth_options]
18
+ self.options.add_opt_simple(:validator,"identifier of validator (optional for central)")
19
+ self.options.add_opt_simple(:asperabrowserurl,"URL for simple aspera web ui")
20
+ self.options.add_opt_simple(:name,"sync name")
21
+ self.options.add_opt_list(:token,[:aspera,:basic,:auto],'todo: type of token used for transfers')
22
+ self.options.set_option(:asperabrowserurl,'https://asperabrowser.mybluemix.net')
23
+ self.options.set_option(:token,:aspera)
24
+ self.options.parse_options!
25
+ end
26
+ return if env[:man_only]
27
+ if env.has_key?(:node_api)
28
+ @api_node=env[:node_api]
29
+ else
30
+ @api_node=basic_auth_api unless env[:man_only]
31
+ end
32
+ end
33
+
34
+ def c_textify_browse(table_data)
35
+ return table_data.map {|i| i['permissions']=i['permissions'].map { |x| x['name'] }.join(','); i }
36
+ end
37
+
38
+ # key/value is defined in main in hash_table
39
+ def c_textify_bool_list_result(list,name_list)
40
+ list.each_index do |i|
41
+ if name_list.include?(list[i]['key'])
42
+ list[i]['value'].each do |item|
43
+ list.push({'key'=>item['name'],'value'=>item['value']})
44
+ end
45
+ list.delete_at(i)
46
+ # continue at same index because we delete current one
47
+ redo
48
+ end
49
+ end
50
+ end
51
+
52
+ # reduce the path from a result on given named column
53
+ def c_result_remove_prefix_path(result,column,path_prefix)
54
+ if !path_prefix.nil?
55
+ case result[:type]
56
+ when :object_list
57
+ result[:data].each do |item|
58
+ item[column].replace(item[column][path_prefix.length..-1]) if item[column].start_with?(path_prefix)
59
+ end
60
+ when :single_object
61
+ item=result[:data]
62
+ item[column].replace(item[column][path_prefix.length..-1]) if item[column].start_with?(path_prefix)
63
+ end
64
+ end
65
+ return result
66
+ end
67
+
68
+ # translates paths results into CLI result, and removes prefix
69
+ def c_result_translate_rem_prefix(resp,type,success_msg,path_prefix)
70
+ resres={:data=>[],:type=>:object_list,:fields=>[type,'result']}
71
+ JSON.parse(resp[:http].body)['paths'].each do |p|
72
+ result=success_msg
73
+ if p.has_key?('error')
74
+ Log.log.error("#{p['error']['user_message']} : #{p['path']}")
75
+ result="ERROR: "+p['error']['user_message']
76
+ end
77
+ resres[:data].push({type=>p['path'],'result'=>result})
78
+ end
79
+ return c_result_remove_prefix_path(resres,type,path_prefix)
80
+ end
81
+
82
+ # get path arguments from command line, and add prefix
83
+ def get_next_arg_add_prefix(path_prefix,name,number=:single)
84
+ thepath=self.options.get_next_argument(name,number)
85
+ return thepath if path_prefix.nil?
86
+ return File.join(path_prefix,thepath) if thepath.is_a?(String)
87
+ return thepath.map {|p| File.join(path_prefix,p)} if thepath.is_a?(Array)
88
+ raise StandardError,"expect: nil, String or Array"
89
+ end
90
+
91
+ SIMPLE_ACTIONS=[:nagios_check,:events, :space, :info, :license, :mkdir, :mklink, :mkfile, :rename, :delete, :search ]
92
+
93
+ COMMON_ACTIONS=[:browse, :upload, :download, :api_details ].concat(SIMPLE_ACTIONS)
94
+
95
+ # common API to node and Shares
96
+ # prefix_path is used to list remote sources in Faspex
97
+ def execute_simple_common(command,prefix_path)
98
+ case command
99
+ when :nagios_check
100
+ nagios=Nagios.new
101
+ begin
102
+ info=@api_node.read('info')[:data]
103
+ nagios.add_ok('node api','accessible')
104
+ nagios.check_time_offset(info['current_time'],'node api')
105
+ nagios.check_product_version( 'node api','entsrv', info['version'])
106
+ rescue => e
107
+ nagios.add_critical('node api',e.to_s)
108
+ end
109
+ begin
110
+ @api_node.call({:operation=>'POST',:subpath=>'services/soap/Transfer-201210',:headers=>{'Content-Type'=>'text/xml;charset=UTF-8','SOAPAction'=>'FASPSessionNET-200911#GetSessionInfo'},:text_body_params=>SAMPLE_SOAP_CALL})[:http].body
111
+ nagios.add_ok('central','accessible by node')
112
+ rescue => e
113
+ nagios.add_critical('central',e.to_s)
114
+ end
115
+ return nagios.result
116
+ when :events
117
+ events=@api_node.read('events',self.options.get_option(:value,:optional))[:data]
118
+ return { :type=>:object_list, :data => events}
119
+ when :info
120
+ node_info=@api_node.read('info')[:data]
121
+ return { :type=>:single_object, :data => node_info, :textify => lambda { |table_data| c_textify_bool_list_result(table_data,['capabilities','settings'])}}
122
+ when :license # requires: asnodeadmin -mu <node user> --acl-add=internal --internal
123
+ node_license=@api_node.read('license')[:data]
124
+ if node_license['failure'].is_a?(String) and node_license['failure'].include?('ACL')
125
+ Log.log.error("server must have: asnodeadmin -mu <node user> --acl-add=internal --internal")
126
+ end
127
+ return { :type=>:single_object, :data => node_license}
128
+ when :delete
129
+ paths_to_delete = get_next_arg_add_prefix(prefix_path,"file list",:multiple)
130
+ resp=@api_node.create('files/delete',{:paths=>paths_to_delete.map{|i| {'path'=>i.start_with?('/') ? i : '/'+i} }})
131
+ return c_result_translate_rem_prefix(resp,'file','deleted',prefix_path)
132
+ when :search
133
+ search_root = get_next_arg_add_prefix(prefix_path,"search root")
134
+ parameters={'path'=>search_root}
135
+ other_options=self.options.get_option(:value,:optional)
136
+ parameters.merge!(other_options) unless other_options.nil?
137
+ resp=@api_node.create('files/search',parameters)
138
+ result={ :type=>:object_list, :data => resp[:data]['items']}
139
+ return Main.result_empty if result[:data].empty?
140
+ result[:fields]=result[:data].first.keys.select{|i|!['basename','permissions'].include?(i)}
141
+ self.format.display_status("Items: #{resp[:data]['item_count']}/#{resp[:data]['total_count']}")
142
+ self.format.display_status("params: #{resp[:data]['parameters'].keys.map{|k|"#{k}:#{resp[:data]['parameters'][k]}"}.join(',')}")
143
+ return c_result_remove_prefix_path(result,'path',prefix_path)
144
+ when :space
145
+ # TODO: could be a list of path
146
+ path_list=get_next_arg_add_prefix(prefix_path,"folder path or ext.val. list")
147
+ path_list=[path_list] unless path_list.is_a?(Array)
148
+ resp=@api_node.create('space',{ "paths" => path_list.map {|i| {:path=>i} } } )
149
+ result={:data=>resp[:data]['paths'],:type=>:object_list}
150
+ #return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
151
+ return c_result_remove_prefix_path(result,'path',prefix_path)
152
+ when :mkdir
153
+ path_list=get_next_arg_add_prefix(prefix_path,"folder path or ext.val. list")
154
+ path_list=[path_list] unless path_list.is_a?(Array)
155
+ #TODO
156
+ #resp=@api_node.create('space',{ "paths" => path_list.map {|i| {:type=>:directory,:path=>i} } } )
157
+ resp=@api_node.create('files/create',{ "paths" => [{ :type => :directory, :path => path_list } ] } )
158
+ return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
159
+ when :mklink
160
+ target=get_next_arg_add_prefix(prefix_path,"target")
161
+ path_list=get_next_arg_add_prefix(prefix_path,"link path")
162
+ resp=@api_node.create('files/create',{ "paths" => [{ :type => :symbolic_link, :path => path_list, :target => {:path => target} } ] } )
163
+ return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
164
+ when :mkfile
165
+ path_list=get_next_arg_add_prefix(prefix_path,"file path")
166
+ contents64=Base64.strict_encode64(self.options.get_next_argument("contents"))
167
+ resp=@api_node.create('files/create',{ "paths" => [{ :type => :file, :path => path_list, :contents => contents64 } ] } )
168
+ return c_result_translate_rem_prefix(resp,'folder','created',prefix_path)
169
+ when :rename
170
+ path_base=get_next_arg_add_prefix(prefix_path,"path_base")
171
+ path_src=get_next_arg_add_prefix(prefix_path,"path_src")
172
+ path_dst=get_next_arg_add_prefix(prefix_path,"path_dst")
173
+ resp=@api_node.create('files/rename',{ "paths" => [{ "path" => path_base, "source" => path_src, "destination" => path_dst } ] } )
174
+ return c_result_translate_rem_prefix(resp,'entry','moved',prefix_path)
175
+ when :browse
176
+ thepath=get_next_arg_add_prefix(prefix_path,"path")
177
+ query={ :path => thepath}
178
+ additional_query=self.options.get_option(:query,:optional)
179
+ query.merge!(additional_query) unless additional_query.nil?
180
+ send_result=@api_node.create('files/browse', query)[:data]
181
+ #example: send_result={'items'=>[{'file'=>"filename1","permissions"=>[{'name'=>'read'},{'name'=>'write'}]}]}
182
+ # if there is no items
183
+ case send_result['self']['type']
184
+ when 'directory','container' # directory: node, container: shares
185
+ result={ :data => send_result['items'] , :type => :object_list, :textify => lambda { |table_data| c_textify_browse(table_data) } }
186
+ self.format.display_status("Items: #{send_result['item_count']}/#{send_result['total_count']}")
187
+ else # 'file','symbolic_link'
188
+ result={ :data => send_result['self'] , :type => :single_object}
189
+ #result={ :data => [send_result['self']] , :type => :object_list, :textify => lambda { |table_data| c_textify_browse(table_data) } }
190
+ #raise "unknown type: #{send_result['self']['type']}"
191
+ end
192
+ return c_result_remove_prefix_path(result,'path',prefix_path)
193
+ when :upload
194
+ # we send only a list of one transfer request
195
+ transfer_request = { :paths => [ { :destination => self.transfer.destination_folder('send') } ] }
196
+ transfer_request.deep_merge!(@add_request_param)
197
+ send_result=@api_node.create('files/upload_setup',{:transfer_requests => [ { :transfer_request => transfer_request } ] } )[:data]
198
+ # only one request, so only one answer
199
+ transfer_spec=send_result['transfer_specs'].first['transfer_spec']
200
+ # delete this part, as the returned value contains only destination, and not sources
201
+ transfer_spec.delete('paths')
202
+ return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
203
+ when :download
204
+ transfer_request = {:paths => self.transfer.ts_source_paths }
205
+ transfer_request.deep_merge!(@add_request_param)
206
+ send_result=@api_node.create('files/download_setup',{:transfer_requests => [ { :transfer_request => transfer_request } ] } )[:data]
207
+ # only one request, so only one answer
208
+ transfer_spec=send_result['transfer_specs'].first['transfer_spec']
209
+ return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
210
+ when :api_details
211
+ return { :type=>:single_object, :data => @api_node.params }
212
+ end
213
+ end
214
+
215
+ def execute_async
216
+ command=self.options.get_next_command([:list,:delete,:files,:show,:counters,:bandwidth])
217
+ unless command.eql?(:list)
218
+ asyncname=self.options.get_option(:name,:optional)
219
+ if asyncname.nil?
220
+ asyncid=self.options.get_option(:id,:mandatory)
221
+ if asyncid.eql?('ALL') and [:show,:delete].include?(command)
222
+ asyncids=@api_node.read('async/list')[:data]['sync_ids']
223
+ else
224
+ Integer(asyncid) # must be integer
225
+ asyncids=[asyncid]
226
+ end
227
+ else
228
+ asyncids=@api_node.read('async/list')[:data]['sync_ids']
229
+ summaries=@api_node.create('async/summary',{'syncs' => asyncids})[:data]['sync_summaries']
230
+ selected=summaries.select{|s|s['name'].eql?(asyncname)}.first
231
+ raise "no such sync: #{asyncname}" if selected.nil?
232
+ asyncid=selected['snid']
233
+ asyncids=[asyncid]
234
+ end
235
+ pdata={'syncs' => asyncids}
236
+ end
237
+ case command
238
+ when :list
239
+ resp=@api_node.read('async/list')[:data]['sync_ids']
240
+ return { :type => :value_list, :data => resp, :name=>'id' }
241
+ when :show
242
+ resp=@api_node.create('async/summary',pdata)[:data]['sync_summaries']
243
+ return Main.result_empty if resp.empty?
244
+ if asyncid.eql?('ALL')
245
+ return { :type => :object_list, :data => resp, :fields => ['snid','name','local_dir','remote_dir'] }
246
+ else
247
+ return { :type => :single_object, :data => resp.first }
248
+ end
249
+ when :delete
250
+ resp=@api_node.create('async/delete',pdata)[:data]
251
+ return { :type => :single_object, :data => resp, :name=>'id' }
252
+ when :bandwidth
253
+ pdata['seconds']=100 # TODO: as parameter with --value
254
+ resp=@api_node.create('async/bandwidth',pdata)[:data]
255
+ data=resp['bandwidth_data']
256
+ return Main.result_empty if data.empty?
257
+ data=data.first[asyncid]['data']
258
+ return { :type => :object_list, :data => data, :name=>'id' }
259
+ when :files
260
+ # count int
261
+ # filename str
262
+ # skip int
263
+ # status int
264
+ filter=self.options.get_option(:value,:optional)
265
+ pdata.merge!(filter) unless filter.nil?
266
+ resp=@api_node.create('async/files',pdata)[:data]
267
+ data=resp['sync_files']
268
+ data=data.first[asyncid] unless data.empty?
269
+ iteration_data=[]
270
+ skip_ids_persistency=nil
271
+ if self.options.get_option(:once_only,:mandatory)
272
+ skip_ids_persistency=PersistencyActionOnce.new(
273
+ manager: @agents[:persistency],
274
+ data: iteration_data,
275
+ ids: ['sync_files',self.options.get_option(:url,:mandatory),self.options.get_option(:username,:mandatory),asyncid])
276
+ unless iteration_data.first.nil?
277
+ data.select!{|l| l['fnid'].to_i>iteration_data.first}
278
+ end
279
+ iteration_data[0]=data.last['fnid'].to_i unless data.empty?
280
+ end
281
+ return Main.result_empty if data.empty?
282
+ skip_ids_persistency.save unless skip_ids_persistency.nil?
283
+ return { :type => :object_list, :data => data, :name=>'id' }
284
+ when :counters
285
+ resp=@api_node.create('async/counters',pdata)[:data]["sync_counters"].first[asyncid].last
286
+ return Main.result_empty if resp.nil?
287
+ return { :type => :single_object, :data => resp }
288
+ end
289
+ end
290
+
291
+ ACTIONS=[ :postprocess,:stream, :transfer, :cleanup, :forward, :access_key, :watch_folder, :service, :async, :central, :asperabrowser, :basic_token ].concat(COMMON_ACTIONS)
292
+
293
+ def execute_action(command=nil,prefix_path=nil)
294
+ command||=self.options.get_next_command(ACTIONS)
295
+ case command
296
+ when *COMMON_ACTIONS; return execute_simple_common(command,prefix_path)
297
+ when :async; return execute_async()
298
+ when :stream
299
+ command=self.options.get_next_command([ :list, :create, :show, :modify, :cancel ])
300
+ case command
301
+ when :list
302
+ resp=@api_node.read('ops/transfers',self.options.get_option(:value,:optional))
303
+ return { :type => :object_list, :data => resp[:data], :fields=>['id','status'] } # TODO
304
+ when :create
305
+ resp=@api_node.create('streams',self.options.get_option(:value,:mandatory))
306
+ return { :type => :single_object, :data => resp[:data] }
307
+ when :show
308
+ trid=self.options.get_next_argument("transfer id")
309
+ resp=@api_node.read('ops/transfers/'+trid)
310
+ return { :type=>:other_struct, :data => resp[:data] }
311
+ when :modify
312
+ trid=self.options.get_next_argument("transfer id")
313
+ resp=@api_node.update('streams/'+trid,self.options.get_option(:value,:mandatory))
314
+ return { :type=>:other_struct, :data => resp[:data] }
315
+ when :cancel
316
+ trid=self.options.get_next_argument("transfer id")
317
+ resp=@api_node.cancel('streams/'+trid)
318
+ return { :type=>:other_struct, :data => resp[:data] }
319
+ else
320
+ raise "error"
321
+ end
322
+ when :transfer
323
+ command=self.options.get_next_command([ :list, :cancel, :show ])
324
+ res_class_path='ops/transfers'
325
+ if [:cancel, :show].include?(command)
326
+ one_res_id=self.options.get_option(:id,:mandatory)
327
+ one_res_path="#{res_class_path}/#{one_res_id}"
328
+ end
329
+ case command
330
+ when :list
331
+ # could use ? :subpath=>'transfers'
332
+ resp=@api_node.read(res_class_path,self.options.get_option(:value,:optional))
333
+ return { :type => :object_list, :data => resp[:data], :fields=>['id','status','start_spec.direction','start_spec.remote_user','start_spec.remote_host','start_spec.destination_path']}
334
+ when :cancel
335
+ resp=@api_node.cancel(one_res_path)
336
+ return { :type=>:other_struct, :data => resp[:data] }
337
+ when :show
338
+ resp=@api_node.read(one_res_path)
339
+ return { :type=>:other_struct, :data => resp[:data] }
340
+ else
341
+ raise "error"
342
+ end
343
+ when :access_key
344
+ return self.entity_action(@api_node,'access_keys',['id','root_file_id','storage'],:id,'self')
345
+ when :service
346
+ command=self.options.get_next_command([ :list, :create, :delete])
347
+ if [:delete].include?(command)
348
+ svcid=self.options.get_option(:id,:mandatory)
349
+ end
350
+ case command
351
+ when :list
352
+ resp=@api_node.read('rund/services')
353
+ return { :type=>:object_list, :data => resp[:data]["services"] }
354
+ when :create
355
+ # @json:'{"type":"WATCHFOLDERD","run_as":{"user":"user1"}}'
356
+ params=self.options.get_next_argument("Run creation data (structure)")
357
+ resp=@api_node.create('rund/services',params)
358
+ return Main.result_status("#{resp[:data]['id']} created")
359
+ when :delete
360
+ resp=@api_node.delete("rund/services/#{svcid}")
361
+ return Main.result_status("#{svcid} deleted")
362
+ end
363
+ when :watch_folder
364
+ res_class_path='v3/watchfolders'
365
+ #return entity_action(@api_node,'v3/watchfolders',nil,:id)
366
+ command=self.options.get_next_command([ :create, :list, :show, :modify, :delete, :state])
367
+ if [:show,:modify,:delete,:state].include?(command)
368
+ one_res_id=self.options.get_option(:id,:mandatory)
369
+ one_res_path="#{res_class_path}/#{one_res_id}"
370
+ end
371
+ # hum, to avoid: Unable to convert 2016_09_14 configuration
372
+ @api_node.params[:headers]||={}
373
+ @api_node.params[:headers]['X-aspera-WF-version']='2017_10_23'
374
+ case command
375
+ when :create
376
+ resp=@api_node.create(res_class_path,self.options.get_option(:value,:mandatory))
377
+ return Main.result_status("#{resp[:data]['id']} created")
378
+ when :list
379
+ resp=@api_node.read(res_class_path,self.options.get_option(:value,:optional))
380
+ return { :type=>:value_list, :data => resp[:data]['ids'], :name=>'id' }
381
+ when :show
382
+ return {:type=>:single_object, :data=>@api_node.read(one_res_path)[:data]}
383
+ when :modify
384
+ @api_node.update(one_res_path,self.options.get_option(:value,:mandatory))
385
+ return Main.result_status("#{one_res_id} updated")
386
+ when :delete
387
+ @api_node.delete(one_res_path)
388
+ return Main.result_status("#{one_res_id} deleted")
389
+ when :state
390
+ return { :type=>:single_object, :data => @api_node.read("#{one_res_path}/state")[:data] }
391
+ end
392
+ when :central
393
+ command=self.options.get_next_command([ :session,:file])
394
+ validator_id=self.options.get_option(:validator)
395
+ validation={"validator_id"=>validator_id} unless validator_id.nil?
396
+ request_data=self.options.get_option(:value,:optional)
397
+ request_data||={}
398
+ case command
399
+ when :session
400
+ command=self.options.get_next_command([ :list])
401
+ case command
402
+ when :list
403
+ request_data.deep_merge!({"validation"=>validation}) unless validation.nil?
404
+ resp=@api_node.create('services/rest/transfers/v1/sessions',request_data)
405
+ return {:type=>:object_list,:data=>resp[:data]["session_info_result"]["session_info"],:fields=>["session_uuid","status","transport","direction","bytes_transferred"]}
406
+ end
407
+ when :file
408
+ command=self.options.get_next_command([ :list, :modify])
409
+ case command
410
+ when :list
411
+ request_data.deep_merge!({"validation"=>validation}) unless validation.nil?
412
+ resp=@api_node.create('services/rest/transfers/v1/files',request_data)
413
+ return {:type=>:object_list,:data=>resp[:data]["file_transfer_info_result"]["file_transfer_info"],:fields=>["session_uuid","file_id","status","path"]}
414
+ when :modify
415
+ request_data.deep_merge!(validation) unless validation.nil?
416
+ @api_node.update('services/rest/transfers/v1/files',request_data)
417
+ return Main.result_status('updated')
418
+ end
419
+ end
420
+ when :asperabrowser
421
+ browse_params={
422
+ 'nodeUser' => self.options.get_option(:username,:mandatory),
423
+ 'nodePW' => self.options.get_option(:password,:mandatory),
424
+ 'nodeURL' => self.options.get_option(:url,:mandatory)
425
+ }
426
+ # encode parameters so that it looks good in url
427
+ encoded_params=Base64.strict_encode64(Zlib::Deflate.deflate(JSON.generate(browse_params))).gsub(/=+$/, '').tr('+/', '-_').reverse
428
+ OpenApplication.instance.uri(self.options.get_option(:asperabrowserurl)+'?goto='+encoded_params)
429
+ return Main.result_status('done')
430
+ when :basic_token
431
+ return Main.result_status("Basic "+Base64.strict_encode64("#{self.options.get_option(:username,:mandatory)}:#{self.options.get_option(:password,:mandatory)}"))
432
+ end # case command
433
+ raise "ERROR: shall not reach this line"
434
+ end # execute_action
435
+ end # Main
436
+ end # Plugin
437
+ end # Cli
438
+ end # Aspera