aspera-cli 4.19.0 → 4.20.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +20 -0
- data/CONTRIBUTING.md +16 -4
- data/README.md +344 -164
- data/bin/asession +26 -19
- data/examples/build_exec +65 -76
- data/examples/build_exec_rubyc +40 -0
- data/examples/get_proto_file.rb +7 -0
- data/lib/aspera/agent/alpha.rb +8 -8
- data/lib/aspera/agent/base.rb +2 -18
- data/lib/aspera/agent/connect.rb +14 -13
- data/lib/aspera/agent/direct.rb +23 -24
- data/lib/aspera/agent/httpgw.rb +2 -3
- data/lib/aspera/agent/node.rb +10 -10
- data/lib/aspera/agent/trsdk.rb +17 -20
- data/lib/aspera/api/alee.rb +15 -0
- data/lib/aspera/api/aoc.rb +126 -97
- data/lib/aspera/api/ats.rb +1 -1
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/httpgw.rb +15 -10
- data/lib/aspera/api/node.rb +33 -12
- data/lib/aspera/ascmd.rb +56 -48
- data/lib/aspera/ascp/installation.rb +99 -42
- data/lib/aspera/ascp/management.rb +3 -2
- data/lib/aspera/ascp/products.rb +12 -0
- data/lib/aspera/assert.rb +10 -5
- data/lib/aspera/cli/formatter.rb +27 -17
- data/lib/aspera/cli/hints.rb +2 -1
- data/lib/aspera/cli/info.rb +12 -10
- data/lib/aspera/cli/main.rb +16 -13
- data/lib/aspera/cli/manager.rb +5 -0
- data/lib/aspera/cli/plugin.rb +15 -29
- data/lib/aspera/cli/plugins/alee.rb +3 -3
- data/lib/aspera/cli/plugins/aoc.rb +222 -194
- data/lib/aspera/cli/plugins/ats.rb +16 -14
- data/lib/aspera/cli/plugins/config.rb +53 -45
- data/lib/aspera/cli/plugins/console.rb +3 -3
- data/lib/aspera/cli/plugins/faspex.rb +11 -21
- data/lib/aspera/cli/plugins/faspex5.rb +44 -42
- data/lib/aspera/cli/plugins/faspio.rb +2 -2
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/node.rb +153 -95
- data/lib/aspera/cli/plugins/orchestrator.rb +14 -13
- data/lib/aspera/cli/plugins/preview.rb +8 -9
- data/lib/aspera/cli/plugins/server.rb +5 -9
- data/lib/aspera/cli/plugins/shares.rb +2 -2
- data/lib/aspera/cli/sync_actions.rb +2 -2
- data/lib/aspera/cli/transfer_agent.rb +12 -14
- data/lib/aspera/cli/transfer_progress.rb +35 -17
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +3 -4
- data/lib/aspera/coverage.rb +13 -1
- data/lib/aspera/environment.rb +34 -18
- data/lib/aspera/faspex_gw.rb +2 -2
- data/lib/aspera/json_rpc.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +7 -12
- data/lib/aspera/log.rb +3 -4
- data/lib/aspera/oauth/base.rb +39 -45
- data/lib/aspera/oauth/factory.rb +11 -4
- data/lib/aspera/oauth/generic.rb +4 -8
- data/lib/aspera/oauth/jwt.rb +3 -3
- data/lib/aspera/oauth/url_json.rb +1 -2
- data/lib/aspera/oauth/web.rb +5 -2
- data/lib/aspera/persistency_action_once.rb +16 -8
- data/lib/aspera/preview/utils.rb +5 -16
- data/lib/aspera/rest.rb +100 -76
- data/lib/aspera/transfer/faux_file.rb +4 -4
- data/lib/aspera/transfer/parameters.rb +14 -16
- data/lib/aspera/transfer/spec.rb +12 -12
- data/lib/aspera/transfer/sync.rb +1 -5
- data/lib/aspera/transfer/uri.rb +1 -1
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/aspera/web_auth.rb +166 -17
- data/lib/aspera/web_server_simple.rb +4 -3
- data/lib/transfer_pb.rb +84 -0
- data/lib/transfer_services_pb.rb +82 -0
- data.tar.gz.sig +0 -0
- metadata +24 -5
- metadata.gz.sig +0 -0
data/bin/asession
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
gem_lib_folder = File.join(File.dirname(File.dirname(File.realpath(__FILE__))), 'lib')
|
5
|
+
Kernel.load(File.join(gem_lib_folder, 'aspera/coverage.rb'))
|
6
|
+
$LOAD_PATH.unshift(gem_lib_folder)
|
6
7
|
require 'aspera/agent/direct'
|
7
8
|
require 'aspera/cli/extended_value'
|
8
9
|
require 'aspera/ascp/installation'
|
9
10
|
require 'aspera/log'
|
10
11
|
require 'json'
|
11
12
|
# extended transfer spec parameter (only used in asession)
|
12
|
-
|
13
|
+
PARAM_SPEC = 'spec'
|
14
|
+
# log level
|
13
15
|
PARAM_LOG_LEVEL = 'loglevel'
|
16
|
+
# transfer agent options
|
17
|
+
PARAM_AGENT = 'agent'
|
14
18
|
# by default go to /tmp/username.filelist
|
15
19
|
PARAM_TMP_FILE_LIST_FOLDER = 'file_list_folder'
|
20
|
+
PARAM_SDK = 'sdk'
|
16
21
|
# place transfer spec in that
|
17
|
-
PARAM_SPEC = 'spec'
|
18
22
|
SAMPLE_DEMO = '"remote_host":"demo.asperasoft.com","remote_user":"asperaweb","ssh_port":33001,"remote_password":"demoaspera"'
|
19
23
|
SAMPLE_DEMO2 = '"direction":"receive","destination_root":"./test.dir"'
|
20
24
|
def assert_usage(assertion, error_message)
|
@@ -23,28 +27,30 @@ def assert_usage(assertion, error_message)
|
|
23
27
|
$stderr.puts('USAGE')
|
24
28
|
$stderr.puts(' asession')
|
25
29
|
$stderr.puts(' asession -h|--help')
|
26
|
-
$stderr.puts(' asession <session spec extended value>')
|
30
|
+
$stderr.puts(' asession [<session spec extended value>]')
|
27
31
|
$stderr.puts(' ')
|
28
32
|
$stderr.puts(' If no argument is provided, default will be used: @json:@stdin')
|
29
33
|
$stderr.puts(' -h, --help display this message')
|
30
|
-
$stderr.puts(' <session spec extended value> a dictionary
|
34
|
+
$stderr.puts(' <session spec extended value> a dictionary (Hash)')
|
31
35
|
$stderr.puts(' The value can be either:')
|
32
36
|
$stderr.puts(" the JSON description itself, e.g. @json:'{\"xx\":\"yy\",...}'")
|
33
37
|
$stderr.puts(' @json:@stdin, if the JSON is provided from stdin')
|
34
38
|
$stderr.puts(' @json:@file:<path>, if the JSON is provided from a file')
|
35
|
-
$stderr.puts(
|
39
|
+
$stderr.puts(' The following keys are recognized in session spec:')
|
40
|
+
$stderr.puts(" #{PARAM_SPEC} : mandatory, contains the transfer spec")
|
41
|
+
$stderr.puts(" #{PARAM_LOG_LEVEL} : modify log level (to stderr)")
|
42
|
+
$stderr.puts(" #{PARAM_AGENT} : modify transfer agent parameters, e.g. ascp_args")
|
43
|
+
$stderr.puts(" #{PARAM_TMP_FILE_LIST_FOLDER} : location of temporary files")
|
44
|
+
$stderr.puts(" #{PARAM_SDK} : location of SDK (ascp)")
|
36
45
|
$stderr.puts(' Asynchronous commands can be provided on STDIN, examples:')
|
37
46
|
$stderr.puts(' {"type":"START","source":"/aspera-test-dir-tiny/200KB.2"}')
|
38
47
|
$stderr.puts(' {"type":"START","source":"xx","destination":"yy"}')
|
39
48
|
$stderr.puts(' {"type":"DONE"}')
|
40
|
-
$stderr.puts(%Q(Note: debug information can be placed on STDERR, using the "#{PARAM_LOG_LEVEL}" parameter in session spec (debug=0)))
|
41
49
|
$stderr.puts('EXAMPLES')
|
42
50
|
$stderr.puts(%Q( asession @json:'{"#{PARAM_SPEC}":{#{SAMPLE_DEMO},#{SAMPLE_DEMO2},"paths":[{"source":"/aspera-test-dir-tiny/200KB.1"}]}}'))
|
43
51
|
$stderr.puts(%Q( echo '{"#{PARAM_SPEC}":{"remote_host":...}}'|asession @json:@stdin))
|
44
52
|
Process.exit(0)
|
45
53
|
end
|
46
|
-
Aspera::Ascp::Installation.instance.sdk_folder = File.join(Dir.home, '.aspera', 'sdk')
|
47
|
-
|
48
54
|
parameter_source_err_msg = ' (argument), did you specify: "@json:" ?'
|
49
55
|
# by default assume JSON input on stdin if no argument
|
50
56
|
if ARGV.empty?
|
@@ -62,23 +68,24 @@ rescue
|
|
62
68
|
assert_usage(false, "Cannot parse argument: #{session_argument}")
|
63
69
|
end
|
64
70
|
# ensure right type
|
65
|
-
assert_usage(session_spec.is_a?(Hash), "The value must be a
|
66
|
-
assert_usage(session_spec[PARAM_SPEC].is_a?(Hash), "
|
71
|
+
assert_usage(session_spec.is_a?(Hash), "The value must be a Hash#{parameter_source_err_msg}")
|
72
|
+
assert_usage(session_spec[PARAM_SPEC].is_a?(Hash), "The value must contain key #{PARAM_SPEC} with Hash value")
|
67
73
|
# additional debug capability
|
68
|
-
if session_spec.key?(PARAM_LOG_LEVEL)
|
69
|
-
Aspera::Log.instance.level = session_spec[PARAM_LOG_LEVEL]
|
70
|
-
end
|
74
|
+
Aspera::Log.instance.level = session_spec[PARAM_LOG_LEVEL] if session_spec.key?(PARAM_LOG_LEVEL)
|
71
75
|
# possibly override temp folder
|
72
76
|
if session_spec.key?(PARAM_TMP_FILE_LIST_FOLDER)
|
73
77
|
Aspera::Transfer::Parameters.file_list_folder = session_spec[PARAM_TMP_FILE_LIST_FOLDER]
|
74
78
|
end
|
75
|
-
session_spec[
|
76
|
-
session_spec[
|
77
|
-
session_spec[
|
79
|
+
session_spec[PARAM_SDK] = File.join(Dir.home, '.aspera', 'sdk') unless session_spec.key?(PARAM_SDK)
|
80
|
+
Aspera::Ascp::Installation.instance.sdk_folder = session_spec[PARAM_SDK]
|
81
|
+
session_spec[PARAM_AGENT] = {} unless session_spec.key?(PARAM_AGENT)
|
82
|
+
agent_params = session_spec[PARAM_AGENT]
|
83
|
+
agent_params['quiet'] = true
|
84
|
+
agent_params['management_cb'] = ->(event) do
|
78
85
|
puts JSON.generate(Aspera::Ascp::Management.enhanced_event_format(event))
|
79
86
|
end
|
80
87
|
# get local agent (ascp), disable ascp output on stdout to not mix with JSON events
|
81
|
-
client = Aspera::Agent::Direct.new(**
|
88
|
+
client = Aspera::Agent::Direct.new(**agent_params.symbolize_keys)
|
82
89
|
# start transfer (asynchronous)
|
83
90
|
job_id = client.start_transfer(session_spec[PARAM_SPEC])
|
84
91
|
# async commands
|
data/examples/build_exec
CHANGED
@@ -1,85 +1,74 @@
|
|
1
1
|
#!/bin/bash
|
2
|
-
|
2
|
+
# Glibc for various OS: https://gist.github.com/wagenet/35adca1a032cec2999d47b6c40aa45b1
|
3
|
+
# https://distrowatch.com/table.php?distribution=redhat
|
4
|
+
# RHEL 8 : glibc 2.28
|
5
|
+
# RHEL 9 : glibc 2.34
|
6
|
+
# https://distrowatch.com/table.php?distribution=ubuntu
|
7
|
+
# Ubuntu 18.10 cosmic : glibc 2.28
|
8
|
+
# Ubuntu 21.10 impish : gblic 2.34
|
9
|
+
# https://www.ibm.com/docs/en/ahts/4.4.x?topic=release-notes
|
10
|
+
# ascp 4.4.5 : gblic 2.28
|
11
|
+
# dwarfs requires boost >= 1.65
|
12
|
+
# boost requires cmake >= 3.30
|
3
13
|
set -e
|
4
14
|
|
5
|
-
if test $# -ne
|
6
|
-
echo "Usage: $0 <
|
15
|
+
if test $# -ne 5; then
|
16
|
+
echo "Usage: $0 <CLI_EXECUTABLE> <CLI_PATH> <GEM_NAME> <GEM_VERSION> <DIR_TMP>" 1>&2
|
7
17
|
exit 1
|
8
18
|
fi
|
9
19
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
20
|
+
CLI_EXECUTABLE=$1
|
21
|
+
CLI_PATH=$(realpath $2)
|
22
|
+
GEM_NAME=$3
|
23
|
+
GEM_VERSION=$4
|
24
|
+
DIR_TMP=$(realpath $5)
|
14
25
|
|
15
|
-
echo "
|
16
|
-
echo "Executable: $CLI_TARGET_EXECUTABLE"
|
17
|
-
echo "Exec Name: $CLI_EXEC_NAME"
|
18
|
-
echo "Entry: $CLI_ENTRY_SCRIPT"
|
26
|
+
echo "Building: $(basename $CLI_EXECUTABLE)"
|
19
27
|
|
20
|
-
# tebako
|
28
|
+
# tebako compilation
|
29
|
+
tebako_env=$DIR_TMP/tebako-env
|
30
|
+
# project files (gem)
|
31
|
+
tebako_root=$DIR_TMP/tebako-root
|
32
|
+
# only provide the name, not path
|
33
|
+
tebako_entry=$(basename $CLI_PATH)
|
34
|
+
tebako_output=$CLI_EXECUTABLE
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
else
|
62
|
-
# https://github.com/you54f/ruby-packer
|
63
|
-
# https://github.com/YOU54F/ruby-packer/releases
|
64
|
-
set -e
|
65
|
-
FOLDER="$(dirname $0)/../tmp"
|
66
|
-
RUBYC="$FOLDER/rubyc"
|
67
|
-
if test ! -e "$RUBYC"; then
|
68
|
-
mkdir -p "$FOLDER"
|
69
|
-
case $(uname -sm|tr ' ' -) in
|
70
|
-
Darwin-arm64)
|
71
|
-
curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Darwin-arm64.tar.gz | tar -xz -C "$FOLDER"
|
72
|
-
mv "$FOLDER/rubyc-Darwin-arm64" "$RUBYC"
|
73
|
-
;;
|
74
|
-
Linux-x86_64)
|
75
|
-
curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Linux-x86_64.tar.gz | tar -xz -C "$FOLDER"
|
76
|
-
mv "$FOLDER/rubyc-Linux-x86_64" "$RUBYC"
|
77
|
-
;;
|
78
|
-
*)
|
79
|
-
echo "This architecture is not supported." >&2
|
80
|
-
exit 1
|
81
|
-
;;
|
82
|
-
esac
|
83
|
-
fi
|
84
|
-
exec "$RUBYC" -o "$CLI_TARGET_EXECUTABLE" "$CLI_ENTRY_SCRIPT"
|
85
|
-
fi
|
36
|
+
container_tag=alpine-3.17
|
37
|
+
#container_tag=ubuntu-20.04
|
38
|
+
|
39
|
+
gem install tebako
|
40
|
+
mkdir -p $tebako_env $tebako_root
|
41
|
+
(cd $tebako_root && gem fetch $GEM_NAME:$GEM_VERSION)
|
42
|
+
case $(uname -s) in
|
43
|
+
Darwin)
|
44
|
+
brew update
|
45
|
+
# install tools
|
46
|
+
brew install bash binutils bison flex gnu-sed lz4 pkg-config xz
|
47
|
+
# install libs
|
48
|
+
brew install boost double-conversion fmt gdbm glog jemalloc libevent libffi libsodium libyaml ncurses openssl@3 zlib
|
49
|
+
# make sure tools are reachable
|
50
|
+
export PATH=/opt/homebrew/opt/flex/bin:/opt/homebrew/opt/bison/bin:$PATH
|
51
|
+
# remove binutils from path so that macos `ar` is used
|
52
|
+
export PATH=$(echo $PATH|tr : \\n|grep -v /binutils/|tr \\n :)
|
53
|
+
;;
|
54
|
+
Linux)
|
55
|
+
tebako_root=/mnt/w
|
56
|
+
tebako_prefix="podman run -it --rm -v $PWD:$tebako_root ghcr.io/tamatebako/tebako-${container_tag}:0.8.6"
|
57
|
+
tebako_opts=--patchelf
|
58
|
+
tebako_output=$tebako_root/$(basename $CLI_EXECUTABLE)
|
59
|
+
;;
|
60
|
+
LinuxLocal)
|
61
|
+
dnf module reset ruby
|
62
|
+
dnf module install ruby:3.3
|
63
|
+
dnf install -y cmake git bash sudo autoconf boost-devel flex bison make clang binutils-devel libevent-devel libacl-devel sed python3 pkgconfig curl lz4-devel openssl-devel zlib-devel xz zip unzip tar xz-devel elfutils-devel libffi-devel gdbm-devel ncurses-devel readline-devel ruby-devel gettext-devel brotli-devel clang libxslt-devel
|
64
|
+
echo TODO
|
65
|
+
exit 1
|
66
|
+
dnf install
|
67
|
+
;;
|
68
|
+
*)
|
69
|
+
echo "This OS is not supported." >&2
|
70
|
+
exit 1
|
71
|
+
;;
|
72
|
+
esac
|
73
|
+
set -x
|
74
|
+
exec $tebako_prefix tebako press --root=$tebako_root --entry-point=$tebako_entry --output=$tebako_output --prefix=$tebako_env $tebako_opts
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
if test $# -ne 5; then
|
6
|
+
echo "Usage: $0 <CLI_EXECUTABLE> <CLI_PATH> <GEM_NAME> <GEM_VERSION> <DIR_TMP>" 1>&2
|
7
|
+
exit 1
|
8
|
+
fi
|
9
|
+
|
10
|
+
CLI_EXECUTABLE=$1
|
11
|
+
CLI_PATH=$(realpath $2)
|
12
|
+
GEM_NAME=$3
|
13
|
+
GEM_VERSION=$4
|
14
|
+
DIR_TMP=$(realpath $5)
|
15
|
+
|
16
|
+
echo "Building: $(basename $CLI_EXECUTABLE)"
|
17
|
+
|
18
|
+
# https://github.com/you54f/ruby-packer
|
19
|
+
# https://github.com/you54f/ruby-packer/releases
|
20
|
+
set -e
|
21
|
+
FOLDER="$(dirname $0)/../tmp"
|
22
|
+
RUBYC="$FOLDER/rubyc"
|
23
|
+
if test ! -e "$RUBYC"; then
|
24
|
+
mkdir -p "$FOLDER"
|
25
|
+
case $(uname -sm|tr ' ' -) in
|
26
|
+
Darwin-arm64)
|
27
|
+
curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Darwin-arm64.tar.gz | tar -xz -C "$FOLDER"
|
28
|
+
mv "$FOLDER/rubyc-Darwin-arm64" "$RUBYC"
|
29
|
+
;;
|
30
|
+
Linux-x86_64)
|
31
|
+
curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Linux-x86_64.tar.gz | tar -xz -C "$FOLDER"
|
32
|
+
mv "$FOLDER/rubyc-Linux-x86_64" "$RUBYC"
|
33
|
+
;;
|
34
|
+
*)
|
35
|
+
echo "This architecture is not supported." >&2
|
36
|
+
exit 1
|
37
|
+
;;
|
38
|
+
esac
|
39
|
+
fi
|
40
|
+
exec "$RUBYC" -o "$CLI_EXECUTABLE" "$CLI_PATH"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Retrieve `transfer.proto` from the web
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(File.dirname(File.realpath(__FILE__))), 'lib'))
|
6
|
+
require 'aspera/ascp/installation'
|
7
|
+
Aspera::Ascp::Installation.instance.install_sdk(folder: ARGV.first, backup: false, with_exe: false) {|name| '/' if name.end_with?('transfer.proto')}
|
data/lib/aspera/agent/alpha.rb
CHANGED
@@ -82,29 +82,29 @@ module Aspera
|
|
82
82
|
transfer = @client_app_api.get_transfer(app_id: @application_id, transfer_id: @xfer_id)
|
83
83
|
case transfer['status']
|
84
84
|
when 'initiating', 'queued'
|
85
|
-
notify_progress(
|
85
|
+
notify_progress(:pre_start, session_id: nil, info: transfer['status'])
|
86
86
|
when 'running'
|
87
87
|
if !started
|
88
|
-
notify_progress(session_id: @xfer_id
|
88
|
+
notify_progress(:session_start, session_id: @xfer_id)
|
89
89
|
started = true
|
90
90
|
end
|
91
91
|
if !pre_calc && (transfer['bytes_expected'] != 0)
|
92
|
-
notify_progress(
|
92
|
+
notify_progress(:session_size, session_id: @xfer_id, info: transfer['bytes_expected'])
|
93
93
|
pre_calc = true
|
94
94
|
else
|
95
|
-
notify_progress(
|
95
|
+
notify_progress(:transfer, session_id: @xfer_id, info: transfer['bytes_written'])
|
96
96
|
end
|
97
97
|
when 'completed'
|
98
|
-
notify_progress(
|
98
|
+
notify_progress(:end, session_id: @xfer_id)
|
99
99
|
break
|
100
100
|
when 'failed'
|
101
|
-
notify_progress(
|
101
|
+
notify_progress(:end, session_id: @xfer_id)
|
102
102
|
raise Transfer::Error, transfer['error_desc']
|
103
103
|
when 'cancelled'
|
104
|
-
notify_progress(
|
104
|
+
notify_progress(:end, session_id: @xfer_id)
|
105
105
|
raise Transfer::Error, 'Transfer cancelled by user'
|
106
106
|
else
|
107
|
-
notify_progress(
|
107
|
+
notify_progress(:end, session_id: @xfer_id)
|
108
108
|
raise Transfer::Error, "unknown status: #{transfer['status']}: #{transfer['error_desc']}"
|
109
109
|
end
|
110
110
|
sleep(1)
|
data/lib/aspera/agent/base.rb
CHANGED
@@ -14,22 +14,6 @@ module Aspera
|
|
14
14
|
Aspera::Agent.const_get(agent.to_s.capitalize).new(**options)
|
15
15
|
end
|
16
16
|
|
17
|
-
# compute options from user provided and default options
|
18
|
-
def to_move_options(default:, options:)
|
19
|
-
result = options.symbolize_keys
|
20
|
-
available = default.map{|k, v|"#{k}(#{v})"}.join(', ')
|
21
|
-
result.each_key do |k|
|
22
|
-
Aspera.assert_values(k, default.keys){"transfer agent parameter: #{k}"}
|
23
|
-
# check it is the expected type: too limiting, as we can have an Integer or Float, or symbol and string
|
24
|
-
# raise "Invalid value for transfer agent parameter: #{k}, expect #{default[k].class.name}" unless default[k].nil? || v.is_a?(default[k].class)
|
25
|
-
end
|
26
|
-
default.each do |k, v|
|
27
|
-
raise "Missing required agent parameter: #{k}. Parameters: #{available}" if v.eql?(:required) && !result.key?(k)
|
28
|
-
result[k] = v unless result.key?(k)
|
29
|
-
end
|
30
|
-
return result
|
31
|
-
end
|
32
|
-
|
33
17
|
# discover available agents
|
34
18
|
def agent_list
|
35
19
|
base_class = File.basename(__FILE__)
|
@@ -58,8 +42,8 @@ module Aspera
|
|
58
42
|
@progress = progress
|
59
43
|
end
|
60
44
|
|
61
|
-
def notify_progress(**
|
62
|
-
@progress&.event(**
|
45
|
+
def notify_progress(*pos_args, **kw_args)
|
46
|
+
@progress&.event(*pos_args, **kw_args)
|
63
47
|
end
|
64
48
|
end
|
65
49
|
end
|
data/lib/aspera/agent/connect.rb
CHANGED
@@ -24,11 +24,12 @@ module Aspera
|
|
24
24
|
Log.log.debug{"found: #{connect_url}"}
|
25
25
|
@connect_api = Rest.new(
|
26
26
|
base_url: "#{connect_url}/v5/connect", # could use v6 also now
|
27
|
-
headers: {'Origin' =>
|
28
|
-
connect_info = @connect_api.read('info/version')
|
27
|
+
headers: {'Origin' => RestParameters.instance.user_agent})
|
28
|
+
connect_info = @connect_api.read('info/version')
|
29
29
|
Log.log.info('Connect was reached') if method_index > 0
|
30
30
|
Log.log.debug{Log.dump(:connect_version, connect_info)}
|
31
31
|
rescue StandardError => e # Errno::ECONNREFUSED
|
32
|
+
Log.log.debug{"Exception: #{e}"}
|
32
33
|
start_url = CONNECT_START_URIS[method_index]
|
33
34
|
method_index += 1
|
34
35
|
raise StandardError, "Unable to start connect #{method_index} times" if start_url.nil?
|
@@ -51,7 +52,7 @@ module Aspera
|
|
51
52
|
'title' => 'Select Files',
|
52
53
|
'suggestedName' => '',
|
53
54
|
'allowMultipleSelection' => true,
|
54
|
-
'allowedFileTypes' => ''})
|
55
|
+
'allowedFileTypes' => ''})
|
55
56
|
transfer_spec['paths'] = selection['dataTransfer']['files'].map { |i| {'source' => i['name']}}
|
56
57
|
end
|
57
58
|
@request_id = SecureRandom.uuid
|
@@ -67,7 +68,7 @@ module Aspera
|
|
67
68
|
'transfer_spec' => transfer_spec
|
68
69
|
}]}
|
69
70
|
# asynchronous anyway
|
70
|
-
res = @connect_api.create('transfers/start', connect_transfer_args)
|
71
|
+
res = @connect_api.create('transfers/start', connect_transfer_args)
|
71
72
|
@xfer_id = res['transfer_specs'].first['transfer_spec']['tags'][Transfer::Spec::TAG_RESERVED]['xfer_id']
|
72
73
|
end
|
73
74
|
|
@@ -78,7 +79,7 @@ module Aspera
|
|
78
79
|
session_id = @xfer_id
|
79
80
|
begin
|
80
81
|
loop do
|
81
|
-
tr_info = @connect_api.create("transfers/info/#{@xfer_id}", connect_activity_args)
|
82
|
+
tr_info = @connect_api.create("transfers/info/#{@xfer_id}", connect_activity_args)
|
82
83
|
Log.log.trace1{Log.dump(:tr_info, tr_info)}
|
83
84
|
if tr_info['transfer_info'].is_a?(Hash)
|
84
85
|
transfer = tr_info['transfer_info']
|
@@ -89,29 +90,29 @@ module Aspera
|
|
89
90
|
# TODO: get session id
|
90
91
|
case transfer['status']
|
91
92
|
when 'initiating', 'queued'
|
92
|
-
notify_progress(
|
93
|
+
notify_progress(:pre_start, session_id: nil, info: transfer['status'])
|
93
94
|
when 'running'
|
94
95
|
if !started
|
95
|
-
notify_progress(
|
96
|
+
notify_progress(:session_start, session_id: session_id)
|
96
97
|
started = true
|
97
98
|
end
|
98
99
|
if !pre_calc && (transfer['bytes_expected'] != 0)
|
99
|
-
notify_progress(
|
100
|
+
notify_progress(:session_size, session_id: session_id, info: transfer['bytes_expected'])
|
100
101
|
pre_calc = true
|
101
102
|
else
|
102
|
-
notify_progress(
|
103
|
+
notify_progress(:transfer, session_id: session_id, info: transfer['bytes_written'])
|
103
104
|
end
|
104
105
|
when 'completed'
|
105
|
-
notify_progress(
|
106
|
+
notify_progress(:end, session_id: session_id)
|
106
107
|
break
|
107
108
|
when 'failed'
|
108
|
-
notify_progress(
|
109
|
+
notify_progress(:end, session_id: session_id)
|
109
110
|
raise Transfer::Error, transfer['error_desc']
|
110
111
|
when 'cancelled'
|
111
|
-
notify_progress(
|
112
|
+
notify_progress(:end, session_id: session_id)
|
112
113
|
raise Transfer::Error, 'Transfer cancelled by user'
|
113
114
|
else
|
114
|
-
notify_progress(
|
115
|
+
notify_progress(:end, session_id: session_id)
|
115
116
|
raise Transfer::Error, "unknown status: #{transfer['status']}: #{transfer['error_desc']}"
|
116
117
|
end
|
117
118
|
end
|
data/lib/aspera/agent/direct.rb
CHANGED
@@ -151,7 +151,7 @@ module Aspera
|
|
151
151
|
args:
|
152
152
|
)
|
153
153
|
Aspera.assert_type(session, Hash)
|
154
|
-
notify_progress(
|
154
|
+
notify_progress(:pre_start, session_id: nil, info: 'starting')
|
155
155
|
begin
|
156
156
|
command_pid = nil
|
157
157
|
# we use Socket directly, instead of TCPServer, as it gives access to lower level options
|
@@ -169,7 +169,7 @@ module Aspera
|
|
169
169
|
# get location of command executable (ascp, async)
|
170
170
|
command_path = Ascp::Installation.instance.path(name)
|
171
171
|
command_pid = Environment.secure_spawn(env: env, exec: command_path, args: command_arguments)
|
172
|
-
notify_progress(
|
172
|
+
notify_progress(:pre_start, session_id: nil, info: "waiting for #{name} to start")
|
173
173
|
mgt_server_socket.listen(1)
|
174
174
|
# TODO: timeout does not work when Process.spawn is used... until process exits, then it works
|
175
175
|
Log.log.debug{"before select, timeout: #{@spawn_timeout_sec}"}
|
@@ -197,24 +197,23 @@ module Aspera
|
|
197
197
|
Log.log.error((event['Description']).to_s) if event['Type'].eql?('FILEERROR') # cspell:disable-line
|
198
198
|
end
|
199
199
|
Log.log.debug('management io closed')
|
200
|
-
last_event = processor.last_event
|
201
200
|
# check that last status was received before process exit
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
raise Transfer::Error.new(last_event['Description'], last_event['Code'].to_i)
|
213
|
-
when 'DONE'
|
214
|
-
nil
|
215
|
-
else
|
216
|
-
raise "unexpected last event type: #{last_event['Type']}"
|
201
|
+
last_event = processor.last_event
|
202
|
+
raise Transfer::Error, "internal: no management event (#{last_event.class})" unless last_event.is_a?(Hash)
|
203
|
+
case last_event['Type']
|
204
|
+
when 'ERROR'
|
205
|
+
if /bearer token/i.match?(last_event['Description']) &&
|
206
|
+
session[:token_regenerator].respond_to?(:refreshed_transfer_token)
|
207
|
+
# regenerate token here, expired, or error on it
|
208
|
+
# Note: in multi-session, each session will have a different one.
|
209
|
+
Log.log.warn('Regenerating token for transfer')
|
210
|
+
env['ASPERA_SCP_TOKEN'] = session[:token_regenerator].refreshed_transfer_token
|
217
211
|
end
|
212
|
+
raise Transfer::Error.new(last_event['Description'], last_event['Code'].to_i)
|
213
|
+
when 'DONE'
|
214
|
+
nil
|
215
|
+
else
|
216
|
+
raise Transfer::Error, "unexpected last event type: #{last_event['Type']}, #{last_event['Description']}"
|
218
217
|
end
|
219
218
|
rescue SystemCallError => e
|
220
219
|
# Process.spawn failed, or socket error
|
@@ -253,24 +252,24 @@ module Aspera
|
|
253
252
|
when 'INIT'
|
254
253
|
@pre_calc_sent = false
|
255
254
|
@pre_calc_last_size = nil
|
256
|
-
notify_progress(
|
255
|
+
notify_progress(:session_start, session_id: session_id)
|
257
256
|
when 'NOTIFICATION' # sent from remote
|
258
257
|
if event.key?('PreTransferBytes')
|
259
258
|
@pre_calc_sent = true
|
260
|
-
notify_progress(
|
259
|
+
notify_progress(:session_size, session_id: session_id, info: event['PreTransferBytes'])
|
261
260
|
end
|
262
261
|
when 'STATS' # during transfer
|
263
262
|
@pre_calc_last_size = event['TransferBytes'].to_i + event['StartByte'].to_i
|
264
|
-
notify_progress(
|
263
|
+
notify_progress(:transfer, session_id: session_id, info: @pre_calc_last_size)
|
265
264
|
when 'DONE', 'ERROR' # end of session
|
266
265
|
total_size = event['TransferBytes'].to_i + event['StartByte'].to_i
|
267
266
|
if !@pre_calc_sent && !total_size.zero?
|
268
|
-
notify_progress(
|
267
|
+
notify_progress(:session_size, session_id: session_id, info: total_size)
|
269
268
|
end
|
270
269
|
if @pre_calc_last_size != total_size
|
271
|
-
notify_progress(
|
270
|
+
notify_progress(:transfer, session_id: session_id, info: total_size)
|
272
271
|
end
|
273
|
-
notify_progress(
|
272
|
+
notify_progress(:end, session_id: session_id)
|
274
273
|
# cspell:disable
|
275
274
|
when 'SESSION'
|
276
275
|
when 'ARGSTOP'
|
data/lib/aspera/agent/httpgw.rb
CHANGED
@@ -23,8 +23,7 @@ module Aspera
|
|
23
23
|
@gw_api.upload(transfer_spec)
|
24
24
|
when Transfer::Spec::DIRECTION_RECEIVE
|
25
25
|
@gw_api.download(transfer_spec)
|
26
|
-
else
|
27
|
-
raise "unexpected direction: [#{transfer_spec['direction']}]"
|
26
|
+
else Aspera.error_unexpected_value(transfer_spec['direction']){'direction'}
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
@@ -54,7 +53,7 @@ module Aspera
|
|
54
53
|
api_version: api_version,
|
55
54
|
upload_chunk_size: upload_chunk_size,
|
56
55
|
synchronous: synchronous,
|
57
|
-
notify_cb: ->(**
|
56
|
+
notify_cb: ->(*pa, **ka) { notify_progress(*pa, **ka) }
|
58
57
|
)
|
59
58
|
end
|
60
59
|
end
|
data/lib/aspera/agent/node.rb
CHANGED
@@ -78,7 +78,7 @@ module Aspera
|
|
78
78
|
if !transfer_spec['wss_enabled'] && transfer_spec['remote_host'].eql?(URI.parse(node_api_.base_url).host)
|
79
79
|
transfer_spec['remote_host'] = '127.0.0.1'
|
80
80
|
end
|
81
|
-
resp = node_api_.create('ops/transfers', transfer_spec)
|
81
|
+
resp = node_api_.create('ops/transfers', transfer_spec)
|
82
82
|
@transfer_id = resp['id']
|
83
83
|
Log.log.debug{"tr_id=#{@transfer_id}"}
|
84
84
|
return @transfer_id
|
@@ -92,31 +92,31 @@ module Aspera
|
|
92
92
|
# lets emulate management events to display progress bar
|
93
93
|
loop do
|
94
94
|
# status is empty sometimes with status 200...
|
95
|
-
transfer_data = node_api_.read("ops/transfers/#{@transfer_id}")
|
95
|
+
transfer_data = node_api_.read("ops/transfers/#{@transfer_id}") || {'status' => 'unknown'} rescue {'status' => 'waiting(api error)'}
|
96
96
|
case transfer_data['status']
|
97
97
|
when 'waiting', 'partially_completed', 'unknown', 'waiting(read error)'
|
98
|
-
notify_progress(
|
98
|
+
notify_progress(:pre_start, session_id: nil, info: transfer_data['status'])
|
99
99
|
when 'running'
|
100
100
|
if !session_started
|
101
|
-
notify_progress(session_id: @transfer_id
|
101
|
+
notify_progress(:session_start, session_id: @transfer_id)
|
102
102
|
session_started = true
|
103
103
|
end
|
104
104
|
message = transfer_data['status']
|
105
105
|
message = "#{message} (#{transfer_data['error_desc']})" if !transfer_data['error_desc']&.empty?
|
106
|
-
notify_progress(
|
106
|
+
notify_progress(:pre_start, session_id: nil, info: message)
|
107
107
|
if bytes_expected.nil? &&
|
108
108
|
transfer_data['precalc'].is_a?(Hash) &&
|
109
109
|
transfer_data['precalc']['status'].eql?('ready')
|
110
110
|
bytes_expected = transfer_data['precalc']['bytes_expected']
|
111
|
-
notify_progress(
|
111
|
+
notify_progress(:session_size, session_id: @transfer_id, info: bytes_expected)
|
112
112
|
end
|
113
|
-
notify_progress(
|
113
|
+
notify_progress(:transfer, session_id: @transfer_id, info: transfer_data['bytes_transferred'])
|
114
114
|
when 'completed'
|
115
|
-
notify_progress(
|
116
|
-
notify_progress(
|
115
|
+
notify_progress(:transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
|
116
|
+
notify_progress(:end, session_id: @transfer_id)
|
117
117
|
break
|
118
118
|
when 'failed'
|
119
|
-
notify_progress(
|
119
|
+
notify_progress(:end, session_id: @transfer_id)
|
120
120
|
# Bug in HSTS ? transfer is marked failed, but there is no reason
|
121
121
|
break if transfer_data['error_code'].eql?(0) && transfer_data['error_desc'].empty?
|
122
122
|
raise Transfer::Error, "status: #{transfer_data['status']}. code: #{transfer_data['error_code']}. description: #{transfer_data['error_desc']}"
|