cnvrg 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 27f1b54ab10e9cc75d4c290fa0802c11a148275c
4
- data.tar.gz: 4e80f1fbb3b2d3c4bd5450708359de08212105a3
3
+ metadata.gz: ffd4052a08f7eb71ea98aa8f19de96bdff87fc44
4
+ data.tar.gz: 3b6590a222fac4dd9f76ff426741c6a8307d03d3
5
5
  SHA512:
6
- metadata.gz: eb9766dc5c54ad8b5d8e4463178dc0cd696e76c214dd1e8d89d67f23369d68e716647ac253484c65f273352196530626b9e1a35f932b4484226f603c12056079
7
- data.tar.gz: 009acaba20cd093a9ed713ba96025b65f981616a47d22e63ec6474d4d91677afef99f141b976c78727f193f5524b5587569d1bf6c4948bb9a0cab6866767c81c
6
+ metadata.gz: 80a6c9f306f598d71b0b16e1cad9ada5d25183ec634197c49b4271784ffb39afc33e0d1c68b4729dcc27c426442355a29b0ff578bb3b60f23e108803d3ec5356
7
+ data.tar.gz: dd6e15721cb90947998f1e9e568e5f8a57bf0a6f8e16b30a9cb2d5e9d732b75a331bebe1e08ec202527bdb1b9a95972902611395a6f877da00024e79d4012912
@@ -34,11 +34,15 @@ Gem::Specification.new do |spec|
34
34
  spec.add_runtime_dependency 'aws-sdk'
35
35
  spec.add_runtime_dependency 'sucker_punch', '~> 2.0'
36
36
  spec.add_runtime_dependency 'urlcrypt', '~> 0.1.1'
37
- spec.add_runtime_dependency 'logstash-logger'
38
- spec.add_runtime_dependency 'launchy'
39
- spec.add_runtime_dependency 'docker-api'
40
- spec.add_runtime_dependency 'rubyzip'
41
- spec.add_runtime_dependency 'activesupport'
37
+ spec.add_runtime_dependency 'logstash-logger', '~> 0.22.1'
38
+ spec.add_runtime_dependency 'launchy', '~> 2.4'
39
+ spec.add_runtime_dependency 'docker-api', '~> 1.33'
40
+ spec.add_runtime_dependency 'rubyzip', '~> 1.2'
41
+ spec.add_runtime_dependency 'activesupport', '~> 5.0'
42
+ spec.add_runtime_dependency 'ruby-progressbar'
43
+ spec.add_runtime_dependency 'net-ssh'
44
+
45
+
42
46
 
43
47
 
44
48
  end
@@ -3,6 +3,5 @@ require 'cnvrg/version'
3
3
  require 'cnvrg/cli'
4
4
  require 'thor'
5
5
 
6
-
7
6
  module Cnvrg
8
7
  end
@@ -1,6 +1,8 @@
1
1
  require 'fileutils'
2
2
  require 'cnvrg/files'
3
3
  require 'docker'
4
+ require 'net/ssh'
5
+
4
6
 
5
7
  module Cnvrg
6
8
  class Images
@@ -46,7 +48,6 @@ module Cnvrg
46
48
  end
47
49
 
48
50
  rescue => e
49
- puts e
50
51
  end
51
52
 
52
53
  end
@@ -80,22 +81,111 @@ module Cnvrg
80
81
 
81
82
  end
82
83
  end
84
+ def store_image_build_commands(working_dir, cmd)
85
+ begin
86
+ custom_image_file = working_dir+"/.cnvrg/custom_image.txt"
87
+ if !File.exist? custom_image_file
88
+ FileUtils.touch [custom_image_file]
89
+ end
90
+ File.open(custom_image_file, 'a' ) do |f|
91
+ f.puts cmd
92
+ end
93
+ rescue
94
+ end
83
95
 
84
- def create_custom_image(new_image_name)
85
- new_image_name = @project_slug+"_"+@commit_id unless !new_image_name.empty?
86
- python_arr = get_installed_packages("python")
87
- py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
96
+
97
+ end
98
+ def self.create_new_custom_image(type,owner,image_name,is_public,is_base,image_extend,python3)
99
+ response = Cnvrg::API.request("users/#{owner}/images/custom", 'POST', {instance_type:type,image_name:image_name,is_public:is_public,
100
+ is_base:is_base,image_extend:image_extend,
101
+ python3:python3})
102
+ return response
103
+ end
104
+ def self.revoke_custom_new_image(owner,slug)
105
+ response = Cnvrg::API.request("users/#{owner}/images/#{slug}/revoke_image", 'GET')
106
+ return response
107
+ end
108
+ def self.commit_custom_image(owner,slug)
109
+ response = Cnvrg::API.request("users/#{owner}/images/#{slug}/commit_custom_image", 'GET')
110
+ return response
111
+ end
112
+ def self.ssh_to_machine(resp)
113
+
114
+ sts_path = resp["result"]["sts_path"]
115
+
116
+ uri = URI.parse(sts_path)
117
+
118
+ http_object = Net::HTTP.new(uri.host, uri.port)
119
+ http_object.use_ssl = true if uri.scheme == 'https'
120
+ request = Net::HTTP::Get.new(sts_path)
121
+
122
+ body = ""
123
+ http_object.start do |http|
124
+ response = http.request request
125
+ body = response.read_body
126
+ end
127
+
128
+ URLcrypt::key = [body].pack('H*')
129
+
130
+ ip = URLcrypt.decrypt(resp["result"]["machine_i"])
131
+
132
+ user = URLcrypt.decrypt(resp["result"]["machine_u"])
133
+ key = URLcrypt.decrypt(resp["result"]["machine_k"])
134
+ tempssh = Tempfile.new "sshkey"
135
+ tempssh.write open(key).read
136
+ tempssh.rewind
137
+ key_path = tempssh.path
138
+ count = 0
139
+ while count < 5
140
+
141
+ begin
142
+ ssh = Net::SSH.start(ip, user=user, :keys => key_path, :timeout => 10)
143
+ if !ssh.nil?
144
+ return ssh
145
+ else
146
+ count+=1
147
+ sleep(2)
148
+
149
+ end
150
+ rescue
151
+ count+=1
152
+ sleep(2)
153
+
154
+
155
+ end
156
+ end
157
+ if tempssh
158
+ tempssh.close
159
+ tempssh.unlink
160
+ end
161
+ return false
162
+ end
163
+
164
+
165
+
166
+ def create_custom_image(new_image_name,working_dir,stored_commands)
167
+
168
+ python2_arr = get_installed_packages("python2")
169
+ py2 = python2_arr.join(",") unless python2_arr.nil? or python2_arr.empty?
170
+ python3_arr = get_installed_packages("python3")
171
+ py3 = python3_arr.join(",") unless python3_arr.nil? or python3_arr.empty?
88
172
  system_arr = get_installed_packages("system")
89
173
  sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
90
- bash_history = get_bash_history
91
- response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/custom", 'POST', {image_slug: @image_slug, libraries: py,
92
- dpkg: sys, new_image_name: new_image_name})
174
+
175
+ response = Cnvrg::API.request("users/#{@owner}/projects/#{@project_slug}/images/push", 'POST', {image_slug: @image_slug, py2: py2,py3:py3,
176
+ dpkg: sys, new_image_name: new_image_name,
177
+ run_commands:stored_commands})
93
178
  if Cnvrg::CLI.is_response_success(response) and !response["result"]["slug"].nil?
94
179
  container = get_container()
95
- update_image(new_image_name+":latest", container, response["result"]["slug"])
180
+ name = response["result"]["name"]
181
+ container = get_container()
182
+ container.commit({repo:name,tag:"latest"})
183
+ update_image(name+":latest", container, response["result"]["slug"])
184
+ File.truncate(working_dir+"/.cnvrg/custom_image.txt", 0)
185
+
96
186
  end
97
187
 
98
- return response
188
+ return true
99
189
 
100
190
  end
101
191
 
@@ -151,9 +241,10 @@ module Cnvrg
151
241
  def create_container(port=7654, is_remote=false)
152
242
  begin
153
243
  image_settings = {
154
- 'Image' => "#{@image_name}:#{@image_tag}",
244
+ 'Image' => "#{@image_name}:latest",
155
245
  'User' => 'ds',
156
- 'Cmd' => '/home/ds/run_ipython.sh',
246
+ 'Cmd' => '/usr/local/cnvrg/run_ipython.sh',
247
+ 'WorkingDir' => '/home/ds/notebooks',
157
248
  'ExposedPorts' => {
158
249
  '8888/tcp' => {},
159
250
  },
@@ -166,9 +257,6 @@ module Cnvrg
166
257
  },
167
258
  },
168
259
  }
169
- # if !is_remote
170
- # image_settings['HostConfig'].merge!({ 'Binds' => ["#{@working_dir}:/home/ds/notebooks"]})
171
- # end
172
260
  container = Docker::Container.create(image_settings)
173
261
  container.start()
174
262
  netrc = File.open(File.expand_path('~')+"/.netrc", "rb")
@@ -178,10 +266,6 @@ module Cnvrg
178
266
  p = container.exec(command, tty: true)
179
267
  command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.netrc"]
180
268
  p = container.exec(command, tty: true)
181
- command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
182
- container.exec(command, tty: true)
183
- command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
184
- container.exec(command, tty: true)
185
269
  config = File.open(File.expand_path('~')+"/.cnvrg/config.yml", "rb")
186
270
  config_content = config.read
187
271
  container.store_file("/home/ds/.cnvrg/config.yml", config_content)
@@ -204,7 +288,6 @@ module Cnvrg
204
288
  if e.message.include? "is not running"
205
289
  return create_container(port-1)
206
290
  end
207
- puts e
208
291
  return false
209
292
  rescue SignalException
210
293
 
@@ -224,25 +307,28 @@ module Cnvrg
224
307
  File.open(@working_dir+"/.cnvrg/pip_base.txt", "w+") { |f| f.write pip }
225
308
  File.open(@working_dir+"/.cnvrg/dpkg_base.txt", "w+") { |f| f.write dpkg }
226
309
  rescue => e
227
- puts e
228
310
  end
229
311
 
230
312
 
231
313
  end
232
314
 
233
- def remote_notebook(notebook_path, instance_type, kernel)
315
+ def remote_notebook(notebook_path, instance_type, kernel,data,data_commit)
234
316
  response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/remote_notebook", 'POST', {dir: notebook_path,
235
317
  project_slug: @project_slug,
236
318
  instance_type: instance_type,
237
- kernel: kernel})
319
+ kernel: kernel,
320
+ dataset_slug:data,
321
+ dataset_commit: data_commit})
238
322
  return response
239
323
  end
240
324
 
241
325
  def get_installed_packages(repo)
242
326
  container = get_container()
243
327
  case repo
244
- when "python"
328
+ when "python2"
245
329
  command = ['/bin/bash', '-lc', '/opt/ds/bin/pip freeze']
330
+ when "python3"
331
+ command = ['/bin/bash', '-lc', '/opt/ds3/bin/pip3 freeze']
246
332
  when "system"
247
333
  command = ["/bin/bash", "-lc", "dpkg -l | grep '^ii' | awk '{print $2\"==\"$3}'"]
248
334
  end
@@ -269,8 +355,8 @@ module Cnvrg
269
355
  py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
270
356
  system_arr = self.get_installed_packages("system")
271
357
  sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
272
- bash_history = self.get_bash_history
273
- diff = [py, sys, bash_history]
358
+ # bash_history = self.get_bash_history
359
+ diff = [py, sys]
274
360
 
275
361
  end
276
362
 
@@ -57,7 +57,10 @@ module Cnvrg
57
57
  else
58
58
  response
59
59
  end
60
- when 'POST'
60
+ when 'POST'
61
+ conn.options.timeout = 420
62
+ conn.options.open_timeout =420
63
+
61
64
  response = conn.post "#{endpoint_uri}/#{resource}", data
62
65
 
63
66
  if parse_request == true
@@ -70,12 +73,12 @@ module Cnvrg
70
73
  fr.headers['Auth-Token'] = @pass
71
74
  fr.headers['User-Agent'] = "#{Cnvrg::API::USER_AGENT}"
72
75
  fr.headers["Content-Type"] = "multipart/form-data"
73
-
76
+
74
77
  fr.request :multipart
75
78
  fr.request :url_encoded
76
79
  fr.adapter :net_http
77
80
  end
78
-
81
+
79
82
 
80
83
  # what if windows?
81
84
  # data[:file] = Faraday::UploadIO.new(data[:absolute_path], content_type)
@@ -104,7 +107,7 @@ module Cnvrg
104
107
  else
105
108
  end
106
109
  rescue => e
107
- puts e
110
+ puts e
108
111
  return nil
109
112
  end
110
113
 
@@ -7,7 +7,7 @@ require 'uri'
7
7
  require 'open-uri'
8
8
  require 'json'
9
9
  require 'yaml'
10
- require 'digest' # sha1
10
+ require 'digest' # sha1up
11
11
  require "highline/import"
12
12
  require 'socket'
13
13
  include Open4
@@ -18,6 +18,10 @@ require 'cnvrg/project'
18
18
  require 'cnvrg/files'
19
19
  require 'cnvrg/experiment'
20
20
  require 'cnvrg/Images'
21
+ require 'cnvrg/dataset'
22
+ require 'cnvrg/datafiles'
23
+ require 'cnvrg/data'
24
+ require 'cnvrg/ssh'
21
25
  require 'etc'
22
26
  require 'logstash-logger'
23
27
  require 'cnvrg/job'
@@ -29,27 +33,116 @@ require 'fileutils'
29
33
  require 'zip'
30
34
  require 'active_support/all'
31
35
  require 'thor'
36
+ require 'pathname'
37
+ require 'enumerator'
38
+
39
+ class Thor
40
+ module Base
41
+ def initialize(args = [], local_options = {}, config = {})
42
+ parse_options = Thor.class_options
43
+
44
+ # The start method splits inbound arguments at the first argument
45
+ # that looks like an option (starts with - or --). It then calls
46
+ # new, passing in the two halves of the arguments Array as the
47
+ # first two parameters.
48
+
49
+ command_options = config.delete(:command_options) # hook for start
50
+ parse_options = parse_options.merge(command_options) if command_options
51
+ if local_options.is_a?(Array)
52
+ array_options = local_options
53
+ hash_options = {}
54
+ else
55
+ # Handle the case where the class was explicitly instantiated
56
+ # with pre-parsed options.
57
+ array_options = []
58
+ hash_options = local_options
59
+
60
+ end
61
+
62
+ # Let Thor::Options parse the options first, so it can remove
63
+ # declared options from the array. This will leave us with
64
+ # a list of arguments that weren't declared.
65
+ stop_on_unknown = Thor.stop_on_unknown_option? config[:current_command]
66
+ opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
67
+ real_options = []
68
+
69
+ real_args = [].replace(array_options)
70
+ if local_options.is_a? (Array) and !local_options.empty? and args.empty?
71
+ array_options.each_with_index do |p, i|
72
+ opt = p
73
+ if p.include? "="
74
+ opt = p.split("=")[0]
75
+ end
76
+ option = is_option(parse_options.values, opt)
77
+ if !option
78
+ break
79
+ else
80
+ real_options << p
81
+ real_args.delete(p)
82
+ if !p.include? "=" and option.type != :boolean
83
+ if i+1< array_options.size
84
+ real_options << array_options[i+1]
85
+ real_args.delete(array_options[i+1])
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ args = real_args
94
+ else
95
+ if !args.empty? and local_options.is_a? Array and !local_options.empty?
96
+ args = args + local_options
97
+ else
98
+ args = args.flatten()
99
+ end
100
+
101
+ end
102
+
103
+
104
+ self.options = opts.parse(real_options)
105
+ self.options = config[:class_options].merge(options) if config[:class_options]
106
+
107
+ # If unknown options are disallowed, make sure that none of the
108
+ # remaining arguments looks like an option.
109
+ opts.check_unknown! if Thor.check_unknown_options?(config)
110
+
111
+ # Add the remaining arguments from the options parser to the
112
+ # arguments passed in to initialize. Then remove any positional
113
+ # arguments declared using #argument (this is primarily used
114
+ # by Thor::Group). Tis will leave us with the remaining
115
+ # positional arguments.
116
+ to_parse = args
117
+ to_parse += opts.remaining unless self.class.strict_args_position?(config)
118
+ thor_args = Thor::Arguments.new(self.class.arguments)
119
+ thor_args.parse(to_parse).each { |k, v| __send__("#{k}=", v) }
120
+ @args = thor_args.remaining
121
+ end
122
+
123
+ def is_option (options, p)
124
+ options.each do |o|
125
+ if !o.aliases.nil?
126
+ if (o.aliases.is_a? Array and o.aliases.include? p) or (o.aliases.is_a? Array and o.aliases.size ==1 and o.aliases[0].split(",").include? p) or o.switch_name.eql? p
127
+ return o
128
+ end
129
+ end
130
+
131
+ end
132
+ return false
133
+ end
134
+
135
+ end
136
+ end
137
+
32
138
 
33
- # DEV VERSION
34
- #
35
139
  module Cnvrg
140
+
36
141
  class CLI < Thor
37
142
 
38
143
  INSTALLATION_URLS = {docker: "https://docs.docker.com/engine/installation/", jupyter: "http://jupyter.readthedocs.io/en/latest/install.html"}
39
144
  IP="localhost"
40
145
  PORT=7654
41
- desc '', ''
42
-
43
- def printable_commands(all = true, subcommand = false)
44
- (all ? all_commands : commands).map do |_, command|
45
- next if command.hidden? or (command.description.empty? and command.usage.empty?)
46
- item = []
47
- item << banner(command, false, subcommand)
48
- item << (command.description ? "# #{command.description.gsub(/\s+/m, ' ')}" : "")
49
- item
50
- end.compact
51
- end
52
-
53
146
  class << self
54
147
  # Hackery.Take the run method away from Thor so that we can redefine it.
55
148
  def is_thor_reserved_word?(word, type)
@@ -57,9 +150,10 @@ module Cnvrg
57
150
  super
58
151
  end
59
152
  end
153
+ desc "data", "upload and manage datasets", :hide => true
154
+ subcommand "data", Data
60
155
 
61
- desc "", ""
62
- method_option :schedule, :type => :string, :aliases => ["--s", "-s"], :default => "leahs"
156
+ desc "", "", :hide => true
63
157
 
64
158
  def test
65
159
  # image_settings = {
@@ -77,11 +171,10 @@ module Cnvrg
77
171
  # },
78
172
  # },
79
173
  # }
80
- container = Docker::Container.get('b4d64bf83f41')
81
- s = "/leah/1/2/3/4/5"
82
- command = ["/bin/bash","-lc","sed -i 's#c.NotebookApp.base_url = .*#c.NotebookApp.base_url = \"#{s}\"#' /home/ds/.jupyter/jupyter_notebook_config.py"]
83
- puts container.exec(command, tty: true)
84
-
174
+ # container = Docker::Container.get('b4d64bf83f41')
175
+ # s = "/leah/1/2/3/4/5"
176
+ # command = ["/bin/bash","-lc","sed -i 's#c.NotebookApp.base_url = .*#c.NotebookApp.base_url = \"#{s}\"#' /home/ds/.jupyter/jupyter_notebook_config.py"]
177
+ # puts container.exec(command, tty: true)
85
178
  end
86
179
 
87
180
 
@@ -94,7 +187,7 @@ module Cnvrg
94
187
 
95
188
  map %w(-v --version) => :version
96
189
 
97
- desc 'set api url', 'set api url'
190
+ desc 'api', 'set api url, e.g cnvrg --api "https://cnvrg.io/api"'
98
191
 
99
192
  def set_api_url(url)
100
193
  home_dir = File.expand_path('~')
@@ -110,15 +203,19 @@ module Cnvrg
110
203
  end
111
204
  config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
112
205
  owner = config.to_h[:owner]
206
+ compression_path = "#{File.expand_path('~')}/.cnvrg/tmp"
113
207
 
114
208
  say "Setting default api to be: #{url}", Thor::Shell::Color::BLUE
115
209
  if config.empty?
116
- config = {owner: "", username: "", version_last_check: get_start_day(), api: url}
210
+ config = {owner: "", username: "", version_last_check: get_start_day(), api: url,compression_path: compression_path }
117
211
  else
118
- config = {owner: config.to_h[:owner], username: config.to_h[:username], version_last_check: config.to_h[:version_last_check], api: url}
212
+ if !config.to_h[:compression_path].nil?
213
+ compression_path = config.to_h[:compression_path]
214
+ end
215
+ config = {owner: config.to_h[:owner], username: config.to_h[:username], version_last_check: config.to_h[:version_last_check], api: url, compression_path: compression_path}
119
216
  end
120
217
  res = Cnvrg::API.request("/users/#{owner}/custom_api", 'POST', {custom_api: url})
121
- if Cnvrg::CLI.is_response_success(res)
218
+ if Cnvrg::CLI.is_response_success(res,false)
122
219
 
123
220
  checks = Helpers.checkmark
124
221
 
@@ -136,7 +233,7 @@ module Cnvrg
136
233
  end
137
234
  end
138
235
 
139
- desc '', ''
236
+ desc '', '', :hide => true
140
237
 
141
238
  def set_remote_api_url(owner, current_user, url)
142
239
  home_dir = File.expand_path('~')
@@ -151,7 +248,9 @@ module Cnvrg
151
248
  FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
152
249
  end
153
250
  config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
154
- config = {owner: owner, username: current_user, version_last_check: get_start_day(), api: url}
251
+
252
+ compression_path = "#{home_dir}/.cnvrg/tmp"
253
+ config = {owner: owner, username: current_user, version_last_check: get_start_day(), api: url,compression_path:compression_path}
155
254
  File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
156
255
  say "Done"
157
256
  rescue
@@ -161,57 +260,108 @@ module Cnvrg
161
260
 
162
261
  map %w(-api --api) => :set_api_url
163
262
 
164
- desc 'set default owner', 'set default owner'
263
+ desc 'set_default_owner', 'set default owner'
165
264
 
166
265
  def set_default_owner
266
+ begin
267
+ path = File.expand_path('~')+"/.cnvrg/config.yml"
268
+ if !File.exist?(path)
269
+ say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again", Thor::Shell::Color::RED
167
270
 
168
- path = File.expand_path('~')+"/.cnvrg/config.yml"
169
- if !File.exist?(path)
170
- say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again", Thor::Shell::Color::RED
271
+ exit(0)
272
+ end
273
+ config = YAML.load_file(path)
171
274
 
172
- exit(0)
173
- end
174
- config = YAML.load_file(path)
275
+ username = config.to_h[:username]
276
+ res = Cnvrg::API.request("/users/#{username}/get_possible_owners", 'GET')
277
+ if Cnvrg::CLI.is_response_success(res)
278
+ owner = username
279
+ result = res["result"]
280
+ owners = result["owners"]
281
+ urls = result["urls"]
282
+ choose_owner = result["username"]
283
+ if owners.empty?
284
+ else
285
+ owners << choose_owner
286
+ chosen = false
287
+ while !chosen
288
+ owners_id = owners.each_with_index.map { |x, i| "#{i+1}. #{x}" }
289
+ choose_owner = ask("Choose default owner:\n"+owners_id.join("\n")+"\n")
290
+
291
+ if choose_owner =~ /[[:digit:]]/
292
+ ow_index = choose_owner.to_i-1
293
+ if ow_index<0 or ow_index >= owners.size
294
+ say "No such owner, please choose again", Thor::Shell::Color::BLUE
295
+ chosen = false
296
+ next
297
+ end
298
+ choose_owner = owners[choose_owner.to_i-1]
299
+ chosen = true
175
300
 
176
- username = config.to_h[:username]
177
- res = Cnvrg::API.request("/users/#{username}/get_possible_owners", 'GET')
178
- if Cnvrg::CLI.is_response_success(res)
179
- owner = username
180
- result = res["result"]
181
- owners = result["owners"]
182
- urls = result["urls"]
183
- choose_owner = result["username"]
301
+ else
302
+
303
+ owners_lower = owners.map { |o| o.downcase }
304
+ ow_index = owners_lower.index(choose_owner.downcase)
305
+ if ow_index.nil?
306
+ say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
307
+ else
308
+ chosen = true
309
+ end
310
+ end
184
311
 
185
- if owners.empty?
186
- else
187
- owners << choose_owner
188
- chosen = false
189
- while !chosen
190
- choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
191
-
192
- owners_lower = owners.map { |o| o.downcase }
193
- ow_index = owners_lower.index(choose_owner.downcase)
194
- if ow_index.nil?
195
- say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
196
- else
197
- chosen = true
198
312
  end
313
+
314
+
315
+ end
316
+ if set_owner(choose_owner, result["username"], urls[ow_index])
317
+ say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
318
+ else
319
+ say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
199
320
  end
321
+ end
322
+ rescue SignalException
323
+ say "\nAborting"
324
+ exit(1)
325
+ end
326
+ end
200
327
 
328
+ desc 'set_compression_path', 'set compression path'
329
+ method_option :reset, :type => :boolean, :aliases => ["-r","--reset"], :default => false
201
330
 
331
+ def set_compression_path(*compression_path)
332
+ begin
333
+ if (compression_path.nil? or compression_path.empty?) and options["reset"]
334
+ compression_path = ["#{File.expand_path('~')}/.cnvrg/tmp"]
202
335
  end
203
- if set_owner(owner, username,urls[ow_index])
204
- say "Setting default owner: #{owner}", Thor::Shell::Color::GREEN
205
- else
206
- say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
336
+ compression_path = compression_path.join(" ")
337
+ if !Dir.exist? compression_path
338
+ say "Couldn't find #{compression_path}, please make sure it exist", Thor::Shell::Color::RED
339
+ exit(0)
207
340
  end
341
+
342
+ home_dir = File.expand_path('~')
343
+ path = "#{home_dir}/.cnvrg/config.yml"
344
+ if !File.exist?(path)
345
+ say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again", Thor::Shell::Color::RED
346
+
347
+ exit(0)
348
+ end
349
+ config = YAML.load_file(path)
350
+ config_new = {owner: config.to_h[:owner], username: config.to_h[:username],
351
+ version_last_check: config.to_h[:version_last_check], api: config.to_h[:api], compression_path: compression_path}
352
+ File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config_new.to_yaml }
353
+ checks = Helpers.checkmark
354
+ say "#{checks} Done", Thor::Shell::Color::GREEN
355
+
356
+ rescue SignalException
357
+ say "\nAborting"
358
+ exit(1)
208
359
  end
209
360
  end
210
361
 
211
- map %w(--set-default-owner) => :set_default_owner
212
362
 
213
363
 
214
- desc 'login', 'Authenticate with cnvrg.io and store credentials'
364
+ desc 'login', 'Authenticate with cnvrg.io platform'
215
365
 
216
366
  def login
217
367
  begin
@@ -239,25 +389,46 @@ module Cnvrg
239
389
  owners = result["owners"]
240
390
  urls = result["urls"]
241
391
  choose_owner = result["username"]
242
-
392
+ ow_index = 0
243
393
  if owners.empty?
394
+ choose_owner = result["username"]
244
395
  else
245
- owners << choose_owner
246
- chosen = false
247
- while !chosen
248
- choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
396
+ choose_owner = owners[0]
397
+ end
249
398
 
250
- owners_lower = owners.map { |o| o.downcase }
251
- ow_index = owners_lower.index(choose_owner.downcase)
252
- if ow_index.nil?
253
- say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
254
- else
255
- chosen = true
256
- end
257
- end
399
+ # if owners.empty?
400
+ # else
401
+ # owners << choose_owner
402
+ # chosen = false
403
+ # while !chosen
404
+ # owners_id = owners.each_with_index.map { |x, i| "#{i+1}. #{x}" }
405
+ # choose_owner = ask("Choose default owner:\n"+owners_id.join("\n")+"\n")
406
+ #
407
+ # if choose_owner =~ /[[:digit:]]/
408
+ # ow_index = choose_owner.to_i-1
409
+ # if ow_index<0 or ow_index >= owners.size
410
+ # say "No such owner, please choose again", Thor::Shell::Color::BLUE
411
+ # chosen = false
412
+ # next
413
+ # end
414
+ # choose_owner = owners[choose_owner.to_i-1]
415
+ # chosen = true
416
+ #
417
+ # else
418
+ #
419
+ # owners_lower = owners.map { |o| o.downcase }
420
+ # ow_index = owners_lower.index(choose_owner.downcase)
421
+ # if ow_index.nil?
422
+ # say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
423
+ # else
424
+ # chosen = true
425
+ # end
426
+ # end
427
+ #
428
+ # end
258
429
 
259
430
 
260
- end
431
+ # end
261
432
 
262
433
  if set_owner(choose_owner, result["username"], urls[ow_index])
263
434
  say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
@@ -273,6 +444,11 @@ module Cnvrg
273
444
 
274
445
  exit(1)
275
446
  end
447
+ rescue
448
+
449
+ say "Error Occurred, aborting", Thor::Shell::Color::RED
450
+ logout()
451
+ exit(1)
276
452
  rescue SignalException
277
453
 
278
454
  say "\nAborting"
@@ -302,7 +478,6 @@ module Cnvrg
302
478
 
303
479
  def me()
304
480
  begin
305
-
306
481
  verify_logged_in(false)
307
482
  log_start(__method__, args, options)
308
483
  auth = Cnvrg::Auth.new
@@ -313,6 +488,7 @@ module Cnvrg
313
488
  end
314
489
 
315
490
  log_end(0)
491
+
316
492
  rescue SignalException
317
493
  log_end(-1)
318
494
 
@@ -323,8 +499,8 @@ module Cnvrg
323
499
 
324
500
  ## Projects
325
501
  desc 'new', 'Create a new cnvrg project'
326
- method_option :clean, :type => :boolean, :aliases => ["-c", "--c"], :default => false
327
- method_option :docker_image, :type => :string, :aliases => ["-d", "--d"], :default => ""
502
+ method_option :clean, :type => :boolean, :aliases => ["-c"], :default => false
503
+ method_option :docker_image, :type => :string, :aliases => ["-d"], :default => ""
328
504
 
329
505
  def new(project_name)
330
506
  begin
@@ -354,7 +530,7 @@ module Cnvrg
354
530
  if docker_image_local.size == 0
355
531
 
356
532
  if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
357
- image = pull_image(docker_image)
533
+ image = pull(docker_image)
358
534
  if image
359
535
  say "downloaded image: #{docker_image}"
360
536
  @image = Images.new(working_dir, docker_image)
@@ -392,8 +568,8 @@ module Cnvrg
392
568
  say "created project successfully", Thor::Shell::Color::GREEN
393
569
  say "Linked directory to\t#{@project.url}", Thor::Shell::Color::GREEN
394
570
  rescue => e
395
- puts e
396
- log_end(-1)
571
+ log_end(-1, e.message)
572
+ say "Error occurred, aborting", Thor::Shell::Color::RED
397
573
  if Dir.exist? working_dir
398
574
 
399
575
  @project.revert(working_dir)
@@ -411,6 +587,7 @@ module Cnvrg
411
587
  exit(1)
412
588
  end
413
589
  end
590
+
414
591
  desc 'set_image', 'set_image for a project'
415
592
 
416
593
  def set_image(docker_image)
@@ -422,7 +599,7 @@ module Cnvrg
422
599
  if docker_image_local.size == 0
423
600
 
424
601
  if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
425
- image = pull_image(docker_image)
602
+ image = pull(docker_image)
426
603
  if image
427
604
  say "downloaded image: #{docker_image}"
428
605
  @image = Images.new(working_dir, docker_image)
@@ -447,9 +624,10 @@ module Cnvrg
447
624
  @image.update_image_activity(nil, nil)
448
625
 
449
626
  end
450
- desc 'link', 'Link current directory to a cnvrg project'
451
- method_option :sync, :type => :boolean, :aliases => ["-s", "--s"], :default => true
452
- method_option :docker_image, :type => :string, :aliases => ["-d", "--d"], :default => ""
627
+
628
+ desc 'link', 'Link current directory to a new cnvrg project'
629
+ method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
630
+ method_option :docker_image, :type => :string, :aliases => ["-d"], :default => ""
453
631
 
454
632
  def link
455
633
  begin
@@ -473,7 +651,7 @@ module Cnvrg
473
651
  end
474
652
  working_dir = Dir.getwd
475
653
  owner = CLI.get_owner
476
- if Project.link(owner,project_name, docker)
654
+ if Project.link(owner, project_name, docker)
477
655
  path = Dir.pwd
478
656
  @project = Project.new(path)
479
657
  @project.generate_idx()
@@ -482,7 +660,7 @@ module Cnvrg
482
660
  docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.include? docker_image }.flatten
483
661
  if docker_image_local.size == 0
484
662
  if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
485
- image = pull_image(docker_image)
663
+ image = pull(docker_image)
486
664
  if image
487
665
  say "downloaded image: #{docker_image}"
488
666
  @image = Images.new(working_dir, docker_image)
@@ -506,40 +684,728 @@ module Cnvrg
506
684
  @image = Images.new(working_dir, image_name)
507
685
  end
508
686
  end
509
- if sync
510
- say "Syncing project", Thor::Shell::Color::BLUE
511
- upload(true)
687
+ if sync
688
+ say "Syncing project", Thor::Shell::Color::BLUE
689
+ upload(true)
690
+ end
691
+
692
+ url = @project.url
693
+ check = Helpers.checkmark
694
+ say "#{check} Link finished successfully", Thor::Shell::Color::GREEN
695
+ say "#{project_name}'s location is: #{url}\n", Thor::Shell::Color::GREEN
696
+ log_end(0)
697
+
698
+ else
699
+ log_end(1, "can't link project")
700
+ @project.revert(working_dir) unless @project.nil?
701
+ say "Error linking project, please contact support.", Thor::Shell::Color::RED
702
+ exit(0)
703
+ end
704
+ rescue SignalException
705
+ log_end(-1)
706
+
707
+ say "\nAborting"
708
+ exit(1)
709
+ end
710
+ end
711
+
712
+ desc 'data init', 'Init dataset directory'
713
+ method_option :public, :type => :boolean, :aliases => ["-p", "--public"], :default => false
714
+
715
+ def init_data(public)
716
+ begin
717
+ verify_logged_in(false)
718
+ log_start(__method__, args, options)
719
+ dataset_name =File.basename(Dir.getwd)
720
+ if File.directory?(Dir.getwd+"/.cnvrg")
721
+ config = YAML.load_file("#{Dir.getwd}/.cnvrg/config.yml")
722
+ say "Directory is already linked to #{config[:dataset_slug]}", Thor::Shell::Color::RED
723
+
724
+ exit(0)
725
+ end
726
+ say "Init dataset: #{dataset_name}", Thor::Shell::Color::BLUE
727
+
728
+ working_dir = Dir.getwd
729
+ owner = CLI.get_owner
730
+ if Dataset.init(owner, dataset_name, options["public"])
731
+ path = Dir.pwd
732
+ @dataset = Dataset.new(path)
733
+
734
+ url = @dataset.url
735
+ check = Helpers.checkmark
736
+ say "#{check} Link finished successfully", Thor::Shell::Color::GREEN
737
+ say "#{dataset_name}'s location is: #{url}\n", Thor::Shell::Color::GREEN
738
+ log_end(0)
739
+
740
+ else
741
+ log_end(1, "can't create dataset")
742
+ @dataset.revert(working_dir) unless @dataset.nil?
743
+ say "Error creating dataset, please contact support.", Thor::Shell::Color::RED
744
+ exit(0)
745
+ end
746
+ rescue SignalException
747
+ log_end(-1)
748
+
749
+ say "\nAborting"
750
+ exit(1)
751
+ end
752
+ end
753
+
754
+ desc 'data clone', 'Clone dataset'
755
+ method_option :commit, :type => :string, :aliases => ["-c", "--commit"], :default => ""
756
+
757
+ def clone_data(dataset_url)
758
+ begin
759
+ verify_logged_in(false)
760
+ log_start(__method__, args, options)
761
+ url_parts = dataset_url.split("/")
762
+ project_index = Cnvrg::Helpers.look_for_in_path(dataset_url, "datasets")
763
+ slug = url_parts[project_index+1]
764
+ owner = url_parts[project_index-1]
765
+ response = Cnvrg::API.request("users/#{owner}/datasets/#{slug}/clone", 'GET')
766
+
767
+ Cnvrg::CLI.is_response_success(response)
768
+ dataset_name = response["result"]["name"]
769
+ if (Dir.exists? dataset_name)
770
+ say "Error: Conflict with dir #{dataset_name}", Thor::Shell::Color::RED
771
+ if no? "Sync to repository anyway? (current data might lost)", Thor::Shell::Color::YELLOW
772
+ say "Remove dir in order to clone #{dataset_name}", Thor::Shell::Color::RED
773
+ log_end(1, "conflict with dir #{dataset_name}")
774
+
775
+ exit(1)
776
+ end
777
+
778
+ end
779
+ if Dataset.clone(owner, dataset_name, slug)
780
+ say "Cloning #{dataset_name}", Thor::Shell::Color::BLUE
781
+
782
+ commit_to_clone = options["commit"] || nil
783
+ working_dir = "#{Dir.pwd}/#{dataset_name}"
784
+ @dataset = Dataset.new(working_dir)
785
+ @dataset.generate_idx()
786
+ say "Downloading data", Thor::Shell::Color::BLUE
787
+
788
+
789
+ download_data(false, false, path = working_dir, in_dir=false)
790
+
791
+
792
+ check = Helpers.checkmark
793
+ say "#{check} Clone finished successfully", Thor::Shell::Color::GREEN
794
+ log_end(0)
795
+
796
+ else
797
+ log_end(1, "can't create dataset")
798
+ @dataset.revert(working_dir) unless @dataset.nil?
799
+ say "Error creating dataset, please contact support.", Thor::Shell::Color::RED
800
+ exit(0)
801
+ end
802
+ rescue SignalException
803
+ log_end(-1)
804
+
805
+ say "\nAborting"
806
+ exit(1)
807
+ end
808
+ end
809
+
810
+ desc 'init_data_container', 'Init dataset directory', :hide => true
811
+ method_option :login_content, :type => :string, :aliases => ["-l"], :default => ""
812
+
813
+ def init_data_container(container)
814
+ begin
815
+ login_content = options["login_content"]
816
+
817
+ container = Docker::Container.get(container)
818
+ command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
819
+ container.exec(command, tty: true)
820
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
821
+ container.exec(command, tty: true)
822
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
823
+ container.exec(command, tty: true)
824
+ command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.cnvrg /home/ds/.netrc"]
825
+ container.exec(command, tty: true)
826
+ command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
827
+ container.exec(command, tty: true)
828
+
829
+ rescue SignalException
830
+ log_end(-1)
831
+
832
+ say "\nAborting"
833
+ exit(1)
834
+ end
835
+ end
836
+
837
+ desc 'data_snap', 'Init dataset directory', :hide => true
838
+ method_option :public, :type => :boolean, :aliases => ["-p", "--public"], :default => false
839
+
840
+ def snap_data
841
+ begin
842
+ verify_logged_in(false)
843
+ log_start(__method__, args, options)
844
+
845
+ owner = CLI.get_owner
846
+ path = Dir.pwd
847
+ @dataset = Dataset.new(path)
848
+
849
+ log_end(0)
850
+
851
+ rescue SignalException
852
+ log_end(-1)
853
+
854
+ say "\nAborting"
855
+ exit(1)
856
+ end
857
+ end
858
+
859
+ desc 'data_snap', 'Init dataset directory', :hide => true
860
+
861
+ def data_init_container(owner, dataset_slug, dataset_name)
862
+
863
+ if Dataset.init_container(owner, dataset_slug, dataset_name)
864
+
865
+ say "init finished successfully", Thor::Shell::Color::GREEN
866
+ log_end(0)
867
+
868
+ else
869
+ log_end(1, "can't create dataset")
870
+ say "error creating dataset, please contact support.", Thor::Shell::Color::RED
871
+ exit(0)
872
+ end
873
+ end
874
+
875
+ desc 'data download', 'pull data'
876
+ method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
877
+ method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
878
+
879
+ def download_data(verbose, sync, path=Dir.pwd, in_dir=true)
880
+ begin
881
+ verify_logged_in(in_dir)
882
+ log_start(__method__, args, options)
883
+ if path.nil? or path.empty?
884
+ path = Dir.pwd
885
+ end
886
+ dataset_dir = is_cnvrg_dir(path)
887
+ @dataset = Dataset.new(dataset_dir)
888
+
889
+ @files = Cnvrg::Datafiles.new(@dataset.owner, @dataset.slug)
890
+ new_branch = options["new_branch"] || false
891
+
892
+ res = @dataset.compare_idx(new_branch)["result"]
893
+
894
+ result = res["tree"]
895
+
896
+ commit = res["commit"]
897
+ if result["updated_on_server"].empty? and result["conflicts"].empty? and result["deleted"].empty?
898
+ say "Project is up to date", Thor::Shell::Color::GREEN unless (options["sync"] or sync)
899
+ log_end(0)
900
+ return true
901
+ end
902
+ result = @dataset.downlowd_updated_data(@dataset.last_local_commit)
903
+
904
+ delete = result["result"]["delete"]
905
+ commits = result["result"]["commits"]
906
+ updated_idx = result["result"]["idx"]
907
+ commits.each do |c|
908
+ file_name = @files.download_data_file(c, dataset_dir)
909
+
910
+ if file_name.eql? false or file_name.nil?
911
+ ##RETRY
912
+ next
913
+ end
914
+ file_path = "#{dataset_dir}/#{file_name}"
915
+ success = extarct_tar(file_path, dataset_dir)
916
+ if !success
917
+ #TODO: ?
918
+ end
919
+
920
+ FileUtils.rm_rf([file_path])
921
+
922
+ end
923
+ to_delete = []
924
+ delete.each do |d|
925
+ to_delete << "#{dataset_dir}/#{d}"
926
+ end
927
+ FileUtils.rm_rf(to_delete)
928
+
929
+ @dataset.update_idx(updated_idx)
930
+
931
+
932
+ # result["conflicts"].each do |f|
933
+ # relative_path = f.gsub(/^#{@dataset.local_path}/, "")
934
+ # if @files.download_file_s3(f, relative_path, dataset_dir, conflict=true)
935
+ # successful_changes << relative_path
936
+ # end
937
+ #
938
+ # end
939
+ # update idx with latest commit
940
+ # @dataset.update_idx_with_commit!(commit)
941
+ check = Helpers.checkmark()
942
+ say "#{check} Downloaded changes successfully", Thor::Shell::Color::GREEN
943
+
944
+
945
+ log_end(0)
946
+ end
947
+ rescue
948
+ log_end(-1)
949
+
950
+ say "Error occurd, \nAborting", Thor::Shell::Color::BLUE
951
+ exit(1)
952
+ rescue SignalException
953
+ log_end(-1)
954
+ say "\nAborting", Thor::Shell::Color::BLUE
955
+ exit(1)
956
+ end
957
+
958
+
959
+ desc 'upload_data', 'Upload data files', :hide => true
960
+ method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
961
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb", "--nb"], :desc => "create new branch of commits"
962
+ method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
963
+ method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
964
+
965
+ def upload_data(sync=false, direct=false)
966
+
967
+ begin
968
+ verify_logged_in(true)
969
+ log_start(__method__, args, options)
970
+ dataset_dir = is_cnvrg_dir(Dir.pwd)
971
+ @dataset = Dataset.new(dataset_dir)
972
+
973
+ @files = Cnvrg::Datafiles.new(@dataset.owner, @dataset.slug)
974
+ ignore = options[:ignore] || []
975
+ if !@dataset.update_ignore_list(ignore)
976
+ say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
977
+ end
978
+ result = @dataset.compare_idx(false)
979
+
980
+ commit = result["result"]["commit"]
981
+ if commit != @dataset.last_local_commit and !@dataset.last_local_commit.nil? and !result["result"]["tree"]["updated_on_server"].empty?
982
+ log_end(0)
983
+
984
+ say "Remote server has an updated version, please run `cnvrg download` first, or alternatively: `cnvrg sync`", Thor::Shell::Color::YELLOW
985
+ exit(1)
986
+ end
987
+
988
+ say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE if options["verbose"]
989
+ result = result["result"]["tree"]
990
+ # if result["added"].any? {|x| x.include? ".conflict"} or !result["conflicts"].empty?
991
+ # all = result["added"].select {|x| x.include? ".conflict"} +result["conflicts"].flatten
992
+ # if all.size == 1
993
+ # num = "conflict"
994
+ # else
995
+ # num = "conflicts"
996
+ # end
997
+ # say "Project contains #{all.size} #{num}:", Thor::Shell::Color::RED
998
+ # say "#{all.join("\n")}"
999
+ # say "Please fix #{num}, and retry", Thor::Shell::Color::RED
1000
+ # exit(1)
1001
+ #
1002
+ # end
1003
+ check = Helpers.checkmark()
1004
+
1005
+ if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
1006
+ log_end(0)
1007
+ say "#{check} Dataset is up to date", Thor::Shell::Color::GREEN unless ((options["sync"] or sync) and !direct)
1008
+ return true
1009
+ end
1010
+ update_count = 0
1011
+ update_total = result["added"].size + result["updated_on_local"].size + result["deleted"].size
1012
+ successful_updates = []
1013
+ successful_deletions = []
1014
+ if options["verbose"]
1015
+ if update_total == 1
1016
+ say "Updating #{update_total} file", Thor::Shell::Color::BLUE
1017
+ else
1018
+ say "Updating #{update_total} files", Thor::Shell::Color::BLUE
1019
+ end
1020
+ else
1021
+ say "Syncing files", Thor::Shell::Color::BLUE unless (options["sync"] or sync)
1022
+
1023
+ end
1024
+
1025
+ # Start commit
1026
+
1027
+ commit_sha1 = @files.start_commit(false)["result"]["commit_sha1"]
1028
+ # upload / update
1029
+ begin
1030
+ (result["added"] + result["updated_on_local"]).each do |f|
1031
+ absolute_path = "#{@dataset.local_path}/#{f}"
1032
+ relative_path = f.gsub(/^#{@dataset.local_path + "/"}/, "")
1033
+ if File.directory?(absolute_path)
1034
+ resDir = @files.create_dir(absolute_path, relative_path, commit_sha1)
1035
+ if resDir
1036
+ update_count += 1
1037
+ successful_updates<< relative_path
1038
+ end
1039
+ else
1040
+ res = @files.upload_file(absolute_path, relative_path, commit_sha1)
1041
+
1042
+ if res
1043
+ update_count += 1
1044
+ successful_updates<< relative_path
1045
+ else
1046
+ @files.rollback_commit(commit_sha1)
1047
+ log_end(1, "can't upload, Rolling Back all changes")
1048
+ say "Couldn't upload, Rolling Back all changes.", Thor::Shell::Color::RED
1049
+ exit(0)
1050
+ end
1051
+ end
1052
+ end
1053
+
1054
+ # delete
1055
+ deleted = update_deleted(result["deleted"])
1056
+ deleted.each do |f|
1057
+ relative_path = f.gsub(/^#{@dataset.local_path + "/"}/, "")
1058
+ if relative_path.end_with?("/")
1059
+ if @files.delete_dir(f, relative_path, commit_sha1)
1060
+ # update_count += 1
1061
+ successful_updates<< relative_path
1062
+ end
1063
+ else
1064
+ if @files.delete_file(f, relative_path, commit_sha1)
1065
+ # update_count += 1
1066
+ successful_updates<< relative_path
1067
+ end
1068
+ end
1069
+ end
1070
+
1071
+ rescue SignalException
1072
+ log_end(-1)
1073
+ @files.rollback_commit(commit_sha1)
1074
+ say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
1075
+ exit(0)
1076
+ rescue => e
1077
+ log_end(-1, e.message)
1078
+ @files.rollback_commit(commit_sha1)
1079
+ say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
1080
+ exit(0)
1081
+ end
1082
+ if !result["deleted"].nil? and !result["deleted"].empty?
1083
+ update_count += result["deleted"].size
1084
+ end
1085
+ if update_count == update_total
1086
+ res = @files.end_commit(commit_sha1)
1087
+ if (Cnvrg::CLI.is_response_success(res, false))
1088
+ # save idx
1089
+ begin
1090
+ @dataset.update_idx_with_files_commits!((successful_deletions+successful_updates), res["result"]["commit_time"])
1091
+
1092
+ @dataset.update_idx_with_commit!(commit_sha1)
1093
+ rescue => e
1094
+ log_end(-1, e.message)
1095
+ @files.rollback_commit(commit_sha1)
1096
+ say "Couldn't commit updates, Rolling Back all changes.", Thor::Shell::Color::RED
1097
+ exit(1)
1098
+
1099
+ end
1100
+ if options["verbose"]
1101
+ say "#{check} Done", Thor::Shell::Color::BLUE
1102
+ if successful_updates.size >0
1103
+ say "Updated:", Thor::Shell::Color::GREEN
1104
+ suc = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
1105
+ say suc.join("\n"), Thor::Shell::Color::GREEN
1106
+ end
1107
+ if successful_deletions.size >0
1108
+ say "Deleted:", Thor::Shell::Color::GREEN
1109
+ del = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
1110
+ say del.join("\n"), Thor::Shell::Color::GREEN
1111
+ end
1112
+ say "Total of #{update_count} / #{update_total} files.", Thor::Shell::Color::GREEN
1113
+ else
1114
+ if (options["sync"] or sync) and direct
1115
+ say "#{check} Syncing dataset completed successfully", Thor::Shell::Color::GREEN
1116
+
1117
+ else
1118
+ say "#{check} Changes were updated successfully", Thor::Shell::Color::GREEN
1119
+
1120
+ end
1121
+
1122
+ end
1123
+
1124
+ log_end(0)
1125
+ else
1126
+ @files.rollback_commit(commit_sha1)
1127
+ log_end(1, "error. Rolling Back all changes")
1128
+ say "Error. Rolling Back all changes.", Thor::Shell::Color::RED
1129
+ end
1130
+ else
1131
+ log_end(1, "error. Rolling Back all changes")
1132
+ say "Error occurd, \nRolling back", Thor::Shell::Color::RED
1133
+
1134
+ @files.rollback_commit(commit_sha1)
1135
+ end
1136
+ rescue => e
1137
+
1138
+ log_end(-1)
1139
+
1140
+ say "Error occurd, \nAborting", Thor::Shell::Color::RED
1141
+ @files.rollback_commit(commit_sha1)
1142
+ exit(1)
1143
+ rescue SignalException
1144
+ log_end(-1)
1145
+
1146
+ say "\nAborting", Thor::Shell::Color::BLUE
1147
+ say "\nRolling back all changes", Thor::Shell::Color::BLUE
1148
+ @files.rollback_commit(commit_sha1)
1149
+ exit(1)
1150
+ end
1151
+
1152
+ end
1153
+
1154
+ desc 'data upload', 'push data'
1155
+ method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
1156
+ method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
1157
+ method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
1158
+ method_option :no_compression, :type => :boolean, :aliases => ["-nc", "--no_compression"], :default => false
1159
+
1160
+ def upload_data_tar(ignore, verbose, sync,no_compression)
1161
+
1162
+ begin
1163
+ verify_logged_in(true)
1164
+ log_start(__method__, args, options)
1165
+ dataset_dir = is_cnvrg_dir(Dir.pwd)
1166
+
1167
+ @dataset = Dataset.new(dataset_dir)
1168
+
1169
+ @files = Cnvrg::Datafiles.new(@dataset.owner, @dataset.slug)
1170
+ if !@dataset.update_ignore_list(ignore)
1171
+ say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::RED
1172
+ exit(1)
1173
+ end
1174
+ say "Checking dataset", Thor::Shell::Color::BLUE
1175
+ local_idx = @dataset.generate_idx
1176
+ result = @dataset.compare_idx(false, commit=@dataset.last_local_commit, local_idx= local_idx)
1177
+
1178
+
1179
+ commit = result["result"]["commit"]
1180
+ if commit != @dataset.last_local_commit and !@dataset.last_local_commit.nil? and !result["result"]["tree"]["updated_on_server"].empty?
1181
+ log_end(0)
1182
+
1183
+ say "Remote server has an updated version, please run `cnvrg data download` first", Thor::Shell::Color::YELLOW
1184
+ exit(1)
1185
+ end
1186
+
1187
+ say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE if verbose
1188
+ result = result["result"]["tree"]
1189
+ check = Helpers.checkmark()
1190
+
1191
+ if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
1192
+ log_end(0)
1193
+ say "#{check} Dataset is up to date", Thor::Shell::Color::GREEN unless (sync)
1194
+ return true
1195
+ end
1196
+ update_count = 0
1197
+ update_total = result["added"].size + result["updated_on_local"].size + result["deleted"].size
1198
+ successful_updates = []
1199
+ successful_deletions = []
1200
+
1201
+ # Start commit
1202
+ res = @files.start_commit(false)["result"]
1203
+ commit_sha1 =res["commit_sha1"]
1204
+ commit_time = res["commit_time"]
1205
+ # upload / update
1206
+ begin
1207
+ (result["added"] + result["updated_on_local"]).each do |f|
1208
+ relative_path = f.gsub(/^#{@dataset.local_path + "/"}/, "")
1209
+ successful_updates<< relative_path
1210
+ update_count += 1
1211
+ end
1212
+
1213
+ # delete
1214
+ deleted = update_deleted(result["deleted"])
1215
+ deleted.each do |f|
1216
+ relative_path = f.gsub(/^#{@dataset.local_path + "/"}/, "")
1217
+ successful_updates<< relative_path
1218
+ end
1219
+ @dataset.update_idx_with_files_commits!((successful_deletions+successful_updates), commit_time)
1220
+
1221
+ @dataset.update_idx_with_commit!(commit_sha1)
1222
+ say "Compressing data", Thor::Shell::Color::BLUE
1223
+
1224
+ home_dir = File.expand_path('~')
1225
+ compression_path = get_compression_path
1226
+ tar_path = "#{compression_path}#{@dataset.slug}_#{commit_sha1}.tar.gz"
1227
+ tar_files_path = "#{home_dir}/.cnvrg/tmp/#{@dataset.slug}_#{commit_sha1}.txt"
1228
+ tar_files = (result["added"] + result["updated_on_local"]).join("\n")
1229
+ File.open(tar_files_path, 'w') { |f| f.write tar_files }
1230
+ is_tar = create_tar(dataset_dir, tar_path, tar_files_path,no_compression)
1231
+ if !is_tar
1232
+ say "ERROR: Couldn't compress data", Thor::Shell::Color::RED
1233
+ FileUtils.rm_rf([tar_path]) if File.exist? tar_path
1234
+ FileUtils.rm_rf([tar_files_path]) if File.exist? tar_files_path
1235
+ @files.rollback_commit(commit_sha1)
1236
+ say "Rolling Back all changes.", Thor::Shell::Color::RED
1237
+ exit(1)
1238
+ end
1239
+ say "Uploading data", Thor::Shell::Color::BLUE
1240
+ res = false
1241
+ res = @files.upload_tar_file(tar_path, tar_path, commit_sha1)
1242
+
1243
+ if res
1244
+ say "Commiting data", Thor::Shell::Color::BLUE
1245
+
1246
+ cur_idx = @dataset.get_idx.to_h
1247
+
1248
+ res = @files.end_commit_tar(commit_sha1, cur_idx)
1249
+ if !Cnvrg::CLI.is_response_success(res, false)
1250
+ FileUtils.rm_rf([tar_files_path]) if File.exist? tar_files_path
1251
+ FileUtils.rm_rf([tar_path]) if File.exist? tar_path
1252
+
1253
+
1254
+ @files.rollback_commit(commit_sha1)
1255
+ say "Can't commit, Rolling Back all changes.", Thor::Shell::Color::RED
1256
+ exit(1)
1257
+ end
1258
+
1259
+ else
1260
+ FileUtils.rm_rf([tar_files_path]) if File.exist? tar_files_path
1261
+ FileUtils.rm_rf([tar_path]) if File.exist? tar_path
1262
+
1263
+
1264
+ @files.rollback_commit(commit_sha1)
1265
+ say "Can't upload, Rolling Back all changes.", Thor::Shell::Color::RED
1266
+ exit(1)
1267
+ end
1268
+
1269
+
1270
+ # delete
1271
+ FileUtils.rm_rf([tar_path, tar_files_path])
1272
+
1273
+ rescue SignalException
1274
+ log_end(-1)
1275
+ FileUtils.rm_rf([tar_files_path]) if File.exist? tar_files_path
1276
+ FileUtils.rm_rf([tar_path]) if File.exist? tar_path
1277
+
1278
+
1279
+ @files.rollback_commit(commit_sha1)
1280
+ say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
1281
+ exit(0)
1282
+ rescue => e
1283
+ puts e.message
1284
+ if !Cnvrg::Helpers.internet_connection?
1285
+ say "Seems there is no internet connection", Thor::Shell::Color::RED
1286
+
512
1287
  end
1288
+ FileUtils.rm_rf([tar_files_path]) if File.exist? tar_files_path
1289
+ FileUtils.rm_rf([tar_path]) if File.exist? tar_path
513
1290
 
514
- url = @project.url
515
- check = Helpers.checkmark
516
- say "#{check} Link finished successfully", Thor::Shell::Color::GREEN
517
- say "#{project_name}'s location is: #{url}\n", Thor::Shell::Color::GREEN
518
- log_end(0)
1291
+ log_end(-1, e.message)
1292
+ @files.rollback_commit(commit_sha1)
1293
+ say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
1294
+ exit(0)
1295
+ end
1296
+ if verbose
1297
+ say "#{check} Done", Thor::Shell::Color::BLUE
1298
+ if successful_updates.size >0
1299
+ say "Updated:", Thor::Shell::Color::GREEN
1300
+ suc = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
1301
+ say suc.join("\n"), Thor::Shell::Color::GREEN
1302
+ end
1303
+ if successful_deletions.size >0
1304
+ say "Deleted:", Thor::Shell::Color::GREEN
1305
+ del = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
1306
+ say del.join("\n"), Thor::Shell::Color::GREEN
1307
+ end
519
1308
 
1309
+
1310
+ say "Total of #{update_count} / #{update_total} files.", Thor::Shell::Color::GREEN
520
1311
  else
521
- log_end(1, "can't link project")
522
- @project.revert(working_dir) unless @project.nil?
523
- say "Error linking project, please contact support.", Thor::Shell::Color::RED
524
- exit(0)
1312
+ say "#{check} Changes were updated successfully", Thor::Shell::Color::GREEN
1313
+
525
1314
  end
1315
+
1316
+
1317
+ rescue => e
1318
+ log_end(-1, e.message)
1319
+
1320
+
1321
+ say "Error occurd, \nAborting", Thor::Shell::Color::RED
1322
+ @files.rollback_commit(commit_sha1)
1323
+ exit(1)
526
1324
  rescue SignalException
527
1325
  log_end(-1)
528
1326
 
529
- say "\nAborting"
1327
+ say "\nAborting", Thor::Shell::Color::BLUE
1328
+ say "\nRolling back all changes", Thor::Shell::Color::BLUE
1329
+ @files.rollback_commit(commit_sha1)
530
1330
  exit(1)
531
1331
  end
1332
+
1333
+ log_end(0)
1334
+
1335
+ end
1336
+
1337
+
1338
+ desc 'unlink', 'Unlink a project from current directory', :hide => true
1339
+
1340
+ def create_volume
1341
+ verify_logged_in(false)
1342
+ log_start(__method__, args, options)
1343
+ dataset_dir = is_cnvrg_dir(Dir.pwd)
1344
+ @dataset = Dataset.new(dataset_dir)
1345
+ @dataset.create_volume()
1346
+
1347
+ end
1348
+
1349
+ desc 'data list', 'List all dataset you currently have'
1350
+
1351
+ def list_dataset
1352
+ verify_logged_in(false)
1353
+ log_start(__method__, args, options)
1354
+ dataset_dir = is_cnvrg_dir(Dir.pwd)
1355
+ @dataset = Dataset.new(dataset_dir)
1356
+ owner = @dataset.owner
1357
+ if owner.nil? or owner.empty?
1358
+ owner = CLI.get_owner()
1359
+ end
1360
+ result = @dataset.list(owner)
1361
+ list = result["result"]["list"]
1362
+
1363
+ print_table(list)
1364
+
1365
+ end
1366
+
1367
+ desc 'data commits', 'List all commits for a specific dataset'
1368
+
1369
+ def list_dataset_commits()
1370
+ verify_logged_in(true)
1371
+ log_start(__method__, args, options)
1372
+
1373
+ dataset_dir = is_cnvrg_dir(Dir.pwd)
1374
+ @dataset = Dataset.new(dataset_dir)
1375
+ result = @dataset.list_commits()
1376
+ list = result["result"]["list"]
1377
+
1378
+ print_table(list)
1379
+
1380
+ end
1381
+
1382
+ desc 'commits', 'List all commits for a specific dataset'
1383
+
1384
+ def list_commits()
1385
+ verify_logged_in(true)
1386
+ log_start(__method__, args, options)
1387
+
1388
+ project_dir = is_cnvrg_dir(Dir.pwd)
1389
+ @project = Project.new(project_dir)
1390
+ result = @project.list_commits()
1391
+ list = result["result"]["list"]
1392
+
1393
+ print_table(list)
1394
+
532
1395
  end
533
- desc 'unlink','Unlink a porject'
1396
+
1397
+
1398
+ desc 'unlink', 'Unlink a project from current directory'
1399
+
534
1400
  def unlink
535
1401
  verify_logged_in(false)
536
1402
  log_start(__method__, args, options)
537
1403
  working_dir = is_cnvrg_dir()
538
- list_to_del = [working_dir+"/.cnvrgignore",working_dir+"/.cnvrg"]
1404
+ list_to_del = [working_dir+"/.cnvrgignore", working_dir+"/.cnvrg"]
539
1405
  FileUtils.rm_rf list_to_del
540
1406
  end
541
1407
 
542
- desc 'clone', 'Clone a project'
1408
+ desc 'clone', 'Clone project'
543
1409
  method_option :remote, :type => :boolean, :aliases => ["-r", "--r"], :default => false
544
1410
  method_option :commit, :type => :string, :aliases => ["-c", "--c"], :default => nil
545
1411
 
@@ -587,6 +1453,7 @@ module Cnvrg
587
1453
  Cnvrg::CLI.is_response_success response
588
1454
  working_dir = project_home
589
1455
  docker_image = response["result"]["image"]
1456
+ current_commit = response["result"]["commit"]
590
1457
  idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
591
1458
  File.open(working_dir + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
592
1459
  if !docker_image.nil? and !docker_image.empty? and !remote
@@ -594,7 +1461,7 @@ module Cnvrg
594
1461
  docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{docker_image}:latest" }.flatten
595
1462
  if docker_image_local.size == 0
596
1463
  if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
597
- image = pull_image(docker_image)
1464
+ image = pull(docker_image)
598
1465
  if image
599
1466
  say "downloaded image: #{docker_image}"
600
1467
  @image = Images.new(working_dir, docker_image)
@@ -628,7 +1495,8 @@ module Cnvrg
628
1495
  end
629
1496
  else
630
1497
  # blob
631
- if @files.download_file_s3(f[0], relative_path, project_home)
1498
+
1499
+ if @files.download_file_s3(f[0], relative_path, project_home, commit_sha1=current_commit)
632
1500
  successful_changes << relative_path
633
1501
  end
634
1502
  end
@@ -667,6 +1535,7 @@ module Cnvrg
667
1535
  commit = result["commit"]
668
1536
  result = result["tree"]
669
1537
  say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
1538
+
670
1539
  if result["added"].empty? and result["updated_on_local"].empty? and result["updated_on_server"].empty? and result["deleted"].empty? and result["conflicts"].empty?
671
1540
  say "Project is up to date", Thor::Shell::Color::GREEN
672
1541
  log_end(0)
@@ -713,14 +1582,36 @@ module Cnvrg
713
1582
  end
714
1583
  end
715
1584
 
1585
+ desc '', '', :hide => true
1586
+
1587
+ def revert_exp
1588
+ begin
1589
+ log_start(__method__, args, options)
1590
+ @project = Project.new(get_project_home)
1591
+
1592
+ result = @project.compare_idx(false)["result"]
1593
+ result = result["tree"]
1594
+ if result["added"].size > 0
1595
+ FileUtils.rm_rf(result["added"])
1596
+ end
1597
+ say "Changes were removed successfully", Thor::Shell::Color::GREEN
1598
+
1599
+
1600
+ rescue SignalException
1601
+ log_end(-1)
1602
+ say "\nAborting"
1603
+ exit(1)
1604
+ end
1605
+ end
1606
+
716
1607
 
717
1608
  desc 'upload', 'Upload updated files'
718
- method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
719
- method_option :new_branch, :type => :boolean, :aliases => ["-nb", "--nb"], :desc => "create new branch of commits"
720
- method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
721
- method_option :sync, :type => :boolean, :aliases => ["--v"], :default => false
1609
+ method_option :ignore, :type => :string, :aliases => ["-i"], :desc => "ignore following files", :default => ""
1610
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb"], :desc => "create new branch of commits"
1611
+ method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
1612
+ method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
722
1613
 
723
- def upload(link=false, sync=false)
1614
+ def upload(link=false, sync=false, direct=false, ignore_list="")
724
1615
 
725
1616
  begin
726
1617
  verify_logged_in(true)
@@ -729,12 +1620,30 @@ module Cnvrg
729
1620
  @project = Project.new(get_project_home)
730
1621
 
731
1622
  @files = Cnvrg::Files.new(@project.owner, @project.slug)
732
- ignore = options[:ignore] || []
1623
+ ignore = options[:ignore] || ""
1624
+
1625
+ if ignore.nil? or ignore.empty?
1626
+ ignore = ignore_list
1627
+ end
1628
+ data_ignore = data_dir_include()
1629
+ if !data_ignore.nil?
1630
+ if ignore.nil? or ignore.empty?
1631
+ ignore = data_ignore
1632
+ else
1633
+ ignore ="#{ignore},#{data_ignore}"
1634
+ end
1635
+ end
733
1636
  if !@project.update_ignore_list(ignore)
734
1637
  say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
735
1638
  end
736
1639
  new_branch = options["new_branch"] || false
737
1640
 
1641
+ if options["sync"] or sync
1642
+ new_branch_exp = @project.get_new_branch
1643
+ if new_branch_exp
1644
+ new_branch = new_branch_exp
1645
+ end
1646
+ end
738
1647
  result = @project.compare_idx(new_branch)
739
1648
  commit = result["result"]["commit"]
740
1649
  if !link
@@ -748,9 +1657,23 @@ module Cnvrg
748
1657
  say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE if options["verbose"]
749
1658
  end
750
1659
  result = result["result"]["tree"]
1660
+ # if result["added"].any? {|x| x.include? ".conflict"} or !result["conflicts"].empty?
1661
+ # all = result["added"].select {|x| x.include? ".conflict"} +result["conflicts"].flatten
1662
+ # if all.size == 1
1663
+ # num = "conflict"
1664
+ # else
1665
+ # num = "conflicts"
1666
+ # end
1667
+ # say "Project contains #{all.size} #{num}:", Thor::Shell::Color::RED
1668
+ # say "#{all.join("\n")}"
1669
+ # say "Please fix #{num}, and retry", Thor::Shell::Color::RED
1670
+ # exit(1)
1671
+ #
1672
+ # end
1673
+ check = Helpers.checkmark()
751
1674
  if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
752
1675
  log_end(0)
753
- say "Project is up to date", Thor::Shell::Color::GREEN unless options["sync"]
1676
+ say "#{check} Project is up to date", Thor::Shell::Color::GREEN unless ((options["sync"] or sync) and !direct)
754
1677
  return true
755
1678
  end
756
1679
  update_count = 0
@@ -764,7 +1687,7 @@ module Cnvrg
764
1687
  say "Updating #{update_total} files", Thor::Shell::Color::BLUE
765
1688
  end
766
1689
  else
767
- say "Syncing files", Thor::Shell::Color::BLUE unless options["sync"]
1690
+ say "Syncing files", Thor::Shell::Color::BLUE unless (options["sync"] or sync)
768
1691
 
769
1692
  end
770
1693
 
@@ -798,21 +1721,21 @@ module Cnvrg
798
1721
  end
799
1722
 
800
1723
  # delete
801
- result["deleted"].each do |f|
1724
+ deleted = update_deleted(result["deleted"])
1725
+ deleted.each do |f|
802
1726
  relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
803
1727
  if relative_path.end_with?("/")
804
1728
  if @files.delete_dir(f, relative_path, commit_sha1)
805
- update_count += 1
1729
+ # update_count += 1
806
1730
  successful_updates<< relative_path
807
1731
  end
808
1732
  else
809
1733
  if @files.delete_file(f, relative_path, commit_sha1)
810
- update_count += 1
1734
+ # update_count += 1
811
1735
  successful_updates<< relative_path
812
1736
  end
813
1737
  end
814
1738
  end
815
- log_end(0)
816
1739
 
817
1740
  rescue SignalException
818
1741
  log_end(-1)
@@ -820,11 +1743,14 @@ module Cnvrg
820
1743
  say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
821
1744
  exit(0)
822
1745
  rescue => e
823
- log_end(1, e.message)
1746
+ log_end(-1, e.message)
824
1747
  @files.rollback_commit(commit_sha1)
825
1748
  say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
826
1749
  exit(0)
827
1750
  end
1751
+ if !result["deleted"].nil? and !result["deleted"].empty?
1752
+ update_count += result["deleted"].size
1753
+ end
828
1754
  if update_count == update_total
829
1755
  res = @files.end_commit(commit_sha1)
830
1756
  if (Cnvrg::CLI.is_response_success(res, false))
@@ -834,7 +1760,7 @@ module Cnvrg
834
1760
 
835
1761
  @project.update_idx_with_commit!(commit_sha1)
836
1762
  rescue => e
837
- log_end(1, e.message)
1763
+ log_end(-1, e.message)
838
1764
  @files.rollback_commit(commit_sha1)
839
1765
  say "Couldn't commit updates, Rolling Back all changes.", Thor::Shell::Color::RED
840
1766
  exit(1)
@@ -844,7 +1770,6 @@ module Cnvrg
844
1770
  if image and image.is_docker
845
1771
  image.update_image_activity(commit_sha1, nil)
846
1772
  end
847
- check = Helpers.checkmark()
848
1773
 
849
1774
  if options["verbose"]
850
1775
  say "#{check} Done", Thor::Shell::Color::BLUE
@@ -860,7 +1785,13 @@ module Cnvrg
860
1785
  end
861
1786
  say "Total of #{update_count} / #{update_total} files.", Thor::Shell::Color::GREEN
862
1787
  else
863
- say "#{check} Changes were updated successfully", Thor::Shell::Color::GREEN unless options["sync"]
1788
+ if (options["sync"] or sync) and direct
1789
+ say "#{check} Syncing project completed successfully", Thor::Shell::Color::GREEN
1790
+
1791
+ else
1792
+ say "#{check} Changes were updated successfully", Thor::Shell::Color::GREEN
1793
+
1794
+ end
864
1795
 
865
1796
  end
866
1797
 
@@ -872,13 +1803,14 @@ module Cnvrg
872
1803
  end
873
1804
  else
874
1805
  log_end(1, "error. Rolling Back all changes")
1806
+ say "Error occurd, \nRolling back", Thor::Shell::Color::RED
875
1807
 
876
1808
  @files.rollback_commit(commit_sha1)
877
1809
  end
878
- rescue
1810
+ rescue => e
879
1811
  log_end(-1)
880
1812
 
881
- say "Error occurd, \nAborting", Thor::Shell::Color::BLUE
1813
+ say "Error occurd, \nAborting", Thor::Shell::Color::RED
882
1814
  @files.rollback_commit(commit_sha1)
883
1815
  exit(1)
884
1816
  rescue SignalException
@@ -893,27 +1825,57 @@ module Cnvrg
893
1825
  end
894
1826
 
895
1827
  desc 'download', 'Download updated files'
896
- method_option :new_branch, :type => :boolean, :aliases => ["-nb", "--nb"], :desc => "create new branch of commits"
897
- method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
898
- method_option :sync, :type => :boolean, :aliases => ["--v"], :default => false
1828
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb"], :desc => "create new branch of commits"
1829
+ method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
1830
+ method_option :sync, :type => :boolean, :aliases => ["-s"], :default => false
1831
+ method_option :ignore, :type => :string, :aliases => ["-i"], :desc => "ignore following files", :default => ""
899
1832
 
900
- def download
1833
+ def download(sync=false, ignore_list="")
901
1834
  begin
902
1835
  verify_logged_in(true)
903
1836
  log_start(__method__, args, options)
904
1837
  project_home = get_project_home
905
1838
  @project = Project.new(project_home)
906
1839
  @files = Cnvrg::Files.new(@project.owner, @project.slug)
1840
+ ignore = options[:ignore] || ""
1841
+ if ignore.nil? or ignore.empty?
1842
+ ignore = ignore_list
1843
+ end
1844
+ data_ignore = data_dir_include()
1845
+ if !data_ignore.nil?
1846
+ if ignore.nil? or ignore.empty?
1847
+ ignore = data_ignore
1848
+ else
1849
+ ignore ="#{ignore},#{data_ignore}"
1850
+ end
1851
+ end
1852
+ if !@project.update_ignore_list(ignore)
1853
+ say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
1854
+ end
907
1855
  new_branch = options["new_branch"] || false
908
1856
 
909
1857
  res = @project.compare_idx(new_branch)["result"]
1858
+
910
1859
  result = res["tree"]
1860
+
911
1861
  commit = res["commit"]
912
- if result["updated_on_server"].empty? and result["conflicts"] and result["deleted"].empty?
913
- say "Project is up to date", Thor::Shell::Color::GREEN unless options["sync"]
1862
+ if result["updated_on_server"].empty? and result["conflicts"].empty? and result["deleted"].empty?
1863
+ say "Project is up to date", Thor::Shell::Color::GREEN unless (options["sync"] or sync)
914
1864
  log_end(0)
915
1865
  return true
916
1866
  end
1867
+ # if result["added"].any? {|x| x.include? ".conflict"} or !result["conflicts"].empty?
1868
+ # all = result["added"].select {|x| x.include? ".conflict"} +result["conflicts"].flatten
1869
+ # if all.size == 1
1870
+ # num = "1 conflict"
1871
+ # else
1872
+ # num = "#{result["conflicts"].size} conflicts"
1873
+ # end
1874
+ # say "Project contains #{num}:", Thor::Shell::Color::RED
1875
+ # say "#{all.join("\n")}"
1876
+ # say "Please fix them, and retry", Thor::Shell::Color::RED
1877
+ # exit(1)
1878
+ # end
917
1879
  update_count = 0
918
1880
  update_total = result["updated_on_server"].size + result["conflicts"].size
919
1881
 
@@ -935,7 +1897,7 @@ module Cnvrg
935
1897
 
936
1898
  result["conflicts"].each do |f|
937
1899
  relative_path = f.gsub(/^#{@project.local_path}/, "")
938
- if @files.download_file_s3(f, relative_path, project_home, conflict=true)
1900
+ if @files.download_file_s3(f, relative_path, project_home, commit_sha1=nil, conflict=true)
939
1901
  successful_changes << relative_path
940
1902
  end
941
1903
 
@@ -966,12 +1928,35 @@ module Cnvrg
966
1928
  say successful_changes.join("\n"), Thor::Shell::Color::GREEN
967
1929
  say "Total of #{successful_changes.size} / #{update_total} files.", Thor::Shell::Color::GREEN
968
1930
  else
969
- say "#{check} Downloaded changes successfully", Thor::Shell::Color::GREEN
1931
+ say "#{check} Downloaded changes successfully", Thor::Shell::Color::GREEN unless (sync or options["sync"])
970
1932
  end
971
1933
 
972
1934
 
973
1935
  log_end(0)
974
1936
  end
1937
+ rescue => e
1938
+ log_end(-1)
1939
+
1940
+ say "Error occurd, \nAborting", Thor::Shell::Color::BLUE
1941
+ if successful_changes.nil?
1942
+ exit(1)
1943
+ end
1944
+ successful_changes.each do |f|
1945
+
1946
+ abs_path = "#{@project.local_path}/#{f}"
1947
+ filename = File.basename abs_path
1948
+ say "revoking #{filename}"
1949
+ if result["conflicts"].include? f
1950
+ @files.revoke_download_file(abs_path, f, filename, true)
1951
+ elsif result["updated_on_server"].include? f
1952
+ if File.directory? abs_path
1953
+ @files.revoke_download_dir(abs_path, f, project_home)
1954
+ else
1955
+ @files.revoke_download_file(project_home, abs_path, filename)
1956
+ end
1957
+ end
1958
+ end
1959
+ exit(1)
975
1960
  rescue SignalException
976
1961
  log_end(-1)
977
1962
  say "\nAborting", Thor::Shell::Color::BLUE
@@ -1025,7 +2010,7 @@ module Cnvrg
1025
2010
  if !response["result"]["tree"].nil?
1026
2011
  idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
1027
2012
  File.open(project_home + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
1028
- current_tree = Dir.entries(".").reject { |file| file.start_with? '.' }
2013
+ current_tree = Dir.entries(".").reject { |file| file.start_with? '.' or file.eql? "__init__.py" or file.eql? "uwsgi.ini" }
1029
2014
 
1030
2015
  response["result"]["tree"].each do |f|
1031
2016
  relative_path = f[0].gsub(/^#{@project.local_path}/, "")
@@ -1037,7 +2022,7 @@ module Cnvrg
1037
2022
  end
1038
2023
  else
1039
2024
  # blob
1040
- if @files.download_file_s3(f[0], relative_path, project_home)
2025
+ if @files.download_file_s3(f[0], relative_path, project_home, commit_sha1=commit_sha1)
1041
2026
  current_tree.delete(relative_path)
1042
2027
 
1043
2028
  successful_changes << relative_path
@@ -1055,43 +2040,100 @@ module Cnvrg
1055
2040
  end
1056
2041
 
1057
2042
 
2043
+ desc 'data_jump', 'jump to specific commit', :hide => true
2044
+
2045
+ def data_jump(*commit_sha1)
2046
+ begin
2047
+ verify_logged_in()
2048
+ log_start(__method__, args, options)
2049
+ dataset_dir = is_cnvrg_dir(Dir.pwd)
2050
+ @dataset = Dataset.new(dataset_dir)
2051
+
2052
+ @files = Cnvrg::Datafiles.new(@dataset.owner, @dataset.slug)
2053
+ if commit_sha1.nil? or commit_sha1.empty?
2054
+ commit_sha1 = @dataset.last_local_commit
2055
+ end
2056
+ response = @dataset.compare_commits(commit_sha1)
2057
+ successful_changes = []
2058
+ if !response["result"]["status"].nil?
2059
+ idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
2060
+ File.open(dataset_dir + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
2061
+ status = response["result"]["status"]
2062
+ (status["delete"]).each do |f|
2063
+ relative_path = f[0].gsub(/^#{@dataset.local_path}/, "")
2064
+ FileUtils.rm_rf(relative_path)
2065
+ end
2066
+ # current_tree = Dir.entries(".").reject { |file| file.start_with? '.' }
2067
+ (status["dirs"]).each do |f|
2068
+ relative_path = f[0].gsub(/^#{@dataset.local_path}/, "")
2069
+ # dir
2070
+ if @files.download_dir(dataset_dir, relative_path)
2071
+ # current_tree.delete(relative_path[0, relative_path.size-1])
2072
+ successful_changes << relative_path
2073
+ end
2074
+ end
2075
+ (status["download"]).each do |f|
2076
+ relative_path = f["name"].gsub(/^#{@dataset.local_path}/, "")
2077
+ # dir
2078
+ if @files.download_file_s3(f["name"], relative_path, dataset_dir, f["sha1"])
2079
+ successful_changes << relative_path
2080
+ end
2081
+ end
2082
+
2083
+
2084
+ say "Done. Jumped completed successfully", Thor::Shell::Color::GREEN
2085
+ log_end(0)
2086
+ end
2087
+
2088
+ rescue SignalException
2089
+ log_end(-1)
2090
+ exi(1)
2091
+ end
2092
+ end
2093
+
1058
2094
  desc 'sync', 'Sync with remote server'
1059
- method_option :new_branch, :type => :boolean, :aliases => ["--nb"], :desc => "create new branch of commits"
1060
- method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
2095
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb"], :desc => "create new branch of commits"
2096
+ method_option :verbose, :type => :boolean, :aliases => ["-v"], :default => false
2097
+ method_option :ignore, :type => :string, :aliases => ["-i", "--ignore"], :default => ""
1061
2098
 
1062
- def sync
2099
+ def sync(direct=true)
2100
+ verify_logged_in(true) if direct
1063
2101
  if options["verbose"]
1064
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
2102
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
1065
2103
  else
1066
2104
  say 'Syncing project', Thor::Shell::Color::BLUE
1067
2105
  end
1068
2106
 
1069
2107
 
1070
- invoke :download, [], :new_branch => options["new_branch"], :verbose => options["verbose"], :sync=>true
1071
- invoke :upload, [], :new_branch => options["new_branch"], :verbose => options["verbose"],:sync=>true
1072
- check = Helpers.checkmark()
2108
+ invoke :download, [], :new_branch => options["new_branch"], :verbose => options["verbose"], :sync => true
2109
+ invoke :upload, [link=false, sync=true, direct=direct], :new_branch => options["new_branch"], :verbose => options["verbose"], :sync => true,
2110
+ :ignore => options[:ignore]
1073
2111
 
1074
- say "#{check} Syncing project completed successfully", Thor::Shell::Color::GREEN
1075
2112
 
1076
2113
  end
1077
2114
 
1078
2115
 
1079
2116
  desc 'run cmd', 'Runs an experiment'
1080
- method_option :local, :type => :boolean, :aliases => ["--l"], :default => false
1081
- method_option :small, :type => :boolean, :aliases => ["--sm"], :default => false
1082
- method_option :medium, :type => :boolean, :aliases => ["--med"], :default => false
1083
- method_option :large, :type => :boolean, :aliases => ["--lg"], :default => false
2117
+ method_option :local, :type => :boolean, :aliases => ["-l", "--local"], :default => false
2118
+ method_option :small, :type => :boolean, :aliases => ["-sm", "--small"], :default => false
2119
+ method_option :medium, :type => :boolean, :aliases => ["-md", "--medium"], :default => false
2120
+ method_option :large, :type => :boolean, :aliases => ["-lg", "--large"], :default => false
1084
2121
  method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
1085
- method_option :gpuxl, :type => :boolean, :aliases => ["--gxl"], :default => false
1086
- method_option :sync_before, :type => :boolean, :aliases => ["--sb"], :default => true
1087
- method_option :sync_after, :type => :boolean, :aliases => ["--sa"], :default => true
1088
- method_option :title, :type => :string, :aliases => ["--t"], :default => ""
2122
+ method_option :gpuxl, :type => :boolean, :aliases => ["--gpuxl"], :default => false
2123
+ method_option :gpuxxl, :type => :boolean, :aliases => ["--gpuxxl"], :default => false
2124
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sync_before"], :default => true
2125
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sync_after"], :default => true
2126
+ method_option :title, :type => :string, :aliases => ["-t", "--title"], :default => ""
1089
2127
  method_option :log, :type => :boolean, :aliases => ["--log"], :default => false
1090
- method_option :email_notification, :type => :boolean, :aliases => ["--en"], :default => false
1091
- method_option :upload_output, :type => :string, :aliases => ["--uo"], :default => ""
1092
- method_option :commit, :type => :string, :aliases => ["--c"], :default => ""
1093
- method_option :schedule, :type => :string, :aliases => ["--s"], :default => ""
1094
-
2128
+ method_option :email_notification, :type => :boolean, :aliases => ["-en", "--email_notification"], :default => false
2129
+ method_option :upload_output, :type => :string, :aliases => ["-uo", "--upload_output"], :default => ""
2130
+ method_option :commit, :type => :string, :aliases => ["-c", "--commit"], :default => ""
2131
+ method_option :schedule, :type => :string, :aliases => ["-s", "--schedule"], :default => ""
2132
+ method_option :image, :type => :string, :aliases => ["-i", "--image"], :default => ""
2133
+ method_option :grid, :type => :string, :aliases => ["-g", "--grid"], :default => ""
2134
+ method_option :data, :type => :string, :aliases => ["-d", "--data"], :default => ""
2135
+ method_option :data_commit, :type => :string, :aliases => ["--data_commit"], :default => ""
2136
+ method_option :ignore, :type => :string, :aliases => ["-i", "--ignore"], :desc => "ignore following files", :default => ""
1095
2137
 
1096
2138
  def run(*cmd)
1097
2139
  sync_before = options["sync_before"]
@@ -1103,37 +2145,74 @@ module Cnvrg
1103
2145
  upload_output = options["upload_output"]
1104
2146
  local = options["local"]
1105
2147
  schedule = options["schedule"]
2148
+ image = options["image"]
2149
+ grid = options["grid"]
2150
+ data = options["data"]
2151
+ data_commit = options["data_commit"]
2152
+ ignore = options["ignore"]
2153
+ options_hash = Hash[options]
2154
+ real_options = []
2155
+ options_hash.each do |o|
2156
+ real_options << o if (!o[1].eql? "" and !["small", "medium", "large", "gpu", "gpuxl", "gpuxxl"].include? o[0])
2157
+ end
1106
2158
  if local
1107
2159
  invoke :exec, [cmd], :sync_before => sync_before, :sync_after => sync_after, :title => title,
1108
- :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit
2160
+ :log => log, :email_notification => email_notification, :upload_output => upload_output,
2161
+ :commit => commit, :image => image, :data => data, :data_commit => data_commit, :ignore => ignore
1109
2162
  return
1110
2163
  else
1111
- instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"], "gpu" => options["gpu"], "gpuxl" => options["gpuxl"]}
2164
+ real_options.delete(["local", false])
2165
+ instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"],
2166
+ "gpu" => options["gpu"], "gpuxl" => options["gpuxl"], "gpuxxl" => options["gpuxxl"]}
1112
2167
  instance_type = get_instance_type(instances)
2168
+ if !instance_type.nil? and !instance_type.empty?
2169
+ real_options << ["machine_type", instance_type]
2170
+ end
2171
+ exec_options = real_options.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
2172
+ cmd_to_exec = "#{exec_options} #{cmd.join(" ")}"
1113
2173
  invoke :exec_remote, [cmd], :sync_before => sync_before, :sync_after => sync_after, :title => title, :machine_type => instance_type,
1114
- :schedule => schedule, :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit
2174
+ :schedule => schedule, :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit,
2175
+ :image => image, :grid => grid, :data => data, :data_commit => data_commit, :ignore => ignore
1115
2176
  return
1116
2177
  end
1117
- end
1118
2178
 
2179
+ # if local
2180
+ #
2181
+ # else
1119
2182
 
1120
- desc '', ''
1121
- method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
1122
- method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
1123
- method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
1124
- method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
1125
- method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
1126
- method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
1127
- method_option :commit, :type => :string, :aliases => ["--c", "-c"], :default => ""
1128
2183
 
2184
+ # invoke :exec_remote, [cmd_to_exec.split(" ")], :sync_before => sync_before, :sync_after => sync_after, :title => title, :machine_type => instance_type,
2185
+ # :schedule => schedule, :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit,
2186
+ # :image => image, :grid => grid, :data => data, :data_commit => data_commit, :ignore => ignore
2187
+ # return
2188
+ # end
2189
+ end
2190
+
2191
+
2192
+ desc '', '', :hide => true
2193
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb,--sync_before"], :default => true
2194
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa,--sync_after"], :default => true
2195
+ method_option :title, :type => :string, :aliases => ["-t", "--title"], :default => ""
2196
+ method_option :log, :type => :boolean, :aliases => ["--log"], :default => false
2197
+ method_option :email_notification, :type => :boolean, :aliases => ["-en,--email_notification"], :default => false
2198
+ method_option :upload_output, :type => :string, :aliases => ["-uo,--upload_output"], :default => ""
2199
+ method_option :commit, :type => :string, :aliases => ["-c", "--commit"], :default => ""
2200
+ method_option :image, :type => :string, :aliases => ["-i", "--image"], :default => ""
2201
+ method_option :indocker, :type => :boolean, :aliases => ["--indocker"], :default => false
2202
+ method_option :data, :type => :string, :aliases => ["-d", "--data"], :default => ""
2203
+ method_option :data_commit, :type => :string, :aliases => ["-dc", "--data_commit"], :default => ""
2204
+ method_option :ignore, :type => :string, :aliases => ["-i", "--ignore"], :desc => "ignore following files", :default => ""
2205
+ method_option :remote, :type => :boolean, :aliases => ["--remote"], :default => false
2206
+ method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
1129
2207
  def exec(*cmd)
2208
+
1130
2209
  log = []
1131
2210
  cpu_average =0
1132
2211
  memory_average = 0
1133
2212
  verify_logged_in(true)
1134
2213
  log_start(__method__, args, options)
1135
- working_dir = Dir.pwd
1136
- image = is_project_with_docker(working_dir)
2214
+ working_dir = is_cnvrg_dir
2215
+ script_path = get_cmd_path_in_dir(working_dir, Dir.pwd)
1137
2216
 
1138
2217
 
1139
2218
  sync_before = options["sync_before"]
@@ -1141,8 +2220,14 @@ module Cnvrg
1141
2220
  print_log = options["log"]
1142
2221
  title = options["title"]
1143
2222
  commit = options["commit"] || nil
2223
+ image = options["image"] || nil
2224
+ indocker = options["indocker"] || false
2225
+ ignore = options[:ignore] || ""
2226
+
2227
+
1144
2228
  email_notification = options["email_notification"]
1145
2229
  upload_output = options["upload_output"]
2230
+ upload_output = "1m" if upload_output.nil? or upload_output.empty?
1146
2231
  time_to_upload = calc_output_time(upload_output)
1147
2232
  project_home = get_project_home
1148
2233
  @project = Project.new(project_home)
@@ -1154,38 +2239,55 @@ module Cnvrg
1154
2239
  else
1155
2240
  if sync_before
1156
2241
  # Sync before run
1157
- invoke :sync, [], :new_branch => is_new_branch
2242
+
2243
+ invoke :sync, [false], :new_branch => is_new_branch, :ignore => ignore
1158
2244
  end
1159
2245
  end
2246
+ #set image for the project
2247
+ if !image.nil? and !image.empty?
2248
+ invoke :set_image, [image]
2249
+ end
2250
+ if !indocker
2251
+ image_proj = is_project_with_docker(working_dir)
1160
2252
 
1161
2253
 
1162
- if image and image.is_docker
1163
- container= image.get_container
1164
- if !container
1165
- say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
1166
- exit(1)
2254
+ if image_proj and image_proj.is_docker
2255
+ container= image_proj.get_container
2256
+ if !container
2257
+ say "Couldn't create container with image #{image_proj.image_name}:#{image_proj.image_tag}", Thor::Shell::Color::RED
2258
+ exit(1)
2259
+ end
2260
+
2261
+
2262
+ exec_args = args.flatten.join(" ")
2263
+ options_hash = Hash[options]
2264
+ options_hash.except!("image", "indocker")
2265
+ exec_options = options_hash.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
2266
+ command_to_run = copy_args.join(" ")
2267
+ command = ["/bin/bash", "-lc", "cnvrg exec --indocker #{exec_options} #{command_to_run} #{exec_args}"]
2268
+ puts container.exec(command, tty: true)
2269
+ container.stop()
2270
+ exit(0)
1167
2271
  end
1168
- exec_args = args.flatten.join(" ")
1169
- exec_options = options.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
1170
- command_to_run = cmd.join(" ")
1171
- command = ["/bin/bash", "-lc", "cnvrg exec_docker #{exec_options} #{command_to_run} #{exec_args}"]
1172
- puts container.exec(command, tty: true)
1173
- container.stop()
1174
- exit(0)
1175
2272
  end
1176
-
2273
+ remote = options["remote"]
2274
+ if remote
2275
+ docker_id = `cat /etc/hostname`
2276
+ docker_id = docker_id.strip()
2277
+ end
2278
+ is_on_gpu = options["gpu"]
1177
2279
  start_commit = @project.last_local_commit
1178
2280
  cmd = cmd.join("\s")
1179
2281
 
1180
- say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
1181
-
1182
2282
  @exp = Experiment.new(@project.owner, @project.slug)
1183
2283
 
1184
2284
  platform = RUBY_PLATFORM
1185
2285
  machine_name = Socket.gethostname
1186
2286
  begin
1187
- machine_activity = @exp.get_machine_activity(Dir.pwd)
1188
- @exp.start(cmd, platform, machine_name, start_commit, title, email_notification, machine_activity)
2287
+ machine_activity = @exp.get_machine_activity(working_dir)
2288
+ @exp.start(cmd, platform, machine_name, start_commit, title, email_notification, machine_activity, script_path)
2289
+ say "Experiment's live results: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
2290
+ say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
1189
2291
  unless @exp.slug.nil?
1190
2292
  real = Time.now
1191
2293
  exp_success = true
@@ -1197,19 +2299,34 @@ module Cnvrg
1197
2299
  begin
1198
2300
  stdout.each do |line|
1199
2301
  cur_time = Time.now
1200
- monitor = %x{ps aux|awk '{print $2,$3,$4}'|grep #{pid} }
1201
- monitor_by = monitor.split(" ")
1202
- memory = monitor_by[2]
1203
- cpu = monitor_by[1]
2302
+ if remote
2303
+ stats = usage_metrics_in_docker(docker_id)
2304
+ cpu = stats[0]
2305
+ memory = stats[1]
2306
+ else
2307
+ memory = memory_usage()
2308
+ cpu = cpu_usage()
2309
+ end
2310
+
1204
2311
  memory_total << memory.to_f
1205
2312
  cpu_total << cpu.to_f
1206
2313
  real_time= Time.now-real
1207
2314
 
1208
- cur_log = {time: cur_time,
2315
+ cur_log = { time: cur_time,
1209
2316
  message: line,
1210
2317
  type: "stdout",
1211
- real: real_time}
1212
- if print_log
2318
+ real: real_time,
2319
+ cpu: cpu,
2320
+ memory: memory
2321
+ }
2322
+ if is_on_gpu
2323
+ gpu_stats = gpu_util
2324
+ gpu_utilization = gpu_stats[0]
2325
+ gpu_memory_util = gpu_stats[1]
2326
+ cur_log.merge!(gpu_util:gpu_utilization,gpu_memory_util:gpu_memory_util)
2327
+ end
2328
+
2329
+ if print_log
1213
2330
  puts cur_log
1214
2331
  end
1215
2332
  log << cur_log
@@ -1218,8 +2335,8 @@ module Cnvrg
1218
2335
  if time_to_upload !=0
1219
2336
  if time_to_upload <= Time.now - start_loop
1220
2337
  #upload current log
1221
- cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
1222
- memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
2338
+ # cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
2339
+ # memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
1223
2340
 
1224
2341
  @exp.upload_temp_log(log, cpu_average, memory_average)
1225
2342
  log = []
@@ -1243,8 +2360,7 @@ module Cnvrg
1243
2360
  end
1244
2361
 
1245
2362
  rescue Errno::EIO => e
1246
- puts e
1247
- # break
2363
+ # break
1248
2364
  rescue Errno::ENOENT
1249
2365
  log_end(1, "command #{cmd} isn't valid")
1250
2366
 
@@ -1256,8 +2372,11 @@ module Cnvrg
1256
2372
  exp_success = false
1257
2373
  say "The process exited!", Thor::Shell::Color::RED
1258
2374
  rescue => e
1259
- puts e
1260
- log_end(1, e.message)
2375
+ log_end(-1, e.message)
2376
+ res = @exp.end(log, 1, start_commit, cpu_average, memory_average)
2377
+
2378
+ say "Error occurred,aborting", Thor::Shell::Color::RED
2379
+ exit(0)
1261
2380
  end
1262
2381
  ::Process.wait pid
1263
2382
  cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
@@ -1268,7 +2387,7 @@ module Cnvrg
1268
2387
  end
1269
2388
  if !exp_success
1270
2389
  if !Cnvrg::Helpers.internet_connection?
1271
- wait_offline = agree "Seems like you're offline, wait until your'e back online?", Thor::Shell::Color::YELLOW
2390
+ wait_offline = agree "Seems like you're offline, wait until you're back online?", Thor::Shell::Color::YELLOW
1272
2391
  if wait_offline
1273
2392
  say "Waiting until your'e online..", Thor::Shell::Color::BLUE
1274
2393
  while !Cnvrg::Helpers.internet_connection?
@@ -1291,23 +2410,21 @@ module Cnvrg
1291
2410
  end
1292
2411
  if sync_after
1293
2412
  # Sync after run
1294
- if !commit.nil?
1295
- invoke :sync, [], :new_branch => true
1296
2413
 
1297
- else
1298
- invoke :sync, [], :new_branch => true
1299
- end
2414
+
2415
+ download(sync=true, ignore_list=ignore)
2416
+ upload(link=false, sync=true, direct=false, ignore_list=ignore)
2417
+
1300
2418
  end
1301
2419
  end_commit = @project.last_local_commit
1302
2420
 
1303
2421
  res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1304
2422
  check = Helpers.checkmark()
1305
- say "#{check} Done. Experiment's result: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
2423
+ say "#{check} Done. Experiment's results were updated!", Thor::Shell::Color::GREEN
1306
2424
  log_end(0)
1307
2425
  end
1308
2426
  rescue => e
1309
- puts e
1310
- log_end(1, e.message)
2427
+ log_end(-1, e.message)
1311
2428
  if container
1312
2429
  container.stop()
1313
2430
  end
@@ -1334,7 +2451,7 @@ module Cnvrg
1334
2451
  end
1335
2452
  end
1336
2453
 
1337
- desc '', ''
2454
+ desc '', '', :hide => true
1338
2455
  method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
1339
2456
  method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
1340
2457
  method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
@@ -1373,7 +2490,7 @@ module Cnvrg
1373
2490
  machine_name = Socket.gethostname
1374
2491
  begin
1375
2492
 
1376
- @exp.start(cmd, platform, machine_name, start_commit, title, email_notification, machine_activity)
2493
+ @exp.start(cmd, platform, machine_name, start_commit, title, email_notification, machine_activity, Dir.pwd)
1377
2494
  unless @exp.slug.nil?
1378
2495
  real = Time.now
1379
2496
  exp_success = true
@@ -1443,7 +2560,9 @@ module Cnvrg
1443
2560
  exp_success = false
1444
2561
  say "The process exited!", Thor::Shell::Color::RED
1445
2562
  rescue => e
1446
- log_end(1, e.message)
2563
+ log_end(-1, e.message)
2564
+ say "Error occurred, aborting", Thor::Shell::Color::RED
2565
+ exit(0)
1447
2566
  end
1448
2567
  ::Process.wait pid
1449
2568
  cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
@@ -1493,7 +2612,7 @@ module Cnvrg
1493
2612
  log_end(0)
1494
2613
  end
1495
2614
  rescue => e
1496
- log_end(1, e.message)
2615
+ log_end(-1, e.message)
1497
2616
  say "Couldn't run #{cmd}, check your input parameters", Thor::Shell::Color::RED
1498
2617
  exit(1)
1499
2618
  end
@@ -1517,22 +2636,33 @@ module Cnvrg
1517
2636
  end
1518
2637
  end
1519
2638
 
1520
- desc '', ''
1521
- method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
1522
- method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
1523
- method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
1524
- method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
1525
- method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
1526
- method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
1527
- method_option :machine_type, :type => :string, :aliases => ["--i", "-i"], :default => ""
1528
- method_option :schedule, :type => :string, :aliases => ["--s", "-s"], :default => ""
1529
- method_option :commit, :type => :string, :aliases => ["--c", "-c"], :default => nil
2639
+ desc '', '', :hide => true
2640
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sync_before"], :default => true
2641
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sync_after"], :default => true
2642
+ method_option :title, :type => :string, :aliases => ["-t", "--title"], :default => ""
2643
+ method_option :log, :type => :boolean, :aliases => ["--log"], :default => false
2644
+ method_option :email_notification, :type => :boolean, :aliases => ["-en", "--email_notification"], :default => false
2645
+ method_option :upload_output, :type => :string, :aliases => ["-uo", "--upload_output"], :default => ""
2646
+ method_option :machine_type, :type => :string, :default => ""
2647
+ method_option :schedule, :type => :string, :aliases => ["-s", "--schedule"], :default => ""
2648
+ method_option :commit, :type => :string, :aliases => ["-c, --commit"], :default => nil
2649
+ method_option :image, :type => :string, :aliases => ["-i", "--image"], :default => ""
2650
+ method_option :grid, :type => :string, :aliases => ["-g", "--grid"], :default => ""
2651
+ method_option :data, :type => :string, :aliases => ["-d", "--data"], :default => ""
2652
+ method_option :data_commit, :type => :string, :aliases => ["--data_commit"], :default => ""
2653
+ method_option :ignore, :type => :string, :aliases => ["-i", "--ignore"], :desc => "ignore following files", :default => ""
1530
2654
 
1531
2655
  def exec_remote(*cmd)
1532
2656
  verify_logged_in(true)
1533
2657
  log_start(__method__, args, options)
1534
2658
  working_dir = is_cnvrg_dir
2659
+ path_to_cmd = get_cmd_path_in_dir(working_dir, Dir.pwd)
2660
+
1535
2661
  begin
2662
+ grid = options["grid"] || nil
2663
+ data = options["data"] || nil
2664
+ data_commit = options["data_commit"] || nil
2665
+ sync_before = options["sync_before"]
1536
2666
 
1537
2667
  instance_type = options["machine_type"] || nil
1538
2668
  schedule = options["schedule"] || ""
@@ -1554,12 +2684,22 @@ module Cnvrg
1554
2684
  new_time = new_time[0, new_time.size-6] #remove timezone
1555
2685
  schedule = "at #{new_time}"
1556
2686
  end
1557
-
2687
+ upload_output = options["upload_output"]
2688
+ time_to_upload = calc_output_time(upload_output)
2689
+ if time_to_upload==0 or time_to_upload==-1
2690
+ upload_output_option = "--upload_output=1m"
2691
+ else
2692
+ upload_output_option = "--upload_output=#{upload_output}"
2693
+ end
2694
+ remote = "--remote=true"
2695
+ if !instance_type.nil? and instance_type.include? "gpu"
2696
+ remote= "#{remote} --gpu=true"
2697
+ end
1558
2698
 
1559
2699
  options_hash = Hash[options]
1560
- options_hash.except!("schedule", "machine_type")
2700
+ options_hash.except!("schedule", "machine_type", "image", "upload_output", "grid", "data", "data_commit", "local", "small", "medium", "large", "gpu", "gpuxl", "gpuxxl")
1561
2701
  exec_options = options_hash.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
1562
- command = "#{exec_options} --uo=1m #{cmd.flatten.join(" ")}"
2702
+ command = "#{exec_options} #{remote} #{upload_output_option} #{cmd.flatten.join(" ")}"
1563
2703
  commit_to_run = options["commit"] || nil
1564
2704
  if !schedule.nil? and !schedule.empty?
1565
2705
 
@@ -1567,32 +2707,51 @@ module Cnvrg
1567
2707
 
1568
2708
  end
1569
2709
  project = Project.new(working_dir)
2710
+ choose_image = options["image"]
1570
2711
 
1571
-
2712
+ if !choose_image.nil? and !choose_image.empty?
2713
+ invoke :set_image, [choose_image]
2714
+ end
1572
2715
  image = is_project_with_docker(working_dir)
1573
2716
  if !image or !image.is_docker
1574
- say "Couldn't find image related to project", Thor::Shell::Color::RED
1575
- default = yes? "use cnvrg default image?", Thor::Shell::Color::YELLOW
1576
- if default
1577
- image = Images.new(working_dir, "cnvrg")
1578
- image_slug = image.image_slug
1579
- else
1580
- exit(0)
2717
+ # say "Couldn't find image related to project", Thor::Shell::Color::RED
2718
+
2719
+ image_slug = "cnvrg"
2720
+ if instance_type.eql? "gpu" or instance_type.eql? "gpuxl"
2721
+ image_slug = "cnvrg_gpu"
1581
2722
  end
2723
+ # default = yes? "use #{default_image_name} default image?", Thor::Shell::Color::YELLOW
2724
+ # if default
2725
+ # image = Images.new(working_dir, default_image_name)
2726
+ # image_slug = image.image_slug
2727
+ # else
2728
+ # exit(0)
2729
+ # end
1582
2730
  else
1583
2731
  image_slug = image.image_slug
1584
2732
  end
1585
2733
 
2734
+ invoke :sync, [false], [] if sync_before
2735
+
1586
2736
 
2737
+ if command.include? "'"
2738
+ oc = command.to_enum(:scan, /'/).map { Regexp.last_match }
2739
+ pairs = oc.enum_for(:each_slice, 2).to_a
2740
+ pairs.each_with_index do |p,i|
2741
+ add=0
2742
+ if i!=0
2743
+ add=2*i
2744
+ end
2745
+ total_loc = command[p[0].offset(0)[0]+add..p[1].offset(0)[0]+add]
2746
+ command[p[0].offset(0)[0]+add..p[1].offset(0)[0]+add] = "\"#{total_loc}\""
2747
+ end
1587
2748
 
1588
- invoke :sync, [], []
1589
2749
 
2750
+ end
1590
2751
  say "Running remote experiment", Thor::Shell::Color::BLUE
1591
2752
  exp = Experiment.new(project.owner, project.slug)
1592
-
1593
- res = exp.exec_remote(command, commit_to_run, instance_type, image_slug, schedule, local_timestamp)
2753
+ res = exp.exec_remote(command, commit_to_run, instance_type, image_slug, schedule, local_timestamp, grid, path_to_cmd, data, data_commit)
1594
2754
  if Cnvrg::CLI.is_response_success(res)
1595
-
1596
2755
  # if res["result"]["machine"] == -1
1597
2756
  # say "There are no available machines", Thor::Shell::Color::BLUE
1598
2757
  # create = yes? "create new machine?", Thor::Shell::Color::YELLOW
@@ -1624,7 +2783,13 @@ module Cnvrg
1624
2783
  # end
1625
2784
  # else
1626
2785
  check = Helpers.checkmark()
1627
- say "#{check} Experiment's is on: #{Cnvrg::Helpers.remote_url}/#{project.owner}/projects/#{project.slug}/experiments/#{res["result"]["exp_url"]}", Thor::Shell::Color::GREEN
2786
+ str = "#{check} Experiment's is on: #{Cnvrg::Helpers.remote_url}/#{project.owner}/projects/#{project.slug}/experiments/#{res["result"]["exp_url"]}"
2787
+
2788
+ if res["result"]["grid"]
2789
+ str = "Running grid search. #{Cnvrg::Helpers.remote_url}/#{project.owner}/projects/#{project.slug}/experiments?grid=#{res["result"]["exp_url"]} "
2790
+ end
2791
+
2792
+ say str, Thor::Shell::Color::GREEN
1628
2793
 
1629
2794
  exit(0)
1630
2795
  # end
@@ -1644,21 +2809,30 @@ module Cnvrg
1644
2809
  end
1645
2810
 
1646
2811
  desc 'deploy', 'Deploys model to production'
1647
- method_option :machine_type, :type => :string, :aliases => ["--i", "-i"], :default => ""
1648
- method_option :schedule, :type => :string, :aliases => ["--s", "-s"], :default => ""
1649
- method_option :commit, :type => :string, :aliases => ["--c", "-c"], :default => ""
2812
+ method_option :small, :type => :boolean, :aliases => ["-sm", "--small"], :default => false
2813
+ method_option :medium, :type => :boolean, :aliases => ["-md", "--medium"], :default => false
2814
+ method_option :large, :type => :boolean, :aliases => ["-lg", "--large"], :default => false
2815
+ method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
2816
+ method_option :gpuxl, :type => :boolean, :aliases => ["--gpuxl"], :default => false
2817
+ method_option :gpuxxl, :type => :boolean, :aliases => ["--gpuxxl"], :default => false
2818
+ method_option :schedule, :type => :string, :aliases => ["--schedule", "-s"], :default => ""
2819
+
2820
+ method_option :commit, :type => :string, :aliases => ["--commit", "-c"], :default => ""
2821
+ method_option :workers, :type => :string, :aliases => ["--workers", "-w"], :default => ""
2822
+ method_option :file_as_input, :type => :boolean, :aliases => ["--input", "-i"], :default => false
1650
2823
 
1651
2824
  def deploy(file_to_run, function)
1652
2825
  verify_logged_in(true)
1653
2826
  log_start(__method__, args, options)
1654
2827
  working_dir = is_cnvrg_dir
1655
2828
  begin
2829
+ instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"],
2830
+ "gpu" => options["gpu"], "gpuxl" => options["gpuxl"], "gpuxxl" => options["gpuxxl"]}
2831
+ instance_type = get_instance_type(instances)
1656
2832
 
1657
- instance_type = options["machine_type"] || nil
1658
2833
  schedule = options["schedule"] || ""
1659
2834
 
1660
2835
 
1661
-
1662
2836
  if !schedule.nil? and !schedule.empty?
1663
2837
 
1664
2838
  local_timestamp = get_schedule_date
@@ -1667,26 +2841,34 @@ module Cnvrg
1667
2841
  project = Project.new(working_dir)
1668
2842
  commit_to_run = options["commit"] || nil
1669
2843
 
2844
+ workers = options["workers"] || nil
2845
+ begin
2846
+ num_workers = workers.to_i
2847
+ rescue
2848
+ say "Number of workers should be a number between 1 to 10", Thor::Shell::Color::RED
2849
+ exit(1)
2850
+ end
2851
+ file_as_input = options["file_as_input"] || false
2852
+
1670
2853
 
1671
2854
  image = is_project_with_docker(working_dir)
1672
2855
  if !image or !image.is_docker
1673
- say "Couldn't find image related to project", Thor::Shell::Color::RED
1674
- default = yes? "use cnvrg default image?", Thor::Shell::Color::YELLOW
1675
- if default
1676
- image = Images.new(working_dir, "cnvrg")
1677
- image_slug = image.image_slug
1678
- else
1679
- exit(0)
1680
- end
2856
+ # say "Couldn't find image related to project", Thor::Shell::Color::RED
2857
+ # default = yes? "use cnvrg default image?", Thor::Shell::Color::YELLOW
2858
+ # if default
2859
+ image = Images.new(working_dir, "cnvrg")
2860
+ image_slug = image.image_slug
2861
+ # else
2862
+ # exit(0)
2863
+ # end
1681
2864
  else
1682
2865
  image_slug = image.image_slug
1683
2866
  end
1684
2867
 
1685
2868
 
2869
+ invoke :sync, [false], []
1686
2870
 
1687
- invoke :sync, [], []
1688
-
1689
- res = project.deploy(file_to_run, function, nil, commit_to_run, instance_type, image_slug, schedule, local_timestamp)
2871
+ res = project.deploy(file_to_run, function, nil, commit_to_run, instance_type, image_slug, schedule, local_timestamp, num_workers, file_as_input)
1690
2872
 
1691
2873
  if Cnvrg::CLI.is_response_success(res)
1692
2874
 
@@ -1742,27 +2924,37 @@ module Cnvrg
1742
2924
 
1743
2925
  method_option :kernel, :type => :string, :aliases => ["--k", "-k"], :default => ""
1744
2926
  method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
1745
- method_option :local, :type => :boolean, :aliases => ["--l"], :default => false
1746
- method_option :small, :type => :boolean, :aliases => ["--sm"], :default => false
1747
- method_option :medium, :type => :boolean, :aliases => ["--med"], :default => false
1748
- method_option :large, :type => :boolean, :aliases => ["--lg"], :default => false
2927
+ method_option :local, :type => :boolean, :aliases => ["-l"], :default => false
2928
+ method_option :small, :type => :boolean, :aliases => ["-sm", "--small"], :default => false
2929
+ method_option :medium, :type => :boolean, :aliases => ["-md", "--medium"], :default => false
2930
+ method_option :large, :type => :boolean, :aliases => ["-lg", "--large"], :default => false
1749
2931
  method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
1750
- method_option :gpuxl, :type => :boolean, :aliases => ["--gxl"], :default => false
1751
- desc 'starts a notebook session', 'starts a notebook session remotely or locally'
2932
+ method_option :gpuxl, :type => :boolean, :aliases => ["--gpuxl"], :default => false
2933
+ method_option :gpuxxl, :type => :boolean, :aliases => ["--gpuxxl"], :default => false
2934
+ method_option :image, :type => :string, :aliases => ["-i", "--image"], :default => ""
2935
+ method_option :data, :type => :string, :aliases => ["-d", "--data"], :default => ""
2936
+ method_option :data_commit, :type => :string, :aliases => ["--data_commit"], :default => ""
2937
+
2938
+
2939
+ desc 'notebook', 'starts a notebook session remotely or locally'
1752
2940
 
1753
- def notebook()
2941
+ def notebook
1754
2942
  local = options["local"]
1755
2943
  notebook_dir = options["notebook_dir"]
1756
2944
  kernel = options["kernel"]
1757
-
2945
+ image = options["image"]
2946
+ data = options["data"]
2947
+ data_commit = options["data_commit"]
1758
2948
  if local
1759
- invoke :run_notebook, [], :notebook_dir => notebook_dir, :remote => false, :kernel => kernel
2949
+ invoke :run_notebook, [], :notebook_dir => notebook_dir, :remote => false, :kernel => kernel, :image => image
1760
2950
  return
1761
2951
  else
1762
- instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"], "gpu" => options["gpu"], "gpuxl" => options["gpuxl"]}
2952
+ instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"],
2953
+ "gpu" => options["gpu"], "gpuxl" => options["gpuxl"], "gpuxxl" => options["gpuxxl"]}
1763
2954
  instance_type = get_instance_type(instances)
1764
2955
 
1765
- invoke :remote_notebook, [], :notebook_dir => notebook_dir, :kernel => kernel, :machine_type => instance_type
2956
+ invoke :remote_notebook, [], :notebook_dir => notebook_dir, :kernel => kernel, :machine_type => instance_type, :image => image,
2957
+ :data => data, :data_commit => data_commit
1766
2958
  return
1767
2959
 
1768
2960
  end
@@ -1771,9 +2963,13 @@ module Cnvrg
1771
2963
  end
1772
2964
 
1773
2965
  desc 'remote_notebook', 'run notebook server on remote server'
1774
- method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
1775
- method_option :machine_type, :type => :string, :aliases => ["--i", "-i"], :default => ""
1776
- method_option :kernel, :type => :string, :aliases => ["--k", "-k"], :default => ""
2966
+ method_option :notebook_dir, :type => :string, :aliases => ["-n"], :default => "", :desc => "relative path to notebook dir from current directory"
2967
+ method_option :machine_type, :type => :string, :default => ""
2968
+ method_option :kernel, :type => :string, :aliases => ["--kernel", "-k"], :default => ""
2969
+ method_option :image, :type => :string, :aliases => ["-i"], :default => ""
2970
+ method_option :data, :type => :string, :aliases => ["-d", "--data"], :default => ""
2971
+ method_option :data_commit, :type => :string, :aliases => ["--data_commit"], :default => ""
2972
+
1777
2973
 
1778
2974
  def remote_notebook()
1779
2975
  verify_logged_in(true)
@@ -1784,23 +2980,35 @@ module Cnvrg
1784
2980
  notebook_dir = options["notebook_dir"]
1785
2981
  instance_type = options["machine_type"] || nil
1786
2982
  kernel = options["kernel"] || nil
2983
+ data = options["data"]
2984
+ data_commit = options["data_commit"]
1787
2985
 
1788
2986
 
1789
2987
  begin
2988
+ choose_image = options["image"]
1790
2989
 
2990
+ if !choose_image.nil? and !choose_image.empty?
2991
+ invoke :set_image, [choose_image]
2992
+ end
1791
2993
  @image = is_project_with_docker(working_dir)
1792
- if !@image.is_docker
1793
- say "Couldn't find image related to project", Thor::Shell::Color::RED
1794
- exit(0)
2994
+ if !@image or !@image.is_docker
2995
+ # say "Couldn't find image related to project", Thor::Shell::Color::RED
2996
+ default_image_name = "cnvrg"
2997
+ if instance_type.eql? "gpu" or instance_type.eql? "gpuxl"
2998
+ default_image_name = "cnvrg-gpu"
2999
+ end
3000
+ # default = yes? "use #{default_image_name} default image?", Thor::Shell::Color::YELLOW
3001
+ # if default
3002
+ @image = Images.new(working_dir, default_image_name)
3003
+ # else
3004
+ # exit(0)
3005
+ # end
1795
3006
  end
1796
3007
 
1797
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
1798
-
1799
- download()
1800
- upload()
3008
+ invoke :sync, [false], []
1801
3009
 
1802
3010
 
1803
- res = @image.remote_notebook(notebook_dir, instance_type, kernel)
3011
+ res = @image.remote_notebook(notebook_dir, instance_type, kernel, data, data_commit)
1804
3012
  if Cnvrg::CLI.is_response_success(res)
1805
3013
  if res["result"]["machine"] == -1
1806
3014
  say "There are no available machines", Thor::Shell::Color::BLUE
@@ -1839,7 +3047,7 @@ module Cnvrg
1839
3047
  note_url = res["result"]["notebook_url"]
1840
3048
  @image.set_note_url(note_url)
1841
3049
  check = Helpers.checkmark()
1842
- say "#{check} Notebook is on: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/show/#{note_url}", Thor::Shell::Color::GREEN
3050
+ say "#{check} Notebook is on: #{Cnvrg::Helpers.remote_url}/#{@image.owner}/projects/#{@image.project_slug}/notebook_sessions/show/#{note_url}", Thor::Shell::Color::GREEN
1843
3051
  # Launchy.open(url)
1844
3052
 
1845
3053
  exit(0)
@@ -1907,9 +3115,8 @@ module Cnvrg
1907
3115
 
1908
3116
  end
1909
3117
  rescue => e
1910
- puts e
1911
- log_end(-1)
1912
- say "Error occurd, Aborting"
3118
+ log_end(-1, e.message)
3119
+ say "Error occurred, aborting", Thor::Shell::Color::RED
1913
3120
  if container
1914
3121
  container.stop()
1915
3122
  end
@@ -1970,9 +3177,8 @@ module Cnvrg
1970
3177
  end
1971
3178
  end
1972
3179
  rescue => e
1973
- puts e
1974
- log_end(-1)
1975
- say "Error occurd, Aborting"
3180
+ log_end(-1, e.message)
3181
+ say "Error occurred, aborting"
1976
3182
  if container
1977
3183
  container.stop()
1978
3184
  end
@@ -1989,6 +3195,7 @@ module Cnvrg
1989
3195
  method_option :remote, :type => :boolean, :aliases => ["-r", "--r"], :default => false, :desc => "run on remote machine"
1990
3196
  method_option :kernel, :type => :string, :aliases => ["-k", "--k"], :default => "", :desc => "default kernel"
1991
3197
  method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
3198
+ method_option :image, :type => :string, :aliases => ["-i"], :default => ""
1992
3199
 
1993
3200
  def run_notebook
1994
3201
 
@@ -2002,7 +3209,7 @@ module Cnvrg
2002
3209
  notebook_dir = options["notebook_dir"]
2003
3210
  remote = options["remote"] || false
2004
3211
  kernel = options["kernel"] || ""
2005
-
3212
+ notebooks_pid = nil
2006
3213
 
2007
3214
  if notebook_dir.empty?
2008
3215
  notebook_dir = project_dir
@@ -2010,107 +3217,148 @@ module Cnvrg
2010
3217
 
2011
3218
  notebook_dir = project_dir+ notebook_dir
2012
3219
  end
2013
- say "Linking notebook directory to: #{File.basename notebook_dir}", Thor::Shell::Color::BLUE
2014
- image = is_project_with_docker(Dir.pwd)
2015
- if image and image.is_docker and !remote
2016
- container= image.get_container
2017
- if !container
3220
+ choose_image = options["image"]
2018
3221
 
2019
- say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
3222
+ if !choose_image.nil? and !choose_image.empty?
3223
+ invoke :set_image, [choose_image]
3224
+ end
3225
+
3226
+ image = is_project_with_docker(Dir.pwd)
3227
+ if !image
3228
+ jupyter_installed = `which jupyter`
3229
+ if !$?.success?
3230
+ say "Could not find jupyter, Is it installed?", Thor::Shell::Color::RED
2020
3231
  exit(1)
2021
3232
  end
2022
- else
2023
- say "Project is not configured with any image", Thor::Shell::Color::RED
2024
- exit(1)
2025
3233
 
2026
- end
2027
- if options["verbose"]
2028
- say "Syncing project before running", Thor::Shell::Color::BLUE
2029
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
2030
- end
2031
- @project = Project.new(project_dir)
2032
3234
 
2033
- start_commit = @project.last_local_commit
3235
+ cmd = "jupyter-notebook --port=8888"
3236
+ PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
3237
+ begin
3238
+ notebooks_pid = pid
3239
+ stdout.each do |line|
3240
+ puts line
3241
+
3242
+ end
3243
+
3244
+ rescue Errno::EIO => e
3245
+ # break
3246
+ rescue Errno::ENOENT
3247
+ log_end(1, "command #{cmd} isn't valid")
3248
+
3249
+
3250
+ say "command \"#{cmd}\" couldn't be executed, verify command is valid", Thor::Shell::Color::RED
3251
+ rescue PTY::ChildExited
3252
+ log_end(1, "proccess exited")
3253
+ say "The process exited!", Thor::Shell::Color::RED
3254
+ rescue => e
3255
+ log_end(-1, e.message)
3256
+ say "Error occurred,aborting", Thor::Shell::Color::RED
3257
+ exit(0)
3258
+
3259
+ end
3260
+
2034
3261
 
2035
- if (note_slug=image.note_slug)
2036
- say "There is a running notebook session in: https://cnvrg.io/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/show/#{note_slug}", Thor::Shell::Color::BLUE
2037
- new = yes? "Create a new session?", Thor::Shell::Color::YELLOW
2038
- if !new
2039
- exit(0)
2040
3262
  end
2041
3263
 
2042
3264
  end
2043
- invoke :sync, [], :verbose => options["verbose"]
2044
- say "Done Syncing", Thor::Shell::Color::BLUE if options["verbose"]
2045
- #replace url
2046
- base_url = get_base_url()
2047
3265
 
2048
- local_url = "/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/view/local"
2049
- command = ["/bin/bash","-lc","sed -i 's#c.NotebookApp.base_url = .*#c.NotebookApp.base_url = \"#{local_url}\"#' /home/ds/.jupyter/jupyter_notebook_config.py"]
2050
- container.exec(command, tty: true)
2051
- container.stop()
2052
- container.start()
3266
+ if image and image.is_docker and !remote
3267
+ container= image.get_container
3268
+ if !container
3269
+ say "Couldn't start docker container", Thor::Shell::Color::RED
3270
+ exit(1)
2053
3271
 
2054
- @note = Experiment.new(@project.owner, @project.slug)
2055
- port = image.container_port()
3272
+ end
2056
3273
 
2057
- command = ["/bin/bash", "-lc", "jupyter notebook list"]
2058
- list = container.exec(command, tty: true)[0]
2059
- if list.empty? or list.nil?
2060
- say "Couldn't start notebook server", Thor::Shell::Color::RED
2061
- log_end(1, "can't start notebook server")
2062
- exit(1)
2063
- end
3274
+ if options["verbose"]
3275
+ say "Syncing project before running", Thor::Shell::Color::BLUE
3276
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
3277
+ end
3278
+ @project = Project.new(project_dir)
3279
+
3280
+ start_commit = @project.last_local_commit
3281
+
3282
+ if (note_slug=image.note_slug)
3283
+ say "There is a running notebook session in: https://cnvrg.io/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/show/#{note_slug}", Thor::Shell::Color::BLUE
3284
+ new = yes? "Create a new session?", Thor::Shell::Color::YELLOW
3285
+ if !new
3286
+ exit(0)
3287
+ end
3288
+
3289
+ end
3290
+ invoke :sync, [false], :verbose => options["verbose"]
3291
+ say "Done Syncing", Thor::Shell::Color::BLUE if options["verbose"]
3292
+ #replace url
3293
+ base_url = get_base_url()
3294
+
3295
+ local_url = "/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/view/local"
3296
+ command = ["/bin/bash", "-lc", "sed -i 's#c.NotebookApp.base_url = .*#c.NotebookApp.base_url = \"#{local_url}\"#' /home/ds/.jupyter/jupyter_notebook_config.py"]
3297
+ container.exec(command, tty: true)
3298
+ container.stop()
3299
+ container.start()
3300
+ sleep(7)
3301
+ @note = Experiment.new(@project.owner, @project.slug)
3302
+ port = image.container_port()
3303
+
3304
+ command = ["/bin/bash", "-lc", "jupyter notebook list"]
3305
+ list = container.exec(command, tty: true)[0]
3306
+ if list.empty? or list.nil?
3307
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
3308
+ log_end(1, "can't start notebook server")
3309
+ exit(1)
3310
+ end
2064
3311
 
2065
- url = list[list.size-1].split(" ::")
2066
- token = url[0][(url[0].index("=")+1)..-1]
3312
+ result = ""
3313
+ list.each do |r|
3314
+ if r.include? "http"
3315
+ result = r
3316
+ end
3317
+ end
3318
+ token = result.to_s.split("::")[0].to_s.match(/(token=)(.+)\s/)[2]
2067
3319
 
2068
- # machine_activity = @note.get_machine_activity(project_dir)
3320
+ # machine_activity = @note.get_machine_activity(project_dir)
2069
3321
 
2070
3322
 
2071
- slug = @note.start_notebook_session(kernel, start_commit, token, port, false, notebook_dir)
2072
- image.set_note_url(slug)
2073
- note_url = "http://localhost:#{port}/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/view/local/?token=#{token}"
3323
+ slug = @note.start_notebook_session(kernel, start_commit, token, port, false, notebook_dir)
3324
+ image.set_note_url(slug)
3325
+ note_url = "http://localhost:#{port}/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/view/local/?token=#{token}"
2074
3326
 
2075
3327
 
2076
- if !note_url.empty?
2077
- check = Helpers.checkmark()
3328
+ if !note_url.empty?
3329
+ check = Helpers.checkmark()
2078
3330
 
2079
- say "#{check} Notebook server started successfully", Thor::Shell::Color::GREEN
2080
- Launchy.open(note_url)
2081
- else
2082
- say "Couldn't start notebook server", Thor::Shell::Color::RED
2083
- log_end(1, "can't start notebook server")
2084
- exit(1)
3331
+ say "#{check} Notebook server started successfully", Thor::Shell::Color::GREEN
3332
+ Launchy.open(note_url)
3333
+ else
3334
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
3335
+ log_end(1, "can't start notebook server")
3336
+ exit(1)
3337
+ end
2085
3338
  end
2086
3339
 
2087
- # jup =verify_software_installed("jupyter-notebook")
2088
- # logs = `#{jup} --no-browser --ip=0.0.0.0 --notebook-dir=#{notebook_dir}`
2089
- # url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
2090
- # if !url.empty?
2091
- # check = Helpers.checkmark()
2092
- #
2093
- # say "#{check} Notebook server started successfully, view notebook in url: #{url}", Thor::Shell::Color::GREEN
2094
- # log_end(0)
2095
- # else
2096
- # say "Couldn't start notebook server", Thor::Shell::Color::RED
2097
- # log_end(1, "can't start notebook server")
2098
- # exit(1)
2099
- # end
3340
+
2100
3341
  rescue => e
2101
- log_end(-1)
2102
- puts e
3342
+ log_end(-1, e.message)
2103
3343
  say "Error occurd, aborting", Thor::Shell::Color::RED
2104
3344
  if container
2105
3345
  container.stop()
2106
3346
  end
2107
3347
  rescue SignalException
2108
- log_end(-1)
2109
- if container
2110
- container.stop()
3348
+ if !notebooks_pid.nil?
3349
+ ::Process.kill(0, notebooks_pid)
3350
+ say "#{check} Notebook has stopped successfully", Thor::Shell::Color::GREEN
3351
+
3352
+
3353
+ invoke :sync, [false], []
3354
+ else
3355
+ log_end(-1)
3356
+
3357
+ if container
3358
+ container.stop()
3359
+ end
2111
3360
  end
2112
- say "Aborting"
2113
- exit(1)
3361
+
2114
3362
  end
2115
3363
 
2116
3364
 
@@ -2131,7 +3379,7 @@ module Cnvrg
2131
3379
 
2132
3380
 
2133
3381
  say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE if options["verbose"]
2134
- invoke :sync, [], :verbose => options["verbose"]
3382
+ invoke :sync, [false], :verbose => options["verbose"]
2135
3383
 
2136
3384
  say "Done Syncing", Thor::Shell::Color::BLUE if options["verbose"]
2137
3385
 
@@ -2176,8 +3424,7 @@ module Cnvrg
2176
3424
  exit(0)
2177
3425
  end
2178
3426
  rescue => e
2179
- puts e
2180
- log_end(-1)
3427
+ log_end(-1, e.message)
2181
3428
  say "Error occurd, aborting"
2182
3429
  if container
2183
3430
  container.stop()
@@ -2225,18 +3472,170 @@ module Cnvrg
2225
3472
  say "#{checks} Done, installing libraries completed", Thor::Shell::Color::GREEN
2226
3473
  container.stop()
2227
3474
 
2228
- log_end(0)
2229
- rescue => e
2230
- log_end(-1)
3475
+ log_end(0)
3476
+ rescue => e
3477
+ log_end(-1, e.message)
3478
+ say "Error occurd, aborting"
3479
+ if container
3480
+ container.stop()
3481
+ end
3482
+ rescue SignalException
3483
+ log_End(-1)
3484
+ if container
3485
+ container.stop()
3486
+ end
3487
+ say "\nAborting"
3488
+ exit(1)
3489
+ end
3490
+
3491
+ end
3492
+
3493
+ desc 'install_libraries', 'Install libraries'
3494
+ method_option :requirement, :type => :string, :aliases => ["-r", "--r"], :default => "", :desc => "Install from the given requirements file"
3495
+
3496
+ def install_python_libraries(*lib)
3497
+ begin
3498
+ verify_logged_in(false)
3499
+ log_start(__method__, args, options)
3500
+ verify_software_installed("docker")
3501
+ image = is_project_with_docker(Dir.pwd)
3502
+ if image and image.is_docker
3503
+ container = image.get_container
3504
+ if !container
3505
+
3506
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
3507
+ exit(1)
3508
+ end
3509
+ else
3510
+ say "Project is not configured with any image", Thor::Shell::Color::RED
3511
+ exit(1)
3512
+
3513
+ end
3514
+ req_file = options["requirement"] || nil
3515
+ if lib.nil? and not req_file.nil?
3516
+ if not File.exist? req_file
3517
+ say "Couldn't find #{req_file}", Thor::Shell::Color::RED
3518
+ exit(1)
3519
+
3520
+ end
3521
+ command_to_run = "pip install -r #{req_file}"
3522
+
3523
+ else
3524
+ command_to_run = lib.join(" ")
3525
+
3526
+ end
3527
+ say "Running #{command_to_run} in container", Thor::Shell::Color::BLUE
3528
+ command = ["/bin/bash", "-lc", "#{command_to_run}"]
3529
+ res = container.exec(command, tty: false)
3530
+ say res[0].join("\n")
3531
+ checks = Helpers.checkmark()
3532
+ say "Updating image", Thor::Shell::Color::BLUE
3533
+
3534
+ image.create_custom_image("")
3535
+ say "#{checks} Done, installing libraries completed", Thor::Shell::Color::GREEN
3536
+ container.stop()
3537
+
3538
+ log_end(0)
3539
+ rescue => e
3540
+ log_end(-1, e.message)
3541
+ say "Error occurd, aborting"
3542
+ if container
3543
+ container.stop()
3544
+ end
3545
+ rescue SignalException
3546
+ if container
3547
+ container.stop()
3548
+ end
3549
+ say "\nAborting"
3550
+ exit(1)
3551
+ end
3552
+
3553
+ end
3554
+
3555
+ method_option :small, :type => :boolean, :aliases => ["-sm", "--small"], :default => false
3556
+ method_option :medium, :type => :boolean, :aliases => ["-md", "--medium"], :default => false
3557
+ method_option :large, :type => :boolean, :aliases => ["-lg", "--large"], :default => false
3558
+ method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
3559
+ method_option :gpuxl, :type => :boolean, :aliases => ["--gpuxl"], :default => false
3560
+ method_option :gpuxxl, :type => :boolean, :aliases => ["--gpuxxl"], :default => false
3561
+ method_option :image, :type => :string, :aliases => ["-i","--image"], :default => ""
3562
+ method_option :public, :type => :boolean, :aliases => ["-p","--public"], :default => false
3563
+ method_option :base, :type => :boolean, :aliases => ["-b","--base"], :default => false
3564
+ method_option :python3, :type => :boolean, :aliases => ["--python3"], :default => false
3565
+
3566
+ desc 'create_custom_image', 'run commands inside containers', :hide=>true
3567
+
3568
+ def create_custom_image(image_name)
3569
+ begin
3570
+ verify_logged_in(false)
3571
+ log_start(__method__, args, options)
3572
+ instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"],
3573
+ "gpu" => options["gpu"], "gpuxl" => options["gpuxl"], "gpuxxl" => options["gpuxxl"]}
3574
+ instance_type = get_instance_type(instances)
3575
+ image_extend = options["image"]
3576
+ public = options["public"]
3577
+ base = options["base"]
3578
+ python3 = options["python3"]
3579
+ owner = CLI.get_owner
3580
+ checks = Helpers.checkmark()
3581
+
3582
+ say "Creating machine for custom image, this may take a few moments...", Thor::Shell::Color::BLUE
3583
+
3584
+ resp = Images.create_new_custom_image(instance_type,owner,image_name,public,base,image_extend,python3)
3585
+ if Cnvrg::CLI.is_response_success(resp,false)
3586
+ image_slug = resp["result"]["slug"]
3587
+ container = resp["result"]["machine_c"]
3588
+ say "#{checks} Created image and machine successfully", Thor::Shell::Color::GREEN
3589
+ say "Connecting to machine", Thor::Shell::Color::BLUE
3590
+ ssh = Ssh.new(resp)
3591
+ if !ssh.is_ssh
3592
+ say "Couldn't connect to machine,aborting", Thor::Shell::Color::RED
3593
+ Images.revoke_custom_new_image(owner, image_slug)
3594
+ log_end(-1,"Couldn't connect to machine,aborting")
3595
+ end
3596
+ say "run command until ctrl + c initiates", Thor::Shell::Color::BLUE
3597
+ begin
3598
+
3599
+ while true
3600
+ command = ask("$>")
3601
+ puts ssh.exec_command(command)
3602
+ end
3603
+
3604
+ rescue SignalException
3605
+ say "Commiting Image..", Thor::Shell::Color::BLUE
3606
+
3607
+ end
3608
+ resp = Images.commit_custom_image(owner,image_slug)
3609
+ if Cnvrg::CLI.is_response_success(resp,false)
3610
+ say "#{checks} Image commited successfuly, email will be sent when image is ready", Thor::Shell::Color::GREEN
3611
+ end
3612
+ if ssh
3613
+ ssh.close_ssh()
3614
+ end
3615
+
3616
+
3617
+
3618
+
3619
+
3620
+
3621
+
3622
+ end
3623
+ rescue =>e
2231
3624
  puts e
2232
- say "Error occurd, aborting"
2233
- if container
2234
- container.stop()
3625
+ if image_slug
3626
+ Images.revoke_custom_new_image(owner, image_slug)
3627
+ end
3628
+ if ssh
3629
+ ssh.close_ssh()
2235
3630
  end
3631
+
3632
+
2236
3633
  rescue SignalException
2237
- log_End(-1)
2238
- if container
2239
- container.stop()
3634
+ if image_slug
3635
+ Images.revoke_custom_new_image(owner, image_slug)
3636
+ end
3637
+ if ssh
3638
+ ssh.close_ssh
2240
3639
  end
2241
3640
  say "\nAborting"
2242
3641
  exit(1)
@@ -2244,15 +3643,26 @@ module Cnvrg
2244
3643
 
2245
3644
  end
2246
3645
 
2247
- desc 'install_libraries', 'Install libraries'
2248
- method_option :requirement, :type => :string, :aliases => ["-r", "--r"], :default => "", :desc => "Install from the given requirements file"
2249
3646
 
2250
- def install_python_libraries(*lib)
3647
+ desc 'build', 'run commands inside containers'
3648
+ method_option :install, :type => :string, :aliases => ["--i"], :default => nil, :desc => "Install from the given instructions file"
3649
+
3650
+ def build(*cmd)
2251
3651
  begin
2252
3652
  verify_logged_in(false)
2253
3653
  log_start(__method__, args, options)
2254
3654
  verify_software_installed("docker")
2255
- image = is_project_with_docker(Dir.pwd)
3655
+ working_dir = is_cnvrg_dir
3656
+ install_file = options["install"] || nil
3657
+ if !install_file.nil?
3658
+ commands = File.open(install_file).read.chop.gsub!("\n", ",").split(",")
3659
+
3660
+ else
3661
+ commands = [cmd.join(" ")]
3662
+ end
3663
+
3664
+
3665
+ image = is_project_with_docker(working_dir)
2256
3666
  if image and image.is_docker
2257
3667
  container = image.get_container
2258
3668
  if !container
@@ -2265,35 +3675,38 @@ module Cnvrg
2265
3675
  exit(1)
2266
3676
 
2267
3677
  end
2268
- req_file = options["requirement"] || nil
2269
- if lib.nil? and not req_file.nil?
2270
- if not File.exist? req_file
2271
- say "Couldn't find #{req_file}", Thor::Shell::Color::RED
2272
- exit(1)
2273
-
3678
+ commands.each do |c|
3679
+ if c.include? "pip"
3680
+ c.sub("pip", "/opt/ds/bin/pip")
3681
+ end
3682
+ if c.include? "pip3"
3683
+ c.sub("pip3", "/opt/ds3/bin/pip3")
2274
3684
  end
2275
- command_to_run = "pip install -r #{req_file}"
2276
3685
 
2277
- else
2278
- command_to_run = lib.join(" ")
3686
+ say "Running #{c}", Thor::Shell::Color::BLUE
3687
+ command = ["/bin/bash", "-lc", "#{c}"]
3688
+ res = container.exec(command, tty: false)
3689
+ if res[2] != 0
3690
+ say "Could not run command: #{c}, #{res[1][0]}", Thor::Shell::Color::RED
3691
+ container.stop()
3692
+ log_end(0)
2279
3693
 
3694
+ exit(1)
3695
+ end
3696
+ say res[0].join("\n")
3697
+ image.store_image_build_commands(working_dir, c)
2280
3698
  end
2281
- say "Running #{command_to_run} in container", Thor::Shell::Color::BLUE
2282
- command = ["/bin/bash", "-lc", "#{command_to_run}"]
2283
- res = container.exec(command, tty: false)
2284
- say res[0].join("\n")
3699
+
2285
3700
  checks = Helpers.checkmark()
2286
3701
  say "Updating image", Thor::Shell::Color::BLUE
2287
-
2288
- image.create_custom_image("")
2289
- say "#{checks} Done, installing libraries completed", Thor::Shell::Color::GREEN
3702
+ # image.create_custom_image("",working_dir)
2290
3703
  container.stop()
3704
+ say "#{checks} Done", Thor::Shell::Color::GREEN
2291
3705
 
2292
3706
  log_end(0)
2293
3707
  rescue => e
2294
- log_end(-1)
2295
- puts e
2296
- say "Error occurd, aborting"
3708
+ log_end(-1, e.message)
3709
+ say "Error occurd, aborting", Thor::Shell::Color::RED
2297
3710
  if container
2298
3711
  container.stop()
2299
3712
  end
@@ -2341,8 +3754,9 @@ module Cnvrg
2341
3754
  log_end(0)
2342
3755
  return new_image.id
2343
3756
  rescue => e
2344
- puts e
2345
-
3757
+ log_end(-1, e.message)
3758
+ say "\nError occurred,aborting"
3759
+ exit(1)
2346
3760
  rescue SignalException
2347
3761
  log_end(-1)
2348
3762
  say "\nAborting"
@@ -2385,15 +3799,13 @@ module Cnvrg
2385
3799
 
2386
3800
  end
2387
3801
 
2388
- desc 'create_custom_image', 'commit notebook changes to create a new notebook image'
2389
- method_option :name, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "new image name"
3802
+ desc 'push', 'push image to cnvrg repository'
2390
3803
 
2391
- def create_custom_image()
3804
+ def push(*name)
2392
3805
  verify_logged_in(true)
2393
3806
  log_start(__method__, args, options)
2394
3807
  working_dir = is_cnvrg_dir()
2395
- image_name = options["name"] || ""
2396
- if !image_name.empty? and image_name == "cnvrg"
3808
+ if !name.empty? and name == "cnvrg"
2397
3809
  say "can't create image with the name cnvrg", Thor::Shell::Color::RED
2398
3810
  exit(1)
2399
3811
  end
@@ -2403,12 +3815,26 @@ module Cnvrg
2403
3815
  say "Couldn't find image related to project", Thor::Shell::Color::RED
2404
3816
  exit(0)
2405
3817
  end
3818
+ if !name.nil? and !name.empty?
3819
+ if name.include? " "
3820
+ name.gsub!(" ", "_")
3821
+ end
3822
+ end
3823
+ stored_commands = File.open(working_dir+"/.cnvrg/custom_image.txt").read.chop.gsub("\n", ",")
3824
+ if stored_commands.nil? or stored_commands.empty?
3825
+ say "Nothing to push", Thor::Shell::Color::BLUE
3826
+ exit(0)
3827
+ end
2406
3828
 
2407
- image.create_custom_image(image_name)
2408
- say "Image was updated successfully", Thor::Shell::Color::BLUE
3829
+ say "Pushing new image", Thor::Shell::Color::BLUE
3830
+ if image.create_custom_image(name, working_dir, stored_commands)
2409
3831
 
3832
+ say "Image was updated successfully", Thor::Shell::Color::GREEN
3833
+ end
2410
3834
  rescue => e
2411
- puts e
3835
+ log_end(-1, e.message)
3836
+ say "error occurred, aborting"
3837
+
2412
3838
  end
2413
3839
  end
2414
3840
 
@@ -2470,8 +3896,8 @@ module Cnvrg
2470
3896
  exit(1)
2471
3897
  end
2472
3898
  rescue => e
2473
- puts e
2474
-
3899
+ log_end(-1, e.message)
3900
+ say "Couldn't upload image file for: #{image_name}", Thor::Shell::Color::RED
2475
3901
  rescue SignalException
2476
3902
  log_end(-1)
2477
3903
 
@@ -2480,7 +3906,7 @@ module Cnvrg
2480
3906
  end
2481
3907
  end
2482
3908
 
2483
- desc '', ''
3909
+ desc '', '', :hide => true
2484
3910
 
2485
3911
  def upload_log()
2486
3912
  log_path = '/home/ds/app/uwsgi.log'
@@ -2489,28 +3915,32 @@ module Cnvrg
2489
3915
 
2490
3916
  end
2491
3917
 
2492
- desc '', ''
3918
+ desc '', '', :hide => true
2493
3919
 
2494
3920
  def exec_container(container_id, *cmd)
2495
3921
  container = Docker::Container.get(container_id)
2496
3922
  container.start()
2497
3923
  cnvrg_command = cmd.join(" ")
2498
3924
  command = ["/bin/bash", "-lc", "#{cnvrg_command}"]
2499
- res = container.exec(command, tty: true,wait:5400)[0]
3925
+ res = container.exec(command, tty: true, wait: 5400)[0]
2500
3926
  say res
2501
-
2502
3927
  end
2503
3928
 
2504
- desc '', ''
3929
+ desc '', '', :hide => true
2505
3930
 
2506
3931
  def port_container(container_id)
2507
3932
  container = Docker::Container.get(container_id)
2508
3933
  say container.json["HostConfig"]["PortBindings"]["8888/tcp"][0]["HostPort"]
3934
+ end
2509
3935
 
3936
+ desc '', '', :hide => true
2510
3937
 
3938
+ def tensor_port_container(container_id)
3939
+ container = Docker::Container.get(container_id)
3940
+ say container.json["HostConfig"]["PortBindings"]["6006/tcp"][0]["HostPort"]
2511
3941
  end
2512
3942
 
2513
- desc '', ''
3943
+ desc '', '', :hide => true
2514
3944
 
2515
3945
  def stop_container(container_id)
2516
3946
  container = Docker::Container.get(container_id)
@@ -2519,13 +3949,13 @@ module Cnvrg
2519
3949
 
2520
3950
  end
2521
3951
 
2522
- desc '', ''
2523
- method_option :login, :type => :string, :aliases => ["-l", "--l"], :default => ""
2524
- method_option :app_dir, :type => :string, :aliases => ["-d", "--d"], :default => "/home/ds/notebooks"
2525
- method_option :cmd, :type => :string, :aliases => ["-c", "--c"], :default => "/home/ds/run_ipython.sh"
3952
+ desc '', '', :hide => true
3953
+ method_option :login, :type => :string, :aliases => ["-l"], :default => ""
3954
+ method_option :app_dir, :type => :string, :aliases => ["-d"], :default => "/home/ds/notebooks"
3955
+ method_option :cmd, :type => :string, :aliases => ["-c"], :default => "/usr/local/cnvrg/run_ipython.sh"
2526
3956
 
2527
3957
 
2528
- def config_remote(image_name, port=7654)
3958
+ def config_remote(image_name, port=7654, tensport=6006)
2529
3959
  local_images = Docker::Image.all
2530
3960
 
2531
3961
  docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{image_name}:latest" }.flatten
@@ -2538,20 +3968,25 @@ module Cnvrg
2538
3968
  login_content = options["login"]
2539
3969
  app_dir = options["app_dir"]
2540
3970
  cmd= options["cmd"]
3971
+ volume_from = options["volume"]
2541
3972
 
2542
3973
  image_settings = {
2543
3974
  'Image' => "#{image_name}:latest",
2544
- 'User' => 'ds',
3975
+
2545
3976
  'Cmd' => cmd,
2546
3977
  'WorkingDir' => app_dir,
2547
3978
  'ExposedPorts' => {
2548
3979
  '8888/tcp' => {},
2549
3980
  },
2550
3981
  'HostConfig' => {
3982
+ 'Binds'=> ["/var/run/docker.sock:/var/run/docker.sock","/usr/bin/docker:/usr/bin/docker" ],
2551
3983
  'PortBindings' => {
2552
3984
  '8888/tcp' => [
2553
3985
  {'HostPort' => "#{port}", 'HostIp' => 'localhost'}
2554
3986
  ],
3987
+ '6006/tcp' => [
3988
+ {'HostPort' => "#{tensport}", 'HostIp' => 'localhost'}
3989
+ ],
2555
3990
  },
2556
3991
  },
2557
3992
  }
@@ -2559,21 +3994,104 @@ module Cnvrg
2559
3994
  container.start()
2560
3995
  command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
2561
3996
  container.exec(command, tty: true)
2562
- command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
3997
+ # command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
3998
+ # container.exec(command, tty: true)
3999
+ # command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
4000
+ # container.exec(command, tty: true)
4001
+ command = ["/bin/bash", "-lc", "sudo chown -R ds:ds /home/ds/.netrc"]
2563
4002
  container.exec(command, tty: true)
2564
- command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
4003
+ command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
2565
4004
  container.exec(command, tty: true)
2566
- command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.cnvrg /home/ds/.netrc"]
4005
+ say "#{container.id}:#{port}##{tensport}"
4006
+ rescue => e
4007
+ puts e
4008
+ if e.message.include? "is not running"
4009
+ return config_remote(image_name, port-1, tensport-1)
4010
+ end
4011
+
4012
+ if container
4013
+ container.kill()
4014
+ end
4015
+ return false
4016
+ end
4017
+ end
4018
+
4019
+
4020
+ desc '', '', :hide => true
4021
+ method_option :login, :type => :string, :aliases => ["-l"], :default => ""
4022
+
4023
+ def config_netrc(container)
4024
+
4025
+ login_content = options["login"]
4026
+
4027
+ container = Docker::Container.get(container)
4028
+ command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
4029
+ container.exec(command, tty: true)
4030
+ command = ["/bin/bash", "-lc", "sudo chown -R ds:ds /home/ds/.netrc"]
4031
+ container.exec(command, tty: true)
4032
+ command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
4033
+ container.exec(command, tty: true)
4034
+ say "OK"
4035
+
4036
+ end
4037
+
4038
+ desc '', '', :hide => true
4039
+ method_option :login, :type => :string, :aliases => ["-l", "--l"], :default => ""
4040
+ method_option :app_dir, :type => :string, :aliases => ["-d", "--d"], :default => "/home/ds/notebooks"
4041
+ method_option :cmd, :type => :string, :aliases => ["-c", "--c"], :default => "/usr/local/cnvrg/run_ipython.sh"
4042
+
4043
+
4044
+ def config_remote_gpu(image_name, port=7654, tensport=6006)
4045
+ local_images = Docker::Image.all
4046
+
4047
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{image_name}:latest" }.flatten
4048
+ if docker_image_local.empty?
4049
+ say "no image"
4050
+ exit(1)
4051
+ end
4052
+
4053
+ begin
4054
+ login_content = options["login"]
4055
+ app_dir = options["app_dir"]
4056
+ cmd= options["cmd"]
4057
+
4058
+ # image_settings = {
4059
+ # 'Image' => "#{image_name}:latest",
4060
+ # 'User' => 'ds',
4061
+ # 'Cmd' => cmd,
4062
+ # 'WorkingDir' => app_dir,
4063
+ # 'ExposedPorts' => {
4064
+ # '8888/tcp' => {},
4065
+ # },
4066
+ # 'HostConfig' => {
4067
+ # 'PortBindings' => {
4068
+ # '8888/tcp' => [
4069
+ # {'HostPort' => "#{port}", 'HostIp' => 'localhost'}
4070
+ # ],
4071
+ # '6006/tcp' => [
4072
+ # {'HostPort' => "6006", 'HostIp' => 'localhost'}
4073
+ # ],
4074
+ # },
4075
+ # },
4076
+ # }
4077
+
4078
+ container_id = `nvidia-docker run -itd -p #{port}:8888 -p #{tensport}:6006 -w #{app_dir} -v /usr/bin/nvidia-smi:/usr/bin/nvidia-smi -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker #{image_name}:latest #{cmd} `
4079
+ container_id = container_id.gsub("\n", "")
4080
+ container = Docker::Container.get(container_id)
4081
+ # container.start()
4082
+ command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
4083
+ container.exec(command, tty: true)
4084
+ command = ["/bin/bash", "-lc", "sudo chown -R ds:ds /home/ds/.netrc"]
2567
4085
  container.exec(command, tty: true)
2568
4086
  command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
2569
4087
  container.exec(command, tty: true)
2570
- say "#{container.id}:#{port}"
4088
+ say "#{container.id}:#{port}##{tensport}"
2571
4089
  rescue => e
2572
4090
  if e.message.include? "is not running"
2573
- return config_remote(image_name, port-1)
4091
+ puts "running asgain with: #{port-1} #{tensport-1}"
4092
+ return config_remote_gpu(image_name, port-1, tensport-1)
2574
4093
  end
2575
- puts "error"
2576
- puts e
4094
+
2577
4095
  if container
2578
4096
  container.kill()
2579
4097
  end
@@ -2581,8 +4099,8 @@ module Cnvrg
2581
4099
  end
2582
4100
  end
2583
4101
 
2584
- desc '', ''
2585
- method_option :login, :type => :string, :aliases => ["-l", "--l"], :default => ""
4102
+ desc '', '', :hide => true
4103
+ method_option :login, :type => :string, :aliases => ["-l"], :default => ""
2586
4104
 
2587
4105
  def config_flask_remote(image_name, port=80)
2588
4106
  local_images = Docker::Image.all
@@ -2598,7 +4116,7 @@ module Cnvrg
2598
4116
  image_settings = {
2599
4117
  'Image' => "#{image_name}:latest",
2600
4118
  'User' => 'ds',
2601
- 'Cmd' => '/home/ds/start_super.sh',
4119
+ 'Cmd' => '/usr/local/cnvrg/start_super.sh',
2602
4120
  'WorkingDir' => '/home/ds/app',
2603
4121
  'ExposedPorts' => {
2604
4122
  '80/tcp' => {},
@@ -2615,21 +4133,54 @@ module Cnvrg
2615
4133
  container.start()
2616
4134
  command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
2617
4135
  container.exec(command, tty: true)
2618
- command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
4136
+ command = ["/bin/bash", "-lc", "sudo chown -R ds:ds /home/ds/.netrc"]
2619
4137
  container.exec(command, tty: true)
2620
- command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
4138
+ command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
2621
4139
  container.exec(command, tty: true)
2622
- command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.cnvrg /home/ds/.netrc"]
4140
+ say "#{container.id}:#{port}"
4141
+ rescue => e
4142
+ pus e
4143
+ if e.message.include? "is not running"
4144
+ return "port is taken"
4145
+ end
4146
+ puts "error"
4147
+ if container
4148
+ container.kill()
4149
+ end
4150
+ return false
4151
+ end
4152
+ end
4153
+
4154
+ desc '', '', :hide => true
4155
+ method_option :login, :type => :string, :aliases => ["-l"], :default => ""
4156
+
4157
+ def config_flask_remote_gpu(image_name, port=80)
4158
+ local_images = Docker::Image.all
4159
+
4160
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{image_name}:latest" }.flatten
4161
+ if docker_image_local.empty?
4162
+ say "no image"
4163
+ exit(1)
4164
+ end
4165
+
4166
+ begin
4167
+ login_content = options["login"]
4168
+ container_id = `nvidia-docker run -itd -p 80:80 -w /home/ds/app #{image_name}:latest /usr/local/cnvrg/start_super.sh`
4169
+ container_id = container_id.gsub("\n", "")
4170
+ container = Docker::Container.get(container_id)
4171
+ command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
4172
+ container.exec(command, tty: true)
4173
+ command = ["/bin/bash", "-lc", "sudo chown -R ds:ds /home/ds/.netrc"]
2623
4174
  container.exec(command, tty: true)
2624
4175
  command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
2625
4176
  container.exec(command, tty: true)
2626
4177
  say "#{container.id}:#{port}"
2627
4178
  rescue => e
4179
+ puts e
2628
4180
  if e.message.include? "is not running"
2629
4181
  return "port is taken"
2630
4182
  end
2631
4183
  puts "error"
2632
- puts e
2633
4184
  if container
2634
4185
  container.kill()
2635
4186
  end
@@ -2637,7 +4188,7 @@ module Cnvrg
2637
4188
  end
2638
4189
  end
2639
4190
 
2640
- desc '', ''
4191
+ desc '', '', :hide => true
2641
4192
 
2642
4193
  def upload_cnvrg_image(image_name)
2643
4194
  verify_logged_in(false)
@@ -2647,12 +4198,12 @@ module Cnvrg
2647
4198
 
2648
4199
  path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}.zip"
2649
4200
  @files = Cnvrg::Files.new("", "")
2650
- python_arr = Cnvrg::Images.get_installed_packages("python")
2651
- py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
2652
- system_arr = Cnvrg::Images.get_installed_packages("system")
2653
- sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
2654
- bash_history = Cnvrg::Images.get_bash_history
2655
- res = @files.upload_image(path, image_name, owner, true, true, sys, py, bash_history, "Image made by cnvrg.io team", "")
4201
+ # python_arr = Cnvrg::Images.get_installed_packages("python")
4202
+ # py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
4203
+ # system_arr = Cnvrg::Images.get_installed_packages("system")
4204
+ # sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
4205
+ # bash_history = Cnvrg::Images.get_bash_history
4206
+ res = @files.upload_image(path, image_name, owner, true, true, "", "", "", "Image made by cnvrg.io team", "")
2656
4207
 
2657
4208
  end
2658
4209
 
@@ -2698,7 +4249,7 @@ module Cnvrg
2698
4249
  end
2699
4250
  end
2700
4251
 
2701
- desc '', ''
4252
+ desc '', '', :hide => true
2702
4253
 
2703
4254
  def download_image(image_name, image_slug)
2704
4255
  begin
@@ -2713,11 +4264,13 @@ module Cnvrg
2713
4264
  if @files.download_image(path, image_slug, owner)
2714
4265
 
2715
4266
  dir_path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}"
2716
- FileUtils.mkdir_p([dir_path])
4267
+ FileUtils.rm_rf([dir_path])
4268
+
2717
4269
  Zip::File.open(path) do |zip_file|
2718
- # Handle entries one by one
2719
4270
  zip_file.each do |entry|
4271
+
2720
4272
  f_path=File.join(dir_path, entry.name)
4273
+ FileUtils.mkdir_p(File.dirname(f_path))
2721
4274
  zip_file.extract(entry, f_path)
2722
4275
  end
2723
4276
  end
@@ -2755,13 +4308,13 @@ module Cnvrg
2755
4308
  owner = Cnvrg::CLI.get_owner()
2756
4309
  res = Cnvrg::API.request("users/#{owner}/images/list", 'GET')
2757
4310
  if Cnvrg::CLI.is_response_success(res)
2758
- printf "%-20s %-20s %-30s %-20s %-20s %-20s\n", "name", "project", "message", "created by", "is_public", "last updated"
4311
+ printf "%-20s %-20s %-30s %-20s %-20s\n", "name", "project", "created by", "is_public", "last updated"
2759
4312
  res["result"]["images"].each do |u|
2760
4313
  time = Time.parse(u["created_at"])
2761
4314
  update_at = get_local_time(time)
2762
4315
  created_by = u["created_by"]
2763
4316
 
2764
- printf "%-20s %-20s %-30s %-20s %-20s %-20s\n", u["name"], u["project"], u["message"], created_by, u["is_public"], update_at
4317
+ printf "%-20s %-20s %-30s %-20s %-20s\n", u["name"], u["project"], created_by, u["is_public"], update_at
2765
4318
  end
2766
4319
  end
2767
4320
  log_end(0)
@@ -2856,22 +4409,33 @@ module Cnvrg
2856
4409
  path = download_image(image_name, image["slug"])
2857
4410
  if path
2858
4411
  say "Building image", Thor::Shell::Color::BLUE
2859
- Docker.options[:read_timeout]=1200
2860
- image = Docker::Image.build_from_dir(path, {'dockerfile' => 'Dockerfile', 't' => "#{image_name}:lastest"})
4412
+ Docker.options[:read_timeout]=216000
4413
+ image = Docker::Image.build_from_dir(path, {'dockerfile' => 'Dockerfile.cpu', 't' => "#{image_name}:latest"}) do |v|
4414
+ begin
4415
+ if (log = JSON.parse(v)) && log.has_key?("stream")
4416
+ next if log["stream"].starts_with? "Step"
4417
+ $stdout.puts log["stream"]
4418
+ end
4419
+ rescue
4420
+ end
4421
+
4422
+ end
4423
+
2861
4424
  if not image.nil?
2862
- say "Finished downloading image, cleaning up..", Thor::Shell::Color::GREEN
2863
4425
  FileUtils.rm_rf(path)
2864
4426
  checks = Helpers.checkmark()
2865
- say "#{checks} Done", Thor::Shell::Color::GREEN
4427
+ say "#{checks} Image built successfully", Thor::Shell::Color::GREEN
2866
4428
  log_end(0)
2867
4429
  return image
2868
4430
  log_end(0)
2869
4431
  else
4432
+
2870
4433
  say "Could not build image", Thor::Shell::Color::RED
2871
4434
  log_end(1, "Could build image")
2872
4435
  return false
2873
4436
  end
2874
4437
  else
4438
+
2875
4439
  say "Could not download image", Thor::Shell::Color::RED
2876
4440
  log_end(1, "Could build image")
2877
4441
  return false
@@ -2899,7 +4463,9 @@ module Cnvrg
2899
4463
  #
2900
4464
  # end
2901
4465
  # end
2902
- rescue
4466
+ rescue => e
4467
+
4468
+
2903
4469
  say "Couldn't build image", Thor::Shell::Color::RED
2904
4470
 
2905
4471
  rescue SignalException
@@ -2929,7 +4495,7 @@ module Cnvrg
2929
4495
  if docker_image_local.size == 0
2930
4496
 
2931
4497
  if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
2932
- image = pull_image(docker_image)
4498
+ image = pull(docker_image)
2933
4499
  if image
2934
4500
  say "downloaded image: #{docker_image}"
2935
4501
  @image = Images.new(working_dir, docker_image)
@@ -3006,7 +4572,12 @@ module Cnvrg
3006
4572
  if url.nil? or url.empty?
3007
4573
  url = "https://cnvrg.io/api"
3008
4574
  end
3009
- config = {owner: owner, username: username, version_last_check: get_start_day(), api: url}
4575
+ config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
4576
+ compression_path = "#{home_dir}/.cnvrg/tmp"
4577
+ if config and !config.nil? and !config.empty? and !config.to_h[:compression_path].nil?
4578
+ compression_path = config.to_h[:compression_path]
4579
+ end
4580
+ config = {owner: owner, username: username, version_last_check: get_start_day(), api: url,compression_path:compression_path}
3010
4581
 
3011
4582
  File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
3012
4583
  return true
@@ -3060,7 +4631,7 @@ module Cnvrg
3060
4631
 
3061
4632
  def log_end(exit_status=0, error=nil)
3062
4633
  begin
3063
- if exit_status==1
4634
+ if exit_status != 0
3064
4635
  $LOG.error exit_status: exit_status, error: error
3065
4636
  else
3066
4637
  $LOG.info exit_status: exit_status
@@ -3072,7 +4643,6 @@ module Cnvrg
3072
4643
  def self.is_response_success(response, should_exit=true)
3073
4644
  if response.nil?
3074
4645
  if !Cnvrg::Helpers.internet_connection?
3075
- # Cnvrg::CLI.log_end(1,"no internet connection")
3076
4646
  say("<%= color('Error:You seems to be offline', RED) %>")
3077
4647
  else
3078
4648
  say("<%= color('Error', RED) %>")
@@ -3107,12 +4677,26 @@ module Cnvrg
3107
4677
  return owner
3108
4678
  end
3109
4679
  end
4680
+
3110
4681
  def get_base_url
3111
4682
  home_dir = File.expand_path('~')
3112
4683
 
3113
4684
  config = YAML.load_file(home_dir+ "/.cnvrg/config.yml")
3114
4685
  api = config.to_h[:api]
3115
- return api.gsub!("/api","")
4686
+ return api.gsub!("/api", "")
4687
+ end
4688
+ def get_compression_path
4689
+ home_dir = File.expand_path('~')
4690
+
4691
+ config = YAML.load_file(home_dir+ "/.cnvrg/config.yml")
4692
+ compression_path = config.to_h[:compression_path]
4693
+ if compression_path.nil?
4694
+ compression_path = "#{home_dir}/.cnvrg/tmp/"
4695
+ end
4696
+ if !compression_path.ends_with? "/"
4697
+ compression_path = compression_path + "/"
4698
+ end
4699
+ return compression_path
3116
4700
  end
3117
4701
 
3118
4702
  def get_project_home
@@ -3166,7 +4750,6 @@ module Cnvrg
3166
4750
  end
3167
4751
  $LOG = LogStashLogger.new(type: :file, path: logfile, sync: true)
3168
4752
  rescue => e
3169
- # puts e
3170
4753
  end
3171
4754
  end
3172
4755
 
@@ -3194,6 +4777,9 @@ module Cnvrg
3194
4777
 
3195
4778
  config = YAML.load_file(File.expand_path('~')+"/.cnvrg/config.yml")
3196
4779
  version_date = config.to_h[:version_last_check]
4780
+ if version_date.nil?
4781
+ version_date = get_start_day()
4782
+ end
3197
4783
  next_day = get_start_day+ 86399
3198
4784
  if not (version_date..next_day).cover?(Time.now)
3199
4785
  if should_update_version()
@@ -3219,11 +4805,15 @@ module Cnvrg
3219
4805
  def is_cnvrg_dir(dir=Dir.pwd)
3220
4806
  current_dir = dir
3221
4807
  home_dir = File.expand_path('~')
4808
+ if current_dir.eql? home_dir
4809
+ return false
4810
+ end
3222
4811
  is_cnvrg = Dir.exist? current_dir+"/.cnvrg"
3223
4812
  until is_cnvrg == true
3224
4813
  current_dir = File.expand_path("..", current_dir)
3225
4814
  is_cnvrg = Dir.exist? current_dir+"/.cnvrg"
3226
- if File.expand_path("..", current_dir).eql? home_dir
4815
+ if ((File.expand_path("..", current_dir).eql? home_dir) or current_dir.eql? home_dir or current_dir.eql? "/") and !is_cnvrg
4816
+ is_cnvrg = false
3227
4817
  break
3228
4818
  end
3229
4819
  end
@@ -3234,6 +4824,19 @@ module Cnvrg
3234
4824
  end
3235
4825
  end
3236
4826
 
4827
+ def data_dir_include()
4828
+ all_dirs = Dir.glob("**/*/", File::FNM_DOTMATCH)
4829
+ all_dirs.flatten!
4830
+ all_dirs.each do |a|
4831
+ if a.include? "/.cnvrg"
4832
+ ignore = File.dirname(a)
4833
+ return ignore
4834
+ end
4835
+ end
4836
+ return nil
4837
+
4838
+ end
4839
+
3237
4840
  def verify_software_installed(software)
3238
4841
  begin
3239
4842
  install_url = Cnvrg::CLI::INSTALLATION_URLS[software.to_sym]
@@ -3409,8 +5012,151 @@ module Cnvrg
3409
5012
 
3410
5013
  end
3411
5014
 
5015
+ def update_deleted(deleted)
5016
+ final = []
5017
+ deleted.each do |d|
5018
+ all_subs = d.split("/")
5019
+ to_add = true
5020
+ value = all_subs[0]
5021
+ all_subs.each_with_index do |a, i|
5022
+ if final.include? value+"/"
5023
+ to_add = false
5024
+ break
5025
+ end
5026
+ value = value+"/"+all_subs[i+1] if i <all_subs.size-1
5027
+ end
5028
+ final << d if to_add
5029
+
5030
+
5031
+ end
5032
+
5033
+
5034
+ return final
5035
+ end
5036
+
5037
+ def get_cmd_path_in_dir(main_dir, sub_dir)
5038
+ first = Pathname.new main_dir
5039
+ second = Pathname.new sub_dir
5040
+ relative = second.relative_path_from first
5041
+ if relative.eql? "."
5042
+ return ""
5043
+ else
5044
+ return relative
5045
+ end
5046
+ end
5047
+
5048
+ def create_tar(path_in, path_out, tar_files,no_compression=false)
5049
+ #The cd is meant for cases when running cnvrg data uplaod not in the main folder
5050
+ begin
5051
+ if no_compression
5052
+ `cd #{path_in} && tar -cf #{path_out} -T #{tar_files}`
5053
+ else
5054
+ `cd #{path_in} && tar -czf #{path_out} -T #{tar_files}`
5055
+ end
5056
+ rescue => e
5057
+ puts "Exception while compressing data: #{e.message}"
5058
+ end
5059
+
5060
+ return $?.success?
5061
+ end
5062
+
5063
+ def extarct_tar(file_path, dir_path)
5064
+ `tar -xvf #{file_path} -C #{dir_path} > /dev/null 2>&1`
5065
+ return $?.success?
5066
+ end
5067
+ def cpu_usage
5068
+ cpu_usage = 0.0
5069
+ begin
5070
+ cpu = `top b -n 2 -d 2 |grep %Cpu |tail -1 |awk '{print $2+$3}'`
5071
+ if !cpu.nil?
5072
+ cpu_usage = cpu.to_f
5073
+ end
5074
+ rescue
5075
+ cpu_usage = 0.0
5076
+ end
5077
+
5078
+ return cpu_usage
5079
+ end
5080
+ def memory_usage
5081
+ prec = 0.0
5082
+ begin
5083
+ used = `free -mt |grep Mem: |awk '{print $3}'`
5084
+ total = `free -mt |grep Mem: |awk '{print $2}'`
5085
+
5086
+ used_f = used.to_f if !used.nil?
5087
+ total_f = total.to_f if !total.nil?
5088
+ prec = (used_f / total_f)*100
5089
+ prec = prec.round(2)
5090
+ rescue
5091
+ prec = 0.0
5092
+ end
5093
+ return prec
5094
+
5095
+
5096
+ end
5097
+ def gpu_util
5098
+ gpu = [0.0, 0.0]
5099
+ begin
5100
+ gpu_stats = `nvidia-smi --query-gpu=utilization.gpu,utilization.memory --format=csv |tail -1`
5101
+
5102
+ if !gpu_stats.nil?
5103
+ gpu = gpu_stats.strip
5104
+ gpu = gpu_stats.gsub!("%","").split(",")
5105
+ gpu[0] = gpu[0].to_f
5106
+ gpu[1] = gpu[1].to_f
5107
+ return gpu
5108
+ end
5109
+
5110
+ rescue
5111
+ return gpu
5112
+ end
5113
+
5114
+
5115
+ end
5116
+ def usage_metrics_in_docker(docker_id)
5117
+ res = [0.0,0.0]
5118
+ begin
5119
+ if docker_id.nil?
5120
+ docker_id = `cat /etc/hostname`
5121
+ end
5122
+ stats = `sudo docker stats #{docker_id} --no-stream --format "{{.CPUPerc}},{{.MemPerc}},{{.BlockIO}}"`
5123
+ if !stats.nil?
5124
+ conv = stats.split(",")
5125
+ cpu = conv[0].gsub!("%","").to_f
5126
+ memory = conv[1].gsub!("%","").to_f
5127
+ res = [cpu,memory]
5128
+ return res
5129
+ end
5130
+ rescue
5131
+ return res
5132
+ end
5133
+
5134
+
5135
+
5136
+ end
5137
+
5138
+ def with_progress_bar
5139
+ not_done = true
5140
+ upload_progress_bar = ProgressBar.create(:title => "Upload progress",
5141
+ :format => '%a <%B> %p%% %t',
5142
+ :starting_at => 0,
5143
+ :total => 600)
5144
+ pb = Thread.new do
5145
+ while not_done do
5146
+ upload_progress_bar.increment
5147
+ sleep(1)
5148
+
5149
+ end
5150
+ end
3412
5151
 
5152
+ yield.tap do # After yielding to the block, save the return value
5153
+ not_done = false # Tell the thread to exit, cleaning up after itself…
5154
+ pb.join # …and wait for it to do so.
5155
+ end
5156
+ end
3413
5157
  end
5158
+
5159
+
3414
5160
  end
3415
5161
  end
3416
5162