File Coverage

blib/lib/HPC/Runner/Command/submit_jobs/Plugin/PBS.pm
Criterion Covered Total %
statement 18 61 29.5
branch 0 12 0.0
condition n/a
subroutine 6 9 66.6
pod 3 3 100.0
total 27 85 31.7


line stmt bran cond sub pod time code
1             package HPC::Runner::Command::submit_jobs::Plugin::PBS;
2              
3 1     1   787 use Moose::Role;
  1         3  
  1         6  
4 1     1   4097 use namespace::autoclean;
  1         2  
  1         7  
5              
6 1     1   56 use Data::Dumper;
  1         2  
  1         46  
7 1     1   6 use IPC::Cmd qw[can_run];
  1         2  
  1         34  
8 1     1   4 use Log::Log4perl;
  1         2  
  1         7  
9 1     1   55 use File::Temp qw/ tempfile /;
  1         2  
  1         605  
10              
11             with 'HPC::Runner::Command::submit_jobs::Plugin::Role::Log';
12              
13             =head1 HPC::Runner::Command::Plugin::Scheduler::Slurm;
14              
15             =cut
16              
17             has 'submit_command' => (
18             is => 'rw',
19             isa => 'Str',
20             default => 'qsub',
21             );
22              
23             has 'template_file' => (
24             is => 'rw',
25             isa => 'Str',
26             default => sub {
27             my $self = shift;
28              
29             my ( $fh, $filename ) = tempfile();
30              
31             my $tt = <<EOF;
32             #!/usr/bin/env bash
33             #
34             #PBS -N [% JOBNAME %]
35             [% IF job.has_queue %]
36             #PBS -q [% job.queue %]
37             [% END %]
38             #PBS -l nodes=[% job.nodes_count %]:ppn=[% job.cpus_per_task %]
39             [% IF job.has_walltime %]
40             #PBS -l walltime=[% job.walltime %]
41             [% END %]
42             #PBS -j oe
43             #PBS -o localhost:[% OUT %]
44             [% IF job.has_mem %]
45             #PBS -l mem=[% job.mem %]
46             [% END %]
47             [% IF ARRAY_STR %]
48             [% PERL %]
49             my \$stash = \$context->stash;
50             my \$array_str=\$stash->get('ARRAY_STR');
51             my \@array = split(':', \$array_str);
52             my \$step = \$array[1];
53             \@array = split('-', \$array[0]);
54             if(\$step == 1){
55             print PERLOUT "\n#PBS -J=".\$array[0]."-".\$array[1];
56             }
57             else{
58             my \@new_array = ();
59             for(my \$x=\$array[0]; \$x <= \$array[1]; \$x = \$x + \$step){
60             push(\@new_array, \$x);
61             }
62             print PERLOUT "\n#PBS -J=".join(',', \@new_array);
63             }
64             [% END %]
65             [% END %]
66             EOF
67              
68             if ( $self->use_batches ) {
69             $tt .= <<EOF;
70             [% IF AFTEROK %]
71             #PBS -W depend=afterok:[% AFTEROK %]
72             [% END %]
73             EOF
74             }
75             else {
76             $tt .= <<EOF;
77             [% IF AFTEROK %]
78             [% PERL %]
79             my \$stash = \$context->stash;
80             my \$afterok=\$stash->get('AFTEROK');
81             my \@array = split(':', \$afterok);
82             foreach my \$a (\@array){
83             \$a = \$a."[]";
84             }
85             my \$newafterok = join(':', \@array);
86              
87             print PERLOUT "\n#PBS -W depend=afterokarray:\$newafterok"
88             [% END %]
89             [% END %]
90             EOF
91             }
92              
93             $tt .= <<EOF;
94             [% IF MODULES %]
95             module load [% MODULES %]
96             [% END %]
97              
98             [% IF job.has_conda_env %]
99             source activate [% job.conda_env %]
100             [% END %]
101              
102             [% COMMAND %]
103             EOF
104              
105             print $fh $tt;
106             return $filename;
107             },
108             predicate => 'has_template_file',
109             clearer => 'clear_template_file',
110             documentation =>
111             q{Path to Slurm template file if you do not wish to use the default}
112             );
113              
114             =head2 Subroutines
115              
116             =cut
117              
118             =head3 submit_jobs
119              
120             Submit jobs to slurm queue using PBS.
121              
122             =cut
123              
124             #TODO IF THESE ARE ARRAYS I NEED -W depend=afterokarray:1234[]
125             # -W depend=afterokarray:12345678[5] for a task in the array
126              
127             sub submit_jobs {
128 0     0 1   my $self = shift;
129              
130 0           my ( $exitcode, $stdout, $stderr ) =
131             $self->submit_to_scheduler(
132             $self->submit_command . " " . $self->slurmfile );
133 0           sleep(5);
134              
135 0 0         if ( $exitcode != 0 ) {
136 0           $self->log->fatal("Job was not submitted successfully");
137 0 0         $self->log->warn( "STDERR: " . $stderr ) if $stderr;
138 0 0         $self->log->warn( "STDOUT: " . $stdout ) if $stdout;
139             }
140              
141 0           my $jobid = $stdout;
142              
143             #When submitting job arrays the array will be 1234[].hpc.nyu.edu
144              
145 0 0         if ( !$jobid ) {
146 0           $self->job_failure;
147             }
148             else {
149 0           $self->log->debug(
150             "Submited job " . $self->slurmfile . "\n\tWith PBS jobid $jobid" );
151             }
152              
153 0           return $jobid;
154             }
155              
156             =head3 update_job_deps
157              
158             Update the job dependencies if using job_array (not batches)
159              
160             TODO - not entirely sure this will work...
161              
162             # This is for Torque
163             # http://docs.adaptivecomputing.com/torque/4-1-4/Content/topics/commands/qalter.htm
164             # $tv = $tmp[0] . ' -t '.$tmp[1];
165              
166             =cut
167              
168             sub update_job_deps {
169 0     0 1   my $self = shift;
170              
171 0 0         return unless $self->has_array_deps;
172              
173 0           $self->log->warn('Task dependencies in PBS is still very experimental!');
174 0           $self->log->warn( 'Please raise any problems as an issue at github.' . "\n"
175             . "\thttp://github.com/biosails/HPC-Runner-Command" );
176              
177 0           while ( my ( $current_task, $v ) = each %{ $self->array_deps } ) {
  0            
178              
179 0           my $cmd;
180 0 0         if ( $self->use_batches ) {
181 0           my $dep_tasks = join( ':', @$v );
182 0           $cmd = "qalter $current_task -W depend=afterok:$dep_tasks";
183             }
184             else {
185 0           foreach my $tv ( @{$v} ) {
  0            
186              
187             # The format is schedulerId_arrayIndex
188 0           $tv =~ s/\n//;
189 0           my @tmp = split( '_', $tv );
190              
191 0           my $dep_scheduler_id =
192             $self->parse_pbs_scheduler_id( $tmp[0], $tmp[1] );
193 0           $tv = $dep_scheduler_id;
194             }
195              
196 0           my @tmp = split( '_', $current_task );
197 0           my $current_scheduler_id =
198             $self->parse_pbs_scheduler_id( $tmp[0], $tmp[1] );
199              
200 0           my $dep_tasks = join( ':', @$v );
201 0           $dep_tasks = '"' . $dep_tasks . '"';
202              
203 0           $cmd =
204             "qalter \"$current_scheduler_id\" -W depend=afterokarray:$dep_tasks";
205              
206             }
207              
208 0           $self->submit_to_scheduler($cmd);
209             }
210             }
211              
212             =head3 parse_pbs_scheduler_id
213              
214             PBS tasks look like
215             1234[].hpc.nyu.edu
216             This needs to be split in order to get the task right
217              
218             =cut
219              
220             sub parse_pbs_scheduler_id {
221 0     0 1   my $self = shift;
222 0           my $pbs_scheduler_id = shift;
223 0           my $task = shift;
224              
225 0           my @split_host = split( '\.', $pbs_scheduler_id );
226 0           my $scheduler_id = shift @split_host;
227 0           $scheduler_id =~ s/\[\]//;
228 0           my $host = join( '.', @split_host );
229              
230 0           my $current_scheduler_id = $scheduler_id . '[' . $task . '].' . $host;
231              
232 0           return $current_scheduler_id;
233             }
234              
235             1;