File Coverage

blib/lib/HPC/Runner/Command/submit_jobs/Utils/Scheduler/Submit.pm
Criterion Covered Total %
statement 18 109 16.5
branch 0 36 0.0
condition 0 3 0.0
subroutine 6 13 46.1
pod 4 6 66.6
total 28 167 16.7


line stmt bran cond sub pod time code
1             package HPC::Runner::Command::submit_jobs::Utils::Scheduler::Submit;
2              
3 1     1   422 use Moose::Role;
  1         2  
  1         6  
4 1     1   4168 use Cwd;
  1         3  
  1         51  
5 1     1   5 use IPC::Open3;
  1         2  
  1         37  
6 1     1   5 use IO::Select;
  1         2  
  1         29  
7 1     1   5 use Symbol;
  1         2  
  1         50  
8 1     1   5 use Try::Tiny;
  1         2  
  1         867  
9              
10             =head3 process_submit_command
11              
12             splitting this off from the main command
13              
14             DEPRACATED process_batch_command
15              
16             Command that hpcrunner.pl execute_job/execute_array uses
17              
18             =cut
19              
20             sub process_submit_command {
21 0     0 1   my $self = shift;
22 0           my $counter = shift;
23              
24 0           my $command = "";
25              
26             ##TODO Discuss changing the log name to just the jobname
27 0           my $logname = $self->create_log_name($counter);
28 0           $self->jobs->{ $self->current_job }->add_lognames($logname);
29              
30 0           $command = "sleep 20\n";
31 0           $command .= "cd " . getcwd() . "\n";
32 0 0         if ( $self->has_custom_command ) {
33 0           $command .= $self->custom_command . " \\\n";
34             }
35             else {
36 0           $command .= "hpcrunner.pl " . $self->subcommand . " \\\n";
37             }
38              
39 0 0         $command .= "\t--project " . $self->project . " \\\n" if $self->has_project;
40              
41 0           my $batch_index_start = $self->gen_batch_index_str;
42              
43 0           my $log = "";
44 0 0         if ( $self->no_log_json ) {
45 0           $log = "\t--no_log_json \\\n";
46             }
47              
48             $command .=
49             "\t--infile "
50             . $self->cmdfile . " \\\n"
51             . "\t--basedir "
52             . $self->basedir . " \\\n"
53             . "\t--commands "
54             . $self->jobs->{ $self->current_job }->commands_per_node . " \\\n"
55             . "\t--batch_index_start "
56             . $self->gen_batch_index_str . " \\\n"
57             . "\t--procs "
58 0           . $self->jobs->{ $self->current_job }->procs . " \\\n"
59             . "\t--logname "
60             . $logname . " \\\n"
61             . $log
62             . "\t--data_dir "
63             . $self->data_dir . " \\\n"
64             . "\t--process_table "
65             . $self->process_table;
66              
67             #TODO Update metastring to give array index
68             my $metastr =
69             $self->job_stats->create_meta_str( $counter, $self->batch_counter,
70             $self->current_job, $self->use_batches,
71 0           $self->jobs->{ $self->current_job } );
72              
73 0 0         $command .= " \\\n\t" if $metastr;
74 0 0         $command .= $metastr if $metastr;
75              
76 0           my $pluginstr = $self->create_plugin_str;
77 0 0         $command .= $pluginstr if $pluginstr;
78              
79 0           my $version_str = $self->create_version_str;
80 0 0         $command .= $version_str if $version_str;
81              
82 0           $command .= "\n\n";
83 0           return $command;
84             }
85              
86             sub create_log_name {
87 0     0 0   my $self = shift;
88 0           my $counter = shift;
89              
90 0           my $logname;
91              
92 0 0         if ( $self->has_project ) {
93 0           $logname = $self->project . "_" . $counter . "_" . $self->current_job;
94             }
95             else {
96 0           $logname = $counter . "_" . $self->current_job;
97             }
98              
99 0           return $logname;
100             }
101              
102             =head3 create_version_str
103              
104             If there is a version add it
105              
106             =cut
107              
108             #TODO Move to git
109              
110             sub create_version_str {
111 0     0 1   my $self = shift;
112              
113 0           my $version_str = "";
114              
115 0 0 0       if ( $self->has_git && $self->has_version ) {
116 0           $version_str .= " \\\n\t";
117 0           $version_str .= "--version " . $self->version;
118             }
119              
120 0           return $version_str;
121             }
122              
123             =head3 process_template
124              
125             =cut
126              
127             sub process_template {
128 0     0 1   my $self = shift;
129 0           my $counter = shift;
130 0           my $command = shift;
131 0           my $ok = shift;
132 0           my $array_str = shift;
133              
134 0           my $jobname = $self->resolve_project($counter);
135              
136             $self->template->process(
137             $self->jobs->{$self->current_job}->template_file,
138             {
139             JOBNAME => $jobname,
140             USER => $self->user,
141             COMMAND => $command,
142             ARRAY_STR => $array_str,
143             AFTEROK => $ok,
144             MODULES => $self->jobs->{ $self->current_job }->join_modules(' '),
145             OUT => $self->logdir
146             . "/$counter" . "_"
147             . $self->current_job . ".log",
148 0 0         job => $self->jobs->{ $self->current_job },
149             },
150             $self->slurmfile
151             ) || die $self->template->error;
152              
153 0           chmod 0777, $self->slurmfile;
154              
155 0           my $scheduler_id;
156             try {
157 0     0     $scheduler_id = $self->submit_jobs;
158 0           };
159              
160 0 0         if ( defined $scheduler_id ) {
161 0           $self->jobs->{ $self->current_job }->add_scheduler_ids($scheduler_id);
162             }
163             else {
164 0           $self->jobs->{ $self->current_job }->add_scheduler_ids('000xxx');
165             }
166             }
167              
168             =head3 submit_to_scheduler
169              
170             Submit the job to the scheduler.
171              
172             Inputs: self, submit_command (sbatch, qsub, etc)
173              
174             Returns: exitcode, stdout, stderr
175              
176             This subroutine was just about 100% from the following perlmonks discussions. All that I did was add in some logging.
177              
178             http://www.perlmonks.org/?node_id=151886
179              
180             This is probably overkill - but occasionally the scheduler takes longer than we think to exit
181              
182             =cut
183              
184             sub submit_to_scheduler {
185 0     0 1   my $self = shift;
186 0           my $submit_command = shift;
187              
188 0           my ( $infh, $outfh, $errfh, $exitcode, $cmdpid, $stdout, $stderr );
189 0           $errfh = gensym();
190 0           eval {
191              
192 0           $cmdpid = open3( $infh, $outfh, $errfh, $submit_command );
193             };
194 0 0         if ($@) {
195 0           $exitcode = $?;
196 0           $stderr = $@;
197 0           $cmdpid = 0;
198 0           $self->app_log->fatal( 'Cmd failed : ' . $submit_command );
199 0           $self->app_log->fatal($@);
200             }
201              
202 0           $infh->autoflush();
203 0 0         return [ $exitcode, '', $stderr, ] if $exitcode;
204              
205 0           my $sel = new IO::Select; # create a select object
206 0           $sel->add( $outfh, $errfh ); # and add the fhs
207              
208 0           while ( my @ready = $sel->can_read ) {
209 0           foreach my $fh (@ready) { # loop through them
210 0           my $line;
211 0           my $len = sysread $fh, $line, 4096;
212 0 0         next unless defined $len;
213 0 0         if ( $len == 0 ) {
214 0           $sel->remove($fh);
215 0           close($fh);
216             }
217             else { # we read data alright
218 0 0         if ( $fh == $outfh ) {
    0          
219 0           $stdout .= $line;
220             }
221             elsif ( $fh == $errfh ) {
222 0           $stderr .= $line;
223             }
224             }
225             }
226             }
227              
228 0 0         waitpid( $cmdpid, 1 ) if $cmdpid;
229 0           $exitcode = $?;
230              
231 0           $sel->remove($outfh);
232 0           $sel->remove($infh);
233              
234 0           return ( $exitcode, $stdout, $stderr );
235             }
236              
237             sub job_failure {
238 0     0 0   my $self = shift;
239              
240 0           $self->log->warn( "Submit scripts will be written, "
241             . "but will not be submitted to the queue." );
242 0           $self->log->warn(
243             "Any pending jobs that depend upon this job will NOT be submitted to the queue."
244             );
245 0           $self->log->warn(
246             "Please look at your submission scripts in " . $self->outdir );
247 0           $self->log->warn(
248             "And your logs in " . $self->logdir . "\nfor more information" );
249 0           $self->log->warn(
250             "Task dependencies are not calculated until the end of submission ... please to do not exit unless you are sure!"
251             );
252 0           $self->jobs->{ $self->current_job }->submission_failure(1);
253             }
254              
255             1;