cnvrg 1.6.33 → 1.9.6
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
- data/cnvrg.gemspec +1 -4
- data/lib/cnvrg/Images.rb +0 -148
- data/lib/cnvrg/api.rb +8 -8
- data/lib/cnvrg/api_v2.rb +14 -0
- data/lib/cnvrg/cli.rb +299 -790
- data/lib/cnvrg/connect_job_ssh.rb +31 -0
- data/lib/cnvrg/data.rb +68 -12
- data/lib/cnvrg/datafiles.rb +333 -37
- data/lib/cnvrg/dataset.rb +65 -29
- data/lib/cnvrg/experiment.rb +10 -4
- data/lib/cnvrg/files.rb +67 -14
- data/lib/cnvrg/helpers.rb +34 -26
- data/lib/cnvrg/helpers/agent.rb +188 -0
- data/lib/cnvrg/helpers/executer.rb +162 -258
- data/lib/cnvrg/job_cli.rb +28 -53
- data/lib/cnvrg/job_ssh.rb +47 -0
- data/lib/cnvrg/logger.rb +4 -0
- data/lib/cnvrg/project.rb +53 -17
- data/lib/cnvrg/ssh.rb +0 -1
- data/lib/cnvrg/version.rb +1 -1
- metadata +10 -34
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Cnvrg
|
|
2
|
+
class ConnectJobSsh
|
|
3
|
+
def initialize(job_id)
|
|
4
|
+
home_dir = File.expand_path('~')
|
|
5
|
+
config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
|
|
6
|
+
@owner = config.to_h[:owner]
|
|
7
|
+
@job_id = job_id
|
|
8
|
+
rescue => e
|
|
9
|
+
@owner = ""
|
|
10
|
+
Cnvrg::Logger.log_info("cnvrg is not configured")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start(username, password)
|
|
14
|
+
Cnvrg::API_V2.request("#{@owner}/job_ssh/#{@job_id}/start" , 'POST', {username: username, password: password})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def status()
|
|
18
|
+
Cnvrg::API_V2.request("#{@owner}/job_ssh/#{@job_id}/status" , 'GET', nil)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def run_portforward_command(pod_name, port, kubeconfig, namespace)
|
|
22
|
+
command = "kubectl"
|
|
23
|
+
if kubeconfig.present?
|
|
24
|
+
command = "kubectl --kubeconfig=#{kubeconfig}"
|
|
25
|
+
end
|
|
26
|
+
bashCommand = "#{command} -n #{namespace} port-forward #{pod_name} #{port}:22"
|
|
27
|
+
puts("\nrunning command #{bashCommand}")
|
|
28
|
+
`#{bashCommand}`
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/cnvrg/data.rb
CHANGED
|
@@ -128,6 +128,7 @@ module Cnvrg
|
|
|
128
128
|
message = options["message"]
|
|
129
129
|
cli.sync_data_new(new_branch, force, verbose, commit, all_files, tags, parallel, chunk_size, init, message)
|
|
130
130
|
end
|
|
131
|
+
|
|
131
132
|
desc 'data download', 'Download files from remote server'
|
|
132
133
|
method_option :new_branch, :type => :boolean, :aliases => ["-nb"], :desc => "create new branch of commits", :default => false
|
|
133
134
|
method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
|
|
@@ -151,27 +152,52 @@ module Cnvrg
|
|
|
151
152
|
method_option :read, :type => :boolean, :aliases => ["-r", "--read"], :default => false
|
|
152
153
|
method_option :remote, :type => :boolean, :aliases => ["-h", "--remote"], :default => false
|
|
153
154
|
method_option :relative, :type => :boolean, :aliases => ["-rel", "--relative"], :default => false
|
|
154
|
-
|
|
155
|
+
method_option :flatten, :type => :boolean, :aliases => ["-f", "--flatten"], :default => false
|
|
156
|
+
method_option :soft, :type => :boolean, :aliases => ["-s", "--soft"], :default => false, :hide => true
|
|
155
157
|
def clone(dataset_url)
|
|
156
|
-
#test
|
|
157
158
|
cli = Cnvrg::CLI.new()
|
|
158
159
|
only_tree =options[:only_tree]
|
|
159
160
|
commit =options[:commit]
|
|
160
161
|
query =options[:query]
|
|
161
162
|
read = options[:read]
|
|
162
163
|
remote = options[:remote]
|
|
163
|
-
|
|
164
|
+
soft = options[:soft]
|
|
165
|
+
flatten = options[:flatten]
|
|
166
|
+
cli.clone_data(
|
|
167
|
+
dataset_url,
|
|
168
|
+
only_tree=only_tree,
|
|
169
|
+
commit=commit,
|
|
170
|
+
query=query,
|
|
171
|
+
read=read,
|
|
172
|
+
remote=remote,
|
|
173
|
+
flatten: flatten,
|
|
174
|
+
relative: options[:relative],
|
|
175
|
+
soft: soft
|
|
176
|
+
)
|
|
164
177
|
end
|
|
165
178
|
|
|
166
179
|
desc 'data verify DATASETS_TITLES', 'verify datasets', :hide => true
|
|
167
|
-
method_option :timeout, :type => :numeric, :aliases => ["-t", "--timeout"], :desc => "Time to wait before returning final answer", :default =>
|
|
168
|
-
|
|
180
|
+
method_option :timeout, :type => :numeric, :aliases => ["-t", "--timeout"], :desc => "Time to wait before returning final answer", :default => nil
|
|
169
181
|
def verify(*dataset_titles)
|
|
170
182
|
cli = Cnvrg::CLI.new()
|
|
171
183
|
timeout =options[:timeout]
|
|
172
184
|
cli.verify_datasets(dataset_titles, timeout)
|
|
173
185
|
end
|
|
174
186
|
|
|
187
|
+
desc 'data scan', 'lookup datasets', :hide => true
|
|
188
|
+
def scan()
|
|
189
|
+
cli = Cnvrg::CLI.new()
|
|
190
|
+
cli.scan_datasets()
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
desc "data block DATASET_TITLES", 'verifying that datasets exists', hide: true
|
|
194
|
+
def block(*dataset_slugs)
|
|
195
|
+
not_verified = true
|
|
196
|
+
while not_verified
|
|
197
|
+
not_verified = dataset_slugs.select{|slug| not Dataset.verify_dataset(slug)}.present?
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
175
201
|
desc 'data set --url=DATASET_URL', 'Set dataset url to other url'
|
|
176
202
|
method_option :url, :type => :string, :aliases => ["--url"], :default => ''
|
|
177
203
|
def set
|
|
@@ -186,19 +212,48 @@ module Cnvrg
|
|
|
186
212
|
desc 'data put DATASET_URL FILES_PREFIX', 'Upload selected files from local dataset directory to remote server'
|
|
187
213
|
method_option :dir, :type => :string, :aliases => ["-d", "--dir"], :default => ''
|
|
188
214
|
method_option :commit, :type => :string, :aliases => ["-c", "--commit"], :default => ''
|
|
215
|
+
method_option :force, :type => :boolean, :aliases => ["-f","--force"], :default => false
|
|
216
|
+
method_option :threads, :type => :numeric, :aliases => ["-t","--threads"], :default => 15
|
|
217
|
+
method_option :chunk_size, :type => :numeric, :aliases => ["-cs","--chunk"], :default => 1000
|
|
218
|
+
method_option :message, :type => :string, :aliases => ["--message"], :desc => "create commit with message", :default => nil
|
|
189
219
|
def put(dataset_url, *files)
|
|
190
220
|
cli = Cnvrg::CLI.new()
|
|
191
221
|
dir = options[:dir]
|
|
222
|
+
force = options["force"]
|
|
192
223
|
commit = options[:commit]
|
|
193
|
-
|
|
224
|
+
message = options[:message]
|
|
225
|
+
threads = options[:threads]
|
|
226
|
+
chunk_size = options[:chunk_size]
|
|
227
|
+
cli.data_put(
|
|
228
|
+
dataset_url,
|
|
229
|
+
files: files,
|
|
230
|
+
dir: dir,
|
|
231
|
+
commit: commit,
|
|
232
|
+
force: force,
|
|
233
|
+
threads: threads,
|
|
234
|
+
chunk_size: chunk_size,
|
|
235
|
+
message: message
|
|
236
|
+
)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
desc 'data rm DATASET_URL FILES_PREFIX', 'Delete selected files from remote server'
|
|
240
|
+
method_option :message, :type => :string, :aliases => ["--message"], :desc => "create commit with message", :default => nil
|
|
241
|
+
def rm(dataset_url, *regex_list)
|
|
242
|
+
cli = Cnvrg::CLI.new()
|
|
243
|
+
message = options[:message]
|
|
244
|
+
cli.data_rm(dataset_url, regex_list: regex_list, message: message)
|
|
194
245
|
end
|
|
195
246
|
|
|
196
247
|
desc 'data clone_query --query=QUERY_SLUG DATASET_URL', 'Clone dataset with specific query'
|
|
197
248
|
method_option :query, :type => :string, :aliases => ["-q", "--query"], :default => nil
|
|
249
|
+
method_option :soft, :type => :boolean, :aliases => ["-s", "--soft"], :default => false, :hide => true
|
|
250
|
+
method_option :flatten, :type => :boolean, :aliases => ["-f", "--flatten"], :default => false
|
|
198
251
|
def clone_query(dataset_url)
|
|
199
252
|
cli = Cnvrg::CLI.new()
|
|
200
|
-
query =options[:query]
|
|
201
|
-
|
|
253
|
+
query = options[:query]
|
|
254
|
+
flatten = options[:flatten]
|
|
255
|
+
soft =options[:soft]
|
|
256
|
+
cli.clone_data_query(dataset_url,query=query, flatten, soft: soft)
|
|
202
257
|
end
|
|
203
258
|
|
|
204
259
|
desc 'data delete DATASET_SLUG', 'Delete dataset'
|
|
@@ -214,12 +269,13 @@ module Cnvrg
|
|
|
214
269
|
cli.list_dataset()
|
|
215
270
|
|
|
216
271
|
end
|
|
217
|
-
desc 'data commits', 'List all commits for a current dataset'
|
|
218
272
|
|
|
219
|
-
|
|
273
|
+
desc 'data commits URL/SLUG', 'List all commits for a given dataset'
|
|
274
|
+
method_option :commit_sha1, :type => :string, :aliases => ["-c", "--commit"], :default => nil
|
|
275
|
+
def commits(dataset_url)
|
|
220
276
|
cli = Cnvrg::CLI.new()
|
|
221
|
-
|
|
222
|
-
|
|
277
|
+
commit_sha1 = options[:commit_sha1]
|
|
278
|
+
cli.list_dataset_commits(dataset_url, commit_sha1:commit_sha1)
|
|
223
279
|
end
|
|
224
280
|
|
|
225
281
|
desc 'data files DATASET_URL', 'Show list of dataset files'
|
data/lib/cnvrg/datafiles.rb
CHANGED
|
@@ -20,6 +20,15 @@ module Cnvrg
|
|
|
20
20
|
@dataset = dataset
|
|
21
21
|
@base_resource = "users/#{owner}/datasets/#{dataset_slug}/"
|
|
22
22
|
@downloader = @dataset.get_storage_client
|
|
23
|
+
@token_issue_time = Time.current
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def refresh_storage_token
|
|
27
|
+
current_time = Time.current
|
|
28
|
+
if current_time - @token_issue_time > 1.hours
|
|
29
|
+
@downloader = @dataset.get_storage_client
|
|
30
|
+
@token_issue_time = Time.current
|
|
31
|
+
end
|
|
23
32
|
end
|
|
24
33
|
|
|
25
34
|
def check_file_sha1(filename, org_sha1, tag: 'conflict')
|
|
@@ -46,6 +55,26 @@ module Cnvrg
|
|
|
46
55
|
paths.map{|p| p.gsub(/^\.\//, '')}
|
|
47
56
|
end
|
|
48
57
|
|
|
58
|
+
def get_files_and_folders(paths)
|
|
59
|
+
files_and_folders = {}
|
|
60
|
+
paths.each do |file|
|
|
61
|
+
if File.exists? file
|
|
62
|
+
if File.directory? file
|
|
63
|
+
Dir.glob("#{file}/**/*").select do |f|
|
|
64
|
+
files_and_folders["#{f}/"] = "folder" if File.directory? f
|
|
65
|
+
files_and_folders[f] = "file" if File.file? f
|
|
66
|
+
end
|
|
67
|
+
files_and_folders["#{file}/"] = "folder"
|
|
68
|
+
else
|
|
69
|
+
files_and_folders[file] = "file"
|
|
70
|
+
end
|
|
71
|
+
next
|
|
72
|
+
end
|
|
73
|
+
raise SignalException.new(1, "Cant find file #{file}") unless File.exists? "#{Dir.pwd}/#{file}"
|
|
74
|
+
end
|
|
75
|
+
return files_and_folders
|
|
76
|
+
end
|
|
77
|
+
|
|
49
78
|
def check_files_sha1(files, resolver, tag)
|
|
50
79
|
conflicts = 0
|
|
51
80
|
files.each do |file|
|
|
@@ -101,22 +130,41 @@ module Cnvrg
|
|
|
101
130
|
end
|
|
102
131
|
end
|
|
103
132
|
|
|
104
|
-
|
|
133
|
+
# This is for backwards compatibility only and should be removed in future versions:
|
|
105
134
|
def put_commit(commit_sha1)
|
|
106
|
-
response = Cnvrg::API.request(
|
|
135
|
+
response = Cnvrg::API.request(
|
|
136
|
+
"#{@base_resource}/commit/latest",
|
|
137
|
+
'PUT',
|
|
138
|
+
{
|
|
139
|
+
commit_sha1: commit_sha1,
|
|
140
|
+
ignore: true # tells the new server to ignore this api call since its coming from the new CLI
|
|
141
|
+
}
|
|
142
|
+
)
|
|
107
143
|
if response.present?
|
|
108
144
|
msg = response['result']
|
|
109
145
|
else
|
|
110
|
-
msg = "
|
|
146
|
+
msg = "Can't save changes in the dataset"
|
|
111
147
|
end
|
|
112
148
|
|
|
113
149
|
Cnvrg::Result.new(Cnvrg::CLI.is_response_success(response, false), msg)
|
|
114
150
|
end
|
|
115
151
|
|
|
152
|
+
def create_progressbar(title, total)
|
|
153
|
+
return ProgressBar.create(
|
|
154
|
+
:title => title,
|
|
155
|
+
:progress_mark => '=',
|
|
156
|
+
:format => "%b>>%i| %p%% %t",
|
|
157
|
+
:starting_at => 0,
|
|
158
|
+
:total => total,
|
|
159
|
+
:autofinish => true
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
|
|
116
163
|
|
|
117
164
|
def upload_multiple_files(commit_sha1, tree, threads: ParallelThreads, force: false, new_branch: false, prefix: '', partial_commit: nil, total: nil)
|
|
118
165
|
begin
|
|
119
166
|
Cnvrg::Logger.log_info("Sending Upload Files request")
|
|
167
|
+
refresh_storage_token
|
|
120
168
|
error = nil
|
|
121
169
|
upload_resp = nil
|
|
122
170
|
10.times do
|
|
@@ -148,6 +196,9 @@ module Cnvrg
|
|
|
148
196
|
end
|
|
149
197
|
|
|
150
198
|
files = results['files']
|
|
199
|
+
|
|
200
|
+
progressbar.progress += tree.keys.length - files.length if progressbar.present?
|
|
201
|
+
progress_semaphore = Mutex.new
|
|
151
202
|
upload_error_files = []
|
|
152
203
|
@temp_upload_progressbar.progress += tree.keys.length - files.length if @temp_upload_progressbar.present?
|
|
153
204
|
Parallel.map((files.keys), in_threads: threads) do |k|
|
|
@@ -159,8 +210,9 @@ module Cnvrg
|
|
|
159
210
|
tree.except!(k)
|
|
160
211
|
Cnvrg::Logger.log_error_message("Error while upload single file #{o["path"]}")
|
|
161
212
|
end
|
|
162
|
-
|
|
213
|
+
progress_semaphore.synchronize { progressbar.progress += 1 if progressbar.present? }
|
|
163
214
|
end
|
|
215
|
+
|
|
164
216
|
blob_ids = files.values.map {|f| f['bv_id']}
|
|
165
217
|
if blob_ids.present?
|
|
166
218
|
dirs = tree.keys.select {|k| tree[k].nil?} || []
|
|
@@ -180,17 +232,231 @@ module Cnvrg
|
|
|
180
232
|
end
|
|
181
233
|
end
|
|
182
234
|
|
|
183
|
-
def
|
|
235
|
+
def delete_multiple_files(commit_sha1, regex_list)
|
|
236
|
+
begin
|
|
237
|
+
Cnvrg::Logger.log_info("Sending Delete Files request")
|
|
238
|
+
resp = Cnvrg::API.request(
|
|
239
|
+
@base_resource + "delete_files",
|
|
240
|
+
'POST_JSON',
|
|
241
|
+
{
|
|
242
|
+
commit_sha1: commit_sha1,
|
|
243
|
+
regex_list: regex_list,
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
unless Cnvrg::CLI.is_response_success(resp, false)
|
|
247
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
248
|
+
raise Exception.new("Got an error message from server, #{resp.try(:fetch, "message")}")
|
|
249
|
+
end
|
|
250
|
+
Cnvrg::Logger.log_info("Delete Files request Successful")
|
|
251
|
+
return resp["files"], resp["folders"], resp["job_id"]
|
|
252
|
+
rescue => e
|
|
253
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
254
|
+
Cnvrg::Logger.log_error(e)
|
|
255
|
+
raise e
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def delete_file_chunk(commit_sha1, regex_list, chunk_size, offset)
|
|
260
|
+
begin
|
|
261
|
+
resp = Cnvrg::API.request(
|
|
262
|
+
@base_resource + "delete_files_by_chunk",
|
|
263
|
+
'POST_JSON',
|
|
264
|
+
{
|
|
265
|
+
commit_sha1: commit_sha1,
|
|
266
|
+
regex_list: regex_list,
|
|
267
|
+
chunk_size: chunk_size,
|
|
268
|
+
offset: offset
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
unless Cnvrg::CLI.is_response_success(resp, false)
|
|
272
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
273
|
+
raise Exception.new("Got an error message from server, #{resp.try(:fetch, "message")}")
|
|
274
|
+
end
|
|
275
|
+
return resp["total_changes"]
|
|
276
|
+
rescue => e
|
|
277
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
278
|
+
Cnvrg::Logger.log_error(e)
|
|
279
|
+
raise e
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def get_delete_progress(commit_sha1, job_id)
|
|
284
|
+
begin
|
|
285
|
+
resp = Cnvrg::API.request(
|
|
286
|
+
@base_resource + "get_delete_progress",
|
|
287
|
+
'POST_JSON',
|
|
288
|
+
{
|
|
289
|
+
commit_sha1: commit_sha1,
|
|
290
|
+
job_id: job_id
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
unless Cnvrg::CLI.is_response_success(resp, false)
|
|
294
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
295
|
+
raise Exception.new("Got an error message from server, #{resp.try(:fetch, "message")}")
|
|
296
|
+
end
|
|
297
|
+
return resp["total_deleted"]
|
|
298
|
+
rescue => e
|
|
299
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
300
|
+
Cnvrg::Logger.log_error(e)
|
|
301
|
+
raise e
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def request_upload_files(commit_sha1, tree, force, new_branch, partial_commit)
|
|
306
|
+
retry_count = 0
|
|
307
|
+
loop do
|
|
308
|
+
upload_resp = Cnvrg::API.request(@base_resource + "upload_files", 'POST_JSON', {
|
|
309
|
+
commit_sha1: commit_sha1,
|
|
310
|
+
tree: tree,
|
|
311
|
+
force: force,
|
|
312
|
+
is_branch: new_branch,
|
|
313
|
+
partial_commit: partial_commit
|
|
314
|
+
})
|
|
315
|
+
if not (Cnvrg::CLI.is_response_success(upload_resp, false))
|
|
316
|
+
#Cnvrg::Logger.log_method(bind: binding)
|
|
317
|
+
retry_count += 1
|
|
318
|
+
|
|
319
|
+
puts "Failed request upload files: #{Time.current}"
|
|
320
|
+
puts upload_resp
|
|
321
|
+
|
|
322
|
+
if retry_count > 5
|
|
323
|
+
raise Exception.new("Got an error message from server, #{upload_resp.try(:fetch, "message")}")
|
|
324
|
+
end
|
|
325
|
+
sleep 5
|
|
326
|
+
next
|
|
327
|
+
end
|
|
328
|
+
return upload_resp['result'].with_indifferent_access
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def upload_multiple_files_optimized(files, commit_sha1, threads: ParallelThreads, chunk_size: 1000, force: false, new_branch: false, prefix: '', partial_commit: nil)
|
|
334
|
+
cli = CLI.new
|
|
335
|
+
cli.log_message("Using #{threads} threads with chunk size of #{chunk_size}.", Thor::Shell::Color::GREEN)
|
|
336
|
+
|
|
337
|
+
progressbar = create_progressbar("Upload Progress", files.size)
|
|
338
|
+
cli = CLI.new
|
|
339
|
+
|
|
340
|
+
# Vars to handle the parallelism
|
|
341
|
+
progress_mutex = Mutex.new
|
|
342
|
+
file_queue = Queue.new
|
|
343
|
+
progress_queue = Queue.new
|
|
344
|
+
worker_threads = []
|
|
345
|
+
|
|
346
|
+
# Vars to keep track of uploaded files and directories
|
|
347
|
+
dirs = []
|
|
348
|
+
uploaded_files = []
|
|
349
|
+
|
|
350
|
+
begin
|
|
351
|
+
# Init working threads that handle the upload of the files:
|
|
352
|
+
threads.times do |i|
|
|
353
|
+
worker_threads[i] = Thread.new do
|
|
354
|
+
# wait for file_queue.close to break the loop
|
|
355
|
+
while file = file_queue.deq
|
|
356
|
+
success = upload_single_file(cli, file)
|
|
357
|
+
file[:success] = success
|
|
358
|
+
if not success
|
|
359
|
+
cli.log_message("Error while uploading file: #{file[:absolute_path]}", Thor::Shell::Color::RED)
|
|
360
|
+
Cnvrg::Logger.log_error_message("Error while upload single file #{file["path"]}")
|
|
361
|
+
end
|
|
362
|
+
progress_queue << file
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# init the thread that handles the file upload progress and saving them in the server
|
|
368
|
+
progress_thread = Thread.new do
|
|
369
|
+
loop do
|
|
370
|
+
file = progress_queue.deq(non_block: true) rescue nil # to prevent deadlocks
|
|
371
|
+
unless file.nil?
|
|
372
|
+
progress_mutex.synchronize {
|
|
373
|
+
progressbar.progress += 1
|
|
374
|
+
uploaded_files.append(file) if file[:success]
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if uploaded_files.size == chunk_size or progressbar.finished?
|
|
378
|
+
refresh_storage_token
|
|
379
|
+
# puts "progress: #{progress_queue.length}"
|
|
380
|
+
# puts "files: #{file_queue.length}"
|
|
381
|
+
Cnvrg::Logger.info("Sending Upload files save")
|
|
382
|
+
blob_ids = uploaded_files.map {|f| f['bv_id']}
|
|
383
|
+
upload_resp = Cnvrg::API.request(@base_resource + "upload_files_save", "POST", {commit: commit_sha1, blob_ids: blob_ids, dirs: dirs})
|
|
384
|
+
unless Cnvrg::CLI.is_response_success(upload_resp, false)
|
|
385
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
386
|
+
raise Exception.new("Got an error message from server, #{upload_resp.try(:fetch, "message")}")
|
|
387
|
+
end
|
|
388
|
+
# cli.log_message("Saved file chunk to server", Thor::Shell::Color::GREEN)
|
|
389
|
+
uploaded_files = []
|
|
390
|
+
dirs = []
|
|
391
|
+
end
|
|
392
|
+
else
|
|
393
|
+
sleep(0.1)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
if progressbar.finished?
|
|
397
|
+
# puts "finished"
|
|
398
|
+
file_queue.close()
|
|
399
|
+
progress_queue.close()
|
|
400
|
+
Thread.exit
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
file_chunks = files.each_slice(chunk_size).to_a
|
|
406
|
+
# Fetch the required files from the server:
|
|
407
|
+
Parallel.map((file_chunks), in_threads: 10) do |files_chunk|
|
|
408
|
+
|
|
409
|
+
tree = @dataset.generate_chunked_idx(files_chunk, prefix: prefix)
|
|
410
|
+
results = request_upload_files(commit_sha1, tree, force, new_branch, partial_commit)
|
|
411
|
+
|
|
412
|
+
# puts "Got #{results['files'].size} files to upload from #{files_chunk.size} files"
|
|
413
|
+
|
|
414
|
+
if results['files'].blank?
|
|
415
|
+
progress_mutex.synchronize { progressbar.progress += tree.keys.length }
|
|
416
|
+
next
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Handle directories:
|
|
420
|
+
new_dirs = tree.keys.select {|k| tree[k].nil?}
|
|
421
|
+
dirs += new_dirs
|
|
422
|
+
|
|
423
|
+
files_to_upload = results['files']
|
|
424
|
+
progress_mutex.synchronize {
|
|
425
|
+
progressbar.progress += tree.keys.length - files_to_upload.length
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
files_to_upload.keys.each do |key|
|
|
429
|
+
while file_queue.size > 5000
|
|
430
|
+
sleep(0.1)
|
|
431
|
+
end
|
|
432
|
+
file_queue.push tree[key].merge(files_to_upload[key])
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
progress_thread.join()
|
|
437
|
+
worker_threads.each(&:join)
|
|
438
|
+
|
|
439
|
+
rescue => e
|
|
440
|
+
puts e
|
|
441
|
+
Cnvrg::Logger.log_method(bind: binding)
|
|
442
|
+
Cnvrg::Logger.log_error(e)
|
|
443
|
+
raise e
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def upload_single_file(cli, file)
|
|
448
|
+
success = false
|
|
184
449
|
begin
|
|
185
450
|
file = file.as_json
|
|
186
451
|
Cnvrg::Logger.log_info("Uploading #{file["absolute_path"]}")
|
|
187
452
|
@downloader.safe_upload(file["path"], file["absolute_path"])
|
|
453
|
+
success = true
|
|
188
454
|
Cnvrg::Logger.log_info("#{file["absolute_path"]} uploaded.")
|
|
189
455
|
rescue => e
|
|
190
456
|
Cnvrg::Logger.log_error_message("Error while upload single file #{file["path"]}")
|
|
191
457
|
Cnvrg::Logger.log_error(e)
|
|
192
|
-
return false
|
|
193
458
|
end
|
|
459
|
+
success
|
|
194
460
|
end
|
|
195
461
|
|
|
196
462
|
def upload_file(absolute_path, relative_path, commit_sha1)
|
|
@@ -859,45 +1125,57 @@ module Cnvrg
|
|
|
859
1125
|
return false
|
|
860
1126
|
end
|
|
861
1127
|
end
|
|
1128
|
+
|
|
862
1129
|
def revoke_download(tar_files, extracted_files)
|
|
863
1130
|
begin
|
|
864
|
-
|
|
865
1131
|
FileUtils.rm_rf(tar_files) unless (tar_files.nil? or tar_files.empty?)
|
|
866
1132
|
FileUtils.rm_rf(extracted_files) unless (extracted_files.nil? or extracted_files.empty?)
|
|
867
|
-
|
|
868
1133
|
rescue => e
|
|
869
1134
|
return false
|
|
870
1135
|
end
|
|
871
|
-
|
|
872
1136
|
return true
|
|
873
|
-
|
|
874
1137
|
end
|
|
1138
|
+
|
|
875
1139
|
def delete_commit(commit_sha1)
|
|
876
1140
|
response = Cnvrg::API.request("#{base_resource}/commit/#{commit_sha1}", 'DELETE')
|
|
877
1141
|
Cnvrg::CLI.is_response_success(response, true)
|
|
878
1142
|
return response
|
|
879
1143
|
end
|
|
1144
|
+
|
|
880
1145
|
def get_commit(commit_sha1)
|
|
881
1146
|
response = Cnvrg::API.request("#{base_resource}/commit/#{commit_sha1}", 'GET')
|
|
882
1147
|
Cnvrg::CLI.is_response_success(response, true)
|
|
883
1148
|
return response
|
|
884
1149
|
end
|
|
885
1150
|
|
|
886
|
-
def start_commit(new_branch,force=false,
|
|
1151
|
+
def start_commit(new_branch, force=false, chunks: 0, dataset: @dataset, message:nil)
|
|
887
1152
|
begin
|
|
888
1153
|
#if we are pushing with force or to branch we dont need to send current/next commit cause we want to
|
|
889
1154
|
# create a new commit.
|
|
890
1155
|
idx = (force || new_branch) ? {} : dataset.get_idx
|
|
891
1156
|
commit = idx[:commit]
|
|
892
1157
|
next_commit = idx[:next_commit]
|
|
893
|
-
response = Cnvrg::API.request(
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1158
|
+
response = Cnvrg::API.request(
|
|
1159
|
+
"#{base_resource}/commit/start",
|
|
1160
|
+
'POST',
|
|
1161
|
+
{
|
|
1162
|
+
dataset_slug: @dataset_slug,
|
|
1163
|
+
new_branch: new_branch,
|
|
1164
|
+
force:force,
|
|
1165
|
+
username: @owner,
|
|
1166
|
+
current_commit: commit,
|
|
1167
|
+
next_commit: next_commit,
|
|
1168
|
+
total_chunks: chunks,
|
|
1169
|
+
message: message
|
|
1170
|
+
}
|
|
1171
|
+
)
|
|
1172
|
+
Cnvrg::CLI.is_response_success(response, true)
|
|
1173
|
+
return response
|
|
897
1174
|
rescue => e
|
|
898
1175
|
return false
|
|
899
1176
|
end
|
|
900
1177
|
end
|
|
1178
|
+
|
|
901
1179
|
def last_valid_commit()
|
|
902
1180
|
begin
|
|
903
1181
|
#if we are pushing with force or to branch we dont need to send current/next commit cause we want to
|
|
@@ -910,15 +1188,24 @@ module Cnvrg
|
|
|
910
1188
|
end
|
|
911
1189
|
end
|
|
912
1190
|
|
|
913
|
-
def end_commit(commit_sha1,force, success: true, uploaded_files: 0 )
|
|
1191
|
+
def end_commit(commit_sha1, force, success: true, uploaded_files: 0, commit_type: nil)
|
|
914
1192
|
begin
|
|
915
|
-
response = Cnvrg::API.request(
|
|
1193
|
+
response = Cnvrg::API.request(
|
|
1194
|
+
"#{base_resource}/commit/end",
|
|
1195
|
+
'POST',
|
|
1196
|
+
{
|
|
1197
|
+
commit_sha1: commit_sha1,
|
|
1198
|
+
force:force,
|
|
1199
|
+
success: success,
|
|
1200
|
+
uploaded_files: uploaded_files,
|
|
1201
|
+
commit_type: commit_type
|
|
1202
|
+
}
|
|
1203
|
+
)
|
|
916
1204
|
Cnvrg::CLI.is_response_success(response, true)
|
|
917
1205
|
return response
|
|
918
1206
|
rescue => e
|
|
919
1207
|
return false
|
|
920
1208
|
end
|
|
921
|
-
|
|
922
1209
|
end
|
|
923
1210
|
|
|
924
1211
|
def end_commit_tar(commit_sha1, cur_idx)
|
|
@@ -1001,34 +1288,43 @@ module Cnvrg
|
|
|
1001
1288
|
end
|
|
1002
1289
|
end
|
|
1003
1290
|
|
|
1004
|
-
def
|
|
1005
|
-
|
|
1291
|
+
def last_valid_commit()
|
|
1292
|
+
begin
|
|
1293
|
+
response = Cnvrg::API.request("#{base_resource}/last_valid_commit", 'GET')
|
|
1294
|
+
Cnvrg::CLI.is_response_success(response, true)
|
|
1295
|
+
return response
|
|
1296
|
+
rescue => e
|
|
1297
|
+
return false
|
|
1298
|
+
end
|
|
1006
1299
|
end
|
|
1007
1300
|
|
|
1008
|
-
def download_multiple_files_s3(files, project_home, conflict: false, progressbar: nil, read_only:false)
|
|
1301
|
+
def download_multiple_files_s3(files, project_home, conflict: false, progressbar: nil, read_only:false, flatten: false)
|
|
1009
1302
|
begin
|
|
1303
|
+
refresh_storage_token
|
|
1010
1304
|
parallel_options = {
|
|
1011
1305
|
in_threads: ParallelThreads,
|
|
1012
1306
|
isolation: true
|
|
1013
1307
|
}
|
|
1014
1308
|
Parallel.map(files["keys"], parallel_options) do |f|
|
|
1015
1309
|
begin
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1310
|
+
file_path = f['name']
|
|
1311
|
+
file_path = File.basename(f['name']) if flatten
|
|
1312
|
+
local_path = @dataset.local_path + '/' + file_path
|
|
1313
|
+
Cnvrg::Logger.log_info("Downloading #{local_path}")
|
|
1314
|
+
progressbar.progress += 1 if progressbar.present?
|
|
1315
|
+
if local_path.end_with? "/"
|
|
1316
|
+
@downloader.mkdir(local_path, recursive: true)
|
|
1317
|
+
next
|
|
1318
|
+
end
|
|
1319
|
+
# blob
|
|
1320
|
+
local_path = "#{local_path}.conflict" if conflict
|
|
1321
|
+
storage_path = f["path"]
|
|
1322
|
+
if File.exists? local_path
|
|
1323
|
+
Cnvrg::Logger.log_info("Trying to download #{local_path} but its already exists, skipping..")
|
|
1324
|
+
next
|
|
1325
|
+
end
|
|
1326
|
+
resp = @downloader.download(storage_path, local_path)
|
|
1327
|
+
Cnvrg::Logger.log_info("Download #{local_path} success resp: #{resp}")
|
|
1032
1328
|
rescue => e
|
|
1033
1329
|
Cnvrg::Logger.log_error(e)
|
|
1034
1330
|
end
|