cnvrg 0.0.14.0 → 0.0.15
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 +9 -5
- data/lib/cnvrg/Images.rb +76 -15
- data/lib/cnvrg/api.rb +7 -4
- data/lib/cnvrg/cli.rb +2148 -526
- data/lib/cnvrg/data.rb +72 -0
- data/lib/cnvrg/datafiles.rb +509 -0
- data/lib/cnvrg/dataset.rb +296 -0
- data/lib/cnvrg/experiment.rb +19 -10
- data/lib/cnvrg/files.rb +302 -208
- data/lib/cnvrg/helpers.rb +42 -1
- data/lib/cnvrg/job.rb +0 -1
- data/lib/cnvrg/project.rb +55 -15
- data/lib/cnvrg/ssh.rb +95 -0
- data/lib/cnvrg/version.rb +2 -1
- data/lib/cnvrg.rb +0 -1
- metadata +48 -17
@@ -0,0 +1,296 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
module Cnvrg
|
3
|
+
class Dataset
|
4
|
+
attr_reader :slug, :owner, :title, :local_path, :working_dir
|
5
|
+
|
6
|
+
RemoteURL ||= "https://cnvrg.io"
|
7
|
+
|
8
|
+
def initialize(project_home)
|
9
|
+
begin
|
10
|
+
config = YAML.load_file(project_home+"/.cnvrg/config.yml")
|
11
|
+
@local_path = project_home
|
12
|
+
@title = config[:dataset_name]
|
13
|
+
@slug = config[:dataset_slug]
|
14
|
+
@owner = config[:owner]
|
15
|
+
@working_dir = project_home
|
16
|
+
rescue => e
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def last_local_commit
|
23
|
+
idx = YAML.load_file(@local_path + "/.cnvrg/idx.yml")
|
24
|
+
return idx[:commit]
|
25
|
+
end
|
26
|
+
|
27
|
+
def snapshot
|
28
|
+
commit = last_local_commit
|
29
|
+
response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/volumes/create", 'POST', {data_commit: commit})
|
30
|
+
CLI.is_response_success(response)
|
31
|
+
return response
|
32
|
+
|
33
|
+
end
|
34
|
+
def list(owner)
|
35
|
+
response = Cnvrg::API.request("users/#{owner}/datasets/list", 'GET')
|
36
|
+
CLI.is_response_success(response)
|
37
|
+
return response
|
38
|
+
|
39
|
+
end
|
40
|
+
def list_commits
|
41
|
+
response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/list_commits", 'GET')
|
42
|
+
CLI.is_response_success(response)
|
43
|
+
return response
|
44
|
+
|
45
|
+
end
|
46
|
+
def url
|
47
|
+
url = Cnvrg::Helpers.remote_url
|
48
|
+
"#{url}/#{self.owner}/projects/#{self.slug}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def update_ignore_list(new_ignore)
|
52
|
+
|
53
|
+
if new_ignore.nil? or new_ignore.empty?
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
begin
|
57
|
+
File.open(self.local_path+"/.cnvrgignore", "a+") do |f|
|
58
|
+
f.puts("\n")
|
59
|
+
|
60
|
+
new_ignore.each do |i|
|
61
|
+
f.puts("#{i}\n")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
return true
|
65
|
+
rescue
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_ignore_list
|
71
|
+
ignore_list = []
|
72
|
+
File.open(self.local_path+"/.cnvrgignore", "r").each_line do |line|
|
73
|
+
line = line.strip
|
74
|
+
|
75
|
+
if line.start_with? "#" or ignore_list.include? line
|
76
|
+
next
|
77
|
+
end
|
78
|
+
if line.end_with? "/" or File.directory?(line)
|
79
|
+
if line.end_with? "/"
|
80
|
+
ignore_list << line.chop
|
81
|
+
else
|
82
|
+
ignore_list << line
|
83
|
+
end
|
84
|
+
all_sub = Dir.glob("#{line}/**/*", File::FNM_DOTMATCH).flatten
|
85
|
+
ignore_list << all_sub.flatten
|
86
|
+
ignore_list << line
|
87
|
+
else
|
88
|
+
ignore_list << line
|
89
|
+
end
|
90
|
+
end
|
91
|
+
return ignore_list.flatten
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def self.init(owner, dataset_name, is_public=false)
|
97
|
+
list_dirs = [".cnvrg"
|
98
|
+
]
|
99
|
+
list_files = [
|
100
|
+
".cnvrgignore",
|
101
|
+
".cnvrg/config.yml"
|
102
|
+
]
|
103
|
+
|
104
|
+
cnvrgignore = Helpers.cnvrgignore_content
|
105
|
+
begin
|
106
|
+
response = Cnvrg::API.request("cli/create_dataset", 'POST', {title: dataset_name, owner: owner, is_public: is_public})
|
107
|
+
Cnvrg::CLI.is_response_success(response)
|
108
|
+
response = JSON.parse response["result"]
|
109
|
+
dataset_slug = response["slug"]
|
110
|
+
|
111
|
+
config = {dataset_name: dataset_name,
|
112
|
+
dataset_slug: dataset_slug,
|
113
|
+
owner: owner}
|
114
|
+
FileUtils.mkdir_p list_dirs
|
115
|
+
FileUtils.touch list_files
|
116
|
+
File.open(".cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
117
|
+
File.open(".cnvrgignore", "w+") { |f| f.write cnvrgignore } unless File.exist? ".cnvrgignore"
|
118
|
+
rescue => e
|
119
|
+
"Exception in init data: #{e.message}"
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
return true
|
123
|
+
end
|
124
|
+
def self.clone(owner, dataset_name,dataset_slug)
|
125
|
+
|
126
|
+
begin
|
127
|
+
list_dirs = [ dataset_name, "#{dataset_name}/.cnvrg"
|
128
|
+
]
|
129
|
+
list_files = [
|
130
|
+
"#{dataset_name}/.cnvrgignore",
|
131
|
+
"#{dataset_name}/.cnvrg/config.yml"
|
132
|
+
]
|
133
|
+
|
134
|
+
config = {dataset_name: dataset_name,
|
135
|
+
dataset_slug: dataset_slug,
|
136
|
+
owner: owner}
|
137
|
+
|
138
|
+
|
139
|
+
cnvrgignore = Helpers.cnvrgignore_content
|
140
|
+
FileUtils.mkdir_p list_dirs
|
141
|
+
FileUtils.touch list_files
|
142
|
+
File.open("#{dataset_name}/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
143
|
+
File.open("#{dataset_name}/.cnvrgignore", "w+") { |f| f.write cnvrgignore } unless File.exist? ".cnvrgignore"
|
144
|
+
rescue => e
|
145
|
+
puts "Exception in clone request:#{e.message}"
|
146
|
+
return false
|
147
|
+
end
|
148
|
+
return true
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.init_container(owner, dataset_slug,dataset_name)
|
152
|
+
|
153
|
+
cnvrgignore = Helpers.cnvrgignore_content
|
154
|
+
begin
|
155
|
+
list_dirs = [ ".cnvrg"
|
156
|
+
]
|
157
|
+
list_files = [
|
158
|
+
".cnvrgignore",
|
159
|
+
".cnvrg/config.yml"
|
160
|
+
]
|
161
|
+
FileUtils.mkdir_p list_dirs
|
162
|
+
FileUtils.touch list_files
|
163
|
+
|
164
|
+
config = {dataset_name: dataset_name,
|
165
|
+
dataset_slug: dataset_slug,
|
166
|
+
owner: owner}
|
167
|
+
File.open(".cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
168
|
+
|
169
|
+
File.open(".cnvrgignore", "w+") { |f| f.write cnvrgignore } unless File.exist? ".cnvrgignore"
|
170
|
+
rescue => e
|
171
|
+
return false
|
172
|
+
end
|
173
|
+
return true
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
def get_idx
|
178
|
+
YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
|
179
|
+
end
|
180
|
+
def url
|
181
|
+
url = Cnvrg::Helpers.remote_url
|
182
|
+
"#{url}/#{self.owner}/datasets/#{self.slug}"
|
183
|
+
end
|
184
|
+
def generate_idx
|
185
|
+
if File.exists? "#{self.local_path}/.cnvrg/idx.yml"
|
186
|
+
old_idx = YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
|
187
|
+
else
|
188
|
+
old_idx = nil
|
189
|
+
end
|
190
|
+
|
191
|
+
tree_idx = Hash.new(0)
|
192
|
+
|
193
|
+
list = Dir.glob("#{self.local_path}/**/**", File::FNM_DOTMATCH).reject { |x| (x =~ /\/\.{1,2}$/) or (x =~ /^#{self.local_path}\/\.cnvrg\/*/) }
|
194
|
+
list_ignore = self.get_ignore_list()
|
195
|
+
list.each do |e|
|
196
|
+
label = e.gsub(self.local_path + "/", "")
|
197
|
+
if File.directory? e
|
198
|
+
if list_ignore.include? label
|
199
|
+
next
|
200
|
+
end
|
201
|
+
tree_idx[label+"/"] = nil
|
202
|
+
else
|
203
|
+
if list_ignore.include? label
|
204
|
+
next
|
205
|
+
end
|
206
|
+
sha1 = Digest::SHA1.file(e).hexdigest
|
207
|
+
if old_idx.nil? or old_idx.to_h["tree"].nil?
|
208
|
+
tree_idx[label] = {sha1: sha1, commit_time: nil}
|
209
|
+
elsif old_idx["tree"][label].nil? or old_idx["tree"][label]["sha1"] != sha1
|
210
|
+
tree_idx[label] = {sha1: sha1, commit_time: nil}
|
211
|
+
else
|
212
|
+
tree_idx[label] = old_idx["tree"][label]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
idx = {commit: old_idx.to_h[:commit], tree: tree_idx}
|
218
|
+
|
219
|
+
File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx.to_yaml }
|
220
|
+
return YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
|
221
|
+
end
|
222
|
+
def create_volume
|
223
|
+
response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/volumes/create", 'POST')
|
224
|
+
CLI.is_response_success(response)
|
225
|
+
return response
|
226
|
+
end
|
227
|
+
|
228
|
+
def downlowd_updated_data(current_commit)
|
229
|
+
|
230
|
+
response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/downlowd_updated_data", 'POST', {current_commit: current_commit})
|
231
|
+
CLI.is_response_success(response,false)
|
232
|
+
return response
|
233
|
+
end
|
234
|
+
def compare_idx(new_branch, commit=last_local_commit,local_idx=nil)
|
235
|
+
if local_idx.nil?
|
236
|
+
local_idx = self.generate_idx
|
237
|
+
end
|
238
|
+
|
239
|
+
response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/status", 'POST', {idx: local_idx, new_branch: new_branch, current_commit: commit})
|
240
|
+
CLI.is_response_success(response,false)
|
241
|
+
return response
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
def compare_commits(commit)
|
247
|
+
response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/compare_commits", 'POST', {compare_commit: commit,current_commit:last_local_commit})
|
248
|
+
CLI.is_response_success(response,false)
|
249
|
+
return response
|
250
|
+
end
|
251
|
+
|
252
|
+
def compare_commit(commit)
|
253
|
+
if commit.nil? or commit.empty?
|
254
|
+
commit = last_local_commit
|
255
|
+
end
|
256
|
+
response = Cnvrg::API.request("users/#{self.owner}/projects/#{self.slug}/commit/compare", 'POST', {current_commit: commit})
|
257
|
+
CLI.is_response_success(response,false)
|
258
|
+
update_is_new_branch(response["result"]["new_branch"])
|
259
|
+
return response["result"]["new_branch"]
|
260
|
+
end
|
261
|
+
|
262
|
+
def update_idx_with_files_commits!(files, commit_time)
|
263
|
+
|
264
|
+
idx_hash = YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
|
265
|
+
files.each do |path|
|
266
|
+
idx_hash[:tree].to_h[path].to_h[:commit_time] = commit_time
|
267
|
+
end
|
268
|
+
File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx_hash.to_yaml }
|
269
|
+
|
270
|
+
return true
|
271
|
+
end
|
272
|
+
def update_idx(idx)
|
273
|
+
File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx.to_yaml }
|
274
|
+
|
275
|
+
return true
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
def update_idx_with_commit!(commit)
|
280
|
+
idx_hash = YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
|
281
|
+
idx_hash[:commit] = commit
|
282
|
+
|
283
|
+
File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx_hash.to_yaml }
|
284
|
+
return true
|
285
|
+
end
|
286
|
+
|
287
|
+
def revert(working_dir)
|
288
|
+
FileUtils.rm_rf working_dir
|
289
|
+
# response = Cnvrg::API.request("users/#{self.owner}/projects/#{self.slug}/revert", 'GET')
|
290
|
+
# CLI.is_response_success(response)
|
291
|
+
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
end
|
data/lib/cnvrg/experiment.rb
CHANGED
@@ -9,11 +9,11 @@ module Cnvrg
|
|
9
9
|
@slug = nil
|
10
10
|
end
|
11
11
|
|
12
|
-
def start(input, platform, machine_name, start_commit, name, email_notification, machine_activity)
|
12
|
+
def start(input, platform, machine_name, start_commit, name, email_notification, machine_activity,script_path)
|
13
13
|
res = Cnvrg::API.request(@base_resource + "experiment/start", 'POST',
|
14
14
|
{input: input, platform: platform, machine_name: machine_name, start_commit: start_commit,
|
15
|
-
title: name, email_notification: email_notification, machine_activity: machine_activity})
|
16
|
-
Cnvrg::CLI.is_response_success(res)
|
15
|
+
title: name, email_notification: email_notification, machine_activity: machine_activity,script_path:script_path})
|
16
|
+
Cnvrg::CLI.is_response_success(res,false)
|
17
17
|
|
18
18
|
@slug = res.to_h["result"].to_h["slug"]
|
19
19
|
|
@@ -37,7 +37,7 @@ module Cnvrg
|
|
37
37
|
def end_notebook_session(notebook_slug, end_commit)
|
38
38
|
res = Cnvrg::API.request(@base_resource + "notebook/end_session", 'POST',
|
39
39
|
{notebook_slug: notebook_slug, end_commit: end_commit})
|
40
|
-
Cnvrg::CLI.is_response_success(res)
|
40
|
+
Cnvrg::CLI.is_response_success(res,false)
|
41
41
|
|
42
42
|
return res
|
43
43
|
|
@@ -78,27 +78,36 @@ module Cnvrg
|
|
78
78
|
|
79
79
|
end
|
80
80
|
|
81
|
-
def exec_remote(command, commit_to_run, instance_type, image_slug,scheduling_query,local_timestamp)
|
81
|
+
def exec_remote(command, commit_to_run, instance_type, image_slug,scheduling_query,local_timestamp, grid,path_to_cmd,data, data_commit)
|
82
82
|
response = Cnvrg::API.request("users/#{@owner}/projects/#{@project_slug}/experiment/remote", 'POST', {command: command, image_slug: image_slug,
|
83
83
|
commit_sha1: commit_to_run,
|
84
84
|
instance_type: instance_type,
|
85
85
|
scheduling_query:scheduling_query,
|
86
|
-
local_timestamp:local_timestamp
|
86
|
+
local_timestamp:local_timestamp,
|
87
|
+
grid: grid,
|
88
|
+
path_to_cmd:path_to_cmd,dataset_slug:data,
|
89
|
+
dataset_commit: data_commit})
|
87
90
|
return response
|
88
91
|
end
|
89
92
|
|
90
93
|
def upload_temp_log(temp_log, cpu_average, memory_average)
|
91
94
|
response = Cnvrg::API.request(@base_resource + "experiment/upload_temp_log", 'POST', {output: temp_log,
|
92
|
-
exp_slug: @slug
|
93
|
-
|
94
|
-
Cnvrg::CLI.is_response_success(response)
|
95
|
+
exp_slug: @slug})
|
96
|
+
Cnvrg::CLI.is_response_success(response,false)
|
95
97
|
end
|
96
98
|
|
97
99
|
def end(output, exit_status, end_commit, cpu_average, memory_average)
|
100
|
+
#if remote try to remove
|
98
101
|
response = Cnvrg::API.request(@base_resource + "experiment/end", 'POST', {output: output, exp_slug: @slug,
|
99
102
|
exit_status: exit_status, end_commit: end_commit,
|
100
103
|
cpu_average: cpu_average, memory_average: memory_average})
|
101
|
-
Cnvrg::CLI.is_response_success(response)
|
104
|
+
Cnvrg::CLI.is_response_success(response,false)
|
105
|
+
|
106
|
+
begin
|
107
|
+
FileUtils.rm_rf(["/home/ds/.cnvrg/tmp/exec.log"])
|
108
|
+
rescue
|
109
|
+
|
110
|
+
end
|
102
111
|
end
|
103
112
|
end
|
104
113
|
end
|