File Coverage

blib/lib/HPC/Runner/Command/submit_jobs/Plugin/Slurm.pm
Criterion Covered Total %
statement 15 42 35.7
branch 0 16 0.0
condition 0 3 0.0
subroutine 5 7 71.4
pod 2 2 100.0
total 22 70 31.4


line stmt bran cond sub pod time code
1             package HPC::Runner::Command::submit_jobs::Plugin::Slurm;
2              
3 1     1   1640 use Moose::Role;
  1         4  
  1         9  
4 1     1   9458 use namespace::autoclean;
  1         5  
  1         15  
5              
6 1     1   106 use File::Temp qw/ tempfile /;
  1         3  
  1         92  
7 1     1   10 use File::Slurp;
  1         5  
  1         126  
8 1     1   11 use File::Spec;
  1         5  
  1         732  
9              
10             with 'HPC::Runner::Command::submit_jobs::Plugin::Role::Log';
11              
12             =head1 HPC::Runner::Command::Plugin::Scheduler::Slurm;
13              
14             Use the SLURM scheduler
15              
16             =cut
17              
18             has 'submit_command' => (
19             is => 'rw',
20             isa => 'Str',
21             default => 'sbatch',
22             );
23              
24             =head3 template_file
25              
26             actual template file
27              
28             One is generated here for you, but you can always supply your own with --template_file /path/to/template
29              
30             #TODO add back PBS support and add SGE support
31              
32             =cut
33              
34             has 'template_file' => (
35             is => 'rw',
36             isa => 'Str',
37             default => sub {
38             my $self = shift;
39              
40             my ( $fh, $filename ) = tempfile();
41              
42             my $tt = <<EOF;
43             #!/usr/bin/env bash
44             #
45             #SBATCH --share
46             #SBATCH --job-name=[% JOBNAME %]
47             #SBATCH --output=[% OUT %]
48             [% IF job.has_account %]
49             #SBATCH --account=[% job.account %]
50             [% END %]
51             [% IF job.has_partition %]
52             #SBATCH --partition=[% job.partition %]
53             [% END %]
54             [% IF job.has_nodes_count %]
55             #SBATCH --nodes=[% job.nodes_count %]
56             [% END %]
57             [% IF job.has_ntasks %]
58             #SBATCH --ntasks=[% job.ntasks %]
59             [% END %]
60             [% IF job.has_cpus_per_task %]
61             #SBATCH --cpus-per-task=[% job.cpus_per_task %]
62             [% END %]
63             [% IF job.has_ntasks_per_node %]
64             #SBATCH --ntasks-per-node=[% job.ntasks_per_node %]
65             [% END %]
66             [% IF job.has_mem %]
67             #SBATCH --mem=[% job.mem %]
68             [% END %]
69             [% IF job.has_walltime %]
70             #SBATCH --time=[% job.walltime %]
71             [% END %]
72             [% IF ARRAY_STR %]
73             #SBATCH --array=[% ARRAY_STR %]
74             [% END %]
75             [% IF AFTEROK %]
76             #SBATCH --dependency=afterok:[% AFTEROK %]
77             [% END %]
78              
79             [% IF MODULES %]
80             module load [% MODULES %]
81             [% END %]
82              
83             [% IF job.has_conda_env %]
84             source activate [% job.conda_env %]
85             [% END %]
86              
87             [% COMMAND %]
88              
89             EOF
90              
91             print $fh $tt;
92             return $filename;
93             },
94             predicate => 'has_template_file',
95             clearer => 'clear_template_file',
96             documentation =>
97             q{Path to Slurm template file if you do not wish to use the default}
98             );
99              
100              
101              
102             =head2 Subroutines
103              
104             =cut
105              
106             =head3 submit_jobs
107              
108             Submit jobs to slurm queue using sbatch.
109              
110             Format is
111              
112             Submitted batch job <job_id>
113              
114             Where <job_id> is just only numeric
115             =cut
116              
117             sub submit_jobs {
118 0     0 1   my $self = shift;
119              
120 0           my ( $exitcode, $stdout, $stderr ) =
121             $self->submit_to_scheduler(
122             $self->submit_command . " " . $self->slurmfile );
123              
124 0           sleep(3);
125              
126 0 0 0       if ( ! defined $exitcode || $exitcode != 0 ) {
127 0           $self->log->warn("Job was not submitted successfully");
128 0 0         $self->log->warn( "STDERR: " . $stderr ) if $stderr;
129 0 0         $self->log->warn( "STDOUT: " . $stdout ) if $stdout;
130             }
131              
132 0 0         my ($jobid) = $stdout =~ m/(\d.*)$/ if $stdout;
133              
134 0 0         if ( !$jobid ) {
135 0           $self->job_failure;
136             }
137             else {
138 0           $self->app_log->info( "Submitted job "
139             . $self->slurmfile
140             . "\n\tWith Slurm jobid $jobid" );
141             }
142              
143 0           return $jobid;
144             }
145              
146             =head3 update_job_deps
147              
148             Update the job dependencies if using job_array (not batches)
149              
150             =cut
151              
152             sub update_job_deps {
153 0     0 1   my $self = shift;
154              
155 0 0         return unless $self->has_array_deps;
156              
157 0           my $array_deps_file = File::Spec->catdir( $self->logdir, 'array_deps.tsv' );
158 0           my $array_log_file = File::Spec->catdir( $self->logdir, 'array_deps.log' );
159              
160 0           while ( my ( $current_task, $v ) = each %{ $self->array_deps } ) {
  0            
161 0           my $dep_tasks = join( ':', @{$v} );
  0            
162 0           my $cmd =
163             "scontrol update job=$current_task depend=afterok:$dep_tasks";
164              
165 0           my ( $exitcode, $stdout, $stderr ) = $self->submit_to_scheduler($cmd);
166 0           write_file(
167             $array_deps_file,
168             { append => 1 },
169             $current_task . "\t" . $dep_tasks . "\n"
170             );
171              
172 0           my $info =
173             "Task Deps:\t"
174             . $current_task . "\t"
175             . $dep_tasks . "\n"
176             . "ExitCode: $exitcode\n";
177 0 0         $info .= "Stderr: $stderr\n" if $stderr;
178 0 0         $info .= "Stdout: $stdout\n" if $stdout;
179              
180 0           write_file( $array_log_file, {append => 1}, $info );
181             }
182             }
183              
184             1;