Commit d302bf98 authored by Leigh Stoller's avatar Leigh Stoller

Checkpoint

parent 434ad9ae
......@@ -123,10 +123,10 @@ CREATE TABLE `geni_slivers` (
`resource_type` varchar(40) NOT NULL default '',
`created` datetime default NULL,
`credential_idx` int(10) unsigned default NULL,
`ticket_idx` int(10) unsigned default NULL,
`component_idx` int(10) unsigned NOT NULL default '0',
`aggregate_idx` int(10) unsigned default NULL,
`component_uuid` varchar(40) default NULL,
`aggregate_uuid` varchar(40) default NULL,
`status` enum('ready','broken') NOT NULL default 'ready',
`rspec_string` text,
PRIMARY KEY (`idx`),
UNIQUE KEY `uuid` (`uuid`),
INDEX `slice_uuid` (`slice_uuid`)
......@@ -221,13 +221,11 @@ CREATE TABLE `geni_userkeys` (
#
DROP TABLE IF EXISTS `geni_resources`;
CREATE TABLE `geni_resources` (
`idx` mediumint(8) unsigned NOT NULL default '0',
`resource_uuid` varchar(40) NOT NULL default '',
`resource_type` varchar(40) NOT NULL default '',
`created` datetime default NULL,
`component_idx` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`idx`),
UNIQUE KEY `resource_uuid` (`resource_uuid`)
`component_uuid` varchar(40) NOT NULL default '',
PRIMARY KEY (`resource_uuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
#
......
......@@ -17,7 +17,7 @@ LIB_SCRIPTS = GeniDB.pm GeniUser.pm GeniSAClient.pm \
GeniComponent.pm GeniCH.pm GeniCHClient.pm GeniEmulab.pm \
GeniAuthority.pm GeniCertificate.pm GeniAggregate.pm
SCRIPTS = test.pl node.pl test2.pl addauthority
SCRIPTS = test.pl addnode.pl test2.pl addauthority
OPS_LIBS = GeniCMClient.pm GeniSAClient.pm GeniCHClient.pm
#
......
......@@ -178,6 +178,8 @@ sub PrefixMatch($$)
my $uuid_prefix = $self->uuid_prefix();
print "$uuid, $uuid_prefix, $self\n";
if ($uuid =~ /^\w+\-\w+\-\w+\-\w+\-(\w+)$/) {
return 1
if ("$uuid_prefix" eq "$1");
......
......@@ -325,7 +325,12 @@ sub Register($)
#
# Need to verify the UUID is permitted for the SA making the request.
#
if (! $authority->PrefixMatch($uuid)) {
my $slice_authority = GeniAuthority->Lookup($ENV{'GENIUUID'});
if (!defined($slice_authority)) {
print STDERR "Could not find authority object for caller.\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
if (! $slice_authority->PrefixMatch($uuid)) {
return GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"uuid: Prefix mismatch");
}
......@@ -355,7 +360,7 @@ sub Register($)
"uid: ". TBFieldErrorString());
}
my $newuser = GeniUser->Create($hrn, $uid, $uuid,
$name, $email, $cert, $authority,
$name, $email, $cert, $slice_authority,
$keys);
if (!defined($newuser)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
......@@ -397,10 +402,16 @@ sub Register($)
#
# Need to verify the UUID is permitted for the SA making the request.
#
if (! $authority->PrefixMatch($uuid)) {
my $slice_authority = GeniAuthority->Lookup($ENV{'GENIUUID'});
if (!defined($slice_authority)) {
print STDERR "Could not find authority object for caller.\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
if (! $slice_authority->PrefixMatch($uuid)) {
return GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"uuid: Prefix mismatch");
}
#
# Make sure slice hrn and uuid are unique.
#
......@@ -410,7 +421,7 @@ sub Register($)
}
my $newslice = GeniSlice->Create($hrn, $uuid, $creator_uuid,
$cert, $authority);
$cert, $slice_authority);
if (!defined($newslice)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"$hrn/$uuid could not be registered");
......
......@@ -54,6 +54,106 @@ my $AVAIL = "$TB/sbin/avail";
my $TBSWAP = "$TB/bin/tbswap";
my $SWAPEXP = "$TB/bin/swapexp";
#
# Respond to a GetTicket request.
#
sub Resolve($)
{
my ($argref) = @_;
my $uuid = $argref->{'uuid'};
my $hrn = $argref->{'hrn'};
my $cred = $argref->{'credential'};
my $type = $argref->{'type'};
if (! defined($cred)) {
return GeniResponse->MalformedArgsResponse();
}
if (! (defined($type) && ($type =~ /^(Node)$/))) {
return GeniResponse->MalformedArgsResponse();
}
# Allow lookup by uuid or hrn.
if (! (defined($uuid) || defined($hrn))) {
return GeniResponse->MalformedArgsResponse();
}
if (defined($uuid) && !($uuid =~ /^[-\w]*$/)) {
return GeniResponse->MalformedArgsResponse();
}
if (defined($hrn) && !($hrn =~ /^[-\w\.]*$/)) {
return GeniResponse->MalformedArgsResponse();
}
my $credential = GeniCredential->CreateFromSigned($cred);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create GeniCredential object");
}
#
# Make sure the credential was issued to the caller, but no special
# permission required to resolve component resources.
#
if ($credential->owner_uuid() ne $ENV{'GENIUUID'}) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"This is not your credential!");
}
if ($type eq "Node") {
my $node;
if (defined($uuid)) {
$node= Node->Lookup($uuid);
}
else {
#
# We only want the last token for node lookup.
#
if ($hrn =~ /\./) {
($hrn) = ($hrn =~ /\.(\w*)$/);
}
$node= Node->Lookup($hrn);
}
if (!defined($node)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED,
undef, "Nothing here by that name");
}
# Return a blob.
my $blob = { "hrn" => "${OURDOMAIN}." . $node->node_id(),
"uuid" => $node->uuid(),
};
#
# Get the list of interfaces for the node.
#
my @interfaces;
if ($node->AllInterfaces(\@interfaces) != 0) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not get interfaces for $uuid");
}
my @iblobs = ();
foreach my $interface (@interfaces) {
my $iblob = { "uuid" => $interface->uuid(),
"iface" => $interface->iface(),
"type" => $interface->type(),
"card" => $interface->card(),
"port" => $interface->port(),
"role" => $interface->role(),
"IP" => $interface->IP(),
"mask" => $interface->mask(),
"MAC" => $interface->mac(),
};
push(@iblobs, $iblob);
}
$blob->{'interfaces'} = \@iblobs
if (@iblobs);
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
return GeniResponse->Create(GENIRESPONSE_UNSUPPORTED);
}
#
# Discover resources on this component, returning a resource availablity spec
#
......@@ -111,7 +211,11 @@ sub DiscoverResources($)
$xml .= "<node uuid=\"$uuid\" name=\"$nodeid\">".
"<available>true</available></node>\n";
my @interfaces = Interface->LookupAll($node);
my @interfaces;
if ($node->AllInterfaces(\@interfaces) != 0) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not get interfaces for $uuid");
}
foreach my $interface (@interfaces) {
my $iface_uuid = $interface->uuid();
my $iface = $interface->iface();
......@@ -369,7 +473,7 @@ sub RedeemTicket($)
next;
}
}
if (!$otheruser->BindToSlice($slice) != 0) {
if ($otheruser->BindToSlice($slice) != 0) {
print STDERR "Could not bind $otheruser to $slice\n";
}
}
......@@ -393,13 +497,17 @@ sub RedeemTicket($)
#
my %slivers = ();
foreach my $ref (@{$ticket->rspec()->{'node'}}) {
my $virtualization_type = $ref->{'virtualization_type'};
my $resource_uuid = $ref->{'uuid'};
my $node = Node->Lookup($resource_uuid);
if (!defined($node)) {
$message = "Unknown resource_uuid in ticket: $resource_uuid";
goto bad;
}
my $sliver = GeniSliver::Node->Create($slice, $owner, $resource_uuid);
my $sliver = GeniSliver::Node->Create($slice,
$owner->uuid(),
$resource_uuid,
$ref);
if (!defined($sliver)) {
$message = "Could not create GeniSliver object for $resource_uuid";
goto bad;
......@@ -451,8 +559,10 @@ sub RedeemTicket($)
$message = "No such interface $iface on node $nodeobject";
goto bad;
}
my $sliver = GeniSliver::Interface->Create($slice, $owner,
$interface->uuid());
my $sliver = GeniSliver::Interface->Create($slice,
$owner->uuid(),
$interface->uuid(),
$ticket->rspec()->{'link'}->{$linkname});
if (!defined($sliver)) {
$message = "Could not create GeniSliver ".
"$interface in $linkname";
......
......@@ -168,7 +168,7 @@ sub LookupByResource($$)
if (! ($uuid =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/));
my $query_result =
DBQueryWarn("select component_idx from geni_resources ".
DBQueryWarn("select component_uuid from geni_resources ".
"where resource_uuid='$uuid'");
return undef
......@@ -189,15 +189,15 @@ sub NewResource($$)
return -1
if (! ref($self));
my $idx = TBGetUniqueIndex('next_resource', 1);
my $component_idx = $self->idx();
my $component_uuid = $self->uuid();
$uuid = DBQuoteSpecial("$uuid");
return -1
if (! DBQueryWarn("replace into geni_resources set ".
" idx=$idx, resource_uuid=$uuid, ".
" resource_uuid=$uuid, ".
" resource_type='node', ".
" created=now(), component_idx=$component_idx"));
" created=now(), ".
" component_uuid='$component_uuid'"));
return 0;
}
......@@ -312,17 +312,12 @@ sub DiscoverResources($$$$$)
#
sub GetTicket($$$$$;$)
{
my ($self, $slice, $rspec, $user, $credential, $vtopo) = @_;
my $rspec_xml = $rspec;
my ($self, $slice, $rspec_xml, $context, $credential, $vtopo) = @_;
# Must be a real reference.
return undef
if (! ref($self));
# The rspec is passed as XML. If we get a ref, convert it.
if (ref($rspec_xml)) {
$rspec_xml = XMLout($rspec_xml, RootName => "rspec");
}
my $args = { "credential" => $credential->asString(),
"impotent" => $impotent,
"rspec" => $rspec_xml };
......@@ -330,8 +325,7 @@ sub GetTicket($$$$$;$)
if (defined($vtopo));
my $response =
Genixmlrpc::CallMethodHTTP($self->url(),
$user, "GetTicket", $args);
Genixmlrpc::CallMethod($self->url(), $context, "GetTicket", $args);
return undef
if (!defined($response));
......@@ -350,17 +344,17 @@ sub GetTicket($$$$$;$)
#
sub CreateSliver($$$$)
{
my ($self, $slice, $ticket, $user) = @_;
my ($self, $slice, $ticket, $context) = @_;
# Must be a real reference.
return undef
if (! ref($self));
my $response =
Genixmlrpc::CallMethodHTTP($self->url(), $user,
"RedeemTicket",
{ "ticket" => $ticket->asString(),
"impotent" => $impotent });
Genixmlrpc::CallMethod($self->url(), $context,
"RedeemTicket",
{ "ticket" => $ticket->asString(),
"impotent" => $impotent });
return undef
if (!defined($response));
......@@ -377,8 +371,10 @@ sub CreateSliver($$$$)
return undef;
}
my $sliver = GeniSliver->Create($slice, $user, undef, undef,
$credential, $self);
my $sliver = GeniSliver::Client->Create($slice, $ticket->owner_uuid(),
$ticket->rspec(),
$credential, $self);
if (!defined($sliver)) {
print STDERR "Could not create local sliver object.\n";
return undef;
......@@ -391,7 +387,7 @@ sub CreateSliver($$$$)
#
sub DestroySliver($$$)
{
my ($self, $sliver, $user) = @_;
my ($self, $sliver, $context) = @_;
# Must be a real reference.
return -1
......@@ -402,11 +398,10 @@ sub DestroySliver($$$)
if (!defined($credential));
my $response =
Genixmlrpc::CallMethodHTTP($self->url(), $user,
"DeleteSliver",
{ "impotent" => $impotent,
"credential" =>
$credential->asString() });
Genixmlrpc::CallMethod($self->url(), $context,
"DeleteSliver",
{ "impotent" => $impotent,
"credential" => $credential->asString() });
if ($response->code() != GENIRESPONSE_SUCCESS) {
print STDERR "Could not destroy sliver $sliver\n";
......@@ -420,7 +415,7 @@ sub DestroySliver($$$)
#
sub StartSliver($$$)
{
my ($self, $sliver, $user) = @_;
my ($self, $sliver, $context) = @_;
# Must be a real reference.
return -1
......@@ -431,11 +426,10 @@ sub StartSliver($$$)
if (!defined($credential));
my $response =
Genixmlrpc::CallMethodHTTP($self->url(), $user,
"StartSliver",
{ "impotent" => $impotent,
"credential" =>
$credential->asString() });
Genixmlrpc::CallMethod($self->url(), $context,
"StartSliver",
{ "impotent" => $impotent,
"credential" => $credential->asString() });
if ($response->code() != GENIRESPONSE_SUCCESS) {
print STDERR "Could not start sliver $sliver\n";
......
......@@ -54,6 +54,16 @@ sub AllocateSlivers($$$)
my ($class, $experiment, $nodelist) = @_;
my $thisuser = User->ThisUser();
#
# The RPC context for this test script is mostly as an SA.
#
Genixmlrpc->SetContext(Genixmlrpc->Context("@prefix@/etc/genisa.pem"));
#
# except when it has to be as the user.
#
my $context = Genixmlrpc->UserContext($thisuser);
#
# Create a Geni user from current user doing the operation.
#
......@@ -105,7 +115,7 @@ sub AllocateSlivers($$$)
print STDERR "Could not sign slice credential $credential!\n";
return -1;
}
if ($credential->Store() == 0) {
if ($credential->Store() != 0) {
print STDERR "Could not store slice credential $credential!\n";
return -1;
}
......@@ -120,13 +130,28 @@ sub AllocateSlivers($$$)
# XXX We are still not using rspecs anywhere.
#
foreach my $node (@{ $nodelist }) {
my $sliver_idx;
return -1
if ($node->GetGeniSliverInfo(\$sliver_idx) != 0);
next
if ($node->genisliver_idx());
if ($sliver_idx);
#
# The node is a virtnode, but we want a ticket for the physnode.
#
my $physnode = Node->Lookup($node->phys_nodeid());
return -1
if (!defined($physnode));
my $node_uuid = $node->uuid();
my $rspec = {'node' => {$node_uuid =>
{"uuid" => $node_uuid}}};
my $node_uuid = $physnode->uuid();
my $rspec =
"<rspec xmlns=\"http://protogeni.net/resources/rspec/0.1\"> " .
" <node uuid=\"$node_uuid\" ".
" virtualization_type=\"emulab-vnode\"> " .
" </node>" .
"</rspec>";
#
# XXX The component is stored in the geni_resources table. Not sure
# how that will work out.
......@@ -141,7 +166,7 @@ sub AllocateSlivers($$$)
# Get ticket from component.
#
my $ticket = $component->GetTicket($slice, $rspec,
$thisuser, $credential);
$context, $credential);
if (!defined($ticket)) {
print STDERR "Could not get ticket from CM for $node\n";
......@@ -165,7 +190,7 @@ sub AllocateSlivers($$$)
# since an rspec can have multiple resources (nodes, links),
# and I have not figured out what to do for that yet.
#
if ($node->SetGeniSliverIDX($ticket->idx()) != 0) {
if ($node->SetGeniSliverInfo($ticket->idx()) != 0) {
print STDERR "Could not set sliver (ticket) idx for $node\n";
if ($ticket->Delete() != 0) {
print STDERR "Could not destroy $ticket\n";
......@@ -185,6 +210,16 @@ sub InstantiateSlivers($$$)
my ($class, $experiment, $nodelist) = @_;
my $thisuser = User->ThisUser();
#
# The RPC context for this test script is mostly as an SA.
#
Genixmlrpc->SetContext(Genixmlrpc->Context("@prefix@/etc/genisa.pem"));
#
# except when it has to be as the user.
#
my $context = Genixmlrpc->UserContext($thisuser);
my $slice = GeniSlice->Lookup($experiment->uuid());
if (!defined($slice)) {
print STDERR "No slice exists for $experiment. \n";
......@@ -200,9 +235,13 @@ sub InstantiateSlivers($$$)
# XXX We are still not using rspecs anywhere.
#
foreach my $node (@{ $nodelist }) {
$sliver_idx = $node->genisliver_idx();
my $sliver_idx;
return -1
if ($node->GetGeniSliverInfo(\$sliver_idx) != 0);
next
if (! $sliver_idx);
my $sliver = GeniSliver->Lookup($sliver_idx);
my $sliver = GeniSliver->Lookup($sliver_idx);
next
if (defined($sliver));
......@@ -217,18 +256,18 @@ sub InstantiateSlivers($$$)
#
# Create sliver on component using the ticket.
#
my $sliver = $component->CreateSliver($slice, $ticket, $thisuser);
$sliver = $component->CreateSliver($slice, $ticket, $context);
if (!defined($sliver)) {
print STDERR "Could not create sliver on $component for $node\n";
if ($ticket->Delete() != 0) {
print STDERR "Could not delete $ticket\n";
}
if ($node->SetGeniSliverIDX(0) != 0) {
if ($node->SetGeniSliverInfo(0) != 0) {
print STDERR "Could not clear sliver idx for $node\n";
}
return -1;
}
if ($node->SetGeniSliverIDX($sliver->idx()) != 0) {
if ($node->SetGeniSliverInfo($sliver->idx()) != 0) {
print STDERR "Could not set sliver idx for $node\n";
if ($ticket->Delete() != 0) {
print STDERR "Could not delete $ticket\n";
......@@ -246,6 +285,55 @@ sub InstantiateSlivers($$$)
return 0;
}
#
# Start the slivers.
#
sub StartSlivers($$$)
{
my ($class, $experiment, $nodelist) = @_;
my $thisuser = User->ThisUser();
#
# The RPC context for this test script is mostly as an SA.
#
Genixmlrpc->SetContext(Genixmlrpc->Context("@prefix@/etc/genisa.pem"));
#
# except when it has to be as the user.
#
my $context = Genixmlrpc->UserContext($thisuser);
my $slice = GeniSlice->Lookup($experiment->uuid());
if (!defined($slice)) {
print STDERR "No slice exists for $experiment. \n";
return -1;
}
foreach my $node (@{ $nodelist }) {
my $sliver_idx;
return -1
if ($node->GetGeniSliverInfo(\$sliver_idx) != 0);
next
if (! $sliver_idx);
my $sliver = GeniSliver->Lookup($sliver_idx);
if (!defined($sliver)) {
print STDERR "Could not find sliver for $node in $experiment\n";
return -1;
}
my $component = $sliver->GetComponent();
#
# Create sliver on component using the ticket.
#
if ($component->StartSliver($slice, $sliver, $context) != 0) {
print STDERR "Could not start $sliver on $component for $node\n";
return -1;
}
}
return 0;
}
#
# XXX Need to deal with links between nodes.
#
......@@ -255,6 +343,16 @@ sub DestroySlivers($$$)
my $thisuser = User->ThisUser();
my $errors = 0;
#
# The RPC context for this test script is mostly as an SA.
#
Genixmlrpc->SetContext(Genixmlrpc->Context("@prefix@/etc/genisa.pem"));
#
# except when it has to be as the user.
#
my $context = Genixmlrpc->UserContext($thisuser);
my $slice = GeniSlice->Lookup($experiment->uuid());
if (!defined($slice)) {
print STDERR "No local slice record for $experiment\n";
......@@ -267,10 +365,11 @@ sub DestroySlivers($$$)
# XXX We are still not using rspecs anywhere.
#
foreach my $node (@{ $nodelist }) {
my $sliver_idx;
return -1
if ($node->GetGeniSliverInfo(\$sliver_idx) != 0);
next
if (! $node->genisliver_idx());
$sliver_idx = $node->genisliver_idx();
if (! $sliver_idx);
my $sliver = GeniSliver->Lookup($sliver_idx);
if (!defined($sliver)) {
......@@ -287,12 +386,12 @@ sub DestroySlivers($$$)
}
next;
}
if ($sliver->Destroy != 0) {
if ($sliver->Destroy() != 0) {
print STDERR "Could not destroy $sliver for $node\n";
$errors++;
next;
}
if ($node->SetGeniSliverIDX(0) != 0) {
if ($node->SetGeniSliverInfo(0) != 0) {
print STDERR "Could not clear sliver idx for $node\n";
$errors++;
next;
......
This diff is collapsed.
......@@ -321,8 +321,10 @@ sub Store($)
# another component, we have to generate a locally unique idx for
# the DB insertion.
#
$idx = TBGetUniqueIndex('next_ticket', 1)
if (!defined($idx));
if (!defined($idx)) {
$idx = TBGetUniqueIndex('next_ticket', 1);
$self->{'idx'} = $idx;
}
# A locally generated ticket will not have a component. Might change that.
push(@insert_data, "component_idx=" . $self->component()->idx())
if (defined($self->component()));
......@@ -480,7 +482,7 @@ sub Release($)
}
}
if (@nodeids) {
system("export NORELOAD=1; $NFREE $pid $eid @nodeids");
system("export NORELOAD=1; $NFREE -x -q $pid $eid @nodeids");
}
$self->Delete();
return 0;
......
......@@ -62,6 +62,16 @@ sub AddAuthority($$$$)
}
if (1) {
#
# On real boss.
#
$type = "sa";
$url = "https://www.emulab.net/protogeni/xmlrpc/sa";
$hrn = "sa.emulab.net";
$filename = "@prefix@/etc/genisa.pem";
AddAuthority($type, $url, $hrn, $filename);
}
else {
$type = "sa";
$url = "https://myboss.myelab.testbed.emulab.net/protogeni/xmlrpc/sa";
$hrn = "sa.myelab.testbed.emulab.net";
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2008 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
use lib '@prefix@/lib';
use Genixmlrpc;
use GeniResponse;
use GeniUser;
use GeniCredential;
use GeniComponent;
use English;
use Node;
use Interface;
use Data::Dumper;
my $this_user = User->LookupByUnixId($UID);
if (! defined($this_user)) {
print STDERR "You ($UID) do not exist!\n";
exit(-1);
}
#
# The RPC context for this test script is mostly as an SA, with some
# exceptions below.
#
Genixmlrpc->SetContext(Genixmlrpc->Context("@prefix@/etc/genisa.pem"));
#
# Create a Geni user from local user.
#
my $geniuser = GeniUser->CreateFromLocal($this_user);
if (!defined($geniuser)) {
die("Could not create a geni user from local user $this_user\n");
}
# Register at the ClearingHouse.
$geniuser->Register() == 0
or die("Could not register $geniuser at the Geni ClearingHouse.\n");
#
# Need a credential to resolve a node.
#
my $credential = GeniCredential->Create($geniuser, $geniuser);
if (!defined($credential)) {
die("Could not create credential from $geniuser\n");
}
if ($credential->Sign($GeniCredential::LOCALSA_FLAG)) {
die("Could not sign credential for $geniuser\n");
}
#
# My RPC context.