Commit 8b66840c authored by Gary Wong's avatar Gary Wong

Merge branch 'lbs-greatness'

parents 88dd5a80 33129222
#!/usr/bin/perl -wT
#
# Copyright (c) 2007-2017 University of Utah and the Flux Group.
# Copyright (c) 2007-2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -270,5 +270,34 @@ sub LookupByNickname($$)
return Lookup($class, $aggregate_urn);
}
#
# Check status of aggregate.
#
sub CheckStatus($$;$)
{
my ($self, $perrmsg, $portalrpc) = @_;
require APT_Geni;
if (0 || $self->disabled()) {
$$perrmsg = "The " . $self->name() . " cluster ".
"is currently offline, please try again later.";
return 1;
}
# Ping test. If we cannot get to the aggregate right now, bail.
my $retval = APT_Geni::PingAggregate($self, $perrmsg, $portalrpc);
if ($retval) {
if ($retval < 0) {
$$perrmsg = "Internal error contacting the ".
$self->name() . " cluster: " . $perrmsg;
}
else {
$$perrmsg = "The " . $self->name() . " cluster ".
"is currently unreachable, please try again later.";
}
return 1;
}
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
#!/usr/bin/perl -wT
#
# Copyright (c) 2007-2017 University of Utah and the Flux Group.
# Copyright (c) 2007-2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -574,6 +574,18 @@ sub GetCertificate($)
return $cert;
}
# Helper functions for below.
sub ContextError()
{
return GeniResponse->Create(GENIRESPONSE_ERROR(), undef,
"Could not generate context for RPC");
}
sub CredentialError()
{
return GeniResponse->Create(GENIRESPONSE_ERROR(), undef,
"Could not generate credentials for RPC");
}
#
# Create a dataset on the remote aggregate.
#
......@@ -584,13 +596,14 @@ sub CreateDataset($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential, $speaksfor_credential) =
APT_Geni::GenCredentials($cert, $geniuser, ["blockstores"]);
return undef
return CredentialError
if (! (defined($speaksfor_credential) &&
defined($credential)));
......@@ -624,13 +637,13 @@ sub DeleteDataset($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential, $speaksfor_credential) =
APT_Geni::GenCredentials($cert, $geniuser, ["blockstores"], 1);
return undef
return CredentialError()
if (!defined($credential));
my $credentials = [$credential->asString()];
......@@ -657,13 +670,13 @@ sub ModifyDataset($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential, $speaksfor_credential) =
APT_Geni::GenCredentials($cert, $geniuser, ["blockstores"], 1);
return undef
return CredentialError()
if (!defined($credential));
my $credentials = [$credential->asString()];
......@@ -692,13 +705,13 @@ sub ExtendDataset($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential, $speaksfor_credential) =
APT_Geni::GenCredentials($cert, $geniuser, ["blockstores"], 1);
return undef
return CredentialError()
if (!defined($credential));
my $credentials = [$credential->asString()];
......@@ -726,13 +739,13 @@ sub DescribeDataset($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential, $speaksfor_credential) =
APT_Geni::GenCredentials($cert, $geniuser, ["blockstores"], 1);
return undef
return CredentialError()
if (!defined($credential));
my $credentials = [$credential->asString()];
......@@ -759,13 +772,13 @@ sub GetCredential($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential) =
APT_Geni::GenAuthCredential($cert, ["blockstores"]);
return undef
return CredentialError()
if (!defined($credential));
my $args = {
......@@ -789,13 +802,13 @@ sub ApproveDataset($)
my $geniuser = $self->GetGeniUser();
my $context = APT_Geni::GeniContext();
my $cert = $self->GetCertificate();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($context) && defined($cert)));
my ($credential) =
APT_Geni::GenAuthCredential($cert, ["admin"]);
return undef
return CredentialError()
if (!defined($credential));
my $args = {
......
#!/usr/bin/perl -wT
#
# Copyright (c) 2007-2017 University of Utah and the Flux Group.
# Copyright (c) 2007-2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -523,26 +523,62 @@ sub PortalRPC($$$@)
if ($usemydevtree) {
$cmurl =~ s/protogeni/protogeni\/stoller/;
}
#
# We use the root context to talk to the Cluster RPC server
#
if (!defined($context)) {
$context = RootContext();
if (!defined($context)) {
return GeniResponse->Create(GENIRESPONSE_RPCERROR(), undef,
return GeniResponse->Create(GENIRESPONSE_ERROR(), undef,
"Could not get root context for RPC");
}
}
my $response = Genixmlrpc::CallMethod($cmurl, $context, $method, @args);
if ($response->code() != GENIRESPONSE_SUCCESS()) {
if (!defined($response->output())) {
$response->output("Operation failed, returned " .
$response->code());
$response->output(GENIRESPONSE_STRING($response->code()));
}
}
return $response;
}
#
# Ping an aggregate to see if its alive, using getversion.
#
sub PingAggregate($$;$)
{
my ($aggregate, $perrmsg, $portalrpc) = @_;
my $authority = GetAuthority($aggregate->urn());
my $context = RootContext();
if (!defined($authority)) {
$$perrmsg = "Could not lookup authority for $aggregate!";
return -1;
}
if (!defined($context)) {
$$perrmsg = "Could generate root context!";
return -1;
}
my $cmurl = $authority->url();
if (defined($portalrpc)) {
$cmurl =~ s/\/cm$/\/cluster/;
}
if ($usemydevtree) {
$cmurl =~ s/protogeni/protogeni\/stoller/;
}
my $oldto = Genixmlrpc->SetTimeout(10);
my $response = Genixmlrpc::CallMethod($cmurl, $context, "GetVersion");
Genixmlrpc->SetTimeout($oldto);
# Success is good!
return 0
if ($response->code() == GENIRESPONSE_SUCCESS());
#print STDERR Dumper($response);
$$perrmsg = $response->error();
return $response->code();
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -28,7 +28,7 @@ use Carp;
use English;
use Data::Dumper;
use Date::Parse;
use POSIX qw(tmpnam);
use File::Temp qw(tempfile tmpnam);
use JSON;
use Exporter;
use vars qw(@ISA @EXPORT $AUTOLOAD
......@@ -420,7 +420,8 @@ sub Delete($)
$agg->Delete() == 0
or return -1;
}
$self->webtask()->Delete();
# We do not "own" the webtask until create_sliver exits successfully.
$self->webtask()->Delete() if (defined($self->{'WEBTASK'}));
DBQueryWarn("delete from apt_instances where uuid='$uuid'") or
return -1;
......@@ -448,6 +449,15 @@ sub Unlock($)
}
return $slice->UnLock();
}
sub Locked($)
{
my ($self) = @_;
my $slice = $self->GetGeniSlice();
if (!defined($slice)) {
return 0;
}
return $slice->locked();
}
sub SetStatus($$)
{
......@@ -1511,7 +1521,7 @@ use EmulabConstants;
use WebTask;
use libtestbed;
use Carp;
use POSIX qw(tmpnam);
use File::Temp qw(tempfile tmpnam);
use JSON;
use English;
use GeniResponse;
......@@ -1549,6 +1559,7 @@ sub Lookup($$$)
$self->{'INSTANCE'} = $instance;
$self->{'WEBTASK'} = undef;
$self->{'STATUS'} = undef;
$self->{'AGGREGATE'}= undef;
bless($self, $class);
# Handy;
......@@ -1716,6 +1727,7 @@ sub DESTROY {
$self->{'DBROW'} = undef;
$self->{'WEBTASK'} = undef;
$self->{'HASH'} = undef;
$self->{'AGGREGATE'}= undef;
}
#
......@@ -1917,6 +1929,23 @@ sub GetGeniAuthority($)
return APT_Geni::GetAuthority($self->aggregate_urn());
}
sub GetAptAggregate($)
{
my ($self) = @_;
return $self->{"AGGREGATE"}
if (defined($self->{"AGGREGATE"}));
$self->{"AGGREGATE"} = APT_Aggregate->Lookup($self->aggregate_urn());
return $self->{"AGGREGATE"};
}
sub AptAggregateName($)
{
my ($self) = @_;
return $self->GetAptAggregate()->name();
}
#
# Update the sliverstatus in the webtask.
#
......@@ -2224,6 +2253,18 @@ sub UpdateSliverStatusAll($$)
return 0;
}
# Helper functions for below.
sub ContextError()
{
return GeniResponse->Create(GENIRESPONSE_ERROR(), undef,
"Could not generate context for RPC");
}
sub CredentialError()
{
return GeniResponse->Create(GENIRESPONSE_ERROR(), undef,
"Could not generate credentials for RPC");
}
#
# Ask aggregate to terminate a sliver.
#
......@@ -2237,7 +2278,7 @@ sub Terminate($)
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
......@@ -2251,7 +2292,7 @@ sub Terminate($)
my $slice_credential = APT_Geni::GenAuthCredential($slice);
if (!defined($slice_credential)) {
print STDERR "Could not generate slice credential\n";
return undef;
return CredentialError()
}
$method = "DeleteSliver";
@params = ($slice->urn(), [$slice_credential->asString()], {});
......@@ -2260,7 +2301,7 @@ sub Terminate($)
my $credentials;
my ($slice_credential, $speaksfor_credential) =
APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
return undef
return CredentialError()
if (!defined($slice_credential));
$credentials = [$slice_credential->asString()];
......@@ -2285,34 +2326,7 @@ sub Terminate($)
#
Genixmlrpc->SetTimeout(900);
#
# We have to watch for resource busy errors, and retry. For a while
# at least. Eventually give up cause it might be a permanently locked
# slice cause of earlier error.
#
my $response;
my $tries = 10;
while ($tries) {
$response =
Genixmlrpc::CallMethod($cmurl, $context, $method, @params);
# SEARCHFAILED is success.
return $response
if ($response->code() == GENIRESPONSE_SUCCESS ||
$response->code() == GENIRESPONSE_SEARCHFAILED);
return $response
if ($response->code() != GENIRESPONSE_BUSY);
#
# Wait for a while and try again.
#
$tries--;
if ($tries) {
print STDERR "Slice is busy, will retry again in a bit ...\n";
sleep(30);
}
}
my $response = Genixmlrpc::CallMethod($cmurl, $context, $method, @params);
return $response;
}
......@@ -2330,7 +2344,7 @@ sub Extend($$$$)
my $geniuser = $self->instance()->GetGeniUser();
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
......@@ -2338,7 +2352,7 @@ sub Extend($$$$)
my $slice_credential = APT_Geni::GenAuthCredential($slice);
if (!defined($slice_credential)) {
print STDERR "Could not generate slice credential\n";
return undef;
return CredentialError()
}
$method = "RenewSliver";
@params = ($slice->urn(), [$slice_credential->asString()],
......@@ -2351,7 +2365,7 @@ sub Extend($$$$)
}
my ($slice_credential, $speaksfor_credential) =
APT_Geni::GenCredentials($slice, $geniuser, \@privs, 1);
return undef
return CredentialError()
if (!defined($slice_credential));
$credentials = [$slice_credential->asString()];
......@@ -2381,14 +2395,14 @@ sub Extend($$$$)
$geniuser->emulab_user()->GetStoredCredential();
if (! defined($certificate_string)) {
print STDERR "Could not get stored certificate for $geniuser\n";
return undef;
return CredentialError();
}
my $certificate =
GeniCertificate->LoadFromString($certificate_string);
if (!defined($certificate)) {
print STDERR
"Could not load stored certificate for $geniuser\n";
return undef;
return CredentialError();
}
# This file will be auto deleted.
$certfile = $certificate->WriteToFile();
......@@ -2402,11 +2416,11 @@ sub Extend($$$$)
" -a -o $credname -s $slice_urn -t $days $userarg");
if ($?) {
print STDERR "Could not create extended credential\n";
return undef;
return CredentialError();
}
if (!open(EXT, $credname)) {
print STDERR "Could not open ext credfile $credname\n";
return undef;
return CredentialError();
}
while (<EXT>) {
$extcred .= $_;
......@@ -2432,10 +2446,6 @@ sub Extend($$$$)
my $response;
while ($tries) {
$response = Genixmlrpc::CallMethod($cmurl, $context, $method, @params);
return undef
if (!defined($response));
if ($response->code() != GENIRESPONSE_SUCCESS) {
if (($response->code() == GENIRESPONSE_SERVER_UNAVAILABLE ||
$response->code() == GENIRESPONSE_BUSY) &&
......@@ -2467,7 +2477,7 @@ sub SliceStatus($)
# Shorten default timeout
Genixmlrpc->SetTimeout(30);
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
......@@ -2477,7 +2487,7 @@ sub SliceStatus($)
my $slice_credential = APT_Geni::GenAuthCredential($slice);
if (!defined($slice_credential)) {
print STDERR "Could not generate slice credential\n";
return undef;
return CredentialError();
}
if ($self->isAL2S()) {
@params = ($slice->urn(), [$slice_credential->asString()], {});
......@@ -2523,7 +2533,7 @@ sub GetManifest($)
my $urn = $self->aggregate_urn();
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
......@@ -2531,7 +2541,7 @@ sub GetManifest($)
my $slice_credential = APT_Geni::GenAuthCredential($slice);
if (!defined($slice_credential)) {
print STDERR "Could not generate slice credential\n";
return undef;
return CredentialError();
}
$method = "ListResources";
......@@ -2548,7 +2558,7 @@ sub GetManifest($)
my ($slice_credential, $speaksfor_credential) =
APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
return undef
return CredentialError()
if (!defined($slice_credential));
$credentials = [$slice_credential->asString()];
......@@ -2579,8 +2589,7 @@ sub GetManifest($)
$tries--;
next;
}
print STDERR "Resolve failed on $urn: ".
(defined($response) ? $response->output() : "") . "\n";
print STDERR "Resolve failed on $urn: ". $response->error() . "\n";
return undef;
}
last;
......@@ -2607,7 +2616,7 @@ sub SliceResolve($)
my $urn = $self->aggregate_urn();
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
......@@ -2615,7 +2624,7 @@ sub SliceResolve($)
my $slice_credential = APT_Geni::GenAuthCredential($slice);
if (!defined($slice_credential)) {
print STDERR "Could not generate slice credential\n";
return undef;
return CredentialError();
}
$method = "ListResources";
......@@ -2632,7 +2641,7 @@ sub SliceResolve($)
my ($slice_credential, $speaksfor_credential) =
APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
return undef
return CredentialError()
if (!defined($slice_credential));
$credentials = [$slice_credential->asString()];
......@@ -2651,19 +2660,19 @@ sub SliceResolve($)
sub Provision($$$$)
{
my ($self, $perrmsg, $users, $cert, $key) = @_;
my ($self, $users, $cert, $key) = @_;
my $authority = $self->GetGeniAuthority();
my $urn = $self->aggregate_urn();
my $geniuser = $self->instance()->GetGeniUser();
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
return -1
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
my ($slice_credential, $speaksfor_credential) =
APT_Geni::GenCredentials($slice, $geniuser, undef, 0);
return -1
return CredentialError()
if (! (defined($speaksfor_credential) &&
defined($slice_credential)));
......@@ -2692,32 +2701,7 @@ sub Provision($$$$)
$cmurl = devurl($cmurl) if ($usemydevtree);
$cmurl .= "/3.0";
my $tries = 10;
while ($tries) {
my $response =
Genixmlrpc::CallMethod($cmurl, $context, "Provision", @params);
if (defined($response) && defined($response->logurl())) {
$self->SetPublicURL($response->logurl());
}
if (!defined($response) || $response->code() != GENIRESPONSE_SUCCESS) {
if (defined($response) &&
($response->code() == GENIRESPONSE_SERVER_UNAVAILABLE ||
$response->code() == GENIRESPONSE_BUSY) &&
$tries >= 0) {
print STDERR "Server for $urn reports too busy or slice busy, ".
"waiting a while ...\n";
sleep(int(rand(20)) + 10);
$tries--;
next;
}
$$perrmsg = $response->output()
if (defined($response));
return -1;
}
last;
}
return 0;
return Genixmlrpc::CallMethod($cmurl, $context, "Provision", @params);
}
#
......@@ -2730,13 +2714,13 @@ sub ConsoleInfo($$)
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
my $geniuser = $self->instance()->GetGeniUser();
return undef
return ContextError()
if (! (defined($geniuser) && defined($authority) &&
defined($slice) && defined($context)));
my ($slice_credential, $speaksfor_credential) =
APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
return undef
return CredentialError()
if (! defined($slice_credential));
my $credentials = [$slice_credential->asString()];
......@@ -2764,13 +2748,13 @@ sub ConsoleURL($$)
my $geniuser = $self->instance()->GetGeniUser();
my $slice = $self->instance()->GetGeniSlice();
my $context = APT_Geni::GeniContext();
return undef