neptune 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -32,8 +32,13 @@ By default, Neptune jobs store their outputs in the underlying database
32
32
  that AppScale is running over. As of Neptune 0.0.5, job outputs can
33
33
  also be stored in Amazon S3, Eucalyptus Walrus, and Google Storage.
34
34
 
35
- Sample Neptune job scripts can be found in samples. Test scripts will
36
- be added to the 'test' folder soon.
35
+ Sample Neptune job scripts can be found in samples. Test cases can
36
+ be found in the test folder, with the standard naming convention
37
+ - ts_neptune is the test suite runner, with tc_* containing test
38
+ cases for each type of job that Neptune offers. Before running
39
+ ts_neptune, you should export the environment variable APPSCALE_HEAD_NODE,
40
+ which should be set to the IP address of the AppScale machine that runs
41
+ the Shadow daemon (a.k.a. the Master AppController).
37
42
 
38
43
  Developed by Chris Bunch as part of the AppScale project.
39
44
  See LICENSE for the specifics of the New BSD License
@@ -41,8 +46,9 @@ by which Neptune is released.
41
46
 
42
47
  Check us out on the web:
43
48
 
44
- http://code.google.com/p/appscale
49
+ http://neptune-lang.org
45
50
 
51
+ http://code.google.com/p/appscale
46
52
  http://appscale.cs.ucsb.edu
47
53
 
48
54
  Contributors welcome! We would love to add support for other
@@ -57,6 +63,16 @@ in for a link to that as it becomes available.
57
63
 
58
64
  Version History:
59
65
 
66
+ April 2, 2001 - 0.0.7 released, adding automatic test suite
67
+ and many bug fixes for all scenarios. rcov can also be used
68
+ to generate test coverage information: current coverage stats
69
+ can be found in coverage directory. mapreduce broken at the
70
+ moment - will fix in next release
71
+
72
+ March 28, 2011 - 0.0.6 released, adding support for input jobs,
73
+ so users can place data in the datastore without having to run
74
+ any computation
75
+
60
76
  March 18, 2011 - 0.0.5 released, adding support for storage outside
61
77
  of AppScale to be used. Tested and working with Amazon S3 and Google
62
78
  Storage
@@ -79,6 +79,8 @@
79
79
 
80
80
  <li><a href="#method-i-make_call">#make_call</a></li>
81
81
 
82
+ <li><a href="#method-i-put_input">#put_input</a></li>
83
+
82
84
  <li><a href="#method-i-set_acl">#set_acl</a></li>
83
85
 
84
86
  <li><a href="#method-i-start_neptune_job">#start_neptune_job</a></li>
@@ -241,6 +243,7 @@ def initialize(ip, secret)
241
243
 
242
244
  <span class="ruby-ivar">@conn</span> = <span class="ruby-constant">SOAP</span>::<span class="ruby-constant">RPC</span>::<span class="ruby-constant">Driver</span>.new(&quot;https://#{@ip}:17443&quot;)
243
245
  <span class="ruby-ivar">@conn</span>.add_method(<span class="ruby-string">&quot;neptune_start_job&quot;</span>, <span class="ruby-string">&quot;job_data&quot;</span>, <span class="ruby-string">&quot;secret&quot;</span>)
246
+ <span class="ruby-ivar">@conn</span>.add_method(<span class="ruby-string">&quot;neptune_put_input&quot;</span>, <span class="ruby-string">&quot;job_data&quot;</span>, <span class="ruby-string">&quot;secret&quot;</span>)
244
247
  <span class="ruby-ivar">@conn</span>.add_method(<span class="ruby-string">&quot;neptune_get_output&quot;</span>, <span class="ruby-string">&quot;job_data&quot;</span>, <span class="ruby-string">&quot;secret&quot;</span>)
245
248
  <span class="ruby-ivar">@conn</span>.add_method(<span class="ruby-string">&quot;neptune_get_acl&quot;</span>, <span class="ruby-string">&quot;job_data&quot;</span>, <span class="ruby-string">&quot;secret&quot;</span>)
246
249
  <span class="ruby-ivar">@conn</span>.add_method(<span class="ruby-string">&quot;neptune_set_acl&quot;</span>, <span class="ruby-string">&quot;job_data&quot;</span>, <span class="ruby-string">&quot;secret&quot;</span>)
@@ -282,7 +285,7 @@ end</pre>
282
285
  <div class="method-source-code"
283
286
  id="compile_code-source">
284
287
  <pre>
285
- <span class="ruby-comment"># File lib/app_controller_client.rb, line 137</span>
288
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 152</span>
286
289
  def compile_code(job_data)
287
290
  result = <span class="ruby-string">&quot;&quot;</span>
288
291
  make_call(<span class="ruby-constant">NO_TIMEOUT</span>, false) {
@@ -324,7 +327,7 @@ exceptions mirror that of start_neptune_job.</p>
324
327
  <div class="method-source-code"
325
328
  id="get_acl-source">
326
329
  <pre>
327
- <span class="ruby-comment"># File lib/app_controller_client.rb, line 114</span>
330
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 129</span>
328
331
  def get_acl(job_data)
329
332
  result = <span class="ruby-string">&quot;&quot;</span>
330
333
  make_call(<span class="ruby-constant">NO_TIMEOUT</span>, false) {
@@ -361,7 +364,7 @@ Within AppScale, a special application runs, referred to as the Repository,
361
364
  which provides a key-value interface to Neptune job data. Data is stored as
362
365
  though it were on a file system, therefore output be of the usual form
363
366
  /folder/filename . Currently the contents of the file is returned as a
364
- string to the caller, but as this is inefficient for non-trivial output
367
+ string to the caller, but as this may be inefficient for non-trivial output
365
368
  jobs, the next version of Neptune will add an additional call to directly
366
369
  copy the output to a file on the local filesystem. See <a
367
370
  href="AppControllerClient.html#method-i-start_neptune_job">start_neptune_job</a>
@@ -373,7 +376,7 @@ used for job_data.</p>
373
376
  <div class="method-source-code"
374
377
  id="get_output-source">
375
378
  <pre>
376
- <span class="ruby-comment"># File lib/app_controller_client.rb, line 100</span>
379
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 115</span>
377
380
  def get_output(job_data)
378
381
  result = <span class="ruby-string">&quot;&quot;</span>
379
382
  make_call(<span class="ruby-constant">NO_TIMEOUT</span>, false) {
@@ -423,7 +426,7 @@ The result of the block is returned to the caller.</p>
423
426
  <div class="method-source-code"
424
427
  id="make_call-source">
425
428
  <pre>
426
- <span class="ruby-comment"># File lib/app_controller_client.rb, line 51</span>
429
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 52</span>
427
430
  def make_call(time, retry_on_except)
428
431
  begin
429
432
  <span class="ruby-constant">Timeout</span>::timeout(time) {
@@ -452,6 +455,49 @@ end</pre>
452
455
 
453
456
 
454
457
 
458
+ </div>
459
+
460
+
461
+ <div id="put_input-method" class="method-detail ">
462
+ <a name="method-i-put_input"></a>
463
+
464
+
465
+ <div class="method-heading">
466
+ <span class="method-name">put_input</span><span
467
+ class="method-args">(job_data)</span>
468
+ <span class="method-click-advice">click to toggle source</span>
469
+ </div>
470
+
471
+
472
+ <div class="method-description">
473
+
474
+ <p>Stores a file stored on the user’s local file system in the underlying
475
+ database. The user can specify to use either the underlying database that
476
+ AppScale is using, or alternative storage mechanisms (as of writing, Google
477
+ Storage, Amazon S3, and Eucalyptus Walrus are supported) via the storage
478
+ parameter.</p>
479
+
480
+
481
+
482
+ <div class="method-source-code"
483
+ id="put_input-source">
484
+ <pre>
485
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 96</span>
486
+ def put_input(job_data)
487
+ result = <span class="ruby-string">&quot;&quot;</span>
488
+ make_call(<span class="ruby-constant">NO_TIMEOUT</span>, false) {
489
+ result = conn.neptune_put_input(job_data, <span class="ruby-ivar">@secret</span>)
490
+ }
491
+ abort(result) if result =~ <span class="ruby-regexp">/Error:/</span>
492
+ return result
493
+ end</pre>
494
+ </div>
495
+
496
+ </div>
497
+
498
+
499
+
500
+
455
501
  </div>
456
502
 
457
503
 
@@ -480,7 +526,7 @@ that of start_neptune_job.</p>
480
526
  <div class="method-source-code"
481
527
  id="set_acl-source">
482
528
  <pre>
483
- <span class="ruby-comment"># File lib/app_controller_client.rb, line 128</span>
529
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 143</span>
484
530
  def set_acl(job_data)
485
531
  result = <span class="ruby-string">&quot;&quot;</span>
486
532
  make_call(<span class="ruby-constant">NO_TIMEOUT</span>, false) {
@@ -526,7 +572,7 @@ is the result returned from the AppController.</p>
526
572
  <div class="method-source-code"
527
573
  id="start_neptune_job-source">
528
574
  <pre>
529
- <span class="ruby-comment"># File lib/app_controller_client.rb, line 81</span>
575
+ <span class="ruby-comment"># File lib/app_controller_client.rb, line 82</span>
530
576
  def start_neptune_job(job_data)
531
577
  result = <span class="ruby-string">&quot;&quot;</span>
532
578
  make_call(<span class="ruby-constant">NO_TIMEOUT</span>, false) {
@@ -172,7 +172,7 @@ instead.</p>
172
172
  <div class="method-source-code"
173
173
  id="get_from_yaml-source">
174
174
  <pre>
175
- <span class="ruby-comment"># File lib/common_functions.rb, line 79</span>
175
+ <span class="ruby-comment"># File lib/common_functions.rb, line 82</span>
176
176
  def self.get_from_yaml(keyname, tag, required=true)
177
177
  location_file = <span class="ruby-constant">File</span>.expand_path(&quot;~/.appscale/locations-#{keyname}.yaml&quot;)
178
178
 
@@ -227,7 +227,7 @@ function, as the secret is stored in a YAML file.</p>
227
227
  <div class="method-source-code"
228
228
  id="get_secret_key-source">
229
229
  <pre>
230
- <span class="ruby-comment"># File lib/common_functions.rb, line 104</span>
230
+ <span class="ruby-comment"># File lib/common_functions.rb, line 107</span>
231
231
  def self.get_secret_key(keyname, required=true)
232
232
  return <span class="ruby-constant">CommonFunctions</span>.get_from_yaml(keyname, :secret)
233
233
  end</pre>
@@ -247,7 +247,7 @@ end</pre>
247
247
 
248
248
  <div class="method-heading">
249
249
  <span class="method-name">scp_file</span><span
250
- class="method-args">(local_file_loc, remote_file_loc, target_ip, public_key_loc)</span>
250
+ class="method-args">(local_file_loc, remote_file_loc, target_ip, public_key_loc, is_dir=false)</span>
251
251
  <span class="method-click-advice">click to toggle source</span>
252
252
  </div>
253
253
 
@@ -259,7 +259,8 @@ information from <a
259
259
  href="CommonFunctions.html#method-c-scp_to_shadow">scp_to_shadow</a>,
260
260
  attempts to use scp to copy the file over. Aborts if the scp fails, which
261
261
  can occur if the network is down, if a bad keyname is provided, or if the
262
- wrong IP is given.</p>
262
+ wrong IP is given. If the user specifies that the file to copy is actually
263
+ a directory, we append the -r flag to scp as well.</p>
263
264
 
264
265
 
265
266
 
@@ -267,19 +268,22 @@ wrong IP is given.</p>
267
268
  id="scp_file-source">
268
269
  <pre>
269
270
  <span class="ruby-comment"># File lib/common_functions.rb, line 37</span>
270
- def self.scp_file(local_file_loc, remote_file_loc, target_ip, public_key_loc)
271
+ def self.scp_file(local_file_loc, remote_file_loc, target_ip, public_key_loc, is_dir=false)
271
272
  cmd = <span class="ruby-string">&quot;&quot;</span>
272
273
  local_file_loc = <span class="ruby-constant">File</span>.expand_path(local_file_loc)
273
-
274
+
275
+ ssh_args = <span class="ruby-string">&quot;-o StrictHostkeyChecking=no 2&gt;&amp;1&quot;</span>
276
+ ssh_args &lt;&lt; <span class="ruby-string">&quot; -r &quot;</span> if is_dir
277
+
274
278
  if public_key_loc.class == <span class="ruby-constant">Array</span>
275
279
  public_key_loc.each { |key|
276
280
  key = <span class="ruby-constant">File</span>.expand_path(key)
277
281
  }
278
282
 
279
- cmd = &quot;scp -i #{public_key_loc.join(' -i ')} -o StrictHostkeyChecking=no 2&gt;&amp;1 #{local_file_loc} root@#{target_ip}:#{remote_file_loc}&quot;
283
+ cmd = &quot;scp -i #{public_key_loc.join(' -i ')} #{ssh_args} #{local_file_loc} root@#{target_ip}:#{remote_file_loc}&quot;
280
284
  else
281
285
  public_key_loc = <span class="ruby-constant">File</span>.expand_path(public_key_loc)
282
- cmd = &quot;scp -i #{public_key_loc} -o StrictHostkeyChecking=no 2&gt;&amp;1 #{local_file_loc} root@#{target_ip}:#{remote_file_loc}&quot;
286
+ cmd = &quot;scp -i #{public_key_loc} #{ssh_args} #{local_file_loc} root@#{target_ip}:#{remote_file_loc}&quot;
283
287
  end
284
288
 
285
289
  cmd &lt;&lt; <span class="ruby-string">&quot;; echo $? &gt;&gt; ~/.appscale/retval&quot;</span>
@@ -318,7 +322,7 @@ end</pre>
318
322
 
319
323
  <div class="method-heading">
320
324
  <span class="method-name">scp_to_shadow</span><span
321
- class="method-args">(local_file_loc, remote_file_loc, keyname)</span>
325
+ class="method-args">(local_file_loc, remote_file_loc, keyname, is_dir=false)</span>
322
326
  <span class="method-click-advice">click to toggle source</span>
323
327
  </div>
324
328
 
@@ -335,12 +339,12 @@ by the Neptune job given, but defaults to ”appscale” if not provided.</p>
335
339
  <div class="method-source-code"
336
340
  id="scp_to_shadow-source">
337
341
  <pre>
338
- <span class="ruby-comment"># File lib/common_functions.rb, line 25</span>
339
- def self.scp_to_shadow(local_file_loc, remote_file_loc, keyname)
342
+ <span class="ruby-comment"># File lib/common_functions.rb, line 24</span>
343
+ def self.scp_to_shadow(local_file_loc, remote_file_loc, keyname, is_dir=false)
340
344
  shadow_ip = <span class="ruby-constant">CommonFunctions</span>.get_from_yaml(keyname, :shadow)
341
345
  ssh_key = <span class="ruby-constant">File</span>.expand_path(&quot;~/.appscale/#{keyname}.key&quot;)
342
346
 
343
- self.scp_file(local_file_loc, remote_file_loc, shadow_ip, ssh_key)
347
+ self.scp_file(local_file_loc, remote_file_loc, shadow_ip, ssh_key, is_dir)
344
348
  end</pre>
345
349
  </div>
346
350
 
data/doc/Object.html CHANGED
@@ -41,8 +41,8 @@
41
41
  <li><a href="./lib/app_controller_client_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
42
42
  class="thickbox" title="lib/app_controller_client.rb">lib/app_controller_client.rb</a></li>
43
43
 
44
- <li><a href="./lib/job_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
45
- class="thickbox" title="lib/job.rb">lib/job.rb</a></li>
44
+ <li><a href="./lib/neptune_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
45
+ class="thickbox" title="lib/neptune.rb">lib/neptune.rb</a></li>
46
46
 
47
47
  </ul>
48
48
  </div>
@@ -74,10 +74,12 @@
74
74
 
75
75
  <li><a href="#method-i-do_preprocessing">#do_preprocessing</a></li>
76
76
 
77
- <li><a href="#method-i-job">#job</a></li>
77
+ <li><a href="#method-i-neptune">#neptune</a></li>
78
78
 
79
79
  <li><a href="#method-i-preprocess_compile">#preprocess_compile</a></li>
80
80
 
81
+ <li><a href="#method-i-preprocess_erlang">#preprocess_erlang</a></li>
82
+
81
83
  <li><a href="#method-i-preprocess_mapreduce">#preprocess_mapreduce</a></li>
82
84
 
83
85
  <li><a href="#method-i-preprocess_mpi">#preprocess_mpi</a></li>
@@ -162,6 +164,24 @@ timeout. The next version should replace this and properly timeout and not
162
164
  use long calls unless necessary.</p></dd>
163
165
 
164
166
 
167
+ <dt><a name="NO_NODES_NEEDED">NO_NODES_NEEDED</a></dt>
168
+
169
+ <dd class="description"><p>A list of Neptune jobs that do not require nodes to be spawned up for
170
+ computation</p></dd>
171
+
172
+
173
+ <dt><a name="NO_OUTPUT_NEEDED">NO_OUTPUT_NEEDED</a></dt>
174
+
175
+ <dd class="description"><p>A list of Neptune jobs that do not require the output to be specified
176
+ beforehand</p></dd>
177
+
178
+
179
+ <dt><a name="ALLOWED_STORAGE_TYPES">ALLOWED_STORAGE_TYPES</a></dt>
180
+
181
+ <dd class="description"><p>A list of storage mechanisms that we can use to store and retrieve data to
182
+ for Neptune jobs.</p></dd>
183
+
184
+
165
185
  <dt><a name="NEED_PREPROCESSING">NEED_PREPROCESSING</a></dt>
166
186
 
167
187
  <dd class="description"><p>A list of jobs that require some kind of work to be done before the actual
@@ -203,7 +223,7 @@ method to use based on the type of the job that the user has asked to run.</p>
203
223
  <div class="method-source-code"
204
224
  id="do_preprocessing-source">
205
225
  <pre>
206
- <span class="ruby-comment"># File lib/job.rb, line 34</span>
226
+ <span class="ruby-comment"># File lib/neptune.rb, line 49</span>
207
227
  def do_preprocessing(job_data)
208
228
  job_type = job_data[<span class="ruby-string">&quot;@type&quot;</span>]
209
229
  return unless <span class="ruby-constant">NEED_PREPROCESSING</span>.include?(job_type)
@@ -221,13 +241,13 @@ end</pre>
221
241
  </div>
222
242
 
223
243
 
224
- <div id="job-method" class="method-detail ">
225
- <a name="method-i-job"></a>
244
+ <div id="neptune-method" class="method-detail ">
245
+ <a name="method-i-neptune"></a>
226
246
 
227
247
 
228
248
  <div class="method-heading">
229
- <span class="method-name">job</span><span
230
- class="method-args">(name, &block)</span>
249
+ <span class="method-name">neptune</span><span
250
+ class="method-args">(params)</span>
231
251
  <span class="method-click-advice">click to toggle source</span>
232
252
  </div>
233
253
 
@@ -244,15 +264,14 @@ vice-versa).</p>
244
264
 
245
265
 
246
266
  <div class="method-source-code"
247
- id="job-source">
267
+ id="neptune-source">
248
268
  <pre>
249
- <span class="ruby-comment"># File lib/job.rb, line 119</span>
250
- def job(name, &amp;block)
269
+ <span class="ruby-comment"># File lib/neptune.rb, line 175</span>
270
+ def neptune(params)
251
271
  puts <span class="ruby-string">&quot;Received a request to run a job.&quot;</span>
252
- puts name
253
- block.call()
272
+ puts params[:type]
254
273
 
255
- keyname = <span class="ruby-ivar">@keyname</span> || <span class="ruby-string">&quot;appscale&quot;</span>
274
+ keyname = params[:keyname] || <span class="ruby-string">&quot;appscale&quot;</span>
256
275
 
257
276
  shadow_ip = <span class="ruby-constant">CommonFunctions</span>.get_from_yaml(keyname, :shadow)
258
277
  secret = <span class="ruby-constant">CommonFunctions</span>.get_secret_key(keyname)
@@ -260,20 +279,65 @@ def job(name, &amp;block)
260
279
  ssh_key = <span class="ruby-constant">File</span>.expand_path(&quot;~/.appscale/#{keyname}.key&quot;)
261
280
 
262
281
  job_data = {}
263
- instance_variables.each { |var|
264
- job_data[var] = instance_variable_get(var)
282
+ params.each { |k, v|
283
+ key = &quot;@#{k}&quot;
284
+ job_data[key] = v
265
285
  }
266
286
 
267
287
  job_data[<span class="ruby-string">&quot;@job&quot;</span>] = nil
268
- job_data[<span class="ruby-string">&quot;@type&quot;</span>] = name
269
- job_data[<span class="ruby-string">&quot;@keyname&quot;</span>] = keyname
288
+ job_data[<span class="ruby-string">&quot;@keyname&quot;</span>] = keyname || <span class="ruby-string">&quot;appscale&quot;</span>
289
+ type = job_data[<span class="ruby-string">&quot;@type&quot;</span>]
290
+
291
+ if type == <span class="ruby-string">&quot;upc&quot;</span> or type == <span class="ruby-string">&quot;x10&quot;</span>
292
+ job_data[<span class="ruby-string">&quot;@type&quot;</span>] = <span class="ruby-string">&quot;mpi&quot;</span>
293
+ type = <span class="ruby-string">&quot;mpi&quot;</span>
294
+ end
270
295
 
271
- if (job_data[<span class="ruby-string">&quot;@output&quot;</span>].nil? or job_data[<span class="ruby-string">&quot;@output&quot;</span>] == <span class="ruby-string">&quot;&quot;</span>)
272
- abort(<span class="ruby-string">&quot;Job output must be specified&quot;</span>)
296
+ if job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>].class == <span class="ruby-constant">Hash</span>
297
+ job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>] = job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>].to_a.flatten
273
298
  end
274
299
 
275
- if job_data[<span class="ruby-string">&quot;@output&quot;</span>][0].chr != <span class="ruby-string">&quot;/&quot;</span>
276
- abort(<span class="ruby-string">&quot;Job output must begin with a slash ('/')&quot;</span>)
300
+ if !<span class="ruby-constant">NO_OUTPUT_NEEDED</span>.include?(type)
301
+ if (job_data[<span class="ruby-string">&quot;@output&quot;</span>].nil? or job_data[<span class="ruby-string">&quot;@output&quot;</span>] == <span class="ruby-string">&quot;&quot;</span>)
302
+ abort(<span class="ruby-string">&quot;Job output must be specified&quot;</span>)
303
+ end
304
+
305
+ if job_data[<span class="ruby-string">&quot;@output&quot;</span>][0].chr != <span class="ruby-string">&quot;/&quot;</span>
306
+ abort(<span class="ruby-string">&quot;Job output must begin with a slash ('/')&quot;</span>)
307
+ end
308
+ end
309
+
310
+ if job_data[<span class="ruby-string">&quot;@storage&quot;</span>]
311
+ storage = job_data[<span class="ruby-string">&quot;@storage&quot;</span>]
312
+ unless <span class="ruby-constant">ALLOWED_STORAGE_TYPES</span>.include?(storage)
313
+ msg = &quot;Supported storage types are #{ALLOWED_STORAGE_TYPES.join(', ')}&quot; +
314
+ &quot; - we do not support #{storage}.&quot;
315
+ abort(msg)
316
+ end
317
+
318
+ <span class="ruby-comment"># Our implementation for storing / retrieving via Google Storage uses</span>
319
+ <span class="ruby-comment"># the same library as we do for S3 - so just tell it that it's S3</span>
320
+ if storage == <span class="ruby-string">&quot;gstorage&quot;</span>
321
+ storage = <span class="ruby-string">&quot;s3&quot;</span>
322
+ job_data[<span class="ruby-string">&quot;@storage&quot;</span>] = <span class="ruby-string">&quot;s3&quot;</span>
323
+ end
324
+
325
+ if storage == <span class="ruby-string">&quot;s3&quot;</span>
326
+ [<span class="ruby-string">&quot;EC2_ACCESS_KEY&quot;</span>, <span class="ruby-string">&quot;EC2_SECRET_KEY&quot;</span>, <span class="ruby-string">&quot;S3_URL&quot;</span>].each { |item|
327
+ unless job_data[&quot;@#{item}&quot;]
328
+ if <span class="ruby-constant">ENV</span>[item]
329
+ puts &quot;Using #{item} from environment&quot;
330
+ job_data[&quot;@#{item}&quot;] = <span class="ruby-constant">ENV</span>[item]
331
+ else
332
+ msg = &quot;When storing data to S3, #{item} must be specified or be in &quot; +
333
+ <span class="ruby-string">&quot;your environment. Please do so and try again.&quot;</span>
334
+ abort(msg)
335
+ end
336
+ end
337
+ }
338
+ end
339
+ else
340
+ job_data[<span class="ruby-string">&quot;@storage&quot;</span>] = <span class="ruby-string">&quot;appdb&quot;</span>
277
341
  end
278
342
 
279
343
  <span class="ruby-comment">#if job_data[&quot;@can_run_on&quot;].class == Range</span>
@@ -286,8 +350,27 @@ def job(name, &amp;block)
286
350
 
287
351
  do_preprocessing(job_data)
288
352
 
289
- type = job_data[<span class="ruby-string">&quot;@type&quot;</span>]
290
- if type == <span class="ruby-string">&quot;output&quot;</span>
353
+ ssh_args = &quot;-i ~/.appscale/#{keyname}.key -o StrictHostkeyChecking=no &quot;
354
+
355
+ if type == <span class="ruby-string">&quot;input&quot;</span>
356
+ <span class="ruby-comment"># copy file to remote</span>
357
+ <span class="ruby-comment"># set location</span>
358
+ local_file = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@local&quot;</span>])
359
+ if !<span class="ruby-constant">File</span>.exists?(local_file)
360
+ msg = &quot;the file you specified to copy, #{local_file}, doesn't exist.&quot; +
361
+ <span class="ruby-string">&quot; Please specify a file that exists and try again.&quot;</span>
362
+ abort(msg)
363
+ end
364
+
365
+ remote = &quot;/tmp/neptune-input-#{rand(100000)}&quot;
366
+ scp_cmd = &quot;scp #{ssh_args} #{local_file} root@#{shadow_ip}:#{remote}&quot;
367
+ puts scp_cmd
368
+ `#{scp_cmd}`
369
+
370
+ job_data[<span class="ruby-string">&quot;@local&quot;</span>] = remote
371
+ puts &quot;job data = #{job_data.inspect}&quot;
372
+ return controller.put_input(job_data)
373
+ elsif type == <span class="ruby-string">&quot;output&quot;</span>
291
374
  return controller.get_output(job_data)
292
375
  elsif type == <span class="ruby-string">&quot;get-acl&quot;</span>
293
376
  job_data[<span class="ruby-string">&quot;@type&quot;</span>] = <span class="ruby-string">&quot;acl&quot;</span>
@@ -298,14 +381,13 @@ def job(name, &amp;block)
298
381
  elsif type == <span class="ruby-string">&quot;compile&quot;</span>
299
382
  compiled_location = controller.compile_code(job_data)
300
383
 
301
- ssh_args = &quot;-i ~/.appscale/#{keyname}.key -o StrictHostkeyChecking=no 2&gt;&amp;1 root@#{shadow_ip}&quot;
302
384
  copy_to = job_data[<span class="ruby-string">&quot;@copy_to&quot;</span>]
303
385
 
304
386
  loop {
305
- ssh_command = &quot;ssh #{ssh_args} 'ls #{compiled_location}'&quot;
306
- puts ssh_command
387
+ ssh_command = &quot;ssh #{ssh_args} root@#{shadow_ip} 'ls #{compiled_location}' 2&gt;&amp;1&quot;
388
+ <span class="ruby-comment">#puts ssh_command</span>
307
389
  result = `#{ssh_command}`
308
- puts &quot;result was [#{result}]&quot;
390
+ <span class="ruby-comment">#puts &quot;result was [#{result}]&quot;</span>
309
391
  if result =~ <span class="ruby-regexp">/No such file or directory/</span>
310
392
  puts <span class="ruby-string">&quot;Still waiting for code to be compiled...&quot;</span>
311
393
  else
@@ -315,15 +397,23 @@ def job(name, &amp;block)
315
397
  sleep(5)
316
398
  }
317
399
 
318
- scp_command = &quot;scp #{ssh_args}:#{compiled_location} #{copy_to}&quot;
400
+ rm_local = &quot;rm -rf #{copy_to}&quot;
401
+ <span class="ruby-comment">#puts rm_local</span>
402
+ `#{rm_local}`
403
+
404
+ scp_command = &quot;scp -r #{ssh_args} root@#{shadow_ip}:#{compiled_location} #{copy_to} 2&gt;&amp;1&quot;
319
405
  puts scp_command
320
406
  `#{scp_command}`
407
+
408
+ out = <span class="ruby-constant">File</span>.open(&quot;#{copy_to}/compile_out&quot;) { |f| f.read.chomp! }
409
+ err = <span class="ruby-constant">File</span>.open(&quot;#{copy_to}/compile_err&quot;) { |f| f.read.chomp! }
410
+ return {:out =&gt; out, :err =&gt; err }
321
411
  else
322
412
  result = controller.start_neptune_job(job_data)
323
413
  if result =~ <span class="ruby-regexp">/job is now running\Z/</span>
324
- return :success
414
+ return {:result =&gt; :success, :msg =&gt; result}
325
415
  else
326
- return :failure
416
+ return {:result =&gt; :failure, :msg =&gt; result}
327
417
  end
328
418
  end
329
419
  end</pre>
@@ -359,7 +449,7 @@ copy over libraries as well.</p>
359
449
  <div class="method-source-code"
360
450
  id="preprocess_compile-source">
361
451
  <pre>
362
- <span class="ruby-comment"># File lib/job.rb, line 45</span>
452
+ <span class="ruby-comment"># File lib/neptune.rb, line 60</span>
363
453
  def preprocess_compile(job_data)
364
454
  code = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@code&quot;</span>])
365
455
  unless <span class="ruby-constant">File</span>.exists?(code)
@@ -368,9 +458,15 @@ def preprocess_compile(job_data)
368
458
 
369
459
  suffix = code.split(<span class="ruby-string">'/'</span>)[-1]
370
460
  dest = &quot;/tmp/#{suffix}&quot;
371
-
372
461
  keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>]
373
- <span class="ruby-constant">CommonFunctions</span>.scp_to_shadow(code, dest, keyname)
462
+ shadow_ip = <span class="ruby-constant">CommonFunctions</span>.get_from_yaml(keyname, :shadow)
463
+
464
+ ssh_args = &quot;-i ~/.appscale/#{keyname}.key -o StrictHostkeyChecking=no root@#{shadow_ip}&quot;
465
+ remove_dir = &quot;ssh #{ssh_args} 'rm -rf #{dest}' 2&gt;&amp;1&quot;
466
+ <span class="ruby-comment">#puts remove_dir</span>
467
+ `#{remove_dir}`
468
+
469
+ <span class="ruby-constant">CommonFunctions</span>.scp_to_shadow(code, dest, keyname, is_dir=true)
374
470
 
375
471
  job_data[<span class="ruby-string">&quot;@code&quot;</span>] = dest
376
472
  end</pre>
@@ -381,6 +477,49 @@ end</pre>
381
477
 
382
478
 
383
479
 
480
+ </div>
481
+
482
+
483
+ <div id="preprocess_erlang-method" class="method-detail ">
484
+ <a name="method-i-preprocess_erlang"></a>
485
+
486
+
487
+ <div class="method-heading">
488
+ <span class="method-name">preprocess_erlang</span><span
489
+ class="method-args">(job_data)</span>
490
+ <span class="method-click-advice">click to toggle source</span>
491
+ </div>
492
+
493
+
494
+ <div class="method-description">
495
+
496
+
497
+
498
+
499
+
500
+ <div class="method-source-code"
501
+ id="preprocess_erlang-source">
502
+ <pre>
503
+ <span class="ruby-comment"># File lib/neptune.rb, line 81</span>
504
+ def preprocess_erlang(job_data)
505
+ source_code = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@code&quot;</span>])
506
+ unless <span class="ruby-constant">File</span>.exists?(source_code)
507
+ file_not_found = &quot;The specified code, #{job_data['@code']},&quot; +
508
+ <span class="ruby-string">&quot; didn't exist. Please specify one that exists and try again&quot;</span>
509
+ abort(file_not_found)
510
+ end
511
+ dest_code = <span class="ruby-string">&quot;/tmp/&quot;</span>
512
+
513
+ keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>]
514
+ <span class="ruby-constant">CommonFunctions</span>.scp_to_shadow(source_code, dest_code, keyname)
515
+ end</pre>
516
+ </div>
517
+
518
+ </div>
519
+
520
+
521
+
522
+
384
523
  </div>
385
524
 
386
525
 
@@ -409,11 +548,12 @@ will copy it into HDFS for us.</p>
409
548
  <div class="method-source-code"
410
549
  id="preprocess_mapreduce-source">
411
550
  <pre>
412
- <span class="ruby-comment"># File lib/job.rb, line 67</span>
551
+ <span class="ruby-comment"># File lib/neptune.rb, line 101</span>
413
552
  def preprocess_mapreduce(job_data)
414
- items_to_copy = [<span class="ruby-string">&quot;@map&quot;</span>, <span class="ruby-string">&quot;@reduce&quot;</span>] if job_data[<span class="ruby-string">&quot;@map&quot;</span>] and job_data[<span class="ruby-string">&quot;@reduce&quot;</span>]
553
+ return
554
+ <span class="ruby-comment">#items_to_copy = [&quot;@map&quot;, &quot;@reduce&quot;] if job_data[&quot;@map&quot;] and job_data[&quot;@reduce&quot;]</span>
415
555
  items_to_copy = [<span class="ruby-string">&quot;@mapreducejar&quot;</span>] if job_data[<span class="ruby-string">&quot;@mapreducejar&quot;</span>]
416
- items_to_copy &lt;&lt; <span class="ruby-string">&quot;@input&quot;</span> if job_data[<span class="ruby-string">&quot;@copy_input&quot;</span>]
556
+ <span class="ruby-comment">#items_to_copy &lt;&lt; &quot;@input&quot; if job_data[&quot;@copy_input&quot;]</span>
417
557
  items_to_copy.each { |item|
418
558
  source = <span class="ruby-constant">File</span>.expand_path(job_data[item])
419
559
  unless <span class="ruby-constant">File</span>.exists?(source)
@@ -461,18 +601,39 @@ job.</p>
461
601
  <div class="method-source-code"
462
602
  id="preprocess_mpi-source">
463
603
  <pre>
464
- <span class="ruby-comment"># File lib/job.rb, line 90</span>
604
+ <span class="ruby-comment"># File lib/neptune.rb, line 125</span>
465
605
  def preprocess_mpi(job_data)
606
+ if job_data[<span class="ruby-string">&quot;@procs_to_use&quot;</span>]
607
+ p = job_data[<span class="ruby-string">&quot;@procs_to_use&quot;</span>]
608
+ n = job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>]
609
+ if p &lt; n
610
+ not_enough_procs = <span class="ruby-string">&quot;When specifying both :procs_to_use and :nodes_to_use&quot;</span> +
611
+ <span class="ruby-string">&quot;, :procs_to_use must be at least as large as :nodes_to_use. Please &quot;</span> +
612
+ &quot;change this and try again. You specified :procs_to_use = #{p} and&quot; +
613
+ &quot;:nodes_to_use = #{n}.&quot;
614
+ abort(not_enough_procs)
615
+ end
616
+ end
617
+
466
618
  source_code = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@code&quot;</span>])
467
619
  unless <span class="ruby-constant">File</span>.exists?(source_code)
468
- file_not_found = &quot;The specified code, #{job_data['@code']},&quot; +
620
+ file_not_found = &quot;The specified code, #{source_code},&quot; +
469
621
  <span class="ruby-string">&quot; didn't exist. Please specify one that exists and try again&quot;</span>
470
622
  abort(file_not_found)
471
623
  end
624
+
625
+ unless <span class="ruby-constant">File</span>.file?(source_code)
626
+ should_be_file = &quot;The specified code, #{source_code}, was not a file - &quot; +
627
+ <span class="ruby-string">&quot; it was a directory or symbolic link. Please specify a file and try again.&quot;</span>
628
+ abort(should_be_file)
629
+ end
630
+
472
631
  dest_code = <span class="ruby-string">&quot;/tmp/thempicode&quot;</span>
473
632
 
474
633
  keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>]
634
+ puts <span class="ruby-string">&quot;Copying over code...&quot;</span>
475
635
  <span class="ruby-constant">CommonFunctions</span>.scp_to_shadow(source_code, dest_code, keyname)
636
+ puts <span class="ruby-string">&quot;Done copying code!&quot;</span>
476
637
  end</pre>
477
638
  </div>
478
639