]> mj.ucw.cz Git - bex.git/blob - lib/bin/bex-queue
bex queue: add --summary option and enable option bundling
[bex.git] / lib / bin / bex-queue
1 #!/usr/bin/perl
2 # Batch EXecutor 3.0 -- Show Queued Jobs
3 # (c) 2011-2012 Martin Mares <mj@ucw.cz>
4
5 use strict;
6 use warnings;
7 use Getopt::Long;
8 use POSIX;
9 use BEX;
10
11 my $op_by_job;
12 my $op_by_host;
13 my $op_rm;
14 my $op_move_to;
15
16 my $queue_name;
17 my $given_job;
18 my $summary;
19
20 sub usage() {
21         print <<AMEN ;
22 Usage: bex queue [<options and actions>] [[!]<machine-or-class> ...]
23
24 Actions:
25     --by-job            Show jobs sorted by job ID (default)
26 -h, --by-host           Show jobs sorted by host
27     --rm                Remove jobs from the queue
28     --move-to=<queue>   Move jobs to a different queue
29
30 Options:
31 -j, --job=<id>          Act on the specified job (default: on all)
32 -q, --queue=<name>      Act on the given queue
33 -s, --summary           Show only a summary
34 AMEN
35         exit 0;
36 }
37
38 Getopt::Long::Configure("bundling");
39 GetOptions(
40         "by-job!" => \$op_by_job,
41         "h|by-host!" => \$op_by_host,
42         "rm!" => \$op_rm,
43         "move-to=s" => \$op_move_to,
44         "j|job=s" => \$given_job,
45         "q|queue=s" => \$queue_name,
46         "s|summary!" => \$summary,
47         "help" => \&usage,
48 ) or die "Try `bex queue --help' for more information.\n";
49
50 my @machines = BEX::Config::parse_machine_list(@ARGV ? @ARGV : '*');
51 my $queue = BEX::Queue->new($queue_name);
52
53 # Select jobs
54 my %jobs = ();
55 my %machs = ();
56 for my $m (@machines) {
57         for my $j ($queue->scan($m)) {
58                 if (defined $given_job) {
59                         next if $j ne $given_job;
60                 }
61                 push @{$jobs{$j}}, $m;
62                 push @{$machs{$m}}, $j;
63         }
64 }
65
66 sub do_ls();
67 sub do_rm();
68 sub do_move_to();
69
70 my $ops = 0 + defined($op_by_host) + defined($op_by_job) + defined($op_rm) + defined($op_move_to);
71 if ($ops > 1) { die "Multiple actions are not allowed\n"; }
72
73 if ($op_rm) { do_rm(); }
74 elsif (defined $op_move_to) { do_move_to(); }
75 else { do_ls(); }
76 exit 0;
77
78 sub do_ls()
79 {
80         my %stat = ();
81         my %mach_locked = ();
82         my %cnt_by_job = ();
83         my %cnt_by_mach = ();
84         for my $m (keys %machs) {
85                 $mach_locked{$m} = $queue->is_locked($m, undef);
86                 for my $j (@{$machs{$m}}) {
87                         my $st = $queue->read_job_status($m, $j);
88                         my $s = $st->{"Status"} // "UNKNOWN";
89                         $cnt_by_job{$j}{$s}++;
90                         $cnt_by_mach{$m}{$s}++;
91                         if (defined($st->{'Time'}) && defined($st->{'Status'})) {
92                                 $stat{$m}{$j} = ' [' . $st->{'Status'} . ' on ' .
93                                                 POSIX::strftime('%Y-%m-%d', localtime $st->{'Time'}) . ']';
94                         } else {
95                                 $stat{$m}{$j} = '';
96                         }
97                         if ($mach_locked{$m} || $queue->is_locked($m, $j)) {
98                                 $stat{$m}{$j} .= ' [LOCKED]';
99                         }
100                 }
101         }
102
103         if ($queue->is_locked(undef, undef)) {
104                 print "### Queue lock present\n\n";
105         }
106
107         if ($summary) {
108                 if ($op_by_host) {
109                         for my $m (sort keys %cnt_by_mach) {
110                                 print "$m: ", join(" ", map { "$_:" . $cnt_by_mach{$m}{$_} } sort keys %{$cnt_by_mach{$m}}), "\n";
111                         }
112                 } else {
113                         for my $j (sort keys %cnt_by_job) {
114                                 print $queue->job_name($j), ": ", join(" ", map { "$_:" . $cnt_by_job{$j}{$_} } sort keys %{$cnt_by_job{$j}}), "\n";
115                         }
116                 }
117         } else {
118                 if ($op_by_host) {
119                         for my $m (sort keys %machs) {
120                                 print "$m", ($mach_locked{$m} ? ' [LOCKED]' : ''), "\n";
121                                 for my $j (@{$machs{$m}}) {
122                                         print "\t" . $queue->job_name($j) . $stat{$m}{$j}, "\n";
123                                 }
124                         }
125                 } else {
126                         for my $j (sort keys %jobs) {
127                                 print $queue->job_name($j), "\n";
128                                 for my $m (sort @{$jobs{$j}}) {
129                                         print "\t$m", $stat{$m}{$j}, "\n";
130                                 }
131                         }
132                 }
133         }
134 }
135
136 sub do_rm()
137 {
138         my $err = 0;
139         for my $m (sort keys %machs) {
140                 for my $j (sort @{$machs{$m}}) {
141                         if (!$queue->lock($m, $j)) {
142                                 print STDERR "Cannot remove $m:", $queue->job_name($j), ", it is locked\n";
143                                 $err = 1;
144                         } else {
145                                 $queue->update_job_status($m, $j, 'REMOVED');
146                                 $queue->remove($m, $j);
147                                 print "Removed $m:", $queue->job_name($j), "\n";
148                         }
149                 }
150         }
151         $queue->unlock;
152         exit $err;
153 }
154
155 sub do_move_to()
156 {
157         my $err = 0;
158         my $dest = BEX::Queue->new($op_move_to);
159         $dest->{'Name'} ne $queue->{'Name'} or die "Moving to the same queue is not permitted\n";
160         for my $j (sort keys %jobs) {
161                 my $job = BEX::Job->new_from_file($queue->job_file($j));
162                 for my $m (sort @{$jobs{$j}}) {
163                         if (!$queue->lock($m, $j)) {
164                                 print STDERR "Cannot move $m:", $queue->job_name($j), ", it is locked\n";
165                                 $err = 1;
166                         } else {
167                                 my $enq = $dest->enqueue($m, $job);
168                                 if ($enq) {
169                                         $dest->update_job_status($m, $job->id, 'NEW', 'Moved to this queue');
170                                 } else {
171                                         $dest->log($m, $job->id, 'REQUEUE', 'Moved to this queue');
172                                 }
173                                 $queue->update_job_status($m, $job->id, 'REMOVED', 'Moved from this queue');
174                                 $queue->remove($m, $j);
175                                 print "Moved $m:", $dest->job_name($j);
176                                 print " (already queued)" if !$enq;
177                                 print "\n";
178                         }
179                 }
180         }
181         $queue->unlock;
182         exit $err;
183 }