#!/usr/bin/perl -wT use strict; use warnings; use CGI::Simple; use CGI::Carp qw(fatalsToBrowser); use DBI; use Net::Amazon::EC2; use DateTime::Format::ISO8601; use Archive::Zip; use MIME::Base64; use IO::String; use Data::Dumper; my $root = '/var/svn/autobuild'; my %config = load_conf("$root/manage.conf"); my $cgi = new CGI::Simple; my $user = $cgi->remote_user; die unless $user; my $dbh = DBI->connect("dbi:SQLite:dbname=$root/$config{database}", '', '', { RaiseError => 1 }); my $ec2 = new Net::Amazon::EC2( AWSAccessKeyId => $config{aws_access_key_id}, SecretAccessKey => $config{aws_secret_access_key}, ); my @build_options = ( { name => 'atlas', title => 'Atlas DLL' }, { name => 'collada', title => 'Collada DLL' }, ); my $action = $cgi->url_param('action'); if (not defined $action or $action eq 'index') { log_action('index'); print_index(''); } elsif ($action eq 'start') { die "Must be POST" unless $cgi->request_method eq 'POST'; log_action('start'); =pod Only one instance may run at once, and we need to prevent race conditions. So: * Use SQLite as a mutex, so only one CGI script can be trying to start at once * If the last attempted start was only a few seconds ago, reject this one since it's probably a double-click or something * Check the list of active machines. If it's non-empty, reject this request. * Otherwise, start the new machine. =cut $dbh->begin_work; die unless 1 == $dbh->do('UPDATE state SET value = ? WHERE key = ?', undef, $$, 'process_mutex'); my ($last_start) = $dbh->selectrow_array('SELECT value FROM state WHERE key = ?', undef, 'last_start'); my $last_start_age = time() - $last_start; die "Last start was only $last_start_age seconds ago - please try again later." if $last_start_age < 10; die unless 1 == $dbh->do('UPDATE state SET value = ? WHERE key = ?', undef, time(), 'last_start'); my $instances_status = get_ec2_status_table(); for (@$instances_status) { if (instance_is_autobuild($_) and $_->{instance_state} ne 'terminated') { die "Already got an active instance ($_->{instance_id}) - can't start another one."; } } # No instances are currently active, and nobody else is in this # instance-starting script, so it's safe to start a new one my $instances = start_ec2_instance(); $dbh->commit; for (@$instances) { $dbh->do('INSERT INTO instances VALUES (?, ?)', undef, $_->{instance_id}, DateTime->now->iso8601); } print_index(generate_status_table($instances, 'Newly started instance') . '
\n$output
Hello $user.
Refresh status | View build logs
EOF if ($got_active_instance) { print qq{\n}; } else { print qq{
\n}; } } sub log_action { my ($action, $params) = @_; $dbh->do('INSERT INTO activity (user, ip, ua, action, params) VALUES (?, ?, ?, ?, ?)', undef, $user, $cgi->remote_addr, $cgi->user_agent, $action, $params); } sub print_activity { my ($days) = @_; print <Date | User | IP | Action | Params | UA EOF my $sth = $dbh->prepare("SELECT * FROM activity WHERE timestamp > datetime('now', ?) ORDER BY id DESC"); $sth->execute("-$days day"); while (my $row = $sth->fetchrow_hashref) { print ' |
---|---|---|---|---|---|
'.$cgi->escapeHTML($row->{$_}) for qw(timestamp user ip action params ua);
print "\n";
}
print <
|