File Coverage

blib/lib/HPC/Runner/Slurm.pm
Criterion Covered Total %
statement 45 79 56.9
branch 0 14 0.0
condition n/a
subroutine 15 16 93.7
pod 1 2 50.0
total 61 111 54.9


line stmt bran cond sub pod time code
1             package HPC::Runner::Slurm;
2              
3 2     2   584632 use File::Path qw(make_path remove_tree);
  2         3  
  2         115  
4 2     2   1292 use File::Temp qw/ tempfile tempdir /;
  2         30271  
  2         112  
5 2     2   820 use IO::File;
  2         1306  
  2         215  
6 2     2   832 use IO::Select;
  2         2222  
  2         71  
7 2     2   10 use Cwd;
  2         2  
  2         81  
8 2     2   881 use IPC::Open3;
  2         3909  
  2         86  
9 2     2   8 use Symbol;
  2         2  
  2         73  
10 2     2   951 use Template;
  2         27799  
  2         69  
11 2     2   1447 use Log::Log4perl qw(:easy);
  2         66715  
  2         9  
12 2     2   2372 use DateTime;
  2         159946  
  2         67  
13 2     2   576 use Data::Dumper;
  2         4273  
  2         103  
14 2     2   9 use List::Util qw/shuffle/;
  2         3  
  2         94  
15              
16 2     2   528 use Moose;
  2         286201  
  2         12  
17 2     2   9298 use namespace::autoclean;
  2         3  
  2         11  
18             extends 'HPC::Runner::Scheduler';
19             with 'MooseX::SimpleConfig';
20              
21             # For pretty man pages!
22             $ENV{TERM}='xterm-256color';
23             our $VERSION = '2.58';
24              
25             =head1 NAME
26              
27             HPC::Runner::Slurm - Job Submission to Slurm
28              
29             =head1 SYNOPSIS
30              
31             Please see the indepth documentation at L<HPC::Runner::Usage>.
32              
33             package Main;
34             extends 'HPC::Runner::Slurm';
35              
36             Main->new_with_options(infile => '/path/to/commands');
37              
38             This module is a wrapper around sbatch and can be used to submit arbirtary bash commands to slurm.
39              
40             It has two levels of management. The first is the main sbatch command, and the second is the actual job, which runs commands in parallel, controlled by HPC::Runner::Threads or HPC::Runner::MCE.
41              
42             It supports job dependencies. Put in the command 'wait' to tell slurm that some job or jobs depend on some other jobs completion. Put in the command 'newnode' to tell HPC::Runner::Slurm to submit the job to a new node.
43              
44             The only necessary option is the --infile.
45              
46             =head2 Submit Script
47              
48             cmd1
49             cmd2 && cmd3
50             cmd4 \
51             --option cmd4 \
52             #Tell HPC::Runner::Slurm to put in some job dependencies.
53             wait
54             cmd5
55             #Tell HPC::Runner::Slurm to pass things off to a new node, but this job doesn't depend on the previous
56             newnode
57             cmd6
58              
59             =head2 get_nodes
60              
61             Get the nodes from sinfo if not supplied
62              
63             If the nodelist is supplied partition must be supplied
64              
65             =cut
66              
67             sub BUILD {
68 6     6 0 8 my $self = shift;
69 6         119 $self->logname('slurm_logs');
70 6         73 $self->log($self->init_log);
71             }
72              
73             #sub get_nodes{
74             #my($self) = @_;
75              
76             #$DB::single=2;
77             ## #Fix - had this backwards
78             #return if $self->slurm_decides;
79              
80             #if($self->nodelist && !$self->partition){
81             #print "If you define a nodelist you must define a partition!\n";
82             #die;
83             #}
84              
85             #my @s = `sinfo -r`;
86             #my $href;
87              
88             #foreach my $s (@s) {
89             #my @nodes = ();
90             #my $noderef = [];
91             #next if $s =~ m/^PARTITION/i;
92             #my @t = ($s =~ /(\S+)/g);
93             #$t[0] =~ s/\*//g;
94             #next unless $t[1] =~ m/up/;
95              
96             #my $nodes = $t[5];
97              
98             ##list of nodes
99             #if($nodes =~ m/\[/){
100             #my($n) = ($nodes =~ m/\[(\S+)\]/g);
101             #my @n = split(",", $n);
102              
103             #foreach my $nt (@n) {
104             #if($nt =~ m/-/){
105             #my(@m) = ($nt =~ m/(\d+)-(\d+)/g);
106             #push(@$noderef, ($m[0]..$m[1]));
107             #}
108             #else{
109             #my($m) = ($nt =~ m/(\d+)/g);
110             #push(@$noderef, $m);
111             #}
112             #}
113             #}
114             #else{ #only one node
115             #my($m) = ($nodes =~ m/(\d+)/g);
116             #push(@$noderef, $m);
117             #}
118              
119             #if(exists $href->{$t[0]}){
120             #my $aref = $href->{$t[0]};
121             #push(@$aref, @$noderef) if $noderef;
122             #$href->{$t[0]} = $aref;
123             #}
124             #else{
125             ## $href->{$t[0]} = \@nodes;
126             #$href->{$t[0]} = $noderef;
127             #}
128             #}
129              
130             ##Got the nodes lets find out which partition has the most nodes
131             ##Unless we already have a defined partition, then we don't care
132              
133             #my $holder = 0;
134             #my $bpart;
135              
136             #while(my($part, $nodes) = each %{$href}){
137             #next unless $nodes;
138             #next unless ref($nodes) eq "ARRAY";
139              
140             #@$nodes = map { $part.$_ } @$nodes;
141              
142             #if(scalar @$nodes > $holder){
143             #$holder = scalar @$nodes;
144             #$bpart = $part;
145             #}
146             #}
147              
148             ##Allow for user defined partition and/or partition/nodelist
149             ##Also randomize nodelist so we quit hammering the first node
150             #$DB::single=2;
151              
152             #if($self->partition && $self->nodelist){
153             #$DB::single=2;
154             #return;
155             #}
156             #elsif($self->partition){
157             #$DB::single=2;
158             #my @shuffle = shuffle @{$href->{$self->partition}};
159             ## $self->nodelist($href->{$self->partition});
160             #$self->nodelist(\@shuffle);
161             #return;
162             #}
163              
164             #$self->partition($bpart);
165             ## $self->nodelist($href->{$bpart});
166             #my @shuffle = shuffle @{$href->{$bpart}};
167             #$self->nodelist(\@shuffle);
168             #}
169              
170              
171              
172             =head2 submit_slurm()
173              
174             Submit jobs to slurm queue using sbatch.
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             You can use the script at the top to test the runner. Just download it, make it executable, and put it in the infile as
180              
181             perl command.pl 1
182             perl command.pl 2
183             #so on and so forth
184              
185             =cut
186              
187             sub submit_slurm{
188 0     0 1   my $self = shift;
189              
190 0           my ($infh,$outfh,$errfh);
191 0           $errfh = gensym(); # if you uncomment this line, $errfh will
192             # never be initialized for you and you
193             # will get a warning in the next print
194             # line.
195 0           my $cmdpid;
196 0           eval{
197 0           $cmdpid = open3($infh, $outfh, $errfh, "sbatch ".$self->slurmfile);
198             };
199 0 0         die $@ if $@;
200              
201 0           my $sel = new IO::Select; # create a select object
202 0           $sel->add($outfh,$errfh); # and add the fhs
203              
204 0           my($stdout, $stderr, $jobid);
205              
206 0           while(my @ready = $sel->can_read) {
207 0           foreach my $fh (@ready) { # loop through them
208 0           my $line;
209             # read up to 4096 bytes from this fh.
210 0           my $len = sysread $fh, $line, 4096;
211 0 0         if(not defined $len){
    0          
212             # There was an error reading
213             #$self->log->fatal("Error from child: $!");
214 0           $self->log_main_messages('fatal', "Error from child: $!");
215             } elsif ($len == 0){
216             # Finished reading from this FH because we read
217             # 0 bytes. Remove this handle from $sel.
218 0           $sel->remove($fh);
219 0           next;
220             } else { # we read data alright
221 0 0         if($fh == $outfh) {
    0          
222 0           $stdout .= $line;
223             #$self->log->info($line);
224 0           $self->log_main_messages('debug', $line)
225             } elsif($fh == $errfh) {
226 0           $stderr .= $line;
227             #$self->log->error($line);
228 0           $self->log_main_messages('error', $line);
229             } else {
230             #$self->log->fatal("Shouldn't be here!\n");
231 0           $self->log_main_messages('fatal', "Shouldn't be here!");
232             }
233             }
234             }
235             }
236              
237 0           waitpid($cmdpid, 1);
238 0           my $exitcode = $?;
239              
240 0 0         ($jobid) = $stdout =~ m/Submitted batch job (\d.*)$/ if $stdout;
241 0 0         if(!$jobid){
242 0           print "No job was submitted! Please check to make sure you have loaded modules shared and slurm!\nFull error is:\t$stderr\n$stdout\nEnd Job error";
243 0           print "Submit scripts will be written, but will not be submitted to the queue. Please look at your files in ".$self->outdir." for more information\n";
244 0           $self->submit_to_slurm(0);
245             }
246             else{
247 0           push(@{$self->jobref->[-1]}, $jobid);
  0            
248 0           print "Submitting job ".$self->slurmfile."\n\tWith Slurm jobid $jobid\n";
249             }
250             }
251              
252             =head1 AUTHOR
253              
254             Jillian Rowe, C<< <jillian.e.rowe at gmail.com> >>
255              
256             =head1 BUGS
257              
258             Please report any bugs or feature requests to C<bug-runner-init at rt.cpan.org>, or through
259             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=HPC-Runner-Slurmm>. I will be notified, and then you'll
260             automatically be notified of progress on your bug as I make changes.
261              
262              
263             =head1 SUPPORT
264              
265             You can find documentation for this module with the perldoc command.
266              
267             perldoc HPC::Runner::Slurm
268              
269              
270             You can also look for information at:
271              
272             =over 4
273              
274             =item * RT: CPAN's request tracker (report bugs here)
275              
276             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=HPC-Runner-Slurm>
277              
278             =item * AnnoCPAN: Annotated CPAN documentation
279              
280             L<http://annocpan.org/dist/HPC-Runner-Slurm>
281              
282             =item * CPAN Ratings
283              
284             L<http://cpanratings.perl.org/d/HPC-Runner-Slurm>
285              
286             =item * Search CPAN
287              
288             L<http://search.cpan.org/dist/HPC-Runner-Slurm/>
289              
290             =back
291              
292             =head1 Acknowledgements
293              
294             Before Version 2.41
295              
296             This module was originally developed at and for Weill Cornell Medical
297             College in Qatar within ITS Advanced Computing Team. With approval from
298             WCMC-Q, this information was generalized and put on github, for which
299             the authors would like to express their gratitude.
300              
301             As of Version 2.41:
302              
303             This modules continuing development is supported by NYU Abu Dhabi in the Center for Genomics and Systems Biology.
304             With approval from NYUAD, this information was generalized and put on bitbucket, for which
305             the authors would like to express their gratitude.
306              
307              
308             =head1 LICENSE AND COPYRIGHT
309              
310             Copyright 2014 Weill Cornell Medical College in Qatar.
311              
312             This program is free software; you can redistribute it and/or modify it
313             under the terms of the the Artistic License (2.0). You may obtain a
314             copy of the full license at:
315              
316             L<http://www.perlfoundation.org/artistic_license_2_0>
317              
318             Any use, modification, and distribution of the Standard or Modified
319             Versions is governed by this Artistic License. By using, modifying or
320             distributing the Package, you accept this license. Do not use, modify,
321             or distribute the Package, if you do not accept this license.
322              
323             If your Modified Version has been derived from a Modified Version made
324             by someone other than you, you are nevertheless required to ensure that
325             your Modified Version complies with the requirements of this license.
326              
327             This license does not grant you the right to use any trademark, service
328             mark, tradename, or logo of the Copyright Holder.
329              
330             This license includes the non-exclusive, worldwide, free-of-charge
331             patent license to make, have made, use, offer to sell, sell, import and
332             otherwise transfer the Package with respect to any patent claims
333             licensable by the Copyright Holder that are necessarily infringed by the
334             Package. If you institute patent litigation (including a cross-claim or
335             counterclaim) against any party alleging that the Package constitutes
336             direct or contributory patent infringement, then this Artistic License
337             to you shall terminate on the date that such litigation is filed.
338              
339             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
340             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
341             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
342             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
343             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
344             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
345             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
346             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
347              
348              
349             =cut
350              
351             __PACKAGE__->meta->make_immutable;
352             #use namespace::autoclean;
353              
354             1;