cnvrg 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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