aspera-cli 4.14.0 → 4.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/BUGS.md +29 -3
- data/CHANGELOG.md +300 -185
- data/CONTRIBUTING.md +74 -23
- data/README.md +2346 -1619
- data/bin/ascli +16 -25
- data/bin/asession +15 -15
- data/examples/dascli +2 -2
- data/examples/proxy.pac +1 -1
- data/lib/aspera/aoc.rb +216 -150
- data/lib/aspera/ascmd.rb +25 -18
- data/lib/aspera/assert.rb +45 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +9 -6
- data/lib/aspera/cli/error.rb +17 -0
- data/lib/aspera/cli/extended_value.rb +51 -16
- data/lib/aspera/cli/formatter.rb +276 -174
- data/lib/aspera/cli/hints.rb +81 -0
- data/lib/aspera/cli/main.rb +114 -147
- data/lib/aspera/cli/manager.rb +181 -136
- data/lib/aspera/cli/plugin.rb +82 -64
- data/lib/aspera/cli/plugins/alee.rb +0 -1
- data/lib/aspera/cli/plugins/aoc.rb +327 -331
- data/lib/aspera/cli/plugins/ats.rb +12 -8
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +575 -439
- data/lib/aspera/cli/plugins/console.rb +40 -0
- data/lib/aspera/cli/plugins/cos.rb +4 -5
- data/lib/aspera/cli/plugins/faspex.rb +111 -92
- data/lib/aspera/cli/plugins/faspex5.rb +245 -182
- data/lib/aspera/cli/plugins/node.rb +239 -160
- data/lib/aspera/cli/plugins/orchestrator.rb +56 -19
- data/lib/aspera/cli/plugins/preview.rb +54 -38
- data/lib/aspera/cli/plugins/server.rb +63 -20
- data/lib/aspera/cli/plugins/shares.rb +64 -38
- data/lib/aspera/cli/sync_actions.rb +68 -0
- data/lib/aspera/cli/transfer_agent.rb +64 -67
- data/lib/aspera/cli/transfer_progress.rb +73 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -1
- data/lib/aspera/command_line_builder.rb +27 -22
- data/lib/aspera/cos_node.rb +6 -4
- data/lib/aspera/coverage.rb +22 -0
- data/lib/aspera/data_repository.rb +33 -2
- data/lib/aspera/environment.rb +21 -8
- data/lib/aspera/fasp/agent_alpha.rb +116 -0
- data/lib/aspera/fasp/agent_base.rb +40 -76
- data/lib/aspera/fasp/agent_connect.rb +21 -22
- data/lib/aspera/fasp/agent_direct.rb +169 -179
- data/lib/aspera/fasp/agent_httpgw.rb +200 -195
- data/lib/aspera/fasp/agent_node.rb +43 -35
- data/lib/aspera/fasp/agent_trsdk.rb +124 -41
- data/lib/aspera/fasp/error_info.rb +2 -2
- data/lib/aspera/fasp/faux_file.rb +52 -0
- data/lib/aspera/fasp/installation.rb +89 -191
- data/lib/aspera/fasp/management.rb +249 -0
- data/lib/aspera/fasp/parameters.rb +86 -47
- data/lib/aspera/fasp/parameters.yaml +75 -8
- data/lib/aspera/fasp/products.rb +162 -0
- data/lib/aspera/fasp/resume_policy.rb +7 -5
- data/lib/aspera/fasp/sync.rb +273 -0
- data/lib/aspera/fasp/transfer_spec.rb +10 -8
- data/lib/aspera/fasp/uri.rb +6 -6
- data/lib/aspera/faspex_gw.rb +11 -8
- data/lib/aspera/faspex_postproc.rb +8 -7
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/id_generator.rb +3 -1
- data/lib/aspera/json_rpc.rb +51 -0
- data/lib/aspera/keychain/encrypted_hash.rb +46 -11
- data/lib/aspera/keychain/macos_security.rb +15 -13
- data/lib/aspera/line_logger.rb +23 -0
- data/lib/aspera/log.rb +61 -19
- data/lib/aspera/nagios.rb +7 -2
- data/lib/aspera/node.rb +105 -21
- data/lib/aspera/node_simulator.rb +214 -0
- data/lib/aspera/oauth.rb +57 -36
- data/lib/aspera/open_application.rb +4 -4
- data/lib/aspera/persistency_action_once.rb +13 -14
- data/lib/aspera/persistency_folder.rb +5 -4
- data/lib/aspera/preview/file_types.rb +56 -268
- data/lib/aspera/preview/generator.rb +28 -39
- data/lib/aspera/preview/options.rb +2 -0
- data/lib/aspera/preview/terminal.rb +36 -16
- data/lib/aspera/preview/utils.rb +23 -29
- data/lib/aspera/proxy_auto_config.rb +6 -3
- data/lib/aspera/rest.rb +127 -80
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +16 -14
- data/lib/aspera/rest_errors_aspera.rb +39 -34
- data/lib/aspera/secret_hider.rb +18 -17
- data/lib/aspera/ssh.rb +10 -5
- data/lib/aspera/temp_file_manager.rb +11 -4
- data/lib/aspera/web_auth.rb +10 -7
- data/lib/aspera/web_server_simple.rb +11 -5
- data.tar.gz.sig +0 -0
- metadata +108 -39
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/listener/line_dump.rb +0 -19
- data/lib/aspera/cli/listener/logger.rb +0 -22
- data/lib/aspera/cli/listener/progress.rb +0 -50
- data/lib/aspera/cli/listener/progress_multi.rb +0 -84
- data/lib/aspera/cli/plugins/sync.rb +0 -44
- data/lib/aspera/fasp/listener.rb +0 -13
- data/lib/aspera/sync.rb +0 -213
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require 'singleton'
|
5
|
-
require 'aspera/log'
|
3
|
+
# cspell:ignore protobuf ckpt
|
6
4
|
require 'aspera/environment'
|
7
5
|
require 'aspera/data_repository'
|
6
|
+
require 'aspera/fasp/products'
|
7
|
+
require 'aspera/log'
|
8
|
+
require 'aspera/assert'
|
9
|
+
require 'aspera/web_server_simple'
|
10
|
+
require 'English'
|
11
|
+
require 'singleton'
|
8
12
|
require 'xmlsimple'
|
9
13
|
require 'zlib'
|
10
14
|
require 'base64'
|
@@ -13,24 +17,18 @@ require 'openssl'
|
|
13
17
|
|
14
18
|
module Aspera
|
15
19
|
module Fasp
|
16
|
-
# Singleton that tells where to find ascp and other local resources (keys..) , using the "path(
|
20
|
+
# Singleton that tells where to find ascp and other local resources (keys..) , using the "path(:name)" method.
|
17
21
|
# It is used by object : AgentDirect to find necessary resources
|
18
|
-
# By default it takes the first Aspera product found
|
22
|
+
# By default it takes the first Aspera product found
|
19
23
|
# but the user can specify ascp location by calling:
|
20
24
|
# Installation.instance.use_ascp_from_product(product_name)
|
21
25
|
# or
|
22
26
|
# Installation.instance.ascp_path=""
|
23
27
|
class Installation
|
24
28
|
include Singleton
|
25
|
-
# known product names
|
26
|
-
PRODUCT_CONNECT = 'Aspera Connect'
|
27
|
-
PRODUCT_CLI_V1 = 'Aspera CLI'
|
28
|
-
PRODUCT_DRIVE = 'Aspera Drive'
|
29
|
-
PRODUCT_ENTSRV = 'Enterprise Server'
|
30
29
|
# protobuf generated files from sdk
|
31
30
|
EXT_RUBY_PROTOBUF = '_pb.rb'
|
32
31
|
RB_SDK_FOLDER = 'lib'
|
33
|
-
ONE_YEAR_SECONDS = 365 * 24 * 60 * 60
|
34
32
|
DEFAULT_ASPERA_CONF = <<~END_OF_CONFIG_FILE
|
35
33
|
<?xml version='1.0' encoding='UTF-8'?>
|
36
34
|
<CONF version="2">
|
@@ -42,9 +40,9 @@ module Aspera
|
|
42
40
|
</default>
|
43
41
|
</CONF>
|
44
42
|
END_OF_CONFIG_FILE
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
# all ascp files (in SDK)
|
44
|
+
FILES = %i[ascp ascp4 transferd ssh_private_dsa ssh_private_rsa aspera_license aspera_conf fallback_certificate fallback_private_key].freeze
|
45
|
+
private_constant :EXT_RUBY_PROTOBUF, :RB_SDK_FOLDER, :DEFAULT_ASPERA_CONF, :FILES
|
48
46
|
# set ascp executable path
|
49
47
|
def ascp_path=(v)
|
50
48
|
@path_to_ascp = v
|
@@ -56,7 +54,7 @@ module Aspera
|
|
56
54
|
|
57
55
|
def sdk_ruby_folder
|
58
56
|
ruby_pb_folder = File.join(sdk_folder, RB_SDK_FOLDER)
|
59
|
-
FileUtils.mkdir_p(ruby_pb_folder)
|
57
|
+
FileUtils.mkdir_p(ruby_pb_folder)
|
60
58
|
return ruby_pb_folder
|
61
59
|
end
|
62
60
|
|
@@ -73,61 +71,36 @@ module Aspera
|
|
73
71
|
# @return the path to folder where SDK is installed
|
74
72
|
def sdk_folder
|
75
73
|
raise 'SDK path was ot initialized' if @sdk_dir.nil?
|
76
|
-
FileUtils.mkdir_p(@sdk_dir)
|
74
|
+
FileUtils.mkdir_p(@sdk_dir)
|
77
75
|
@sdk_dir
|
78
76
|
end
|
79
77
|
|
80
78
|
# find ascp in named product (use value : FIRST_FOUND='FIRST' to just use first one)
|
81
|
-
# or select one from installed_products()
|
79
|
+
# or select one from Products.installed_products()
|
82
80
|
def use_ascp_from_product(product_name)
|
83
81
|
if product_name.eql?(FIRST_FOUND)
|
84
|
-
pl = installed_products.first
|
82
|
+
pl = Products.installed_products.first
|
85
83
|
raise "no FASP installation found\nPlease check manual on how to install FASP." if pl.nil?
|
86
84
|
else
|
87
|
-
pl = installed_products.find{|i|i[:name].eql?(product_name)}
|
85
|
+
pl = Products.installed_products.find{|i|i[:name].eql?(product_name)}
|
88
86
|
raise "no such product installed: #{product_name}" if pl.nil?
|
89
87
|
end
|
90
88
|
self.ascp_path = pl[:ascp_path]
|
91
89
|
Log.log.debug{"ascp_path=#{@path_to_ascp}"}
|
92
90
|
end
|
93
91
|
|
94
|
-
# @return
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
sub_bin: ''
|
103
|
-
})
|
104
|
-
# search installed products: with ascp
|
105
|
-
@found_products = scan_locations.select! do |item|
|
106
|
-
# skip if not main folder
|
107
|
-
next false unless Dir.exist?(item[:app_root])
|
108
|
-
Log.log.debug{"Found #{item[:app_root]}"}
|
109
|
-
sub_bin = item[:sub_bin] || BIN_SUBFOLDER
|
110
|
-
item[:ascp_path] = File.join(item[:app_root], sub_bin, ascp_filename)
|
111
|
-
# skip if no ascp
|
112
|
-
next false unless File.exist?(item[:ascp_path])
|
113
|
-
# read info from product info file if present
|
114
|
-
product_info_file = "#{item[:app_root]}/#{PRODUCT_INFO}"
|
115
|
-
if File.exist?(product_info_file)
|
116
|
-
res_s = XmlSimple.xml_in(File.read(product_info_file), {'ForceArray' => false})
|
117
|
-
item[:name] = res_s['name']
|
118
|
-
item[:version] = res_s['version']
|
119
|
-
else
|
120
|
-
item[:name] = item[:expected]
|
92
|
+
# @return [Hash] with key = file name (String), and value = path to file
|
93
|
+
def file_paths
|
94
|
+
return FILES.each_with_object({}) do |v, m|
|
95
|
+
m[v.to_s] =
|
96
|
+
begin
|
97
|
+
path(v)
|
98
|
+
rescue => e
|
99
|
+
e.message
|
121
100
|
end
|
122
|
-
true # select this version
|
123
|
-
end
|
124
101
|
end
|
125
|
-
return @found_products
|
126
102
|
end
|
127
103
|
|
128
|
-
# all ascp files (in SDK)
|
129
|
-
FILES = %i[ascp ascp4 ssh_bypass_dsa_privkey ssh_bypass_rsa_privkey aspera_license aspera_conf fallback_certificate fallback_cert_privkey].freeze
|
130
|
-
|
131
104
|
def check_or_create_sdk_file(filename, force: false, &block)
|
132
105
|
return Environment.write_file_restricted(File.join(sdk_folder, filename), force: force, mode: 0o644, &block)
|
133
106
|
end
|
@@ -135,6 +108,7 @@ module Aspera
|
|
135
108
|
# get path of one resource file of currently activated product
|
136
109
|
# keys and certs are generated locally... (they are well known values, arch. independent)
|
137
110
|
def path(k)
|
111
|
+
file_is_optional = false
|
138
112
|
case k
|
139
113
|
when :ascp, :ascp4
|
140
114
|
use_ascp_from_product(FIRST_FOUND) if @path_to_ascp.nil?
|
@@ -143,69 +117,42 @@ module Aspera
|
|
143
117
|
file = file.gsub('ascp', 'ascp4') if k.eql?(:ascp4)
|
144
118
|
when :transferd
|
145
119
|
file = transferd_filepath
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
120
|
+
file_is_optional = true
|
121
|
+
when :ssh_private_dsa, :ssh_private_rsa
|
122
|
+
# assume last 3 letters are type
|
123
|
+
type = k.to_s[-3..-1].to_sym
|
124
|
+
file = check_or_create_sdk_file("aspera_bypass_#{type}.pem") {DataRepository.instance.item(type)}
|
150
125
|
when :aspera_license
|
151
|
-
file = check_or_create_sdk_file('aspera-license')
|
152
|
-
Zlib::Inflate.inflate(DataRepository.instance.data(6))
|
153
|
-
end
|
126
|
+
file = check_or_create_sdk_file('aspera-license') {DataRepository.instance.item(:license)}
|
154
127
|
when :aspera_conf
|
155
128
|
file = check_or_create_sdk_file('aspera.conf') {DEFAULT_ASPERA_CONF}
|
156
|
-
when :fallback_certificate, :
|
129
|
+
when :fallback_certificate, :fallback_private_key
|
157
130
|
file_key = File.join(sdk_folder, 'aspera_fallback_cert_private_key.pem')
|
158
131
|
file_cert = File.join(sdk_folder, 'aspera_fallback_cert.pem')
|
159
132
|
if !File.exist?(file_key) || !File.exist?(file_cert)
|
160
133
|
require 'openssl'
|
161
134
|
# create new self signed certificate for http fallback
|
162
|
-
private_key = OpenSSL::PKey::RSA.new(1024)
|
163
135
|
cert = OpenSSL::X509::Certificate.new
|
164
|
-
|
165
|
-
cert
|
166
|
-
cert.not_after = Time.now + ONE_YEAR_SECONDS
|
167
|
-
cert.public_key = private_key.public_key
|
168
|
-
cert.serial = 0x0
|
169
|
-
cert.version = 2
|
170
|
-
cert.sign(private_key, OpenSSL::Digest.new('SHA1'))
|
136
|
+
private_key = OpenSSL::PKey::RSA.new(4096)
|
137
|
+
WebServerSimple.fill_self_signed_cert(cert, private_key)
|
171
138
|
check_or_create_sdk_file('aspera_fallback_cert_private_key.pem', force: true) {private_key.to_pem}
|
172
139
|
check_or_create_sdk_file('aspera_fallback_cert.pem', force: true) {cert.to_pem}
|
173
140
|
end
|
174
141
|
file = k.eql?(:fallback_certificate) ? file_cert : file_key
|
175
|
-
else
|
176
|
-
raise "INTERNAL ERROR: #{k}"
|
142
|
+
else error_unexpected_value(k)
|
177
143
|
end
|
178
|
-
|
144
|
+
return nil if file_is_optional && !File.exist?(file)
|
145
|
+
assert(File.exist?(file)){"no such file: #{file}"}
|
179
146
|
return file
|
180
147
|
end
|
181
148
|
|
182
|
-
# @return the file path of local connect where API's URI can be read
|
183
|
-
def connect_uri
|
184
|
-
connect = get_product_folders(PRODUCT_CONNECT)
|
185
|
-
folder = File.join(connect[:run_root], VAR_RUN_SUBFOLDER)
|
186
|
-
['', 's'].each do |ext|
|
187
|
-
uri_file = File.join(folder, "http#{ext}.uri")
|
188
|
-
Log.log.debug{"checking connect port file: #{uri_file}"}
|
189
|
-
if File.exist?(uri_file)
|
190
|
-
return File.open(uri_file, &:gets).strip
|
191
|
-
end
|
192
|
-
end
|
193
|
-
raise "no connect uri file found in #{folder}"
|
194
|
-
end
|
195
|
-
|
196
|
-
# @ return path to configuration file of aspera CLI
|
197
|
-
def cli_conf_file
|
198
|
-
connect = get_product_folders(PRODUCT_CLI_V1)
|
199
|
-
return File.join(connect[:app_root], BIN_SUBFOLDER, '.aspera_cli_conf')
|
200
|
-
end
|
201
|
-
|
202
149
|
# default bypass key phrase
|
203
|
-
def
|
204
|
-
return
|
150
|
+
def ssh_cert_uuid
|
151
|
+
return DataRepository.instance.item(:uuid)
|
205
152
|
end
|
206
153
|
|
207
|
-
def
|
208
|
-
return %i[
|
154
|
+
def aspera_token_ssh_key_paths
|
155
|
+
return %i[ssh_private_dsa ssh_private_rsa].map{|i|Installation.instance.path(i)}
|
209
156
|
end
|
210
157
|
|
211
158
|
# use in plugin `config`
|
@@ -226,6 +173,47 @@ module Aspera
|
|
226
173
|
return exe_version
|
227
174
|
end
|
228
175
|
|
176
|
+
def ascp_info
|
177
|
+
data = file_paths
|
178
|
+
# read PATHs from ascp directly, and pvcl modules as well
|
179
|
+
Open3.popen3(data['ascp'], '-DDL-') do |_stdin, _stdout, stderr, thread|
|
180
|
+
last_line = ''
|
181
|
+
while (line = stderr.gets)
|
182
|
+
line.chomp!
|
183
|
+
last_line = line
|
184
|
+
case line
|
185
|
+
when /^DBG Path ([^ ]+) (dir|file) +: (.*)$/
|
186
|
+
data[Regexp.last_match(1)] = Regexp.last_match(3)
|
187
|
+
when /^DBG Added module group:"(?<module>[^"]+)" name:"(?<scheme>[^"]+)", version:"(?<version>[^"]+)" interface:"(?<interface>[^"]+)"$/
|
188
|
+
c = Regexp.last_match.named_captures.symbolize_keys
|
189
|
+
data[c[:interface]] ||= {}
|
190
|
+
data[c[:interface]][c[:module]] ||= []
|
191
|
+
data[c[:interface]][c[:module]].push("#{c[:scheme]} v#{c[:version]}")
|
192
|
+
when %r{^DBG License result \(/license/(\S+)\): (.+)$}
|
193
|
+
data[Regexp.last_match(1)] = Regexp.last_match(2)
|
194
|
+
when /^LOG (.+) version ([0-9.]+)$/
|
195
|
+
data['product_name'] = Regexp.last_match(1)
|
196
|
+
data['product_version'] = Regexp.last_match(2)
|
197
|
+
when /^LOG Initializing FASP version ([^,]+),/
|
198
|
+
data['ascp_version'] = Regexp.last_match(1)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
if !thread.value.exitstatus.eql?(1) && !data.key?('root')
|
202
|
+
raise last_line
|
203
|
+
end
|
204
|
+
end
|
205
|
+
# ascp's openssl directory
|
206
|
+
ascp_file = data['ascp']
|
207
|
+
File.binread(ascp_file).scan(/[\x20-\x7E]{4,}/) do |match|
|
208
|
+
if (m = match.match(/OPENSSLDIR.*"(.*)"/))
|
209
|
+
data['openssldir'] = m[1]
|
210
|
+
end
|
211
|
+
end if File.file?(ascp_file)
|
212
|
+
# log is "-" no need to display
|
213
|
+
data.delete('log')
|
214
|
+
return data
|
215
|
+
end
|
216
|
+
|
229
217
|
# download aspera SDK or use local file
|
230
218
|
# extracts ascp binary for current system architecture
|
231
219
|
# @return ascp version (from execution)
|
@@ -267,123 +255,33 @@ module Aspera
|
|
267
255
|
# ensure license file are generated so that ascp invocation for version works
|
268
256
|
path(:aspera_license)
|
269
257
|
path(:aspera_conf)
|
270
|
-
|
271
|
-
|
258
|
+
ascp_file = Products.ascp_filename
|
259
|
+
ascp_path = File.join(sdk_folder, ascp_file)
|
260
|
+
raise "No #{ascp_file} found in SDK archive" unless File.exist?(ascp_path)
|
272
261
|
Environment.restrict_file_access(ascp_path, mode: 0o755)
|
273
262
|
Environment.restrict_file_access(ascp_path.gsub('ascp', 'ascp4'), mode: 0o755)
|
274
|
-
ascp_version = get_ascp_version(
|
263
|
+
ascp_version = get_ascp_version(ascp_path)
|
275
264
|
trd_path = transferd_filepath
|
276
265
|
Log.log.warn{"No #{trd_path} in SDK archive"} unless File.exist?(trd_path)
|
277
266
|
Environment.restrict_file_access(trd_path, mode: 0o755) if File.exist?(trd_path)
|
278
267
|
transferd_version = get_exe_version(trd_path, 'version')
|
279
268
|
sdk_version = transferd_version || ascp_version
|
280
|
-
File.write(File.join(sdk_folder,
|
269
|
+
File.write(File.join(sdk_folder, Products::INFO_META_FILE), "<product><name>IBM Aspera SDK</name><version>#{sdk_version}</version></product>")
|
281
270
|
return sdk_version
|
282
271
|
end
|
283
272
|
|
284
273
|
private
|
285
274
|
|
286
|
-
BIN_SUBFOLDER = 'bin'
|
287
|
-
ETC_SUBFOLDER = 'etc'
|
288
|
-
VAR_RUN_SUBFOLDER = File.join('var', 'run')
|
289
|
-
# product information manifest: XML (part of aspera product)
|
290
|
-
PRODUCT_INFO = 'product-info.mf'
|
291
275
|
# policy for product selection
|
292
276
|
FIRST_FOUND = 'FIRST'
|
293
277
|
|
294
|
-
private_constant :BIN_SUBFOLDER, :ETC_SUBFOLDER, :VAR_RUN_SUBFOLDER, :PRODUCT_INFO
|
295
|
-
|
296
278
|
def initialize
|
297
279
|
@path_to_ascp = nil
|
298
280
|
@sdk_dir = nil
|
299
|
-
@found_products = nil
|
300
|
-
end
|
301
|
-
|
302
|
-
# @return folder paths for specified applications
|
303
|
-
# @param name Connect or CLI
|
304
|
-
def get_product_folders(name)
|
305
|
-
found = installed_products.select{|i|i[:expected].eql?(name) || i[:name].eql?(name)}
|
306
|
-
raise "Product: #{name} not found, please install." if found.empty?
|
307
|
-
return found.first
|
308
|
-
end
|
309
|
-
|
310
|
-
# filename for ascp with optional extension (Windows)
|
311
|
-
def ascp_filename
|
312
|
-
return 'ascp' + Environment.exe_extension
|
313
281
|
end
|
314
282
|
|
315
283
|
def transferd_filepath
|
316
|
-
return File.join(sdk_folder, 'asperatransferd' + Environment.exe_extension)
|
317
|
-
end
|
318
|
-
|
319
|
-
# @return product folders depending on OS fields
|
320
|
-
# :expected M app name is taken from the manifest if present, else defaults to this value
|
321
|
-
# :app_root M main folder for the application
|
322
|
-
# :log_root O location of log files (Linux uses syslog)
|
323
|
-
# :run_root O only for Connect Client, location of http port file
|
324
|
-
# :sub_bin O subfolder with executables, default : bin
|
325
|
-
def product_locations
|
326
|
-
case Aspera::Environment.os
|
327
|
-
when Aspera::Environment::OS_WINDOWS; return [{
|
328
|
-
expected: PRODUCT_CONNECT,
|
329
|
-
app_root: File.join(ENV['LOCALAPPDATA'], 'Programs', 'Aspera', 'Aspera Connect'),
|
330
|
-
log_root: File.join(ENV['LOCALAPPDATA'], 'Aspera', 'Aspera Connect', 'var', 'log'),
|
331
|
-
run_root: File.join(ENV['LOCALAPPDATA'], 'Aspera', 'Aspera Connect')
|
332
|
-
}, {
|
333
|
-
expected: PRODUCT_CLI_V1,
|
334
|
-
app_root: File.join('C:', 'Program Files', 'Aspera', 'cli'),
|
335
|
-
log_root: File.join('C:', 'Program Files', 'Aspera', 'cli', 'var', 'log')
|
336
|
-
}, {
|
337
|
-
expected: PRODUCT_ENTSRV,
|
338
|
-
app_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server'),
|
339
|
-
log_root: File.join('C:', 'Program Files', 'Aspera', 'Enterprise Server', 'var', 'log')
|
340
|
-
}]
|
341
|
-
when Aspera::Environment::OS_X; return [{
|
342
|
-
expected: PRODUCT_CONNECT,
|
343
|
-
app_root: File.join(Dir.home, 'Applications', 'Aspera Connect.app'),
|
344
|
-
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
|
345
|
-
run_root: File.join(Dir.home, 'Library', 'Application Support', 'Aspera', 'Aspera Connect'),
|
346
|
-
sub_bin: File.join('Contents', 'Resources')
|
347
|
-
}, {
|
348
|
-
expected: PRODUCT_CONNECT,
|
349
|
-
app_root: File.join('', 'Applications', 'Aspera Connect.app'),
|
350
|
-
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Connect'),
|
351
|
-
run_root: File.join(Dir.home, 'Library', 'Application Support', 'Aspera', 'Aspera Connect'),
|
352
|
-
sub_bin: File.join('Contents', 'Resources')
|
353
|
-
}, {
|
354
|
-
expected: PRODUCT_CLI_V1,
|
355
|
-
app_root: File.join(Dir.home, 'Applications', 'Aspera CLI'),
|
356
|
-
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera')
|
357
|
-
}, {
|
358
|
-
expected: PRODUCT_ENTSRV,
|
359
|
-
app_root: File.join('', 'Library', 'Aspera'),
|
360
|
-
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera')
|
361
|
-
}, {
|
362
|
-
expected: PRODUCT_DRIVE,
|
363
|
-
app_root: File.join('', 'Applications', 'Aspera Drive.app'),
|
364
|
-
log_root: File.join(Dir.home, 'Library', 'Logs', 'Aspera_Drive'),
|
365
|
-
sub_bin: File.join('Contents', 'Resources')
|
366
|
-
}]
|
367
|
-
else; return [{ # other: Linux and Unix family
|
368
|
-
expected: PRODUCT_CONNECT,
|
369
|
-
app_root: File.join(Dir.home, '.aspera', 'connect'),
|
370
|
-
run_root: File.join(Dir.home, '.aspera', 'connect')
|
371
|
-
}, {
|
372
|
-
expected: PRODUCT_CLI_V1,
|
373
|
-
app_root: File.join(Dir.home, '.aspera', 'cli')
|
374
|
-
}, {
|
375
|
-
expected: PRODUCT_ENTSRV,
|
376
|
-
app_root: File.join('', 'opt', 'aspera')
|
377
|
-
}]
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
# @return a standard bypass key
|
382
|
-
# @param type rsa or dsa
|
383
|
-
# @param id in repository 1 for dsa, 2 for rsa
|
384
|
-
def get_key(type, id)
|
385
|
-
# generate PEM from DER
|
386
|
-
OpenSSL::PKey.const_get(type.upcase).new(DataRepository.instance.data(id)).to_pem
|
284
|
+
return File.join(sdk_folder, 'asperatransferd' + Environment.exe_extension) # cspell:disable-line
|
387
285
|
end
|
388
286
|
end # Installation
|
389
287
|
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aspera
|
4
|
+
module Fasp
|
5
|
+
# executes a local "ascp", connects mgt port, equivalent of "Fasp Manager"
|
6
|
+
class Management
|
7
|
+
# cspell: disable
|
8
|
+
OPERATIONS = %w[
|
9
|
+
NOP
|
10
|
+
START
|
11
|
+
QUERY
|
12
|
+
QUERYRSP
|
13
|
+
STATS
|
14
|
+
STOP
|
15
|
+
ERROR
|
16
|
+
CANCEL
|
17
|
+
DONE
|
18
|
+
RATE
|
19
|
+
FILEERROR
|
20
|
+
SESSION
|
21
|
+
NOTIFICATION
|
22
|
+
INIT
|
23
|
+
VLINK
|
24
|
+
NOTIFICATION
|
25
|
+
PUT
|
26
|
+
WRITE
|
27
|
+
CLOSE
|
28
|
+
SKIP
|
29
|
+
ARGSTOP
|
30
|
+
]
|
31
|
+
|
32
|
+
PARAMETERS = %w[
|
33
|
+
Type
|
34
|
+
File
|
35
|
+
Size
|
36
|
+
Written
|
37
|
+
Bytescont
|
38
|
+
Rate
|
39
|
+
Loss
|
40
|
+
Query
|
41
|
+
Code
|
42
|
+
Password
|
43
|
+
Progress
|
44
|
+
Remaining
|
45
|
+
Elapsed
|
46
|
+
RexInfo
|
47
|
+
BlockInfo
|
48
|
+
DiskInfo
|
49
|
+
RateInfo
|
50
|
+
MinRate
|
51
|
+
Description
|
52
|
+
Elapsedusec
|
53
|
+
ServiceLevel
|
54
|
+
SessionId
|
55
|
+
User
|
56
|
+
Host
|
57
|
+
Encryption
|
58
|
+
Adaptive
|
59
|
+
Direction
|
60
|
+
Remote
|
61
|
+
Port
|
62
|
+
UserStr
|
63
|
+
CommandId
|
64
|
+
StartByte
|
65
|
+
EndByte
|
66
|
+
Token
|
67
|
+
Cookie
|
68
|
+
QueryResponse
|
69
|
+
Source
|
70
|
+
Destination
|
71
|
+
BWMeasurement
|
72
|
+
BWInfo
|
73
|
+
PMTU
|
74
|
+
TransferBytes
|
75
|
+
FileBytes
|
76
|
+
Operation
|
77
|
+
Delay
|
78
|
+
PreTransferFiles
|
79
|
+
PreTransferDirs
|
80
|
+
PreTransferSpecial
|
81
|
+
PreTransferFailed
|
82
|
+
PartialPreTransferBytes
|
83
|
+
PreTransferBytes
|
84
|
+
Priority
|
85
|
+
Transport
|
86
|
+
VlinkID
|
87
|
+
VlinkOn
|
88
|
+
VlinkCapIn
|
89
|
+
VlinkCapOut
|
90
|
+
ManifestFile
|
91
|
+
ArgScansAttempted
|
92
|
+
ArgScansCompleted
|
93
|
+
PathScansAttempted
|
94
|
+
PathScansFailed
|
95
|
+
PathScansIrregular
|
96
|
+
PathScansExcluded
|
97
|
+
DirScansCompleted
|
98
|
+
FileScansCompleted
|
99
|
+
DirCreatesAttempted
|
100
|
+
DirCreatesFailed
|
101
|
+
DirCreatesPassed
|
102
|
+
TransfersAttempted
|
103
|
+
TransfersFailed
|
104
|
+
TransfersPassed
|
105
|
+
TransfersSkipped
|
106
|
+
FallbackProtocol
|
107
|
+
RetryTimeout
|
108
|
+
PreTransferExcluded
|
109
|
+
XferId
|
110
|
+
XferRetry
|
111
|
+
Tags
|
112
|
+
FaspFileArgIndex
|
113
|
+
ArgTransfersStatus
|
114
|
+
ArgTransfersAttempted
|
115
|
+
ArgTransfersFailed
|
116
|
+
ArgTransfersPassed
|
117
|
+
ArgTransfersSkipped
|
118
|
+
FaspFileID
|
119
|
+
RateCap
|
120
|
+
MinRateCap
|
121
|
+
PolicyCap
|
122
|
+
PriorityCap
|
123
|
+
RateLock
|
124
|
+
MinRateLock
|
125
|
+
PolicyLock
|
126
|
+
FileChecksum
|
127
|
+
ServerHostname
|
128
|
+
ServerNodeId
|
129
|
+
ClientNodeId
|
130
|
+
ServerClusterId
|
131
|
+
ClientClusterId
|
132
|
+
FileChecksumType
|
133
|
+
ServerDocroot
|
134
|
+
ClientDocroot
|
135
|
+
NodeUser
|
136
|
+
ClientUser
|
137
|
+
SourcePrefix
|
138
|
+
RemoteAddress
|
139
|
+
TCPPort
|
140
|
+
Cipher
|
141
|
+
ResumePolicy
|
142
|
+
CreatePolicy
|
143
|
+
ManifestPolicy
|
144
|
+
Precalc
|
145
|
+
OverwritePolicy
|
146
|
+
RTTAutocorrect
|
147
|
+
TimePolicy
|
148
|
+
ManifestPath
|
149
|
+
ManifestInprogress
|
150
|
+
PartialFiles
|
151
|
+
FilesEncrypt
|
152
|
+
FilesDecrypt
|
153
|
+
DatagramSize
|
154
|
+
PrepostCommand
|
155
|
+
XoptFlags
|
156
|
+
VLinkVersion
|
157
|
+
PeerVLinkVersion
|
158
|
+
VLinkLocalEnabled
|
159
|
+
VLinkLocalId
|
160
|
+
VLinkLocalCL
|
161
|
+
VLinkRemoteEnabled
|
162
|
+
VLinkRemoteId
|
163
|
+
VLRemoteCL
|
164
|
+
DSPipelineDepth
|
165
|
+
PeerDSPipelineDepth
|
166
|
+
LocalIP
|
167
|
+
SourceBase
|
168
|
+
ReadBlockSize
|
169
|
+
WriteBlockSize
|
170
|
+
ClusterNumNodes
|
171
|
+
ClusterNodeId
|
172
|
+
MoveRange
|
173
|
+
MoveRangeLow
|
174
|
+
MoveRangeHigh
|
175
|
+
Keepalive
|
176
|
+
TestLogin
|
177
|
+
UseProxy
|
178
|
+
ProxyIP
|
179
|
+
RateControlAlgorithm
|
180
|
+
ClientMacAddress
|
181
|
+
Offset
|
182
|
+
ChunkSize
|
183
|
+
PostTransferValidation
|
184
|
+
OverwritePolicyCap
|
185
|
+
ExtraCreatePolicy]
|
186
|
+
# Management port start message
|
187
|
+
MGT_HEADER = 'FASPMGR 2'
|
188
|
+
# empty line is separator to end event information
|
189
|
+
MGT_FRAME_SEPARATOR = ''
|
190
|
+
# fields description for JSON generation
|
191
|
+
# spellchecker: disable
|
192
|
+
INTEGER_FIELDS = %w[Bytescont FaspFileArgIndex StartByte Rate MinRate Port Priority RateCap MinRateCap TCPPort CreatePolicy TimePolicy
|
193
|
+
DatagramSize XoptFlags VLinkVersion PeerVLinkVersion DSPipelineDepth PeerDSPipelineDepth ReadBlockSize WriteBlockSize
|
194
|
+
ClusterNumNodes ClusterNodeId Size Written Loss FileBytes PreTransferBytes TransferBytes PMTU Elapsedusec ArgScansAttempted
|
195
|
+
ArgScansCompleted PathScansAttempted FileScansCompleted TransfersAttempted TransfersPassed Delay].freeze
|
196
|
+
BOOLEAN_FIELDS = %w[Encryption Remote RateLock MinRateLock PolicyLock FilesEncrypt FilesDecrypt VLinkLocalEnabled VLinkRemoteEnabled
|
197
|
+
MoveRange Keepalive TestLogin UseProxy Precalc RTTAutocorrect].freeze
|
198
|
+
BOOLEAN_TRUE = 'Yes'
|
199
|
+
# cspell: enable
|
200
|
+
|
201
|
+
class << self
|
202
|
+
# translates mgt port event into (enhanced) typed event
|
203
|
+
def enhanced_event_format(event)
|
204
|
+
return event.keys.each_with_object({}) do |e, h|
|
205
|
+
# capital_to_snake_case
|
206
|
+
new_name = e
|
207
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
208
|
+
.gsub(/([a-z\d])(usec)$/, '\1_\2')
|
209
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
210
|
+
.downcase
|
211
|
+
value = event[e]
|
212
|
+
value = value.to_i if INTEGER_FIELDS.include?(e)
|
213
|
+
value = value.eql?(BOOLEAN_TRUE) if BOOLEAN_FIELDS.include?(e)
|
214
|
+
h[new_name] = value
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end # class << self
|
218
|
+
|
219
|
+
def initialize
|
220
|
+
# current event being parsed line by line
|
221
|
+
@event_build = nil
|
222
|
+
# last fully built event
|
223
|
+
@last_event = nil
|
224
|
+
end
|
225
|
+
attr_reader :last_event
|
226
|
+
|
227
|
+
def process_line(line)
|
228
|
+
# Log.log.debug{"line=[#{line}]"}
|
229
|
+
case line
|
230
|
+
when MGT_HEADER
|
231
|
+
# begin event
|
232
|
+
@event_build = {}
|
233
|
+
when /^([^:]+): (.*)$/
|
234
|
+
raise 'mgt port: unexpected line: data without header' if @event_build.nil?
|
235
|
+
# event field
|
236
|
+
@event_build[Regexp.last_match(1)] = Regexp.last_match(2)
|
237
|
+
when MGT_FRAME_SEPARATOR
|
238
|
+
raise 'mgt port: unexpected line: end frame without header' if @event_build.nil?
|
239
|
+
@last_event = @event_build
|
240
|
+
@event_build = nil
|
241
|
+
return @last_event
|
242
|
+
else
|
243
|
+
raise "mgt port: unexpected line: [#{line}]"
|
244
|
+
end # case
|
245
|
+
return nil
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|