aspera-cli 4.0.0.pre1
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.
- checksums.yaml +7 -0
- data/README.md +3592 -0
- data/bin/ascli +7 -0
- data/bin/asession +89 -0
- data/docs/Makefile +59 -0
- data/docs/README.erb.md +3012 -0
- data/docs/README.md +13 -0
- data/docs/diagrams.txt +49 -0
- data/docs/secrets.make +38 -0
- data/docs/test_env.conf +117 -0
- data/docs/transfer_spec.html +99 -0
- data/examples/aoc.rb +17 -0
- data/examples/proxy.pac +60 -0
- data/examples/transfer.rb +115 -0
- data/lib/aspera/api_detector.rb +60 -0
- data/lib/aspera/ascmd.rb +151 -0
- data/lib/aspera/ats_api.rb +43 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
- data/lib/aspera/cli/extended_value.rb +88 -0
- data/lib/aspera/cli/formater.rb +238 -0
- data/lib/aspera/cli/listener/line_dump.rb +17 -0
- data/lib/aspera/cli/listener/logger.rb +20 -0
- data/lib/aspera/cli/listener/progress.rb +52 -0
- data/lib/aspera/cli/listener/progress_multi.rb +91 -0
- data/lib/aspera/cli/main.rb +304 -0
- data/lib/aspera/cli/manager.rb +440 -0
- data/lib/aspera/cli/plugin.rb +90 -0
- data/lib/aspera/cli/plugins/alee.rb +24 -0
- data/lib/aspera/cli/plugins/ats.rb +231 -0
- data/lib/aspera/cli/plugins/bss.rb +71 -0
- data/lib/aspera/cli/plugins/config.rb +806 -0
- data/lib/aspera/cli/plugins/console.rb +62 -0
- data/lib/aspera/cli/plugins/cos.rb +106 -0
- data/lib/aspera/cli/plugins/faspex.rb +377 -0
- data/lib/aspera/cli/plugins/faspex5.rb +93 -0
- data/lib/aspera/cli/plugins/node.rb +438 -0
- data/lib/aspera/cli/plugins/oncloud.rb +937 -0
- data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
- data/lib/aspera/cli/plugins/preview.rb +464 -0
- data/lib/aspera/cli/plugins/server.rb +216 -0
- data/lib/aspera/cli/plugins/shares.rb +63 -0
- data/lib/aspera/cli/plugins/shares2.rb +114 -0
- data/lib/aspera/cli/plugins/sync.rb +65 -0
- data/lib/aspera/cli/plugins/xnode.rb +115 -0
- data/lib/aspera/cli/transfer_agent.rb +251 -0
- data/lib/aspera/cli/version.rb +5 -0
- data/lib/aspera/colors.rb +39 -0
- data/lib/aspera/command_line_builder.rb +137 -0
- data/lib/aspera/fasp/aoc.rb +24 -0
- data/lib/aspera/fasp/connect.rb +99 -0
- data/lib/aspera/fasp/error.rb +21 -0
- data/lib/aspera/fasp/error_info.rb +60 -0
- data/lib/aspera/fasp/http_gw.rb +81 -0
- data/lib/aspera/fasp/installation.rb +240 -0
- data/lib/aspera/fasp/listener.rb +11 -0
- data/lib/aspera/fasp/local.rb +377 -0
- data/lib/aspera/fasp/manager.rb +69 -0
- data/lib/aspera/fasp/node.rb +88 -0
- data/lib/aspera/fasp/parameters.rb +235 -0
- data/lib/aspera/fasp/resume_policy.rb +76 -0
- data/lib/aspera/fasp/uri.rb +51 -0
- data/lib/aspera/faspex_gw.rb +196 -0
- data/lib/aspera/hash_ext.rb +28 -0
- data/lib/aspera/log.rb +80 -0
- data/lib/aspera/nagios.rb +71 -0
- data/lib/aspera/node.rb +14 -0
- data/lib/aspera/oauth.rb +319 -0
- data/lib/aspera/on_cloud.rb +421 -0
- data/lib/aspera/open_application.rb +72 -0
- data/lib/aspera/persistency_action_once.rb +42 -0
- data/lib/aspera/persistency_folder.rb +91 -0
- data/lib/aspera/preview/file_types.rb +300 -0
- data/lib/aspera/preview/generator.rb +258 -0
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +35 -0
- data/lib/aspera/preview/utils.rb +131 -0
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.erb.js +287 -0
- data/lib/aspera/proxy_auto_config.rb +34 -0
- data/lib/aspera/rest.rb +296 -0
- data/lib/aspera/rest_call_error.rb +13 -0
- data/lib/aspera/rest_error_analyzer.rb +98 -0
- data/lib/aspera/rest_errors_aspera.rb +58 -0
- data/lib/aspera/ssh.rb +53 -0
- data/lib/aspera/sync.rb +82 -0
- data/lib/aspera/temp_file_manager.rb +37 -0
- data/lib/aspera/uri_reader.rb +25 -0
- 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
|