neptune 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -41,6 +41,9 @@
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/babel_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
45
+ class="thickbox" title="lib/babel.rb">lib/babel.rb</a></li>
46
+
44
47
  <li><a href="./lib/neptune_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
45
48
  class="thickbox" title="lib/neptune.rb">lib/neptune.rb</a></li>
46
49
 
@@ -72,34 +75,10 @@
72
75
  <h3 class="section-header">Methods</h3>
73
76
  <ul class="link-list">
74
77
 
75
- <li><a href="#method-i-compile_code">#compile_code</a></li>
76
-
77
- <li><a href="#method-i-do_preprocessing">#do_preprocessing</a></li>
78
-
79
- <li><a href="#method-i-get_input">#get_input</a></li>
80
-
81
- <li><a href="#method-i-get_job_data">#get_job_data</a></li>
82
-
83
- <li><a href="#method-i-get_std_out_and_err">#get_std_out_and_err</a></li>
78
+ <li><a href="#method-i-babel">#babel</a></li>
84
79
 
85
80
  <li><a href="#method-i-neptune">#neptune</a></li>
86
81
 
87
- <li><a href="#method-i-preprocess_compile">#preprocess_compile</a></li>
88
-
89
- <li><a href="#method-i-preprocess_erlang">#preprocess_erlang</a></li>
90
-
91
- <li><a href="#method-i-preprocess_mpi">#preprocess_mpi</a></li>
92
-
93
- <li><a href="#method-i-preprocess_ssa">#preprocess_ssa</a></li>
94
-
95
- <li><a href="#method-i-run_job">#run_job</a></li>
96
-
97
- <li><a href="#method-i-upload_app_for_cicero">#upload_app_for_cicero</a></li>
98
-
99
- <li><a href="#method-i-validate_storage_params">#validate_storage_params</a></li>
100
-
101
- <li><a href="#method-i-wait_for_compilation_to_finish">#wait_for_compilation_to_finish</a></li>
102
-
103
82
  </ul>
104
83
  </div>
105
84
 
@@ -129,9 +108,17 @@
129
108
 
130
109
  <li><a href="./AppControllerClient.html">AppControllerClient</a></li>
131
110
 
111
+ <li><a href="./AppControllerException.html">AppControllerException</a></li>
112
+
113
+ <li><a href="./BabelHelper.html">BabelHelper</a></li>
114
+
115
+ <li><a href="./BadConfigurationException.html">BadConfigurationException</a></li>
116
+
132
117
  <li><a href="./CommonFunctions.html">CommonFunctions</a></li>
133
118
 
134
- <li><a href="./Kernel.html">Kernel</a></li>
119
+ <li><a href="./FileNotFoundException.html">FileNotFoundException</a></li>
120
+
121
+ <li><a href="./NeptuneHelper.html">NeptuneHelper</a></li>
135
122
 
136
123
  <li><a href="./Object.html">Object</a></li>
137
124
 
@@ -173,6 +160,41 @@ timeout. The next version should replace this and properly timeout and not
173
160
  use long calls unless necessary.</p></dd>
174
161
 
175
162
 
163
+ <dt><a name="NEEDS_BUCKET_INFO">NEEDS_BUCKET_INFO</a></dt>
164
+
165
+ <dd class="description"><p>If the user doesn’t give us enough info to infer what bucket we should
166
+ place their code in, this message is displayed and execution aborts.</p></dd>
167
+
168
+
169
+ <dt><a name="DOES_NOT_EXIST">DOES_NOT_EXIST</a></dt>
170
+
171
+ <dd class="description"><p>The constant string that a Neptune output job returns if the output does
172
+ not yet exist.</p></dd>
173
+
174
+
175
+ <dt><a name="SLEEP_TIME">SLEEP_TIME</a></dt>
176
+
177
+ <dd class="description"><p>The initial amount of time, in seconds, to sleep between output job
178
+ requests. An exponential backoff is used with this value as the starting
179
+ sleep time.</p></dd>
180
+
181
+
182
+ <dt><a name="MAX_SLEEP_TIME">MAX_SLEEP_TIME</a></dt>
183
+
184
+ <dd class="description"><p>The maximum amount of time that we should sleep to, when waiting for output
185
+ job requests.</p></dd>
186
+
187
+
188
+ <dt><a name="ALLOWED_JOB_TYPES">ALLOWED_JOB_TYPES</a></dt>
189
+
190
+ <dd class="description"><p>A list of all the Neptune job types that we support</p></dd>
191
+
192
+
193
+ <dt><a name="JOB_TYPE_NOT_ALLOWED">JOB_TYPE_NOT_ALLOWED</a></dt>
194
+
195
+ <dd class="description"><p>The string to display for disallowed job types.</p></dd>
196
+
197
+
176
198
  <dt><a name="NO_NODES_NEEDED">NO_NODES_NEEDED</a></dt>
177
199
 
178
200
  <dd class="description"><p>A list of Neptune jobs that do not require nodes to be spawned up for
@@ -210,176 +232,12 @@ computation can be performed.</p></dd>
210
232
  <h3 class="section-header">Public Instance Methods</h3>
211
233
 
212
234
 
213
- <div id="compile_code-method" class="method-detail ">
214
- <a name="method-i-compile_code"></a>
235
+ <div id="babel-method" class="method-detail ">
236
+ <a name="method-i-babel"></a>
215
237
 
216
238
 
217
239
  <div class="method-heading">
218
- <span class="method-name">compile_code</span><span
219
- class="method-args">(job_data, ssh_args, shadow_ip, shell=Kernel.method(:`))</span>
220
- <span class="method-click-advice">click to toggle source</span>
221
- </div>
222
-
223
-
224
- <div class="method-description">
225
-
226
- <p>This method sends out a request to compile code, waits for it to finish,
227
- and gets the standard out and error returned from the compilation. This
228
- method returns a hash containing the standard out, error, and a result that
229
- indicates whether or not the compilation was successful.</p>
230
-
231
-
232
-
233
- <div class="method-source-code"
234
- id="compile_code-source">
235
- <pre>
236
- <span class="ruby-comment"># File lib/neptune.rb, line 301</span>
237
- def compile_code(job_data, ssh_args, shadow_ip, shell=<span class="ruby-constant">Kernel</span>.method(:`))
238
- compiled_location = controller.compile_code(job_data)
239
-
240
- copy_to = job_data[<span class="ruby-string">&quot;@copy_to&quot;</span>]
241
-
242
- wait_for_compilation_to_finish(ssh_args, shadow_ip, compiled_location)
243
-
244
- <span class="ruby-constant">FileUtils</span>.rm_rf(copy_to)
245
-
246
- scp_command = &quot;scp -r #{ssh_args} root@#{shadow_ip}:#{compiled_location} #{copy_to} 2&gt;&amp;1&quot;
247
- puts scp_command
248
- shell.call(scp_command)
249
-
250
- code = job_data[<span class="ruby-string">&quot;@code&quot;</span>]
251
- dirs = code.split(<span class="ruby-regexp">/\//</span>)
252
- remote_dir = <span class="ruby-string">&quot;/tmp/&quot;</span> + dirs[-1]
253
-
254
- [remote_dir, compiled_location].each { |remote_files|
255
- ssh_command = &quot;ssh #{ssh_args} root@#{shadow_ip} 'rm -rf #{remote_files}' 2&gt;&amp;1&quot;
256
- puts ssh_command
257
- shell.call(ssh_command)
258
- }
259
-
260
- return get_std_out_and_err(copy_to)
261
- end</pre>
262
- </div>
263
-
264
- </div>
265
-
266
-
267
-
268
-
269
- </div>
270
-
271
-
272
- <div id="do_preprocessing-method" class="method-detail ">
273
- <a name="method-i-do_preprocessing"></a>
274
-
275
-
276
- <div class="method-heading">
277
- <span class="method-name">do_preprocessing</span><span
278
- class="method-args">(job_data)</span>
279
- <span class="method-click-advice">click to toggle source</span>
280
- </div>
281
-
282
-
283
- <div class="method-description">
284
-
285
- <p>Certain types of jobs need steps to be taken before they can be started
286
- (e.g., copying input data or code over). This method dispatches the right
287
- method to use based on the type of the job that the user has asked to run.</p>
288
-
289
-
290
-
291
- <div class="method-source-code"
292
- id="do_preprocessing-source">
293
- <pre>
294
- <span class="ruby-comment"># File lib/neptune.rb, line 52</span>
295
- def do_preprocessing(job_data)
296
- job_type = job_data[<span class="ruby-string">&quot;@type&quot;</span>]
297
- if !<span class="ruby-constant">NEED_PREPROCESSING</span>.include?(job_type)
298
- return
299
- end
300
-
301
- preprocess = &quot;preprocess_#{job_type}&quot;.to_sym
302
- send(preprocess, job_data)
303
- end</pre>
304
- </div>
305
-
306
- </div>
307
-
308
-
309
-
310
-
311
- </div>
312
-
313
-
314
- <div id="get_input-method" class="method-detail ">
315
- <a name="method-i-get_input"></a>
316
-
317
-
318
- <div class="method-heading">
319
- <span class="method-name">get_input</span><span
320
- class="method-args">(job_data, ssh_args, shadow_ip, controller, file=File, shell=Kernel.method(:`))</span>
321
- <span class="method-click-advice">click to toggle source</span>
322
- </div>
323
-
324
-
325
- <div class="method-description">
326
-
327
- <p>This method takes a file on the local user’s computer and stores it
328
- remotely via AppScale. It returns a hash map indicating whether or not the
329
- job succeeded and if it failed, the reason for it.</p>
330
-
331
-
332
-
333
- <div class="method-source-code"
334
- id="get_input-source">
335
- <pre>
336
- <span class="ruby-comment"># File lib/neptune.rb, line 247</span>
337
- def get_input(job_data, ssh_args, shadow_ip, controller, file=<span class="ruby-constant">File</span>,
338
- shell=<span class="ruby-constant">Kernel</span>.method(:`))
339
- result = {:result =&gt; :success}
340
-
341
- if !job_data[<span class="ruby-string">&quot;@local&quot;</span>]
342
- abort(<span class="ruby-string">&quot;You failed to specify a file to copy over via the :local flag.&quot;</span>)
343
- end
344
-
345
- local_file = file.expand_path(job_data[<span class="ruby-string">&quot;@local&quot;</span>])
346
- if !file.exists?(local_file)
347
- reason = &quot;the file you specified to copy, #{local_file}, doesn't exist.&quot; +
348
- <span class="ruby-string">&quot; Please specify a file that exists and try again.&quot;</span>
349
- return {:result =&gt; :failure, :reason =&gt; reason}
350
- end
351
-
352
- remote = &quot;/tmp/neptune-input-#{rand(100000)}&quot;
353
- scp_cmd = &quot;scp -r #{ssh_args} #{local_file} root@#{shadow_ip}:#{remote}&quot;
354
- puts scp_cmd
355
- shell.call(scp_cmd)
356
-
357
- job_data[<span class="ruby-string">&quot;@local&quot;</span>] = remote
358
- puts &quot;job data = #{job_data.inspect}&quot;
359
- response = controller.put_input(job_data)
360
- if response
361
- return {:result =&gt; :success}
362
- else
363
- <span class="ruby-comment"># TODO - expand this to include the reason why it failed</span>
364
- return {:result =&gt; :failure}
365
- end
366
- end</pre>
367
- </div>
368
-
369
- </div>
370
-
371
-
372
-
373
-
374
- </div>
375
-
376
-
377
- <div id="get_job_data-method" class="method-detail ">
378
- <a name="method-i-get_job_data"></a>
379
-
380
-
381
- <div class="method-heading">
382
- <span class="method-name">get_job_data</span><span
240
+ <span class="method-name">babel</span><span
383
241
  class="method-args">(params)</span>
384
242
  <span class="method-click-advice">click to toggle source</span>
385
243
  </div>
@@ -387,106 +245,48 @@ end</pre>
387
245
 
388
246
  <div class="method-description">
389
247
 
390
-
248
+ <p>Babel provides a nice wrapper around Neptune jobs. Instead of making users
249
+ write multiple Neptune jobs to actually run code (e.g., putting input in
250
+ the datastore, run the job, get the output back), Babel automatically
251
+ handles this.</p>
391
252
 
392
253
 
393
254
 
394
255
  <div class="method-source-code"
395
- id="get_job_data-source">
256
+ id="babel-source">
396
257
  <pre>
397
- <span class="ruby-comment"># File lib/neptune.rb, line 162</span>
398
- def get_job_data(params)
399
- job_data = {}
400
- params.each { |k, v|
401
- key = &quot;@#{k}&quot;
402
- job_data[key] = v
403
- }
404
-
405
- job_data.delete(<span class="ruby-string">&quot;@job&quot;</span>)
406
- job_data[<span class="ruby-string">&quot;@keyname&quot;</span>] = params[:keyname] || <span class="ruby-string">&quot;appscale&quot;</span>
407
-
408
- job_data[<span class="ruby-string">&quot;@type&quot;</span>] = job_data[<span class="ruby-string">&quot;@type&quot;</span>].to_s
409
- type = job_data[<span class="ruby-string">&quot;@type&quot;</span>]
410
-
411
- if type == <span class="ruby-string">&quot;upc&quot;</span> or type == <span class="ruby-string">&quot;x10&quot;</span>
412
- job_data[<span class="ruby-string">&quot;@type&quot;</span>] = <span class="ruby-string">&quot;mpi&quot;</span>
413
- type = <span class="ruby-string">&quot;mpi&quot;</span>
414
- end
415
-
416
- <span class="ruby-comment"># kdt jobs also run as mpi jobs, but need to pass along an executable</span>
417
- <span class="ruby-comment"># parameter to let mpiexec know to use python to exec it</span>
418
- if type == <span class="ruby-string">&quot;kdt&quot;</span>
419
- job_data[<span class="ruby-string">&quot;@type&quot;</span>] = <span class="ruby-string">&quot;mpi&quot;</span>
420
- type = <span class="ruby-string">&quot;mpi&quot;</span>
421
-
422
- job_data[<span class="ruby-string">&quot;@executable&quot;</span>] = <span class="ruby-string">&quot;python&quot;</span>
423
- end
424
-
425
- if job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>].class == <span class="ruby-constant">Hash</span>
426
- 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
427
- end
428
-
429
- if !<span class="ruby-constant">NO_OUTPUT_NEEDED</span>.include?(type)
430
- 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>)
431
- abort(<span class="ruby-string">&quot;Job output must be specified&quot;</span>)
258
+ <span class="ruby-comment"># File lib/babel.rb, line 42</span>
259
+ def babel(params)
260
+ <span class="ruby-comment"># Since this whole function should run asynchronously, we run it as a future.</span>
261
+ <span class="ruby-comment"># It automatically starts running in a new thread, and attempting to get the</span>
262
+ <span class="ruby-comment"># value of what this returns causes it to block until the job completes.</span>
263
+ future {
264
+ job_data = <span class="ruby-constant">BabelHelper</span>.convert_from_neptune_params(params)
265
+ <span class="ruby-constant">NeptuneHelper</span>.validate_storage_params(job_data) <span class="ruby-comment"># adds in S3 storage params</span>
266
+
267
+ <span class="ruby-comment"># :code is the only required parameter - everything else can use default vals</span>
268
+ <span class="ruby-constant">NeptuneHelper</span>.require_param(<span class="ruby-string">&quot;@code&quot;</span>, job_data)
269
+
270
+ if job_data[<span class="ruby-string">&quot;@output&quot;</span>].nil? or job_data[<span class="ruby-string">&quot;@output&quot;</span>].empty?
271
+ job_data[<span class="ruby-string">&quot;@output&quot;</span>] = <span class="ruby-constant">BabelHelper</span>.generate_output_location(job_data)
432
272
  end
273
+ <span class="ruby-constant">BabelHelper</span>.ensure_output_does_not_exist(job_data)
433
274
 
434
- if job_data[<span class="ruby-string">&quot;@output&quot;</span>][0].chr != <span class="ruby-string">&quot;/&quot;</span>
435
- abort(<span class="ruby-string">&quot;Job output must begin with a slash ('/')&quot;</span>)
275
+ if job_data[<span class="ruby-string">&quot;@is_remote&quot;</span>]
276
+ <span class="ruby-constant">BabelHelper</span>.validate_inputs(job_data)
277
+ else
278
+ <span class="ruby-constant">BabelHelper</span>.put_code(job_data)
279
+ <span class="ruby-constant">BabelHelper</span>.put_inputs(job_data)
436
280
  end
437
- end
438
-
439
- return job_data
440
- end</pre>
441
- </div>
442
-
443
- </div>
444
-
445
-
446
-
447
-
448
- </div>
449
-
450
-
451
- <div id="get_std_out_and_err-method" class="method-detail ">
452
- <a name="method-i-get_std_out_and_err"></a>
453
-
454
-
455
- <div class="method-heading">
456
- <span class="method-name">get_std_out_and_err</span><span
457
- class="method-args">(location)</span>
458
- <span class="method-click-advice">click to toggle source</span>
459
- </div>
460
-
461
-
462
- <div class="method-description">
463
-
464
- <p>This method returns a hash containing the standard out and standard error
465
- from a completed job, as well as a result field that indicates whether or
466
- not the job completed successfully (success = no errors).</p>
467
-
468
-
469
-
470
- <div class="method-source-code"
471
- id="get_std_out_and_err-source">
472
- <pre>
473
- <span class="ruby-comment"># File lib/neptune.rb, line 330</span>
474
- def get_std_out_and_err(location)
475
- result = {}
476
281
 
477
- out = <span class="ruby-constant">File</span>.open(&quot;#{location}/compile_out&quot;) { |f| f.read.chomp! }
478
- result[:out] = out
479
-
480
- err = <span class="ruby-constant">File</span>.open(&quot;#{location}/compile_err&quot;) { |f| f.read.chomp! }
481
- result[:err] = err
482
-
483
- if result[:err]
484
- result[:result] = :failure
485
- else
486
- result[:result] = :success
487
- end
488
-
489
- return result
282
+ <span class="ruby-constant">BabelHelper</span>.run_job(job_data)
283
+ <span class="ruby-comment"># So actually retrieving the job's output is done via a promise, so only if</span>
284
+ <span class="ruby-comment"># the user actually uses the value do we actually go and poll for output.</span>
285
+ <span class="ruby-comment"># The running of the job is done above, outside of the promise, so</span>
286
+ <span class="ruby-comment"># the job is always run, regardless of whether or not we get its output.</span>
287
+ <span class="ruby-constant">BabelHelper</span>.wait_and_get_output(job_data)
288
+ <span class="ruby-comment"># promise { BabelHelper.wait_and_get_output(job_data) }</span>
289
+ }
490
290
  end</pre>
491
291
  </div>
492
292
 
@@ -512,7 +312,7 @@ end</pre>
512
312
  <div class="method-description">
513
313
 
514
314
  <p>This method is the heart of Neptune - here, we take blocks of code that the
515
- user has written and convert them into HPC job requests. At a high level,
315
+ user has written and convert them into HPC job requests. At a high level,
516
316
  the user can request to run a job, retrieve a job’s output, or modify the
517
317
  access policy (ACL) for the output of a job. By default, job data is
518
318
  private, but a Neptune job can be used to set it to public later (and
@@ -523,15 +323,14 @@ vice-versa).</p>
523
323
  <div class="method-source-code"
524
324
  id="neptune-source">
525
325
  <pre>
526
- <span class="ruby-comment"># File lib/neptune.rb, line 419</span>
326
+ <span class="ruby-comment"># File lib/neptune.rb, line 485</span>
527
327
  def neptune(params)
528
- puts <span class="ruby-string">&quot;Received a request to run a job.&quot;</span>
529
- puts params[:type]
328
+ <span class="ruby-constant">Kernel</span>.puts <span class="ruby-string">&quot;Received a request to run a job.&quot;</span>
329
+ <span class="ruby-constant">Kernel</span>.puts params[:type]
530
330
 
531
- job_data = get_job_data(params)
532
- validate_storage_params(job_data)
533
- puts &quot;job data = #{job_data.inspect}&quot;
534
- do_preprocessing(job_data)
331
+ job_data = <span class="ruby-constant">NeptuneHelper</span>.get_job_data(params)
332
+ <span class="ruby-constant">NeptuneHelper</span>.validate_storage_params(job_data)
333
+ <span class="ruby-constant">Kernel</span>.puts &quot;job data = #{job_data.inspect}&quot;
535
334
  keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>]
536
335
 
537
336
  shadow_ip = <span class="ruby-constant">CommonFunctions</span>.get_from_yaml(keyname, :shadow)
@@ -539,463 +338,9 @@ def neptune(params)
539
338
  ssh_key = <span class="ruby-constant">File</span>.expand_path(&quot;~/.appscale/#{keyname}.key&quot;)
540
339
  ssh_args = &quot;-i ~/.appscale/#{keyname}.key -o StrictHostkeyChecking=no &quot;
541
340
 
542
- return run_job(job_data, ssh_args, shadow_ip, secret)
543
- end</pre>
544
- </div>
545
-
546
- </div>
547
-
548
-
549
-
550
-
551
- </div>
552
-
553
-
554
- <div id="preprocess_compile-method" class="method-detail ">
555
- <a name="method-i-preprocess_compile"></a>
556
-
557
-
558
- <div class="method-heading">
559
- <span class="method-name">preprocess_compile</span><span
560
- class="method-args">(job_data, shell=Kernel.method(:`))</span>
561
- <span class="method-click-advice">click to toggle source</span>
562
- </div>
563
-
564
-
565
- <div class="method-description">
566
-
567
- <p>This preprocessing method copies over the user’s code to the Shadow node
568
- so that it can be compiled there. A future version of this method may also
569
- copy over libraries as well.</p>
570
-
571
-
572
-
573
- <div class="method-source-code"
574
- id="preprocess_compile-source">
575
- <pre>
576
- <span class="ruby-comment"># File lib/neptune.rb, line 65</span>
577
- def preprocess_compile(job_data, shell=<span class="ruby-constant">Kernel</span>.method(:`))
578
- code = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@code&quot;</span>])
579
- if !<span class="ruby-constant">File</span>.exists?(code)
580
- abort(&quot;The source file #{code} does not exist.&quot;)
581
- end
582
-
583
- suffix = code.split(<span class="ruby-string">'/'</span>)[-1]
584
- dest = &quot;/tmp/#{suffix}&quot;
585
- keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>]
586
- shadow_ip = <span class="ruby-constant">CommonFunctions</span>.get_from_yaml(keyname, :shadow)
587
-
588
- ssh_args = &quot;-i ~/.appscale/#{keyname}.key -o StrictHostkeyChecking=no root@#{shadow_ip}&quot;
589
- remove_dir = &quot;ssh #{ssh_args} 'rm -rf #{dest}' 2&gt;&amp;1&quot;
590
- puts remove_dir
591
- shell.call(remove_dir)
592
-
593
- <span class="ruby-constant">CommonFunctions</span>.scp_to_shadow(code, dest, keyname, is_dir=true)
594
-
595
- job_data[<span class="ruby-string">&quot;@code&quot;</span>] = dest
596
- end</pre>
597
- </div>
598
-
599
- </div>
600
-
601
-
602
-
603
-
604
- </div>
605
-
606
-
607
- <div id="preprocess_erlang-method" class="method-detail ">
608
- <a name="method-i-preprocess_erlang"></a>
609
-
610
-
611
- <div class="method-heading">
612
- <span class="method-name">preprocess_erlang</span><span
613
- class="method-args">(job_data, file=File, common_functions=CommonFunctions)</span>
614
- <span class="method-click-advice">click to toggle source</span>
615
- </div>
616
-
617
-
618
- <div class="method-description">
619
-
620
-
621
-
622
-
623
-
624
- <div class="method-source-code"
625
- id="preprocess_erlang-source">
626
- <pre>
627
- <span class="ruby-comment"># File lib/neptune.rb, line 86</span>
628
- def preprocess_erlang(job_data, file=<span class="ruby-constant">File</span>, common_functions=<span class="ruby-constant">CommonFunctions</span>)
629
- if !job_data[<span class="ruby-string">&quot;@code&quot;</span>]
630
- abort(<span class="ruby-string">&quot;When running Erlang jobs, :code must be specified.&quot;</span>)
631
- end
632
-
633
- source_code = file.expand_path(job_data[<span class="ruby-string">&quot;@code&quot;</span>])
634
- if !file.exists?(source_code)
635
- abort(&quot;The specified code, #{job_data['@code']},&quot; +
636
- <span class="ruby-string">&quot; didn't exist. Please specify one that exists and try again&quot;</span>)
637
- end
638
- dest_code = <span class="ruby-string">&quot;/tmp/&quot;</span>
639
-
640
- keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>]
641
- common_functions.scp_to_shadow(source_code, dest_code, keyname)
642
- end</pre>
643
- </div>
644
-
645
- </div>
646
-
647
-
648
-
649
-
650
- </div>
651
-
652
-
653
- <div id="preprocess_mpi-method" class="method-detail ">
654
- <a name="method-i-preprocess_mpi"></a>
655
-
656
-
657
- <div class="method-heading">
658
- <span class="method-name">preprocess_mpi</span><span
659
- class="method-args">(job_data)</span>
660
- <span class="method-click-advice">click to toggle source</span>
661
- </div>
662
-
663
-
664
- <div class="method-description">
665
-
666
- <p>This preprocessing method verifies that the user specified the number of
667
- nodes to use. If they also specified the number of processes to use, we
668
- also verify that this value is at least as many as the number of nodes
669
- (that is, nodes can’t be underprovisioned in MPI).</p>
670
-
671
-
672
-
673
- <div class="method-source-code"
674
- id="preprocess_mpi-source">
675
- <pre>
676
- <span class="ruby-comment"># File lib/neptune.rb, line 106</span>
677
- def preprocess_mpi(job_data)
678
- if !job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>]
679
- abort(<span class="ruby-string">&quot;When running MPI jobs, :nodes_to_use must be specified.&quot;</span>)
680
- end
681
-
682
- if !job_data[<span class="ruby-string">&quot;@procs_to_use&quot;</span>]
683
- abort(<span class="ruby-string">&quot;When running MPI jobs, :procs_to_use must be specified.&quot;</span>)
684
- end
685
-
686
- if job_data[<span class="ruby-string">&quot;@procs_to_use&quot;</span>]
687
- p = job_data[<span class="ruby-string">&quot;@procs_to_use&quot;</span>]
688
- n = job_data[<span class="ruby-string">&quot;@nodes_to_use&quot;</span>]
689
- if p &lt; n
690
- abort(<span class="ruby-string">&quot;When specifying both :procs_to_use and :nodes_to_use&quot;</span> +
691
- <span class="ruby-string">&quot;, :procs_to_use must be at least as large as :nodes_to_use. Please &quot;</span> +
692
- &quot;change this and try again. You specified :procs_to_use = #{p} and&quot; +
693
- &quot;:nodes_to_use = #{n}.&quot;)
694
- end
695
- end
696
-
697
- if job_data[<span class="ruby-string">&quot;@argv&quot;</span>]
698
- argv = job_data[<span class="ruby-string">&quot;@argv&quot;</span>]
699
- if argv.class != <span class="ruby-constant">String</span> and argv.class != <span class="ruby-constant">Array</span>
700
- abort(<span class="ruby-string">&quot;The value specified for :argv must be either a String or Array&quot;</span>)
701
- end
702
-
703
- if argv.class == <span class="ruby-constant">Array</span>
704
- job_data[<span class="ruby-string">&quot;@argv&quot;</span>] = argv.join(<span class="ruby-string">' '</span>)
705
- end
706
- end
707
-
708
- return job_data
709
- end</pre>
710
- </div>
711
-
712
- </div>
713
-
714
-
715
-
716
-
717
- </div>
718
-
719
-
720
- <div id="preprocess_ssa-method" class="method-detail ">
721
- <a name="method-i-preprocess_ssa"></a>
722
-
723
-
724
- <div class="method-heading">
725
- <span class="method-name">preprocess_ssa</span><span
726
- class="method-args">(job_data)</span>
727
- <span class="method-click-advice">click to toggle source</span>
728
- </div>
729
-
730
-
731
- <div class="method-description">
732
-
733
- <p>This preprocessing method verifies that the user specified the number of
734
- trajectories to run, via either :trajectories or :simulations. Both should
735
- not be specified - only one or the other, and regardless of which they
736
- specify, convert it to be :trajectories.</p>
737
-
738
-
739
-
740
- <div class="method-source-code"
741
- id="preprocess_ssa-source">
742
- <pre>
743
- <span class="ruby-comment"># File lib/neptune.rb, line 144</span>
744
- def preprocess_ssa(job_data)
745
- if job_data[<span class="ruby-string">&quot;@simulations&quot;</span>] and job_data[<span class="ruby-string">&quot;@trajectories&quot;</span>]
746
- abort(<span class="ruby-string">&quot;Both :simulations and :trajectories cannot be specified - use one&quot;</span> +
747
- <span class="ruby-string">&quot; or the other.&quot;</span>)
748
- end
749
-
750
- if job_data[<span class="ruby-string">&quot;@simulations&quot;</span>]
751
- job_data[<span class="ruby-string">&quot;@trajectories&quot;</span>] = job_data[<span class="ruby-string">&quot;@simulations&quot;</span>]
752
- job_data.delete(<span class="ruby-string">&quot;@simulations&quot;</span>)
753
- end
754
-
755
- if !job_data[<span class="ruby-string">&quot;@trajectories&quot;</span>]
756
- abort(<span class="ruby-string">&quot;:trajectories needs to be specified when running ssa jobs&quot;</span>)
757
- end
758
-
759
- return job_data
760
- end</pre>
761
- </div>
762
-
763
- </div>
764
-
765
-
766
-
767
-
768
- </div>
769
-
770
-
771
- <div id="run_job-method" class="method-detail ">
772
- <a name="method-i-run_job"></a>
773
-
774
-
775
- <div class="method-heading">
776
- <span class="method-name">run_job</span><span
777
- class="method-args">(job_data, ssh_args, shadow_ip, secret, controller=AppControllerClient, file=File)</span>
778
- <span class="method-click-advice">click to toggle source</span>
779
- </div>
780
-
781
-
782
- <div class="method-description">
783
-
784
- <p>This method actually runs the Neptune job, given information about the job
785
- as well as information about the node to send the request to.</p>
786
-
787
-
788
-
789
- <div class="method-source-code"
790
- id="run_job-source">
791
- <pre>
792
- <span class="ruby-comment"># File lib/neptune.rb, line 376</span>
793
- def run_job(job_data, ssh_args, shadow_ip, secret,
794
- controller=<span class="ruby-constant">AppControllerClient</span>, file=<span class="ruby-constant">File</span>)
795
- controller = controller.new(shadow_ip, secret)
796
-
797
- <span class="ruby-comment"># TODO - right now the job is assumed to succeed in many cases</span>
798
- <span class="ruby-comment"># need to investigate the various failure scenarios</span>
799
- result = { :result =&gt; :success }
800
-
801
- case job_data[<span class="ruby-string">&quot;@type&quot;</span>]
802
- when <span class="ruby-string">&quot;input&quot;</span>
803
- result = get_input(job_data, ssh_args, shadow_ip, controller, file)
804
- when <span class="ruby-string">&quot;output&quot;</span>
805
- result[:output] = controller.get_output(job_data)
806
- when <span class="ruby-string">&quot;get-acl&quot;</span>
807
- job_data[<span class="ruby-string">&quot;@type&quot;</span>] = <span class="ruby-string">&quot;acl&quot;</span>
808
- result[:acl] = controller.get_acl(job_data)
809
- when <span class="ruby-string">&quot;set-acl&quot;</span>
810
- job_data[<span class="ruby-string">&quot;@type&quot;</span>] = <span class="ruby-string">&quot;acl&quot;</span>
811
- result[:acl] = controller.set_acl(job_data)
812
- when <span class="ruby-string">&quot;compile&quot;</span>
813
- result = compile_code(job_data, ssh_args, shadow_ip)
814
- when <span class="ruby-string">&quot;cicero&quot;</span>
815
- upload_app_for_cicero(job_data)
816
- msg = controller.start_neptune_job(job_data)
817
- result[:msg] = msg
818
- result[:result] = :failure if result[:msg] !~ <span class="ruby-regexp">/job is now running\Z/</span>
819
- else
820
- msg = controller.start_neptune_job(job_data)
821
- result[:msg] = msg
822
- result[:result] = :failure if result[:msg] !~ <span class="ruby-regexp">/job is now running\Z/</span>
823
- end
824
-
825
- return result
826
- end</pre>
827
- </div>
828
-
829
- </div>
830
-
831
-
832
-
833
-
834
- </div>
835
-
836
-
837
- <div id="upload_app_for_cicero-method" class="method-detail ">
838
- <a name="method-i-upload_app_for_cicero"></a>
839
-
840
-
841
- <div class="method-heading">
842
- <span class="method-name">upload_app_for_cicero</span><span
843
- class="method-args">(job_data)</span>
844
- <span class="method-click-advice">click to toggle source</span>
845
- </div>
846
-
847
-
848
- <div class="method-description">
849
-
850
-
851
-
852
-
853
-
854
- <div class="method-source-code"
855
- id="upload_app_for_cicero-source">
856
- <pre>
857
- <span class="ruby-comment"># File lib/neptune.rb, line 348</span>
858
- def upload_app_for_cicero(job_data)
859
- if !job_data[<span class="ruby-string">&quot;@app&quot;</span>]
860
- puts <span class="ruby-string">&quot;No app specified, not uploading...&quot;</span>
861
- return
862
- end
863
-
864
- app_location = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@app&quot;</span>])
865
- if !<span class="ruby-constant">File</span>.exists?(app_location)
866
- abort(&quot;The app you specified, #{app_location}, does not exist.&quot; +
867
- <span class="ruby-string">&quot;Please specify one that does and try again.&quot;</span>)
868
- end
869
-
870
- keyname = job_data[<span class="ruby-string">&quot;@keyname&quot;</span>] || <span class="ruby-string">&quot;appscale&quot;</span>
871
- if job_data[<span class="ruby-string">&quot;@appscale_tools&quot;</span>]
872
- upload_app = <span class="ruby-constant">File</span>.expand_path(job_data[<span class="ruby-string">&quot;@appscale_tools&quot;</span>]) +
873
- <span class="ruby-constant">File</span>::<span class="ruby-constant">SEPARATOR</span> + <span class="ruby-string">&quot;bin&quot;</span> + <span class="ruby-constant">File</span>::<span class="ruby-constant">SEPARATOR</span> + <span class="ruby-string">&quot;appscale-upload-app&quot;</span>
874
- else
875
- upload_app = <span class="ruby-string">&quot;appscale-upload-app&quot;</span>
876
- end
877
-
878
- puts &quot;Uploading AppEngine app at #{app_location}&quot;
879
- upload_command = &quot;#{upload_app} --file #{app_location} --test --keyname #{keyname}&quot;
880
- puts upload_command
881
- puts `#{upload_command}`
882
- end</pre>
883
- </div>
884
-
885
- </div>
886
-
887
-
888
-
889
-
890
- </div>
891
-
892
-
893
- <div id="validate_storage_params-method" class="method-detail ">
894
- <a name="method-i-validate_storage_params"></a>
895
-
896
-
897
- <div class="method-heading">
898
- <span class="method-name">validate_storage_params</span><span
899
- class="method-args">(job_data)</span>
900
- <span class="method-click-advice">click to toggle source</span>
901
- </div>
902
-
903
-
904
- <div class="method-description">
905
-
906
-
907
-
908
-
909
-
910
- <div class="method-source-code"
911
- id="validate_storage_params-source">
912
- <pre>
913
- <span class="ruby-comment"># File lib/neptune.rb, line 206</span>
914
- def validate_storage_params(job_data)
915
- if !job_data[<span class="ruby-string">&quot;@storage&quot;</span>]
916
- job_data[<span class="ruby-string">&quot;@storage&quot;</span>] = <span class="ruby-string">&quot;appdb&quot;</span>
917
- end
918
-
919
- storage = job_data[<span class="ruby-string">&quot;@storage&quot;</span>]
920
- if !<span class="ruby-constant">ALLOWED_STORAGE_TYPES</span>.include?(storage)
921
- abort(&quot;Supported storage types are #{ALLOWED_STORAGE_TYPES.join(', ')}&quot; +
922
- &quot; - we do not support #{storage}.&quot;)
923
- end
924
-
925
- <span class="ruby-comment"># Our implementation for storing / retrieving via Google Storage</span>
926
- <span class="ruby-comment"># and Walrus uses</span>
927
- <span class="ruby-comment"># the same library as we do for S3 - so just tell it that it's S3</span>
928
- if storage == <span class="ruby-string">&quot;gstorage&quot;</span> or storage == <span class="ruby-string">&quot;walrus&quot;</span>
929
- storage = <span class="ruby-string">&quot;s3&quot;</span>
930
- job_data[<span class="ruby-string">&quot;@storage&quot;</span>] = <span class="ruby-string">&quot;s3&quot;</span>
931
- end
932
-
933
- if storage == <span class="ruby-string">&quot;s3&quot;</span>
934
- [<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|
935
- if job_data[&quot;@#{item}&quot;]
936
- puts &quot;Using specified #{item}&quot;
937
- else
938
- if <span class="ruby-constant">ENV</span>[item]
939
- puts &quot;Using #{item} from environment&quot;
940
- job_data[&quot;@#{item}&quot;] = <span class="ruby-constant">ENV</span>[item]
941
- else
942
- abort(&quot;When storing data to S3, #{item} must be specified or be in &quot; +
943
- <span class="ruby-string">&quot;your environment. Please do so and try again.&quot;</span>)
944
- end
945
- end
946
- }
947
- end
948
-
949
- return job_data
950
- end</pre>
951
- </div>
952
-
953
- </div>
954
-
955
-
956
-
957
-
958
- </div>
959
-
960
-
961
- <div id="wait_for_compilation_to_finish-method" class="method-detail ">
962
- <a name="method-i-wait_for_compilation_to_finish"></a>
963
-
964
-
965
- <div class="method-heading">
966
- <span class="method-name">wait_for_compilation_to_finish</span><span
967
- class="method-args">(ssh_args, shadow_ip, compiled_location, shell=Kernel.method(:`))</span>
968
- <span class="method-click-advice">click to toggle source</span>
969
- </div>
970
-
971
-
972
- <div class="method-description">
973
-
974
- <p>This method waits for AppScale to finish compiling the user’s code,
975
- indicated by AppScale copying the finished code to a pre-determined
976
- location.</p>
977
-
978
-
979
-
980
- <div class="method-source-code"
981
- id="wait_for_compilation_to_finish-source">
982
- <pre>
983
- <span class="ruby-comment"># File lib/neptune.rb, line 280</span>
984
- def wait_for_compilation_to_finish(ssh_args, shadow_ip, compiled_location,
985
- shell=<span class="ruby-constant">Kernel</span>.method(:`))
986
- loop {
987
- ssh_command = &quot;ssh #{ssh_args} root@#{shadow_ip} 'ls #{compiled_location}' 2&gt;&amp;1&quot;
988
- puts ssh_command
989
- ssh_result = shell.call(ssh_command)
990
- puts &quot;result was [#{ssh_result}]&quot;
991
- if ssh_result =~ <span class="ruby-regexp">/No such file or directory/</span>
992
- puts <span class="ruby-string">&quot;Still waiting for code to be compiled...&quot;</span>
993
- else
994
- puts &quot;compilation complete! Copying compiled code to #{copy_to}&quot;
995
- return
996
- end
997
- sleep(5)
998
- }
341
+ controller = <span class="ruby-constant">AppControllerClient</span>.new(shadow_ip, secret)
342
+ <span class="ruby-constant">NeptuneHelper</span>.do_preprocessing(job_data, controller)
343
+ return <span class="ruby-constant">NeptuneHelper</span>.run_job(job_data, ssh_args, shadow_ip, secret)
999
344
  end</pre>
1000
345
  </div>
1001
346