File Coverage

bin/session
Criterion Covered Total %
statement 58 107 54.2
branch 8 44 18.1
condition 9 18 50.0
subroutine 12 18 66.6
pod n/a
total 87 187 46.5


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             #ABSTRACT: Start an interactive session on the cluster
3             #PODNAME: session
4 2     2   211657 use v5.16;
  2         4  
5 2     2   1184 use Getopt::Long;
  2         20896  
  2         20  
6 2     2   290 use File::Basename;
  2         3  
  2         135  
7 2     2   11 use Carp qw(confess);
  2         3  
  2         77  
8 2     2   995 use Term::ANSIColor qw(:constants);
  2         15820  
  2         1656  
9 2     2   400 use FindBin qw($RealBin);
  2         1142  
  2         245  
10 1 50       77253 if (-e "$RealBin/../dist.ini") {
  0         0  
11 1 50       5 say STDERR "[dev mode] Using local lib" if ($ENV{"DEBUG"});
12 2     2   844 use lib "$RealBin/../lib";
  2         1225  
  2         11  
13             }
14 2     2   1031 use NBI::Slurm;
  2         6  
  2         58573  
15 1         61 my $BIN = basename($0);
16              
17 1 50       7 main() unless caller;
18             1;
19              
20             sub main {
21 1     1   3 my $USER = $ENV{USER};
22 1         8 my $config = NBI::Slurm::load_config("$USER/.nbislurm.config");
23 1   50     5 my $DEFAULT_SESSION = $config->{'session'} // "";
24 1   50     13 my $SPECIAL_SESSION = $config->{'special_session'} // "";
25 1   50     4 my $DEFAULT_HOURS = $config->{'session_hours'} // 4;
26 1         2 my $NAME = "session";
27 1   50     3 my $MEM_MB = $config->{'session_memory'} // 1000;
28 1   50     5 my $CORES = $config->{'session_cpus'} // 1;
29 1         1 my $DAYS = 0;
30 1         6 my $OPT_HOURS;
31             my $OPT_TIME;
32 1         0 my $OPT_INTEL;
33 1         0 my $OPT_PARTITION;
34 1         0 my $OPT_SPECIAL;
35 1         0 my $OPT_VERBOSE;
36              
37             GetOptions(
38             'c|threads=i' => \$CORES,
39             'm|mem=s' => \$MEM_MB,
40             'd|days=i' => \$DAYS,
41             'h|hours=i' => \$OPT_HOURS,
42             'T|t|time=s' => \$OPT_TIME,
43             'n|name=s' => \$NAME,
44             'q|queue=s' => \$OPT_PARTITION,
45             's|special' => \$OPT_SPECIAL,
46             'i|intel' => \$OPT_INTEL,
47             'verbose' => \$OPT_VERBOSE,
48 1     1   1318 'version' => sub { say "session v", $NBI::Slurm::VERSION; exit(0); },
  1         95  
49 0     0   0 'help' => sub { usage(); exit(0); },
  0         0  
50 1 0       26 ) or usage(1);
51              
52             # Get memory
53 0         0 $MEM_MB = parse_memory($MEM_MB);
54              
55 0 0       0 if ($MEM_MB < 350) {
56 0         0 say STDERR RED, "[WARNING]", RESET, "Memory set to $MEM_MB Mb, automatically setting to $MEM_MB Gb", RESET;
57 0         0 $MEM_MB *= 1000;
58             }
59              
60 0         0 my $time = session_resolve_time(
61             hours => $OPT_HOURS,
62             time_string => $OPT_TIME,
63             default_hours => $DEFAULT_HOURS,
64             days => $DAYS,
65             );
66              
67             # Get queue
68 0 0       0 if (not $OPT_PARTITION) {
69 0 0       0 if ($config->{'queue'}) {
70 0         0 $OPT_PARTITION = $config->{'queue'};
71             } else {
72 0         0 $OPT_PARTITION = partition_tag($time->{total_hours});
73             }
74             }
75              
76 0         0 my $PARAMS = $DEFAULT_SESSION;
77 0 0       0 $PARAMS .= $OPT_INTEL ? " --constraint=intel " : "";
78 0 0       0 $PARAMS .= $OPT_SPECIAL ? " $SPECIAL_SESSION " : "";
79              
80 0   0     0 my $PARTITION //= $OPT_PARTITION;
81              
82 0         0 say STDERR "-" x 40;
83             print STDERR YELLOW,
84             "job name ", RESET, $NAME, "\n",
85             YELLOW, "memory ", RESET, $MEM_MB, " Mb\n",
86             YELLOW, "cores ", RESET, $CORES, "\n",
87 0         0 YELLOW, "time ", RESET, $time->{slurm}, "\n",
88             YELLOW, "partition ", RESET, $PARTITION, "\n";
89              
90 0         0 say STDERR "-" x 40;
91 0         0 my $cmd = qq(srun --job-name=$NAME --mem=$MEM_MB -c $CORES --time=$time->{slurm} -n 1 --disable-status -s --pty --partition=$PARTITION $PARAMS -u bash -li);
92              
93 0 0       0 say STDERR $cmd if ($OPT_VERBOSE);
94              
95 0 0       0 if (has_srun() == 0) {
96 0         0 say STDERR RED, "[ERROR] srun not found... Are you on the cluster?", RESET;
97             }
98 0         0 exec($cmd);
99             }
100              
101             sub partition_tag {
102 0     0   0 my $hours = shift;
103 0 0       0 if ($hours <= 2) {
    0          
104 0         0 return "qib-short,nbi-short";
105             } elsif ($hours <= 8) {
106 0         0 return "qib-medium,nbi-medium";
107             } else {
108 0         0 return "qib-long,nbi-long";
109             }
110             }
111              
112             sub session_resolve_time {
113 5     5   17 my %args = @_;
114             confess "ERROR: --hours and --time are mutually exclusive\n"
115 5 100 100     246 if defined $args{hours} && defined $args{time_string};
116              
117             my $hours = defined $args{time_string}
118             ? NBI::Opts::_time_to_hour($args{time_string})
119             : defined $args{hours}
120             ? $args{hours}
121 4 50       14 : $args{default_hours};
    100          
122              
123 4   50     10 $hours += ($args{days} // 0) * 24;
124              
125             return {
126 4         9 total_hours => $hours,
127             slurm => session_hours_to_slurm($hours),
128             };
129             }
130              
131             sub hours_to_days_hours {
132 0     0   0 my $hours = shift;
133 0         0 my $days = int($hours / 24);
134 0         0 my $hours = $hours % 24;
135 0         0 return ($days, $hours);
136             }
137              
138             sub session_hours_to_slurm {
139 6     6   498 my $hours = shift;
140 6         8 my $seconds = int($hours * 3600);
141 6         11 my $days = int($seconds / 86400);
142 6         7 $seconds %= 86400;
143 6         5 my $hh = int($seconds / 3600);
144 6         6 $seconds %= 3600;
145 6         7 my $mm = int($seconds / 60);
146 6         5 my $ss = $seconds % 60;
147 6         48 return sprintf("%d-%02d:%02d:%02d", $days, $hh, $mm, $ss);
148             }
149              
150              
151             sub parse_memory {
152             # Parse string return mb
153 0     0     my $mem = shift;
154 0           my $mb = 0;
155 0 0         if ($mem =~ /^(\d+)$/) {
    0          
    0          
    0          
156 0           $mb = $1;
157             } elsif ($mem =~ /(\d+)\s?Gb?/i) {
158 0           $mb = $1 * 1000;
159             } elsif ($mem =~ /(\d+)\s?Mb?/i) {
160 0           $mb = $1;
161             } elsif ($mem =~ /(\d+)\s?Kb?/i) {
162 0           $mb = int($1 / 1000);
163             } else {
164 0           $mb = $mem;
165             }
166 0           return $mb;
167             }
168             sub usage {
169 0     0     print <<"EOF";
170             Usage: $BIN [options]
171              
172             Options:
173             -c, --threads Number of CPU cores (default: 1)
174             -m, --mem Memory size in MB (default: 1000)
175             -h, --hours Number of hours (default: 4; mutually exclusive with --time)
176             -t, --time Time string like 12h, 1d, 2h30m
177             -n, --name Job name (default: session)
178             -q, --queue Queue/partition name (default: determined by hours)
179             -s, --special Enable the special parameter string from the config file (default: off)
180             -i, --intel Use Intel constraint (default: off)
181              
182             EOF
183 0 0         exit() if ($_[0]);
184             }
185              
186             sub has_srun {
187             # Check if srun is available
188 0     0     my $srun = `srun --version 2> /dev/null`;
189 0           chomp $srun;
190 0 0         if ($srun eq "") {
191 0           return 0;
192             }
193 0           return 1;
194             }
195              
196             __END__