Commit 39956369 authored by Leigh Stoller's avatar Leigh Stoller

Checkpoint SFA support. Not fully working. Also some cleanup

to the GeniRegistry file; move the slice part back into GeniSlice
where it belongs.
parent 5b9b03a7
This diff is collapsed.
......@@ -66,9 +66,8 @@ sub Lookup($$)
$uuid = $token;
}
elsif ($token =~ /^P([\w]+)$/) {
# Only SAs are looked up this way.
# This will be flushed after URNs are fully pushed out.
return GeniAuthority->LookupByPrefix($1);
print STDERR "Deprecated authority lookup by prefix\n";
return undef;
}
elsif ($token =~ /^[\w\.]*$/) {
$query_result =
......@@ -94,9 +93,7 @@ sub Lookup($$)
my $self = {};
$self->{'AUTHORITY'} = $query_result->fetchrow_hashref();
$self->{'version'} = undef;
$self->{'apilevel'} = undef;
$self->{'api'} = undef;
$self->{'_version_info'} = undef;
bless($self, $class);
#
......@@ -180,9 +177,12 @@ sub url($) { return field($_[0], "url"); }
sub hrn($) { return field($_[0], "hrn"); }
sub type($) { return field($_[0], "type"); }
sub disabled($) { return field($_[0], "disabled"); }
sub version($) { return $_[0]->{"version"}; }
sub apilevel($) { return $_[0]->{"apilevel"}; }
sub api($) { return $_[0]->{"api"}; }
sub _version_info($) { return $_[0]->{"_version_info"}; }
sub version($) { return $_[0]->VersionInfo()->{"version"}; }
sub apilevel($) { return $_[0]->VersionInfo()->{"apilevel"}; }
sub api($) { return $_[0]->VersionInfo()->{"api"}; }
sub issfa($) { return $_[0]->VersionInfo()->{"issfa"}; }
sub versiondata($) { return $_[0]->VersionInfo()->{"versiondata"}; }
sub cert($) { return $_[0]->{'CERT'}->cert(); }
sub GetCertificate($) { return $_[0]->{'CERT'}; }
......@@ -266,6 +266,8 @@ sub CheckExisting($$)
#
# Create authority from the ClearingHouse, by looking up the info.
# All authorities are currently stored in the Utah Emulab ClearingHouse,
# at least until we can deal with multiple clearinghouses/registries.
#
sub CreateFromRegistry($$$)
{
......@@ -310,12 +312,12 @@ sub CreateFromRegistry($$$)
#
# Get Version. Ask the Authority what version it is running.
#
sub Version($)
sub VersionInfo($)
{
my ($self) = @_;
return $self->version()
if (defined($self->version()));
return $self->_version_info()
if (defined($self->_version_info()));
#
# The caller had to set up the xmlrpc context.
......@@ -332,38 +334,49 @@ sub Version($)
print STDERR " " . $response->output() . "\n";
return undef;
}
my $ref = {"versiondata" => $response->value() };
if (ref($response->value())) {
# Look for the AM interface.
if (exists($response->value()->{'geni_api'})) {
$self->{'version'} = $response->value()->{'geni_api'};
$ref->{'version'} = $response->value()->{'geni_api'};
# This was wrong; it should be 2.0 not 1.0
$self->{'version'} = 2.0 if ($self->{'version'} == 1.0);
$self->{'apilevel'} = 0;
$self->{'api'} = "AM";
$ref->{'version'} = 2.0 if ($ref->{'version'} == 1.0);
$ref->{'apilevel'} = 0;
$ref->{'api'} = "AM";
$ref->{'issfa'} = exists($response->value()->{'sfa'});
}
else {
$self->{'version'} = $response->value()->{'api'};
$self->{'apilevel'} = $response->value()->{'level'};
$self->{'api'} = "CM";
$ref->{'version'} = $response->value()->{'api'};
$ref->{'apilevel'} = $response->value()->{'level'};
$ref->{'api'} = "CM";
$ref->{'issfa'} = 0;
}
}
else {
$self->{'version'} = $response->value();
$self->{'apilevel'} = 1;
$self->{'api'} = "CM";
$ref->{'version'} = $response->value();
$ref->{'apilevel'} = 1;
$ref->{'api'} = "CM";
$ref->{'issfa'} = 0;
}
return $self->{'version'};
$self->{'_version_info'} = $ref;
return $ref;
}
# Ditto for the API level
sub ApiLevel($)
sub Version($)
{
my ($self) = @_;
return $self->apilevel()
if (defined($self->apilevel()));
return undef
if (!defined($self->VersionInfo()));
return $self->version();
}
sub ApiLevel($)
{
my ($self) = @_;
return undef
if (!defined($self->Version()));
if (!defined($self->VersionInfo()));
return $self->apilevel();
}
......@@ -371,14 +384,20 @@ sub Api($)
{
my ($self) = @_;
return $self->api()
if (defined($self->api()));
return undef
if (!defined($self->Version()));
if (!defined($self->VersionInfo()));
return $self->api();
}
sub IsSFA($)
{
my ($self) = @_;
return undef
if (!defined($self->VersionInfo()));
return $self->issfa();
}
#
# Check that the authority is the issuer of the given certificate.
......@@ -460,6 +479,21 @@ sub LookupByPrefix($$)
return GeniAuthority->Lookup($uuid);
}
#
# Set the disabled bit.
#
sub Disable($)
{
my ($self) = @_;
my $urn = $self->urn();
DBQueryWarn("update geni_authorities set disabled=1 ".
"where urn='$urn'")
or return -1;
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......@@ -19,7 +19,7 @@ use vars qw(@ISA @EXPORT);
#use Devel::TraceUse;
use GeniDB;
use Genixmlrpc;
use GeniRegistry;
use GeniSlice;
use GeniResponse;
use GeniUser;
use GeniComponent;
......@@ -268,21 +268,7 @@ sub Resolve($)
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
if ($type eq "sa") {
my $authority = GeniAuthority->Lookup($lookup_token);
if (!defined($authority)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No such authority $lookup_token");
}
# Return a blob.
my $blob = { "gid" => $authority->cert(),
"url" => $authority->url(),
"urn" => $authority->urn(),
"type" => $authority->type(),
};
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
if ($type eq "cm" || $type eq "am") {
if ($type eq "cm" || $type eq "am" || $type eq "sa") {
my $manager = GeniAuthority->Lookup($lookup_token);
if (!defined($manager)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
......@@ -309,7 +295,7 @@ sub Resolve($)
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
if ($type eq "slice") {
my $slice = GeniRegistry::GeniSlice->Lookup($lookup_token);
my $slice = GeniSlice->Lookup($lookup_token);
if (!defined($slice)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No such slice $lookup_token");
......@@ -702,7 +688,7 @@ sub Remove($)
"$token has been unregistered");
}
if ($type eq "Slice") {
my $slice = GeniRegistry::GeniSlice->Lookup($token);
my $slice = GeniSlice->Lookup($token);
if (!defined($slice)) {
return GeniResponse->Create(GENIRESPONSE_SUCCESS, undef,
"No such slice $token");
......@@ -762,7 +748,7 @@ sub Shutdown($)
return GeniResponse->Create( GENIRESPONSE_FORBIDDEN, undef,
"Insufficient privilege" );
my $slice = GeniRegistry::GeniSlice->Lookup($uuid || $urn);
my $slice = GeniSlice->Lookup($uuid || $urn);
if (!defined($slice)) {
if (!defined($urn)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
......@@ -925,7 +911,7 @@ sub List($)
if ($type eq "slices") {
my @slices;
if (GeniRegistry::GeniSlice->ListAll(\@slices) != 0) {
if (GeniSlice->ListAll(\@slices) != 0) {
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
foreach my $slice (@slices) {
......
......@@ -184,6 +184,7 @@ sub DiscoverResources($)
my $credstr = $argref->{'credential'};
my $available = $argref->{'available'} || 0;
my $compress = $argref->{'compress'} || 0;
my $version = $argref->{'rspec_version'} || undef;
my $credential = CheckCredential($credstr);
return $credential
......@@ -192,10 +193,18 @@ sub DiscoverResources($)
return DiscoverResourcesAux($available, $compress, [$credential]);
}
# Helper function for V2.
sub DiscoverResourcesAux($$$)
sub DiscoverResourcesAux($$$;$)
{
my ($available, $compress, $credentials) = @_;
my ($available, $compress, $credentials, $version) = @_;
my $user_urn = $ENV{'GENIRN'};
$version = "0.2"
if (!defined($version));
# Sanity check since this can come from client.
if (! ($version eq "0.1" || $version eq "0.2" ||$version eq "2.0")) {
return GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"Improper version request");
}
# Oh, for $*%(s sake. Frontier::RPC2 insists on representing a
# Boolean as its own object type -- which Perl always interprets as
......@@ -259,7 +268,7 @@ sub DiscoverResourcesAux($$$)
#
# Acquire the advertisement from ptopgen and compress it if requested.
#
my $xml = GetAdvertisement($available, undef, "0.2", $experiment);
my $xml = GetAdvertisement($available, undef, $version, $experiment);
if (! defined($xml)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start avail");
......
......@@ -24,6 +24,7 @@ use GeniResponse;
use GeniTicket;
use GeniCredential;
use GeniCertificate;
use GeniComponent;
use GeniSlice;
use GeniAggregate;
use GeniSliver;
......@@ -127,21 +128,58 @@ sub Resolve($)
my $node = $object;
my $rspec = GeniCM::GetAdvertisement(0, $node->node_id(), "0.1", undef);
if (! defined($rspec)) {
print STDERR "Could not get advertisement for $node!\n";
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error getting advertisement");
}
my $me = GeniAuthority->Lookup($ENV{'MYURN'});
if (!defined($me)) {
print STDERR
"Could not find local authority object for $ENV{'MYURN'}\n";
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error getting advertisement");
}
my $myurn = GeniHRN::Generate($OURDOMAIN, "node", $node->node_id());
my $myhrn = "${PGENIDOMAIN}." . $node->node_id();
#
# See if the component object exists; if not create it.
#
my $component = GeniComponent->Lookup($node->uuid());
if (!defined($component)) {
my $certificate = GeniCertificate->Lookup($node->uuid());
if (!defined($certificate)) {
$certificate =
GeniCertificate->Create({'urn' => $myurn,
'hrn' => $myhrn,
'email'=> $TBOPS,
'uuid' => $node->uuid(),
'url' => $me->url()});
if (!defined($certificate)) {
print STDERR "Could not generate certificate for $node\n";
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error getting advertisement");
}
}
$component = GeniComponent->Create($certificate, $me);
if (!defined($component)) {
print STDERR "Could not create component for $node\n";
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error getting advertisement");
}
}
# Return a blob.
my $blob = { "hrn" => "${PGENIDOMAIN}." . $node->node_id(),
my $blob = { "hrn" => $myhrn,
"uuid" => $node->uuid(),
"role" => $node->role(),
"hostname" =>
GeniUtil::FindHostname($node->node_id()),
"physctrl" =>
Interface->LookupControl($node->phys_nodeid())->IP(),
"urn" => GeniHRN::Generate($OURDOMAIN,
"node",
$node->node_id()),
"rspec" => $rspec
"urn" => $myurn,
"rspec" => $rspec,
"url" => $me->url(),
"gid" => $component->cert(),
};
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
......@@ -228,6 +266,7 @@ sub DiscoverResources($)
my $credentials = $argref->{'credentials'};
my $available = $argref->{'available'} || 0;
my $compress = $argref->{'compress'} || 0;
my $version = $argref->{'rspec_version'} || undef;
if (! (defined($credentials))) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
......
#!/usr/bin/perl -wT
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2010 University of Utah and the Flux Group.
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
# All rights reserved.
#
package GeniComponent;
......@@ -146,7 +146,21 @@ sub Create($$;$)
my $safe_hrn = DBQuoteSpecial($certificate->hrn());
my $safe_uuid = DBQuoteSpecial($certificate->uuid());
my $safe_url = DBQuoteSpecial($certificate->URL());
my $safe_url = "NULL";
# If there is a URL in the certificate, use that. If not, there had
# better be a manager supplied or else we will not be able to talk
# to it.
if (defined($certificate->URL())) {
$safe_url = DBQuoteSpecial($certificate->URL());
}
elsif (defined($manager)) {
$safe_url = DBQuoteSpecial($manager->url());
}
else {
print STDERR "GeniComponent::Create: No URL or authority supplied.\n";
return undef;
}
# Now tack on other stuff we need.
push(@insert_data, "created=now()");
......@@ -305,24 +319,21 @@ sub CreateFromRegistry($$)
if (defined($component) &&
$component->urn() && $component->manager_uuid());
my $clearinghouse = GeniRegistry::ClearingHouse->Create();
my $registry = GeniRegistry->Create($token);
return undef
if (!defined($clearinghouse));
if (!defined($registry));
my $blob;
return undef
if ($clearinghouse->Resolve($token, "Component", \$blob) != 0);
if ($registry->Resolve($token, "Component", \$blob) != 0);
# Why does PLC Resolve return an array of length one?
$blob = $blob->[0];
my $certificate = GeniCertificate->LoadFromString($blob->{'gid'});
return undef
if (!defined($certificate));
my $manager_certificate =
GeniCertificate->LoadFromString($blob->{'manager_gid'});
if (!defined($certificate)) {
goto bad;
}
#
# At this point, we do not support non-urn sites. They must re-register.
#
......@@ -336,16 +347,48 @@ sub CreateFromRegistry($$)
#
# Create the manager authority as well.
#
my $manager_urn = $manager_certificate->urn();
if (!defined($manager_urn)) {
print STDERR "GeniComponent::CreateFromRegistry: ".
"$manager_certificate does not have a urn.\n";
goto bad;
my $manager_urn;
if (exists($blob->{'manager_gid'})) {
my $manager_certificate =
GeniCertificate->LoadFromString($blob->{'manager_gid'});
if (!defined($certificate)) {
goto bad;
}
$manager_urn = $manager_certificate->urn();
$manager_certificate->Delete();
if (!defined($manager_urn)) {
print STDERR "GeniComponent::CreateFromRegistry: ".
"$manager_certificate does not have a urn.\n";
goto bad;
}
}
else {
#
# Only able to deal with PLC for now. The blob says that the "site"
# is the authority, but that is not true since we have to go all
# the way up to plc.sa to do anything.
#
my ($auth,$type,$id) = GeniHRN::Parse($urn);
return undef
if (!defined($auth));
if ($auth =~ /^plc:/) {
$manager_urn = GeniHRN::Generate("plc", "authority", "sa");
}
else {
print STDERR "Unsupported PLC component: $urn\n";
goto bad;
}
}
my $manager = GeniAuthority->CreateFromRegistry("CM", $manager_urn);
if (!defined($manager)) {
print STDERR "GeniComponent::CreateFromRegistry: ".
"could not create authority $manager_urn\n";
goto bad;
}
$component = GeniComponent->Create($certificate, $manager);
......@@ -359,8 +402,6 @@ sub CreateFromRegistry($$)
bad:
$certificate->Delete()
if (defined($certificate));
$manager_certificate->Delete()
if (defined($manager_certificate));
return undef;
}
......@@ -398,6 +439,23 @@ sub Resolve($)
return undef
if (!defined($manager_version));
#
# XXX: The SFA stores all records in the central registry, not at
# the CM like we do.
#
if ($authority->IsSFA()) {
my $registry = GeniRegistry->Create($self->urn());
return undef
if (!defined($registry));
my $blob;
return undef
if ($registry->Resolve($self->urn(), "Component", \$blob) != 0);
# Why does PLC resolve return an array of length one?
return $blob->[0];
}
#
# Need a credential to make this call. Seems kinda silly.
#
......
#!/usr/bin/perl -w
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2010 University of Utah and the Flux Group.
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
# All rights reserved.
#
package GeniEmulab;
......@@ -44,6 +44,7 @@ use Experiment;
use libdb qw(TBDB_IFACEROLE_CONTROL TBDB_IFACEROLE_EXPERIMENT);
use POSIX qw(strftime);
use Carp;
use Socket;
# Configure variables
my $TB = "@prefix@";
......@@ -184,7 +185,7 @@ sub UnRegisterExperiment($)
return -1;
}
# Needs to move.
GeniRegistry::ClientSliver->SliceDelete($slice);
GeniSlice::ClientSliver->SliceDelete($slice);
if ($slice->Delete()) {
print STDERR "Could not delete $slice for $experiment\n";
......@@ -196,9 +197,9 @@ sub UnRegisterExperiment($)
#
# Create a physical node on the fly.
#
sub CreatePhysNode($)
sub CreatePhysNode($$)
{
my ($node_urn) = @_;
my ($manager_urn, $node_urn) = @_;
my @ifaces;
my $ctrliface;
......@@ -206,10 +207,13 @@ sub CreatePhysNode($)
carp("Not a proper node urn: $node_urn\n");
return -1;
}
print STDERR "$node_urn\n";
if (!defined($manager_urn) || ! GeniHRN::IsValid($manager_urn)) {
carp("Not a proper manager urn: $manager_urn\n");
return -1;
}
print STDERR "$node_urn, $manager_urn\n";
my ($auth,$type,$node_id) = GeniHRN::Parse($node_urn);
my $manager_urn = GeniHRN::Generate($auth, "authority", "cm");
#
# Load the SA cert to act as caller context.
......@@ -240,7 +244,7 @@ sub CreatePhysNode($)
my $component = GeniComponent->CreateFromRegistry($node_urn);
if (!defined($component)) {
print STDERR "Could not lookup $node_urn at ClearingHouse\n";
print STDERR "Could not lookup $node_urn at its registry\n";
return undef;
}
my $node = Node->LookupWideArea($node_urn);
......@@ -256,9 +260,7 @@ sub CreatePhysNode($)
my $hrn = $blob->{'hrn'};
my $IP = $blob->{'physctrl'};
my $hostname = $blob->{'hostname'};
my $uuid = $blob->{'uuid'};
if (! (defined($hrn) && defined($IP) && defined($hostname) &&
defined($uuid))) {
if (! (defined($hrn) && defined($hostname))) {
print STDERR "Missing stuff in blob from CM for $node_urn\n";
goto bad;
}
......@@ -266,10 +268,6 @@ sub CreatePhysNode($)
print STDERR "Invalid hrn '$hrn' in blob from CM for $node_urn\n";
goto bad;
}
if (! ($uuid =~ /^[-\w\.]*$/)) {
print STDERR "Invalid uuid '$uuid' in blob from CM for $node_urn\n";
goto bad;
}
if (! ($hostname =~ /^[-\w\.]*$/)) {
print STDERR
"Invalid hostname '$hostname' in blob from CM for $node_urn\n";
......@@ -286,7 +284,34 @@ sub CreatePhysNode($)
#
# Find control network.
#
if (exists($blob->{'interfaces'})) {
if ($authority->IsSFA()) {
#
# Generate a suitable node_id.
#
my ($pl) = ($blob->{'hrn'} =~ /^([^.]*)\./);
$node_id = "$pl" . "-" . $blob->{'node_id'};
#
# Find the IP from the hostname and generate a stub iface entry.
#
my ($name,undef,undef,undef,@ipaddrs) = gethostbyname($hostname);
if (!defined($name)) {
print STDERR "Cannot resolve $hostname for $node_urn:\n";
goto bad;
}
$IP = inet_ntoa($ipaddrs[0]);
my $ifaceargs = {
"card" => 0,
"role" => TBDB_IFACEROLE_CONTROL(),
"MAC" => '000000000000',
"IP" => $IP,
"type" => "generic",
};
push(@ifaces, $ifaceargs);
$ctrliface = $ifaceargs;
}
elsif (exists($blob->{'interfaces'})) {
foreach my $ref (@{ $blob->{'interfaces'} }) {
my $role = $ref->{'role'};
......
This diff is collapsed.
......@@ -24,6 +24,7 @@ use GeniTicket;
use GeniCredential;
use GeniAuthority;
use GeniComponent;
use GeniSlice;
use GeniUtil;
use GeniUser;
use GeniHRN;
......@@ -100,9 +101,7 @@ sub Lookup($$;$)
$self->{'RSPEC'} = undef;
$self->{'NEWRSPEC'} = undef;
$self->{'MODIFIED'} = 1;
$self->{'manager_version'} = undef;
$self->{'manager_apilevel'} = undef;
$self->{'manager_api'} = undef;
$self->{'_authority'} = undef;
$self->{'last_rpc_error'} = 0;
$self->{'last_rpc_value'} = undef;
$self->{'last_rpc_output'} = undef;
......@@ -240,9 +239,7 @@ sub manifest_idx($) { return field($_[0], "manifest_idx"); }
sub ticket_idx($) { return field($_[0], "ticket_idx"); }
sub newticket_idx($) { return field($_[0], "newticket_idx"); }
sub rspec_idx($) { return field($_[0], "rspec_idx"); }
sub manager_version($) { return $_[0]->{'manager_version'}; }
sub manager_apilevel($) { return $_[0]->{'manager_apilevel'}; }
sub manager_api($) { return $_[0]->{'manager_api'}; }
sub _authority($) { return $_[0]->{'_authority'}; }
sub last_rpc_error($) { return $_[0]->{'last_rpc_error'}; }
sub last_rpc_output($) { return $_[0]->{'last_rpc_output'}; }
sub last_rpc_value($) { return $_[0]->{'last_rpc_value'}; }
......@@ -529,14 +526,14 @@ sub UpdateManifest($$)
}
#
# Get Version. Ask the CM what version it is running.
# Get Authority.
#
sub ManagerVersion($)
sub Authority($)
{
my ($self) = @_;
return $self->manager_version()
if (defined($self->manager_version()));
return $self->_authority()
if (defined($self->_authority()));
my $manager_urn = $self->manager_urn();
......@@ -566,35 +563,40 @@ sub ManagerVersion($)
return undef;
}
}
$self->{'manager_version'} = $authority->Version();
$self->{'manager_apilevel'} = $authority->ApiLevel();
$self->{'manager_api'} = $authority->Api();
return $self->{'manager_version'};
$self->{'_authority'} = $authority;
return $authority;
}
# Ditto the API level.
sub ManagerApiLevel($)
sub Version($)
{
my ($self) = @_;
return $self->manager_apilevel()
if (defined($self->manager_apilevel()));
return undef
if (!defined($self->ManagerVersion()));
return $self->manager_apilevel();
if (!defined($self->Authority()));
return $self->Authority()->Version();
}
sub ManagerApi($)
sub ApiLevel($)
{
my ($self) = @_;
return $self->manager_api()
if (defined($self->manager_api()));
return undef
if (!defined($self->Authority()));
return $self->Authority()->ApiLevel();
}
sub Api($)
{
my ($self) = @_;
return undef