Commit 47a79e43 authored by Leigh B Stoller's avatar Leigh B Stoller
Browse files

Add entrypoints to 1) approve a pending reservation, 2) get reservation

system info from all clusters (freecount,forecast).x
parent b65ef1fb
......@@ -37,6 +37,8 @@ sub usage()
{
print("Usage: manage_reservations [-a <urn>] list [-u uid | -p pid]\n");
print("Usage: manage_reservations [-a <urn>] delete pid idx\n");
print("Usage: manage_reservations [-a <urn>] approve idx\n");
print("Usage: manage_reservations [-a <urn>] systeminfo\n");
exit(-1);
}
my $optlist = "dt:a:";
......@@ -79,6 +81,7 @@ use libEmulab;
use libtestbed;
use WebTask;
use APT_Geni;
use APT_Aggregate;
use GeniResponse;
use GeniUser;
......@@ -87,6 +90,8 @@ sub fatal($);
sub DoReserve();
sub DoList();
sub DoDelete();
sub DoApprove();
sub DoSystemInfo();
sub readfile($);
#
......@@ -142,6 +147,12 @@ elsif ($action eq "list") {
elsif ($action eq "delete") {
DoDelete();
}
elsif ($action eq "approve") {
DoApprove();
}
elsif ($action eq "systeminfo") {
DoSystemInfo();
}
else {
usage();
}
......@@ -429,6 +440,173 @@ sub DoDelete()
exit(0);
}
#
# Approve a reservation.
#
sub DoApprove()
{
usage()
if (@ARGV != 1);
my $idx = shift(@ARGV);
# Check this since Reservation->Lookup() does not validate.
fatal("Invalid index")
if ($idx !~ /^\d+$/);
if (!$this_user->IsAdmin()) {
fatal("No permission to approve reservations")
}
# PortalRPC will use the root context in this case, which is
# essentially saying the caller is an admin.
my $response =
APT_Geni::PortalRPC($authority, undef, "ApproveReservation",
{"idx" => $idx});
if (GeniResponse::IsError($response)) {
#
# All errors are fatal.
#
fatal($response->output());
}
if (defined($webtask)) {
$webtask->Exited(0);
}
else {
print Dumper($response);
}
exit(0);
}
#
# Get the reservation system info.
#
sub DoSystemInfo()
{
my $optlist = "p:";
my $portal;
my $errmsg;
my @aggregates = ($authority);
my @webtasks = ();
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"p"})) {
$portal = $options{"p"}
}
usage()
if (@ARGV);
#
# Portal argument says to ignore aggregate argument, and contact
# all aggregates listed for the portal.
#
if (defined($portal)) {
@aggregates = ();
my @list = APT_Aggregate->LookupForPortal($portal);
foreach my $aggregate (@list) {
my $authority = APT_Geni::GetAuthority($aggregate->urn());
if (!defined($authority)) {
$errmsg = "Cannot lookup authority for $aggregate";
goto bad;
}
push(@aggregates, $authority);
}
}
my $coderef = sub {
my ($blob) = @_;
my $authority = $blob->{"authority"};
my $webtask = $blob->{"webtask"};
# PortalRPC will use the root context in this case, which is
# essentially saying the caller is an admin. But thats okay
# for this call, it is just informational.
my $response =
APT_Geni::PortalRPC($authority, undef, "ReservationSystemInfo");
if (GeniResponse::IsError($response)) {
#
# All errors are fatal.
#
if (defined($webtask)) {
$webtask->output($response->output());
$webtask->Exited(-1);
}
else {
print STDERR $response->output() . "\n";
}
return -1;
}
if (defined($webtask)) {
$webtask->value($response->value());
$webtask->Exited(0);
}
return 0;
};
#
# Multiple aggregates, we use parrun. We need a webtask for each
# authority to communicate the results back to the parent, who
# then combines them all.
#
my @return_codes = ();
my @agglist = ();
foreach my $auth (@aggregates) {
my $temptask = WebTask->CreateAnonymous();
# For delete below.
push(@webtasks, $temptask);
push(@agglist, {"authority" => $auth,
"webtask" => $temptask});
}
if (ParRun({"maxwaittime" => 60,
"maxchildren" => scalar(@agglist)},
\@return_codes, $coderef, @agglist)) {
#
# The parent caught a signal. Leave things intact so that we can
# kill things cleanly later.
#
$errmsg = "Internal error get reservation info";
goto bad;
}
#
# Check the exit codes, create return structure for the web interface.
#
my $blob = {};
foreach my $agg (@agglist) {
my $code = shift(@return_codes);
my $auth = $agg->{'authority'};
my $wtask = $agg->{'webtask'};
$wtask->Refresh();
if ($code) {
$errmsg = $wtask->output();
goto bad;
}
$blob->{$auth->urn()} = $wtask->value();
}
if (defined($webtask)) {
$webtask->value($blob);
$webtask->Exited(0);
}
else {
print Dumper($blob);
}
foreach my $temptask (@webtasks) {
$temptask->Delete();
}
exit(0);
bad:
foreach my $temptask (@webtasks) {
$temptask->Delete();
}
fatal($errmsg);
}
sub fatal($)
{
my ($mesg) = @_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment