@@ -18,20 +18,24 @@ use LWP::UserAgent;
18
18
use REST::Client;
19
19
use Bio::KBase::AppService::AppConfig ' :all' ;
20
20
21
+ use Getopt::Long::Descriptive;
21
22
use base ' Class::Accessor' ;
22
23
23
24
use Data::Dumper;
24
25
25
- __PACKAGE__ -> mk_accessors(qw( callback donot_create_job_result donot_create_result_folder
26
+ __PACKAGE__ -> mk_accessors(qw( execute_callback preflight_callback donot_create_job_result donot_create_result_folder
26
27
workspace_url workspace params app_definition result_folder
28
+ app_def params proc_params stdout_file stderr_file
29
+ hostname json
27
30
task_id app_service_url) );
28
31
29
32
sub new
30
33
{
31
- my ($class , $callback ) = @_ ;
34
+ my ($class , $execute_callback , $preflight_callback ) = @_ ;
32
35
33
36
my $self = {
34
- callback => $callback ,
37
+ execute_callback => $execute_callback ,
38
+ preflight_callback => $preflight_callback ,
35
39
};
36
40
return bless $self , $class ;
37
41
}
@@ -48,32 +52,28 @@ sub run
48
52
{
49
53
my ($self , $args ) = @_ ;
50
54
51
- #
52
- # Hack to finding task id.
53
- #
54
- my $host = ` hostname -f` ;
55
- $host = ` hostname` if !$host ;
56
- chomp $host ;
55
+ $self -> set_task_id();
57
56
58
- my $task_id = ' TBD' ;
59
- if ($ENV {AWE_TASK_ID })
60
- {
61
- $task_id = $ENV {AWE_TASK_ID };
62
- }
63
- elsif ($ENV {PWD } =~ / ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})_\d +_\d +$ /i )
64
- {
65
- $task_id = $1 ;
66
- }
67
- else
57
+ my $opt ;
58
+ do {
59
+ local @ARGV = @$args ;
60
+ ($opt , my $usage ) = describe_options(" %c %o app-service-url app-definition.json param-values.json [stdout-file stderr-file]" ,
61
+ [" preflight" , " Run the app in preflight mode. Print a JSON object representing the expected runtime, requested CPU count, and memory use for this application invocation." ],
62
+ [" help|h" , " Show this help message." ]);
63
+ print ($usage -> text), exit (0) if $opt -> help;
64
+ die ($usage -> text) unless @ARGV == 3 or @ARGV == 5;
65
+
66
+ my $appserv_url = shift @ARGV ;
67
+ $self -> app_service_url($appserv_url );
68
+ $args = [@ARGV ];
69
+ };
70
+
71
+ $self -> process_parameters($args );
72
+
73
+ if ($opt -> preflight)
68
74
{
69
- $task_id = " UNK- $host - $$ " ;
75
+ return $self -> run_preflight() ;
70
76
}
71
- $self -> task_id($task_id );
72
-
73
- @$args == 3 or @$args == 5 or die " Usage: $0 app-service-url app-definition.json param-values.json [stdout-file stderr-file]\n " ;
74
-
75
- my $appserv_url = shift @$args ;
76
- $self -> app_service_url($appserv_url );
77
77
78
78
#
79
79
# If we are running at the terminal, do not set up this infrastructure.
@@ -87,7 +87,7 @@ sub run
87
87
88
88
my $ua = LWP::UserAgent-> new();
89
89
my $rest = REST::Client-> new();
90
- $rest -> setHost(" $appserv_url / $ task_id" );
90
+ $rest -> setHost($self -> appservice_url . " / " . $self -> task_id);
91
91
$self -> {rest } = $rest ;
92
92
93
93
my $sel = IO::Select-> new();
@@ -110,7 +110,7 @@ sub run
110
110
}
111
111
112
112
$self -> write_block(" pid" , $pid );
113
- $self -> write_block(" hostname" , $host );
113
+ $self -> write_block(" hostname" , $self -> hostname );
114
114
115
115
$stdout_pipe -> reader();
116
116
$stderr_pipe -> reader();
@@ -166,17 +166,59 @@ sub run
166
166
return $rc ;
167
167
}
168
168
169
+ sub run_preflight
170
+ {
171
+ my ($self ) = @_ ;
172
+
173
+ return unless $self -> preflight_callback();
174
+
175
+ $self -> preflight_callback()-> ($self , $self -> app_def, $self -> params, $self -> proc_params);
176
+ }
177
+
178
+ sub set_task_id
179
+ {
180
+ my ($self ) = @_ ;
181
+
182
+ #
183
+ # Hack to finding task id.
184
+ #
185
+ my $host = ` hostname -f` ;
186
+ $host = ` hostname` if !$host ;
187
+ chomp $host ;
188
+ $self -> hostname($host );
189
+
190
+ my $task_id = ' TBD' ;
191
+ if ($ENV {AWE_TASK_ID })
192
+ {
193
+ $task_id = $ENV {AWE_TASK_ID };
194
+ }
195
+ elsif ($ENV {SLURM_JOB_ID })
196
+ {
197
+ $task_id = $ENV {SLURM_JOB_ID };
198
+ }
199
+ elsif ($ENV {PWD } =~ / ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})_\d +_\d +$ /i )
200
+ {
201
+ $task_id = $1 ;
202
+ }
203
+ else
204
+ {
205
+ $task_id = " UNK-$host -$$ " ;
206
+ }
207
+ $self -> task_id($task_id );
208
+ }
209
+
169
210
sub write_block
170
211
{
171
212
my ($self , $path , $data ) = @_ ;
172
213
$self -> {rest }-> POST($path , $data );
173
214
}
174
215
175
- sub subproc_run
216
+ sub process_parameters
176
217
{
177
218
my ($self , $args ) = @_ ;
178
219
179
220
my $json = JSON::XS-> new-> pretty(1)-> relaxed(1);
221
+ $self -> json($json );
180
222
181
223
my $app_def_file = shift @$args ;
182
224
my $params_file = shift @$args ;
@@ -185,8 +227,31 @@ sub subproc_run
185
227
my $stderr_file = shift @$args ;
186
228
187
229
my $app_def = $json -> decode(scalar read_file($app_def_file ));
188
- my $params = $json -> decode(scalar read_file($params_file ));
189
230
231
+ my $params_txt ;
232
+ my $params_from_cmdline ;
233
+ my $file_error ;
234
+ if (open (my $fh , " <" , $params_file ))
235
+ {
236
+ $params_txt = read_file($fh );
237
+ }
238
+ else
239
+ {
240
+ $file_error = $! ;
241
+ # for immediate-mode testing, allow specification of params as inline text.
242
+ $params_from_cmdline = 1;
243
+ $params_txt = $params_file ;
244
+ }
245
+
246
+ my $params = eval { $json -> decode($params_txt ); };
247
+ if (!$params )
248
+ {
249
+ die " Error reading or parsing params (file error $! ; parse error $@ )" ;
250
+ }
251
+ if (ref ($params ) ne ' HASH' )
252
+ {
253
+ die " Invalid parameters (must be JSON object)" ;
254
+ }
190
255
#
191
256
# Preprocess parameters to create hash of named parameters, looking for
192
257
# missing required values and filling in defaults.
@@ -224,68 +289,63 @@ sub subproc_run
224
289
{
225
290
die " Errors found in parameter processing:\n " . join (" \n " , @errors ), " \n " ;
226
291
}
292
+
293
+ $self -> app_def($app_def );
294
+ $self -> params($params );
295
+ $self -> proc_params(\%proc_param );
296
+ $self -> stdout_file($stdout_file );
297
+ $self -> stderr_file($stderr_file );
227
298
299
+ }
300
+
301
+ sub subproc_run
302
+ {
303
+ my ($self , $args ) = @_ ;
304
+
228
305
my $ws = Bio::P3::Workspace::WorkspaceClientExt-> new($self -> workspace_url);
229
306
$self -> {workspace } = $ws ;
230
- $self -> {params } = \%proc_param ;
231
- $self -> {app_definition } = $app_def ;
232
307
233
308
if (!defined ($self -> donot_create_result_folder()) || $self -> donot_create_result_folder() == 0) {
234
309
$self -> create_result_folder();
235
310
}
236
-
237
- my $host = ` hostname -f` ;
238
- $host = ` hostname` if !$host ;
239
- chomp $host ;
240
311
my $start_time = gettimeofday;
241
312
242
313
my $job_output ;
243
- if ($stdout_file )
314
+ if ($self -> stdout_file)
244
315
{
245
- my $stdout_fh = IO::File-> new($stdout_file , " w+" );
246
- my $stderr_fh = IO::File-> new($stderr_file , " w+" );
316
+ my $stdout_fh = IO::File-> new($self -> stdout_file, " w+" );
317
+ my $stderr_fh = IO::File-> new($self -> stderr_file, " w+" );
247
318
248
- capture(sub { $job_output = $self -> callback -> ($self , $app_def , $params , \ %proc_param ) } , stdout => $stdout_fh , stderr => $stderr_fh );
319
+ capture(sub { $job_output = $self -> execute_callback -> ($self , $self -> app_def, $self -> params, $self -> proc_params ) } , stdout => $stdout_fh , stderr => $stderr_fh );
249
320
}
250
321
else
251
322
{
252
- $job_output = $self -> callback -> ($self , $app_def , $params , \ %proc_param );
323
+ $job_output = $self -> execute_callback -> ($self , $self -> app_def, $self -> params, $self -> proc_params );
253
324
}
254
325
255
- if (! defined ( $self -> donot_create_result_folder()) || $self -> donot_create_result_folder() == 0 )
326
+ if ($self -> params -> { output_path } && $self -> params -> { output_path } && ! $self -> donot_create_result_folder())
256
327
{
257
328
my $end_time = gettimeofday;
258
329
my $elap = $end_time - $start_time ;
259
330
260
331
my $files = $ws -> ls({ paths => [ $self -> result_folder ], recursive => 1});
261
332
262
- #
263
- # Hack to finding task id.
264
- #
265
- my $task_id = ' TBD' ;
266
- if ($ENV {PWD } =~ / ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})_\d +_\d +$ /i )
267
- {
268
- $task_id = $1 ;
269
- }
270
- else
271
- {
272
- $task_id = " Not found in '$ENV {PWD}'" ;
273
- }
333
+ my $task_id = $self -> task_id;
274
334
275
335
my $job_obj = {
276
336
id => $task_id ,
277
- app => $app_def ,
278
- parameters => \ %proc_param ,
337
+ app => $self -> app_def,
338
+ parameters => $self -> roc_params ,
279
339
start_time => $start_time ,
280
340
end_time => $end_time ,
281
341
elapsed_time => $elap ,
282
- hostname => $host ,
342
+ hostname => $self -> hostname ,
283
343
output_files => [ map { [ $_ -> [2] . $_ -> [0], $_ -> [4] ] } @{$files -> {$self -> result_folder}}],
284
344
job_output => $job_output ,
285
345
};
286
346
287
347
my $file = $self -> params-> {output_path } . " /" . $self -> params-> {output_file };
288
- $ws -> save_data_to_file($json -> encode($job_obj ), {}, $file , ' job_result' ,1);
348
+ $ws -> save_data_to_file($self -> json-> encode($job_obj ), {}, $file , ' job_result' ,1);
289
349
}
290
350
delete $self -> {workspace };
291
351
}
@@ -295,10 +355,15 @@ sub create_result_folder
295
355
{
296
356
my ($self ) = @_ ;
297
357
298
- my $base_folder = $self -> params-> {output_path };
299
- my $result_folder = $base_folder . " /." . $self -> params-> {output_file };
300
- $self -> result_folder($result_folder );
301
- $self -> workspace-> create({overwrite => 1, objects => [[$result_folder , ' folder' , { application_type => $self -> app_definition-> {id }}]]});
358
+ my $params = $self -> params;
359
+
360
+ if ($params -> {output_path } && $params -> {output_file })
361
+ {
362
+ my $base_folder = $params -> {output_path };
363
+ my $result_folder = $base_folder . " /." . $params -> {output_file };
364
+ $self -> result_folder($result_folder );
365
+ $self -> workspace-> create({overwrite => 1, objects => [[$result_folder , ' folder' , { application_type => $self -> app_definition-> {id }}]]});
366
+ }
302
367
}
303
368
304
369
sub token
0 commit comments