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