Commit bd282b7d authored by Leigh B. Stoller's avatar Leigh B. Stoller

API changes to the CM as documented in protogeni wiki at:

https://www.protogeni.net/trac/protogeni/wiki/ComponentManagerAPI
parent 16e6a11a
......@@ -111,8 +111,10 @@ CREATE TABLE `geni_tickets` (
`ticket_uuid` varchar(40) NOT NULL default '',
`owner_uuid` varchar(40) NOT NULL default '',
`slice_uuid` varchar(40) NOT NULL default '',
`target_uuid` varchar(40) NOT NULL default '',
`created` datetime default NULL,
`redeem_before` datetime default NULL,
`redeemed` datetime default NULL,
`locked` datetime default NULL,
`valid_until` datetime default NULL,
`component_uuid` varchar(40) NOT NULL default '',
......@@ -161,6 +163,15 @@ CREATE TABLE `geni_crls` (
PRIMARY KEY (`uuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `geni_manifests` (
`idx` int(10) unsigned NOT NULL auto_increment,
`slice_uuid` varchar(40) NOT NULL default '',
`created` datetime default NULL,
`manifest` text,
PRIMARY KEY (`idx`),
UNIQUE KEY `slice_uuid` (`slice_uuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `geni_userkeys`;
CREATE TABLE `geni_userkeys` (
`type` enum('ssh','password') NOT NULL default 'ssh',
......@@ -242,7 +253,9 @@ CREATE TABLE `ticket_history` (
`owner_uuid` varchar(40) NOT NULL default '',
`owner_hrn` varchar(256) NOT NULL default '',
`slice_uuid` varchar(40) NOT NULL default '',
`target_uuid` varchar(40) NOT NULL default '',
`slice_hrn` varchar(256) NOT NULL default '',
`target_hrn` varchar(256) NOT NULL default '',
`created` datetime default NULL,
`redeemed` datetime default NULL,
`expired` datetime default NULL,
......
......@@ -23,6 +23,7 @@ use GeniCertificate;
use GeniSliver;
use GeniSlice;
use GeniRegistry;
use GeniUtil;
use emutil;
use English;
use overload ('""' => 'Stringify');
......@@ -145,7 +146,6 @@ sub Create($$$$$$)
my $uuid = $certificate->uuid();
my $slice_uuid = $slice->uuid();
my $owner_uuid = $owner->uuid();
$aggregate_type = "Aggregate"
if (! defined($aggregate_type));
......@@ -809,19 +809,22 @@ use GeniCredential;
use GeniCertificate;
use GeniRegistry;
use GeniAggregate;
use GeniUtil;
use Experiment;
use Interface;
use Data::Dumper;
sub Create($$$$$$)
{
my ($class, $slice, $owner, $node1sliver, $node2sliver, $rspec) = @_;
my ($class, $slice, $owner, $node1sliver, $node2sliver,
$linkrspec, $node1rspec, $node2rspec) = @_;
my $clearinghouse;
my $linkname = $rspec->{'nickname'};
my $linkname = $linkrspec->{"nickname"} || $linkrspec->{"virtual_id"};
return undef
if (!defined($linkname));
my @interfaces = @{ $linkrspec->{'interface_ref'} };
my $experiment = Experiment->Lookup($slice->uuid());
if (!defined($experiment)) {
print STDERR "Could not map $slice to its experiment\n";
......@@ -847,12 +850,12 @@ sub Create($$$$$$)
return undef;
}
my $node1ref = (@{$rspec->{'linkendpoints'}})[0];
my $node2ref = (@{$rspec->{'linkendpoints'}})[1];
my $iface1ref = $interfaces[0];
my $iface2ref = $interfaces[1];
# These are the ips of the tunnel.
my $ip1 = $node1ref->{'tunnel_ip'};
my $ip2 = $node2ref->{'tunnel_ip'};
my $ip1 = $iface1ref->{'tunnel_ip'};
my $ip2 = $iface2ref->{'tunnel_ip'};
my $ctrlip1;
my $ctrlip2;
my $iface1;
......@@ -861,7 +864,11 @@ sub Create($$$$$$)
# We need the control network addresses, but it is possible that
# one of the nodes is not on this testbed.
if (defined($node1sliver)) {
my $node1 = Node->Lookup($node1ref->{'node_uuid'});
my $node1 = Node->Lookup($node1sliver->resource_uuid());
if (!defined($node1)) {
print STDERR "Tunnel: Could not lookup node for $node1sliver\n";
goto bad;
}
my $interface = Interface->LookupControl($node1);
goto bad
if (!defined($interface));
......@@ -879,7 +886,7 @@ sub Create($$$$$$)
$clearinghouse = GeniRegistry::ClearingHouse->Create();
my $blob;
if ($clearinghouse->Resolve($node1ref->{'node_uuid'},
if ($clearinghouse->Resolve($node1rspec->{'component_uuid'},
"Component", \$blob) != 0) {
print STDERR "Could not lookup node at clearinghouse\n";
goto bad;
......@@ -909,18 +916,22 @@ sub Create($$$$$$)
print STDERR "Could not create a registry client for $component\n";
goto bad;
}
$registry->Resolve($node1ref->{'node_uuid'}, "Node", \$blob);
$registry->Resolve($node1rspec->{'component_uuid'}, "Node", \$blob);
$ctrlip1 = $blob->{'physctrl'}
if (defined($blob) && exists($blob->{'physctrl'}));
if (!defined($ctrlip1)) {
print STDERR "Could get control IP for ".
"$node1ref->{'node_uuid'} at $component\n";
"$node1rspec->{'component_uuid'} at $component\n";
goto bad;
}
}
if (defined($node2sliver)) {
my $node2 = Node->Lookup($node2ref->{'node_uuid'});
my $node2 = Node->Lookup($node2sliver->resource_uuid());
if (!defined($node2)) {
print STDERR "Tunnel: Could not lookup node for $node2sliver\n";
goto bad;
}
my $interface = Interface->LookupControl($node2);
goto bad
if (!defined($interface));
......@@ -939,7 +950,7 @@ sub Create($$$$$$)
if (!defined($clearinghouse));
my $blob;
if ($clearinghouse->Resolve($node2ref->{'node_uuid'},
if ($clearinghouse->Resolve($node2rspec->{'component_uuid'},
"Component", \$blob) != 0) {
print STDERR "Could not lookup node at clearinghouse\n";
goto bad;
......@@ -968,13 +979,13 @@ sub Create($$$$$$)
print STDERR "Could not create a registry client for $component\n";
goto bad;
}
$registry->Resolve($node2ref->{'node_uuid'}, "Node", \$blob);
$registry->Resolve($node2rspec->{'component_uuid'}, "Node", \$blob);
$ctrlip2 = $blob->{'physctrl'}
if (defined($blob) && exists($blob->{'physctrl'}));
if (!defined($ctrlip2)) {
print STDERR "Could get control IP for ".
"$node2ref->{'node_uuid'} at $component\n";
"$node2rspec->{'component_uuid'} at $component\n";
goto bad;
}
}
......@@ -1005,7 +1016,7 @@ sub Create($$$$$$)
bad:
$tunnel->Destroy()
if (defined($tunnel));
$aggregate->Delete(1)
$aggregate->Delete(GENI_PURGEFLAG)
if (defined($aggregate));
return undef;
}
......
......@@ -687,9 +687,9 @@ sub Shutdown($)
# Pass the whole thing off to a script that will contact the
# CMs.
#
my $arg = ($clear ? "resume": "");
my $opt = ($clear ? "-u": "");
# -c option indicates acting as CH.
system("$SLICESHUTDOWN -c $uuid $arg");
system("$SLICESHUTDOWN -c $opt $uuid");
if ($?) {
print STDERR "Could not shutdown $uuid!\n";
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
......
This diff is collapsed.
......@@ -473,9 +473,6 @@ use GeniHRN;
use English;
use emdb;
# Configure variables
my $OURDOMAIN = "@OURDOMAIN@";
#
# Create a wrapper, with the same access names.
#
......
......@@ -464,14 +464,14 @@ sub RemoveSlice($$)
#
sub Shutdown($$$)
{
my ($self, $uuid, $onoff) = @_;
my ($self, $uuid, $clear) = @_;
my $response =
Genixmlrpc::CallMethod($self->authority(),
$self->context(),
"Shutdown",
{ "credential" => $self->credential(),
"onoff" => $onoff,
"clear" => $clear,
"uuid" => $uuid });
return -1
if (!defined($response) || $response->code() != GENIRESPONSE_SUCCESS);
......
......@@ -17,6 +17,7 @@ use GeniRegistry;
use GeniAuthority;
use GeniCredential;
use GeniCertificate;
use GeniAggregate;
use English;
use Data::Dumper;
use vars qw();
......
......@@ -687,6 +687,7 @@ use GeniComponent;
use GeniSlice;
use GeniCredential;
use GeniCertificate;
use GeniUtil;
use Experiment;
use XML::Simple;
use libdb qw(TBDB_ALLOCSTATE_RES_INIT_DIRTY);
......@@ -701,6 +702,12 @@ sub Create($$$$$$)
print STDERR "Could not map $slice to its experiment\n";
return undef;
}
$sliver_uuid = GeniUtil::NewUUID()
if (!defined($sliver_uuid));
if (!defined($sliver_uuid)) {
print STDERR "Could not generate a sliver UUID for node in $slice\n";
return undef;
}
#
# the node is already allocated to the sliver, but still need to enter
......@@ -719,13 +726,13 @@ sub Create($$$$$$)
return undef;
}
if (! $reservation->SameExperiment($experiment)) {
print STDERR "$node is reserved to another, not $reservation\n";
print STDERR "$node is reserved to another, not $experiment\n";
# Signal error so we can look at what happened.
return undef;
}
}
my $hrn = "${PGENIDOMAIN}." . $node->node_id();
my $nickname = $rspec->{'nickname'};
my $nickname = $rspec->{'virtual_id'};
#
# The resource UUID refers to the physical node, but the virtualization
......@@ -809,7 +816,7 @@ sub Provision($;$)
return -1;
}
if (! $reservation->SameExperiment($experiment)) {
print STDERR "$node is reserved to another, not $reservation\n";
print STDERR "$node is reserved to another, not $experiment\n";
# Signal error so we can look at what happened.
return -1;
}
......@@ -918,12 +925,14 @@ sub Provision($;$)
#
# Unprovision a sliver.
#
sub UnProvision($)
sub UnProvision($;$)
{
my ($self) = @_;
my ($self, $nophysfree) = @_;
return -1
if (! ref($self));
$nophysfree = 0
if (!defined($nophysfree));
my $experiment = Experiment->Lookup($self->slice_uuid());
if (!defined($experiment)) {
......@@ -981,7 +990,7 @@ sub UnProvision($)
return -1;
}
if (scalar(@vnodes) > 1) {
if (scalar(@vnodes) > 1 || $nophysfree) {
system("$NFREE -q $pid $eid $node_id");
}
else {
......@@ -995,6 +1004,8 @@ sub UnProvision($)
}
}
else {
goto skip
if (!$nophysfree);
system("$NFREE -q $pid $eid $node_id");
}
if ($?) {
......@@ -1002,6 +1013,7 @@ sub UnProvision($)
$node->Refresh();
return -1;
}
skip:
$node->Refresh();
}
else {
......@@ -1080,11 +1092,11 @@ use GeniCertificate;
sub Create()
{
my ($class, $slice, $user,
$interface_uuid, $node, $rspec) = @_;
$interface_uuid, $node, $linkname, $rspec) = @_;
my $nickname = $rspec->{'nickname'};
my $hrn = "${PGENIDOMAIN}." .
$node->node_id() . "." . $rspec->{'iface_name'};
my $nickname = $node->node_id() . ".$linkname." .
$rspec->{'virtual_interface_id'};
my $hrn = "${PGENIDOMAIN}.$nickname";
return GeniSliver->Create($slice, $user, $interface_uuid,
$node->uuid(), "Interface",
......
<
......@@ -14,7 +14,8 @@ use Exporter;
use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw (TICKET_PURGED TICKET_EXPIRED TICKET_REDEEMED TICKET_RELEASED);
@EXPORT = qw (TICKET_PURGED TICKET_EXPIRED TICKET_REDEEMED
TICKET_RELEASED TICKET_DELETED);
use GeniDB;
use GeniCredential;
......@@ -48,6 +49,7 @@ sub TICKET_PURGED() { return 1; }
sub TICKET_REDEEMED() { return 2; }
sub TICKET_EXPIRED() { return 3; }
sub TICKET_RELEASED() { return 4; }
sub TICKET_DELETED() { return 5; }
# Cache of tickets.
my %tickets = ();
......@@ -65,14 +67,29 @@ BEGIN {
#
sub Lookup($$)
{
my ($class, $idx) = @_;
my ($class, $token) = @_;
my $idx;
my $query_result;
return undef
if (! ($idx =~ /^\d*$/));
if ($token =~ /^\d+$/) {
$idx = $token;
}
elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
$query_result =
DBQueryWarn("select idx from geni_tickets ".
"where ticket_uuid='$token'");
return undef
if (! $query_result || !$query_result->numrows);
($idx) = $query_result->fetchrow_array();
}
else {
return undef;
}
return $tickets{"$idx"}
if (exists($tickets{"$idx"}));
my $query_result =
$query_result =
DBQueryWarn("select * from geni_tickets where idx='$idx'");
return undef
......@@ -99,60 +116,37 @@ sub Lookup($$)
# Mark as coming from the DB.
$ticket->{'idx'} = $idx;
$ticket->{'stored'} = 1;
$ticket->{'LOCKED'} = 0;
# Cache.
$tickets{"$idx"} = $ticket;
return $ticket;
}
#
# Lookup a ticket for a slice. This assumes only a single slice ticket.
#
sub LookupForSlice($$)
{
my ($class, $slice) = @_;
return undef
if (! ref($slice));
my $slice_uuid = $slice->uuid();
my $query_result =
DBQueryWarn("select idx from geni_tickets ".
"where slice_uuid='$slice_uuid'");
return undef
if (!$query_result || !$query_result->numrows);
if ($query_result->numrows != 1) {
print STDERR "Too many tickets stored for $slice\n";
return undef;
}
my ($idx) = $query_result->fetchrow_array();
return GeniTicket->Lookup($idx);
}
#
# Create an unsigned ticket object, to be populated and signed and returned.
#
sub Create($$$$)
{
my ($class, $slice, $owner, $rspec) = @_;
my ($class, $target, $owner, $rspec) = @_;
# Every Ticket gets a new unique index (sequence number).
my $seqno = TBGetUniqueIndex('next_ticket', 1);
my $self = {};
$self->{'rspec'} = $rspec;
$self->{'ticket_uuid'} = undef;
$self->{'slice_uuid'} = $slice->uuid();
$self->{'owner_uuid'} = $owner->uuid();
$self->{'slice_hrn'} = $slice->hrn();
$self->{'owner_hrn'} = $owner->hrn();
$self->{'slice_cert'} = $slice->GetCertificate();
$self->{'owner_cert'} = $owner->GetCertificate();
$self->{'target_uuid'} = $target->uuid();
$self->{'target_hrn'} = $target->hrn();
$self->{'target_cert'} = $target->GetCertificate();
$self->{'seqno'} = $seqno;
$self->{'ticket_string'} = undef;
$self->{'component'} = undef;
$self->{'stored'} = 0; # Stored to the DB.
$self->{'LOCKED'} = 0;
#
# For now, all tickets expire very quickly ...
......@@ -177,13 +171,11 @@ sub field($$) { return ($_[0]->{$_[1]}); }
sub idx($) { return field($_[0], "idx"); }
sub seqno($) { return field($_[0], "seqno"); }
sub rspec($) { return field($_[0], "rspec"); }
sub slice_uuid($) { return field($_[0], "slice_uuid"); }
sub target_uuid($) { return field($_[0], "slice_uuid"); }
sub target_uuid($) { return field($_[0], "target_uuid"); }
sub owner_uuid($) { return field($_[0], "owner_uuid"); }
sub slice_hrn($) { return field($_[0], "slice_hrn"); }
sub target_hrn($) { return field($_[0], "slice_hrn"); }
sub target_hrn($) { return field($_[0], "target_hrn"); }
sub owner_hrn($) { return field($_[0], "owner_hrn"); }
sub slice_cert($) { return field($_[0], "slice_cert"); }
sub target_cert($) { return field($_[0], "target_cert"); }
sub owner_cert($) { return field($_[0], "owner_cert"); }
sub uuid($) { return field($_[0], "ticket_uuid"); }
sub ticket_uuid($) { return field($_[0], "ticket_uuid"); }
......@@ -191,9 +183,11 @@ 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 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 LOCKED($) { return $_[0]->{'LOCKED'}; }
#
# Stringify for output.
......@@ -207,9 +201,9 @@ sub Stringify($)
my $seqno = $self->seqno();
$idx = "S$seqno";
}
my $slice_uuid = $self->slice_uuid();
my $owner_hrn = $self->owner_hrn();
return "[GeniTicket: $idx, slice:$slice_uuid]";
return "[GeniTicket: $idx, owner:$owner_hrn]";
}
#
......@@ -264,15 +258,21 @@ sub CreateFromSignedTicket($$;$$)
# Dig out the rspec.
my ($rspec_node) = $doc->getElementsByTagName("rspec");
return undef
if (!defined($rspec_node));
my $rspec = XMLin($rspec_node->toString(), ForceArray => ["node",
"link"]);
if (!defined($rspec_node)) {
print STDERR "Ticket is missing rspec node\n";
return undef;
}
my $rspec = XMLin($rspec_node->toString(), KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints"]);
# Dig out the ticket uuid.
my ($uuid_node) = $doc->getElementsByTagName("uuid");
return undef
if (!defined($uuid_node));
if (!defined($uuid_node)) {
print STDERR "Ticket is missing uuid node\n";
return undef;
}
my $ticket_uuid = $uuid_node->to_literal();
if (! ($ticket_uuid =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
......@@ -282,12 +282,16 @@ sub CreateFromSignedTicket($$;$$)
# Dig out the target certificate.
my ($cert_node) = $doc->getElementsByTagName("target_gid");
return undef
if (!defined($cert_node));
if (!defined($cert_node)) {
print STDERR "Ticket is missing target gid node\n";
return undef;
}
my $target_certificate =
GeniCertificate->LoadFromString($cert_node->to_literal());
return undef
if (!defined($target_certificate));
if (!defined($target_certificate)) {
print STDERR "Could not get target certificate from string\n";
return undef;
}
if (!($target_certificate->uuid() =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
print STDERR "Invalid target_uuid in credential\n";
......@@ -300,14 +304,16 @@ sub CreateFromSignedTicket($$;$$)
# Dig out the owner certificate.
($cert_node) = $doc->getElementsByTagName("owner_gid");
return undef
if (!defined($cert_node));
if (!defined($cert_node)) {
print STDERR "Ticket is missing owner gid node\n";
return undef;
}
my $owner_certificate =
GeniCertificate->LoadFromString($cert_node->to_literal());
return undef
if (!defined($owner_certificate));
if (!defined($target_certificate)) {
print STDERR "Could not get owner certificate from string\n";
return undef;
}
if (!($owner_certificate->uuid() =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
print STDERR "Invalid target_uuid in credential\n";
return undef;
......@@ -319,8 +325,10 @@ sub CreateFromSignedTicket($$;$$)
# Sequence number
my ($seqno_node) = $doc->getElementsByTagName("serial");
return undef
if (!defined($seqno_node));
if (!defined($seqno_node)) {
print STDERR "Ticket is missing seqno node\n";
return undef;
}
my $seqno = $seqno_node->to_literal();
if (! ($seqno =~ /^\w+$/)) {
......@@ -332,33 +340,33 @@ sub CreateFromSignedTicket($$;$$)
$self->{'idx'} = undef;
$self->{'rspec'} = $rspec;
$self->{'ticket_uuid'} = $ticket_uuid;
$self->{'slice_uuid'} = $target_certificate->uuid();
$self->{'target_uuid'} = $target_certificate->uuid();
$self->{'owner_uuid'} = $owner_certificate->uuid();
$self->{'slice_hrn'} = $target_certificate->hrn();
$self->{'target_hrn'} = $target_certificate->hrn();
$self->{'owner_hrn'} = $owner_certificate->hrn();
$self->{'slice_cert'} = $target_certificate;
$self->{'target_cert'} = $target_certificate;
$self->{'owner_cert'} = $owner_certificate;
$self->{'ticket_string'} = $ticket_string;
$self->{'xmlref'} = $doc;
$self->{'component'} = $component;
$self->{'seqno'} = $seqno;
$self->{'stored'} = 0;
$self->{'LOCKED'} = 0;
#
# We save copies of the tickets we hand out; lets find that record
# in the DB, just to verify.
# We save copies of the tickets we hand out, but delete them
# when redeemed. If we still have it, mark it.
#
if (! $nosig) {
my $query_result =
DBQueryWarn("select * from geni_tickets where idx='$seqno'");
if (!$query_result || !$query_result->numrows) {
print STDERR "Could not find the ticket $seqno in the DB\n";
return undef;
if ($query_result && $query_result->numrows) {
my $row = $query_result->fetchrow_hashref();
$self->{'redeem_before'} = $row->{'redeem_before'};
$self->{'idx'} = $seqno;
$self->{'stored'} = 1;
}
my $row = $query_result->fetchrow_hashref();
$self->{'redeem_before'} = $row->{'redeem_before'};
$self->{'idx'} = $seqno;
$self->{'stored'} = 1;
}
bless($self, $class);
......@@ -388,11 +396,6 @@ sub Delete($$)
or print STDERR "GeniTicket::Delete: ".
"GeniUsage->DeleteTicket($self) failed\n";
}
elsif ($flag == TICKET_REDEEMED) {
GeniUsage->RedeemTicket($self) == 0
or print STDERR "GeniTicket::Delete: ".
"GeniUsage->RedeemTicket($self) failed\n";
}
elsif ($flag == TICKET_RELEASED) {
GeniUsage->ReleaseTicket($self) == 0
or print STDERR "GeniTicket::Delete: ".
......@@ -403,12 +406,70 @@ sub Delete($$)
or print STDERR "GeniTicket::Delete: ".