Commit 9ae6dfa9 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Checkpoint initial cooked mode support, plus other stuff.

parent 85175cd1
......@@ -17,7 +17,7 @@ LIB_SCRIPTS = GeniDB.pm GeniUser.pm \
GeniComponent.pm GeniCH.pm GeniEmulab.pm \
GeniAuthority.pm GeniCertificate.pm GeniAggregate.pm \
GeniUtil.pm GeniRegistry.pm GeniUsage.pm GeniHRN.pm \
GeniSES.pm
GeniSES.pm GeniResource.pm
SBIN_SCRIPTS = plabnodewrapper plabslicewrapper
SCRIPTS = addnode.pl genischemacheck.pl
......
This diff is collapsed.
......@@ -56,22 +56,36 @@ $LOCALMA_FLAG = 3;
# with different permissions. This is basically a cache on the client side of
# credentials in use so that they do not need to be regenerated.
#
sub Lookup($$$)
sub Lookup($$;$)
{
my ($class, $target, $owner) = @_;
my ($class, $arg1, $arg2) = @_;
my $query_result;
if (!defined($arg2)) {
if ($arg1 =~ /^(\d*)$/) {
$query_result =
DBQueryWarn("select * from geni_credentials ".
"where idx='$arg1'");
}
else {
return undef;
}
}
elsif (ref($arg1) && ref($arg2)) {
my $target_uuid = $arg1->uuid();
my $owner_uuid = $arg2->uuid();
$query_result =
DBQueryWarn("select * from geni_credentials ".
"where owner_uuid='$owner_uuid' and ".
" this_uuid='$target_uuid'");
}
else {
return undef;
}
return undef
if (! (ref($target) && ref($owner)));
my $target_uuid = $target->uuid();
my $owner_uuid = $owner->uuid();
if (!$query_result || !$query_result->numrows);
my $query_result =
DBQueryWarn("select * from geni_credentials ".
"where owner_uuid='$owner_uuid' and ".
" this_uuid='$target_uuid'");
return undef
if (!defined($query_result) || !$query_result->numrows);
my $row = $query_result->fetchrow_hashref();
my $credential =
......
This diff is collapsed.
This diff is collapsed.
......@@ -37,6 +37,7 @@ my $TBAUDIT = "@TBAUDITEMAIL@";
my $BOSSNODE = "@BOSSNODE@";
my $CONTROL = "@USERNODE@";
my $OURDOMAIN = "@OURDOMAIN@";
my $PGENIDOMAIN = "@PROTOGENI_DOMAIN@";
# Cache of instances to avoid regenerating them.
my %slices = ();
......@@ -223,9 +224,11 @@ sub CreateFromLocal($$$)
print STDERR "Could not find the local authority record\n";
return undef;
}
my $hrn = $authority->hrn() . "." . $experiment->idx();
my $creator_uuid = $user->uuid();
#
# XXX Form hrn from the domain.
#
my $hrn = "${PGENIDOMAIN}.slices." . $experiment->idx();
#
# Generate a certificate.
......@@ -233,10 +236,10 @@ sub CreateFromLocal($$$)
$certificate = GeniCertificate->Create("slice", $hrn, $user->email());
if (!defined($certificate)) {
print STDERR "GeniSlice::CreateFromLocal: ".
"Could not generate new certificate and UUID for $hrn\n";
"Could not generate new certificate $experiment\n";
return undef;
}
my $slice = GeniSlice->Create($certificate, $creator_uuid,
my $slice = GeniSlice->Create($certificate, $user->uuid(),
$authority, $experiment->idx());
$certificate->Delete()
if (!defined($slice));
......
......@@ -90,11 +90,9 @@ sub Lookup($$)
my $self = {};
$self->{'SLIVER'} = $query_result->fetchrow_hashref();
$self->{'COMPONENT'} = undef; # client
$self->{'SLICE'} = undef; # client/server
$self->{'CREDENTIAL'} = undef; # client
$self->{'SLICE'} = undef; # server
$self->{'AGGREGATE'} = undef; # server
$self->{'RSPEC'} = undef; # client/server
$self->{'RSPEC'} = undef; # server
my $rspec_string = $self->{'SLIVER'}->{'rspec_string'};
if (defined($rspec_string) && $rspec_string ne "") {
......@@ -145,52 +143,33 @@ sub Stringify($)
# Create a sliver record in the DB. On the client side we save the credential
# that allows control of it, for later operations.
#
sub Create($$$$$$$$;$$$)
sub Create($$$$$$$$$)
{
my ($class, $slice, $owner, $uuid, $resource_uuid, $resource_type,
$hrn, $nickname,
$rspec, $credential, $component) = @_;
$hrn, $nickname, $rspec) = @_;
my @insert_data = ();
my $certificate;
# Every sliver gets a new unique index.
my $idx = TBGetUniqueIndex('next_sliver', 1);
if (defined($credential)) {
$certificate = $credential->target_cert();
# Store the certificate for later use.
if ($certificate->Store() != 0) {
print STDERR "Could not store certificate\n";
# Create a cert pair, for this resource uuid.
if (defined($uuid) && $resource_type eq "Node") {
$certificate = GeniCertificate->Lookup($uuid);
if (defined($certificate) && $certificate->hrn() ne $hrn) {
print STDERR "GeniSliver::Create: ".
"Already have a certificate for $hrn/$uuid\n";
return undef;
}
$resource_uuid = $uuid = $credential->this_uuid();
$hrn = $credential->hrn();
if (defined($credential->extensions()) &&
exists($credential->extensions()->{'nickname'})) {
$nickname = $credential->extensions()->{'nickname'};
}
# Store the credential
return undef
if ($credential->Store() != 0);
}
else {
# Create a cert pair, for this resource uuid.
if (defined($uuid) && $resource_type eq "Node") {
$certificate = GeniCertificate->Lookup($uuid);
if (defined($certificate) && $certificate->hrn() ne $hrn) {
print STDERR "GeniSliver::Create: ".
"Already have a certificate for $hrn/$uuid\n";
return undef;
}
}
$certificate = GeniCertificate->Create("sliver", $hrn, $TBOPS, $uuid)
if (!defined($certificate));
$certificate = GeniCertificate->Create("sliver", $hrn, $TBOPS, $uuid)
if (!defined($certificate));
if (!defined($certificate)) {
print STDERR "GeniSliver::Create: ".
"Could not generate new certificate and UUID for $hrn/$uuid\n";
return undef;
}
if (!defined($certificate)) {
print STDERR "GeniSliver::Create: ".
"Could not generate new certificate and UUID for $hrn/$uuid\n";
return undef;
}
my $slice_uuid = $slice->uuid();
my $owner_uuid = $owner->uuid();
......@@ -207,13 +186,6 @@ sub Create($$$$$$$$;$$$)
push(@insert_data, "creator_uuid='$owner_uuid'");
push(@insert_data, "slice_uuid='$slice_uuid'");
# Only on the client side.
push(@insert_data, "credential_idx=" . $credential->idx())
if (defined($credential));
# Only on the client side.
push(@insert_data, "component_uuid='" . $component->uuid() . "'")
if (defined($component));
if (defined($rspec)) {
my $rspec_string = XMLout($rspec, RootName => "rspec");
my $safe_rspec = DBQuoteSpecial($rspec_string);
......@@ -236,11 +208,6 @@ sub Create($$$$$$$$;$$$)
print STDERR
"GeniSliver::Create: GeniUsage->NewSliver($sliver) failed\n";
}
$sliver->{'CREDENTIAL'} = $credential
if (defined($credential));
$sliver->{'COMPONENT'} = $component
if (defined($component));
$sliver->{'AGGREGATE'} = undef;
$sliver->{'SLICE'} = undef;
......@@ -407,52 +374,6 @@ sub GetExperiment($)
return Experiment->Lookup($self->slice_uuid());
}
#
# Get the credential for the sliver.
#
sub GetCredential($$)
{
my ($self, $user) = @_;
return undef
if (! ref($self));
return $self->{'CREDENTIAL'} if (defined($self->{'CREDENTIAL'}));
my $credential = GeniCredential->Lookup($self, $user);
if (!defined($credential)) {
print STDERR "Could not get credential object associated with $self\n";
return undef;
}
$self->{'CREDENTIAL'} = $credential;
return $credential;
}
#
# Get the component for the sliver.
#
sub GetComponent($)
{
my ($self) = @_;
return undef
if (! ref($self));
return $self->{'COMPONENT'} if (defined($self->{'COMPONENT'}));
if (!defined($self->component_uuid())) {
print STDERR "No component associated with $self\n";
return undef;
}
my $component = GeniComponent->Lookup($self->component_uuid());
if (!defined($component)) {
print STDERR "Could not get component object associated with $self\n";
return undef;
}
$self->{'COMPONENT'} = $component;
return $component;
}
#
# Get the slice for the sliver.
#
......@@ -566,128 +487,6 @@ sub NewCredential($$)
return $credential;
}
############################################################################
#
# The client side methods are in packages which inherit from above.
#
package GeniSliver::Client;
use vars qw(@ISA);
@ISA = "GeniSliver";
use GeniDB;
use GeniComponent;
use GeniSlice;
use GeniCredential;
use GeniCertificate;
use libdb qw(TBDB_ALLOCSTATE_RES_INIT_DIRTY);
sub Create()
{
my ($class, $slice, $user, $rspec, $credential, $component) = @_;
return GeniSliver->Create($slice, $user, undef, undef,
"Client", undef, undef, $rspec,
$credential, $component);
}
#
# Client side method to contact the sliver component and start it.
#
sub Start($$)
{
my ($self, $user) = @_;
return -1
if (! ref($self));
my $component = $self->GetComponent();
return -1
if (!defined($component));
return -1
if ($component->StartSliver($self, $user) != 0);
return 0;
}
#
# Client side method to contact the sliver component and destroy it.
#
sub Destroy($$)
{
my ($self, $user) = @_;
return -1
if (! ref($self));
my $component = $self->GetComponent();
return -1
if (!defined($component));
return -1
if ($component->DestroySliver($self, $user) != 0);
# Delete the local object from the DB.
$self->Delete(1) == 0
or return -1;
return 0;
}
#
# On the client side, the aggregate points to the parent sliver when it
# contains multiple resources.
#
sub SetAggregate($$)
{
my ($self, $parent) = @_;
return -1
if (! (ref($self) && ref($parent)));
my $idx = $self->idx();
my $parent_uuid = $parent->uuid();
return -1
if (!DBQueryWarn("update geni_slivers set ".
" aggregate_uuid='$parent_uuid' ".
"where idx='$idx'"));
return 0;
}
sub ClearAggregate($)
{
my ($self) = @_;
return -1
if (! ref($self));
my $idx = $self->idx();
return -1
if (!DBQueryWarn("update geni_slivers set ".
" aggregate_uuid=NULL ".
"where idx='$idx'"));
return 0;
}
sub GetAggregate($)
{
my ($self) = @_;
return undef
if (! ref($self));
return undef
if (!defined($self->aggregate_uuid()));
my $parent = GeniSliver->Lookup($self->aggregate_uuid());
if (!defined($parent)) {
print STDERR "Could not get parent object associated with $self\n";
return undef;
}
return $parent;
}
############################################################################
#
# The server side methods are in packages which inherit from above.
......@@ -704,7 +503,8 @@ use GeniCertificate;
use GeniUtil;
use Experiment;
use XML::Simple;
use libdb qw(TBDB_ALLOCSTATE_RES_INIT_DIRTY TBDB_NODESTATE_SHUTDOWN);
use libdb qw(TBDB_ALLOCSTATE_RES_INIT_DIRTY TBDB_NODESTATE_SHUTDOWN
TBResolveNextOSID);
sub Create($$$$$$)
{
......@@ -866,9 +666,7 @@ sub Provision($;$)
return -1;
}
}
# See below; remote nodes are currently assumed to be running.
$self->SetStatus("ready")
if (!($node->isremotenode() && $node->isvirtnode()));
$self->SetStatus("ready");
return 0;
}
......@@ -1010,12 +808,6 @@ sub Start($)
if ($reservation->SameExperiment($experiment)) {
my $node_id = $node->node_id();
# XXX Need to fix up this status stuff.
if ($node->isremotenode() && $self->status() eq "created") {
$self->SetStatus("ready");
goto done;
}
#
# Reboot and wait?
#
......
......@@ -15,7 +15,7 @@ use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw (TICKET_PURGED TICKET_EXPIRED TICKET_REDEEMED
TICKET_RELEASED TICKET_DELETED);
TICKET_RELEASED TICKET_DELETED TICKET_NOSTATS);
use GeniDB;
use GeniCredential;
......@@ -50,6 +50,7 @@ sub TICKET_REDEEMED() { return 2; }
sub TICKET_EXPIRED() { return 3; }
sub TICKET_RELEASED() { return 4; }
sub TICKET_DELETED() { return 5; }
sub TICKET_NOSTATS() { return 0x1; }
# Cache of tickets.
my %tickets = ();
......@@ -145,6 +146,7 @@ sub Create($$$$)
$self->{'seqno'} = $seqno;
$self->{'ticket_string'} = undef;
$self->{'component'} = undef;
$self->{'slice_uuid'} = undef;
$self->{'stored'} = 0; # Stored to the DB.
$self->{'LOCKED'} = 0;
......@@ -183,10 +185,12 @@ sub ticket($) { return field($_[0], "ticket"); }
sub asString($) { return field($_[0], "ticket_string"); }
sub ticket_string($) { return field($_[0], "ticket_string"); }
sub redeem_before($) { return field($_[0], "redeem_before"); }
sub expires($) { return field($_[0], "expires"); }
sub redeemed($ ) { return field($_[0], "redeemed"); }
sub component_uuid($) { return field($_[0], "component_uuid"); }
sub component($) { return field($_[0], "component"); }
sub stored($) { return field($_[0], "stored"); }
sub slice_uuid($) { return field($_[0], "slice_uuid"); }
sub LOCKED($) { return $_[0]->{'LOCKED'}; }
#
......@@ -201,9 +205,10 @@ sub Stringify($)
my $seqno = $self->seqno();
$idx = "S$seqno";
}
my $owner_hrn = $self->owner_hrn();
my $owner_hrn = $self->owner_hrn();
my $target_uuid = $self->target_uuid();
return "[GeniTicket: $idx, owner:$owner_hrn]";
return "[GeniTicket: $idx, owner:$owner_hrn, target_uuid:$target_uuid]";
}
#
......@@ -336,6 +341,25 @@ sub CreateFromSignedTicket($$;$$)
return undef;
}
# Expiration
my ($expires_node) = $doc->getElementsByTagName("expires");
if (!defined($expires_node)) {
print STDERR "Ticket is missing expires node\n";
return undef;
}
my $expires = $expires_node->to_literal();
if (! ($expires =~ /^[-\w:.\/]+/)) {
print STDERR "Invalid expires date in ticket\n";
return undef;
}
# Convert to a localtime.
my $when = timegm(strptime($expires));
if (!defined($when)) {
print STDERR "Could not parse expires: '$expires'\n";
return undef;
}
my $self = {};
$self->{'idx'} = undef;
$self->{'rspec'} = $rspec;
......@@ -350,7 +374,9 @@ sub CreateFromSignedTicket($$;$$)
$self->{'xmlref'} = $doc;
$self->{'component'} = $component;
$self->{'seqno'} = $seqno;
$self->{'expires'} = $expires;
$self->{'stored'} = 0;
$self->{'slice_uuid'} = undef;
$self->{'LOCKED'} = 0;
#
......@@ -364,6 +390,7 @@ sub CreateFromSignedTicket($$;$$)
if ($query_result && $query_result->numrows) {
my $row = $query_result->fetchrow_hashref();
$self->{'redeem_before'} = $row->{'redeem_before'};
$self->{'slice_uuid'} = $row->{'slice_uuid'};
$self->{'idx'} = $seqno;
$self->{'stored'} = 1;
}
......@@ -470,6 +497,14 @@ sub UnLock($)
return 0;
}
sub SetSlice($$)
{
my ($self, $slice_uuid) = @_;
$self->{'slice_uuid'} = $slice_uuid;
return 0;
}
#
# Return the rspec in XML for the ticket.
#
......@@ -507,17 +542,21 @@ sub Grant($$)
# so we have a record of them. We store them on the server and the client
# side.
#
sub Store($)
sub Store($;$)
{
my ($self) = @_;
my ($self, $flags) = @_;
my @insert_data = ();
$flags = 0
if (!defined($flags));
my $idx = $self->idx();
my $seqno = $self->seqno();
my $target_uuid = $self->target_uuid();
my $owner_uuid = $self->owner_uuid();
my $ticket_uuid = $self->ticket_uuid();
my $expires = $self->redeem_before();
my $expires = $self->redeem_before() || $self->expires();
my $slice_uuid = $self->slice_uuid();
#
# For a locally created/signed ticket, seqno=idx. For a ticket from
......@@ -539,6 +578,7 @@ sub Store($)
push(@insert_data, "ticket_uuid='$ticket_uuid'");
push(@insert_data, "target_uuid='$target_uuid'");
push(@insert_data, "owner_uuid='$owner_uuid'");
push(@insert_data, "slice_uuid='$slice_uuid'");
push(@insert_data, "redeem_before='$expires'");
my $safe_ticket = DBQuoteSpecial($self->ticket_string());
......@@ -548,9 +588,11 @@ sub Store($)
DBQueryWarn("insert into geni_tickets set " . join(",", @insert_data))
or return -1;
if (GeniUsage->NewTicket($self)) {
print STDERR
"GeniTicket::Store: GeniUsage->NewTicket($self) failed\n";
if (! ($flags & TICKET_NOSTATS)) {
if (GeniUsage->NewTicket($self)) {
print STDERR
"GeniTicket::Store: GeniUsage->NewTicket($self) failed\n";
}
}
$tickets{"$idx"} = $self;
......@@ -675,6 +717,72 @@ sub Release($$)
{
my ($self, $flag) = @_;
return -1
if (! ref($self));
$self->ReleaseHolding($flag) == 0
or return -1;
# Older tickets do not have this, but handled in ReleaseHolding.
return 0
if (!defined($self->slice_uuid()) || $self->slice_uuid() eq "");
my $experiment = Experiment->Lookup($self->slice_uuid());
if (!defined($experiment)) {
$self->Delete($flag);
return 0;
}
my $pid = $experiment->pid();
my $eid = $experiment->eid();
my @nodeids = ();
my @nodes = ();
foreach my $ref (@{$self->rspec()->{'node'}}) {
my $resource_uuid = $ref->{'component_uuid'} || $ref->{'uuid'};
# Virtual nodes not created until ticket redeemed.
my $node = Node->Lookup($resource_uuid);
next
if (!defined($node));
my $reservation = $node->Reservation();
next
if (!defined($reservation));
# Watch for duplicates, as in multiple vnodes on a pnode.
next
if (grep {$_ eq $node->node_id()} @nodeids);
#
# If the node is still in the experiment and not incorporated,
# release it. genisliver_idx is not defined until ticket redeemed.
#
if ($reservation->SameExperiment($experiment)) {
my $restable = $node->ReservedTableEntry();
if (defined($restable) &&
!defined($restable->{'genisliver_idx'})) {
push(@nodeids, $node->node_id());
push(@nodes, $node);
}
}
}
if (@nodeids) {
system("export NORELOAD=1; $NFREE -x -q $pid $eid @nodeids");
}
foreach my $node (@nodes) {
$node->Refresh();
}
$self->Delete($flag);
return 0;
}
#