]> mj.ucw.cz Git - bex.git/blob - lib/bin/bex-add
Accept partial job IDs as long as they are unique
[bex.git] / lib / bin / bex-add
1 #!/usr/bin/perl
2 # Batch EXecutor -- Insert to Queue
3 # (c) 2011-2013 Martin Mares <mj@ucw.cz>
4
5 use strict;
6 use warnings;
7 use Getopt::Long;
8 use File::stat;
9 use File::Spec;
10 use BEX;
11
12 my $given_body;
13 my $given_execute;
14 my $given_go;
15 my $given_id;
16 my $queue_name;
17 my $requeue_id;
18 my $given_subject;
19 my $given_template;
20 my @attach = ();
21
22 sub usage() {
23         print <<AMEN ;
24 Usage: bex add [<options>] [!]<machine-or-class> ...
25
26 Options:
27 -a, --attach=<path>     Attach a file or directory to the job
28 -b, --body=<file>       Load job body from the given file
29 -e, --execute=<command> Set job body to the given command
30 -g, --go                Do not run editor, go enqueue the job immediately
31 -i, --id=<id>           Set job ID of the new job
32 -q, --queue=<name>      Insert new jobs to the given queue
33 -r, --requeue=<id>      Re-queue an existing job instead of creating a new one
34                         (and possibly add/replace its attachments)
35 -s, --subject=<subj>    Set subject of the new job
36 -t, --template=<file>   Load job template (headers and body) from the given file
37 AMEN
38         exit 0;
39 }
40
41 GetOptions(
42         "a|attach=s" => \@attach,
43         "b|body=s" => \$given_body,
44         "e|execute=s" => \$given_execute,
45         "g|go!" => \$given_go,
46         "i|id=s" => \$given_id,
47         "q|queue=s" => \$queue_name,
48         "r|requeue=s" => \$requeue_id,
49         "s|subject=s" => \$given_subject,
50         "t|template=s" => \$given_template,
51         "help" => \&usage,
52 ) or die "Try `bex add --help' for more information.\n";
53
54 # Prepare machine set
55 @ARGV or die "No machines specified\n";
56 my @machines = BEX::Config::parse_machine_list(@ARGV);
57 @machines or die "No machines match\n";
58
59 # Verify that all attachments exist
60 for my $a (@attach) {
61         -f $a || -d $a or die "Attachment $a does not exist\n";
62 }
63
64 my $queue = BEX::Queue->new($queue_name);
65 my $job;
66 my $tmp_fn;
67
68 if (defined $requeue_id) {
69         # When requeueing, just fetch the existing job
70         if (defined($given_body) || defined($given_execute) || defined($given_id) || defined($given_subject) || defined($given_template)) {
71                 die "Parameters of a requeued job cannot be changed\n";
72         }
73         my $id = $queue->resolve_job_id($requeue_id);
74         my $fn = $queue->job_file($id);
75         $job = BEX::Job->new_from_file($fn);
76 } else {
77         # Create job template
78         if (defined $given_template) {
79                 $job = BEX::Job->new_from_file($given_template);
80         } else {
81                 $job = BEX::Job->new;
82         }
83         $job->attr('ID', $given_id) if defined $given_id;
84         $job->attr('Subject', $given_subject) if defined $given_subject;
85         if (defined $given_execute) {
86                 $job->attr('body', $given_execute. "\n");
87         } elsif (defined $given_body) {
88                 open B, '<', $given_body or die "Cannot open $given_body: $!\n";
89                 local $/;
90                 $job->attr('body', <B>);
91                 close B;
92         }
93
94         # Let the user edit the template
95         if (!$given_go) {
96                 $tmp_fn = $job->save;
97                 my $orig_stat = stat($tmp_fn) or die;
98                 system $BEX::Config::editor_command, $tmp_fn and die "Editor exited with an error, file kept as $tmp_fn\n";
99                 my $new_stat = stat($tmp_fn) or die "File $tmp_fn disappeared under my hands: $!\n";
100                 if ($new_stat->mtime <= $orig_stat->mtime && $new_stat->size == $orig_stat->size) {
101                         unlink $tmp_fn;
102                         die "Cancelled\n";
103                 }
104                 $job = BEX::Job->new_from_file($tmp_fn);
105         }
106 }
107
108 # Put the job to the queue
109 print "New job ", $job->id, "\n";
110 $queue->save_job($job);
111
112 # Create attachments
113 if (@attach) {
114         my $adir = $queue->attachment_dir($job->id);
115         -d $adir || mkdir $adir or die "Cannot create $adir: $!\n";
116         for my $asrc (@attach) {
117                 $asrc =~ s{/+$}{};
118                 my ($vol, $dir, $base) = File::Spec->splitpath($asrc);
119                 my $adest = File::Spec->catfile($adir, $base);
120                 my $msg = "Attached";
121                 if (-e $adest) {
122                         system "/bin/rm", "-rf", $adest;
123                         $? and die "Cannot delete old attachment $adest\n";
124                         $msg = "Updated attachment";
125                 }
126                 system "/bin/cp", "-a", $asrc, $adest;
127                 $? and die "Cannot copy attachment $asrc to $adest\n";
128                 if (-d $asrc) {
129                         print "$msg $base/...\n";
130                 } else {
131                         print "$msg $base\n";
132                 }
133         }
134 }
135
136 # Enqueue the job on all machines
137 for my $m (@machines) {
138         if ($queue->enqueue($m, $job)) {
139                 $queue->update_job_status($m, $job->id, 'NEW');
140                 print "\t$m\n";
141         } else {
142                 $queue->log($m, $job->id, 'REQUEUE');
143                 print "\t$m (already queued)\n";
144         }
145 }
146
147 # Remove the temporary file if there's any
148 unlink $tmp_fn if defined $tmp_fn;