Commit b63cb055 authored by Leigh Stoller's avatar Leigh Stoller

Big cleanup of GeniComponent stuff. Moved Resolve() into GeniComponent

since it has to be aware of the CM version. Add a Version() call to
GeniAuthority with goes asks the CM what version it is exporting.
Based on that, we know how to do a resolve of a component. Refactored
the code that was used in GeniAggregate when creating tunnels, since
that is where we have to Resolve components. This also turns up in
cooked mode.

Continuine moving towards a urn-only world. If a GeniAuthority or a
GeniComponent does not have the URN set locally in the DB, go back to
the clearinghouse and get it. Error if it is not known, and go bang on
the remote site to update and rerun register_resources.
parent 277f4a62
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# GENIPUBLIC-COPYRIGHT # GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2009 University of Utah and the Flux Group. # Copyright (c) 2008-2010 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
package GeniAggregate; package GeniAggregate;
...@@ -25,6 +25,7 @@ use GeniSlice; ...@@ -25,6 +25,7 @@ use GeniSlice;
use GeniRegistry; use GeniRegistry;
use GeniUtil; use GeniUtil;
use GeniUser; use GeniUser;
use GeniComponent;
use GeniHRN; use GeniHRN;
use emutil; use emutil;
use Lan; use Lan;
...@@ -1295,52 +1296,23 @@ sub Create($$$$$$) ...@@ -1295,52 +1296,23 @@ sub Create($$$$$$)
} }
} }
else { else {
my $component = GeniComponent->Lookup($node1rspec->{'component_uuid'}); my $node_uuid = $node1rspec->{'component_uuid'};
my $blob; my $component = GeniComponent->CreateFromRegistry($node_uuid);
if (!defined($component)) { if (!defined($component)) {
# print STDERR "Could not create component for $node_uuid\n";
# Need to ask the clearinghouse where this node comes from.
#
$clearinghouse = GeniRegistry::ClearingHouse->Create();
if ($clearinghouse->Resolve($node1rspec->{'component_uuid'},
"Component", \$blob) != 0) {
print STDERR "Could not lookup node at clearinghouse\n";
print STDERR Dumper($node1rspec);
goto bad;
}
my $certificate = GeniCertificate->LoadFromString($blob->{'gid'});
goto bad
if (!defined($certificate));
$component = GeniComponent->CreateFromCertificate($certificate);
if (!defined($component)) {
print STDERR "Could not create component from $certificate\n";
goto bad;
}
}
my $credential = GeniRegistry::Client->CreateCredential($component);
if (!defined($credential)) {
print STDERR "Could not create a credential for $component\n";
goto bad; goto bad;
} }
my $registry = GeniRegistry::Client->Create($component, undef, my $blob = $component->Resolve();
$credential); if (!defined($blob)) {
if (!defined($registry)) { print STDERR "Could not Resolve $component\n";
print STDERR "Could not create a registry client for $component\n";
goto bad; goto bad;
} }
$registry->Resolve($node1rspec->{'component_uuid'}, "Node", \$blob); if (!exists($blob->{'physctrl'}) || !defined($blob->{'physctrl'})) {
$ctrlip1 = $blob->{'physctrl'} print STDERR "Could not get control IP for $component\n";
if (defined($blob) && exists($blob->{'physctrl'}));
if (!defined($ctrlip1)) {
print STDERR "Could not get control IP for ".
"$node1rspec->{'component_uuid'} at $component\n";
goto bad; goto bad;
} }
$ctrlip1 = $blob->{'physctrl'};
} }
if (defined($node2sliver)) { if (defined($node2sliver)) {
my $node2 = Node->Lookup($node2sliver->resource_uuid()); my $node2 = Node->Lookup($node2sliver->resource_uuid());
...@@ -1359,51 +1331,23 @@ sub Create($$$$$$) ...@@ -1359,51 +1331,23 @@ sub Create($$$$$$)
} }
} }
else { else {
my $blob; my $node_uuid = $node2rspec->{'component_uuid'};
my $component = GeniComponent->Lookup($node2rspec->{'component_uuid'}); my $component = GeniComponent->CreateFromRegistry($node_uuid);
if (!defined($component)) {
#
# Need to ask the clearinghouse where this node comes from.
#
$clearinghouse = GeniRegistry::ClearingHouse->Create();
if ($clearinghouse->Resolve($node2rspec->{'component_uuid'}, if (!defined($component)) {
"Component", \$blob) != 0) { print STDERR "Could not create component for $node_uuid\n";
print STDERR "Could not lookup node at clearinghouse\n";
print STDERR Dumper($node2rspec);
goto bad;
}
my $certificate = GeniCertificate->LoadFromString($blob->{'gid'});
goto bad
if (!defined($certificate));
$component = GeniComponent->CreateFromCertificate($certificate);
if (!defined($component)) {
print STDERR "Could not create component from $certificate\n";
goto bad;
}
}
my $credential = GeniRegistry::Client->CreateCredential($component);
if (!defined($credential)) {
print STDERR "Could not create a credential for $component\n";
goto bad; goto bad;
} }
my $registry = GeniRegistry::Client->Create($component, undef, my $blob = $component->Resolve();
$credential); if (!defined($blob)) {
if (!defined($registry)) { print STDERR "Could not Resolve $component\n";
print STDERR "Could not create a registry client for $component\n";
goto bad; goto bad;
} }
$registry->Resolve($node2rspec->{'component_uuid'}, "Node", \$blob); if (!exists($blob->{'physctrl'}) || !defined($blob->{'physctrl'})) {
$ctrlip2 = $blob->{'physctrl'} print STDERR "Could not get control IP for $component\n";
if (defined($blob) && exists($blob->{'physctrl'}));
if (!defined($ctrlip2)) {
print STDERR "Could not get control IP for ".
"$node2rspec->{'component_uuid'} at $component\n";
goto bad; goto bad;
} }
$ctrlip2 = $blob->{'physctrl'};
} }
# print STDERR "$ip1, $ip2, $ctrlip1, $ctrlip2\n"; # print STDERR "$ip1, $ip2, $ctrlip1, $ctrlip2\n";
......
...@@ -20,6 +20,8 @@ use vars qw(@ISA @EXPORT); ...@@ -20,6 +20,8 @@ use vars qw(@ISA @EXPORT);
use GeniDB; use GeniDB;
use GeniRegistry; use GeniRegistry;
use GeniHRN; use GeniHRN;
use Genixmlrpc;
use GeniResponse;
use emutil qw(TBGetUniqueIndex); use emutil qw(TBGetUniqueIndex);
use English; use English;
use overload ('""' => 'Stringify'); use overload ('""' => 'Stringify');
...@@ -52,26 +54,11 @@ sub Lookup($$) ...@@ -52,26 +54,11 @@ sub Lookup($$)
$query_result = $query_result =
DBQueryWarn("select uuid from geni_authorities ". DBQueryWarn("select uuid from geni_authorities ".
"where urn='$token'"); "where urn='$token'");
if( $query_result && $query_result->numrows ) {
($uuid) = $query_result->fetchrow_array(); return undef
} else { if (! $query_result || !$query_result->numrows);
# Fallback for backward compatibility (hunt for an
# authority in the database that was never registered with ($uuid) = $query_result->fetchrow_array();
# a URN). This is ugly and fragile and needs to go away
# as soon as all authorities have re-registered with URNs.
my ($auth,$t,$id) = GeniHRN::Parse($token);
my $regexp = "/.[-[:alnum:]]+.${auth}";
$regexp =~ s/\./\\\./g;
$query_result =
DBQueryWarn("select uuid from geni_authorities ".
"where url regexp '$regexp' and ".
" type='$id'");
return undef
if (! $query_result || !$query_result->numrows);
($uuid) = $query_result->fetchrow_array();
}
} }
elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) { elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
$uuid = $token; $uuid = $token;
...@@ -105,6 +92,7 @@ sub Lookup($$) ...@@ -105,6 +92,7 @@ sub Lookup($$)
my $self = {}; my $self = {};
$self->{'AUTHORITY'} = $query_result->fetchrow_hashref(); $self->{'AUTHORITY'} = $query_result->fetchrow_hashref();
$self->{'version'} = undef;
bless($self, $class); bless($self, $class);
# #
...@@ -188,6 +176,7 @@ sub url($) { return field($_[0], "url"); } ...@@ -188,6 +176,7 @@ sub url($) { return field($_[0], "url"); }
sub hrn($) { return field($_[0], "hrn"); } sub hrn($) { return field($_[0], "hrn"); }
sub type($) { return field($_[0], "type"); } sub type($) { return field($_[0], "type"); }
sub disabled($) { return field($_[0], "disabled"); } sub disabled($) { return field($_[0], "disabled"); }
sub version($) { return field($_[0], "version"); }
sub cert($) { return $_[0]->{'CERT'}->cert(); } sub cert($) { return $_[0]->{'CERT'}->cert(); }
sub GetCertificate($) { return $_[0]->{'CERT'}; } sub GetCertificate($) { return $_[0]->{'CERT'}; }
...@@ -257,6 +246,10 @@ sub CreateFromRegistry($$$) ...@@ -257,6 +246,10 @@ sub CreateFromRegistry($$$)
{ {
my ($class, $type, $name) = @_; my ($class, $type, $name) = @_;
my $authority = GeniAuthority->Lookup($name);
return $authority
if (defined($authority) && $authority->urn());
my $clearinghouse = GeniRegistry::ClearingHouse->Create(); my $clearinghouse = GeniRegistry::ClearingHouse->Create();
return undef return undef
if (!defined($clearinghouse)); if (!defined($clearinghouse));
...@@ -269,15 +262,55 @@ sub CreateFromRegistry($$$) ...@@ -269,15 +262,55 @@ sub CreateFromRegistry($$$)
return undef return undef
if (!defined($certificate)); if (!defined($certificate));
my $authority = GeniAuthority->Create($certificate, #
$blob->{'url'}, # At this point, we do not support non-urn sites. They must re-register.
$blob->{'type'}); #
my $urn = $certificate->urn();
if (!defined($urn)) {
print STDERR "GeniAuthority::CreateFromRegistry: ".
"$certificate does not have a urn.\n";
$certificate->Delete();
return undef;
}
$authority = GeniAuthority->Create($certificate,
$blob->{'url'},
$blob->{'type'});
$certificate->Delete() $certificate->Delete()
if (!defined($authority)); if (!defined($authority));
return $authority; return $authority;
} }
#
# Get Version. Ask the Authority what version it is running.
#
sub Version($)
{
my ($self) = @_;
return $self->version()
if (defined($self->version()));
#
# The caller had to set up the xmlrpc context.
#
my $response =
Genixmlrpc::CallMethod($self->url(), undef, "GetVersion");
if (!defined($response)) {
print STDERR "*** Internal error getting version for $self\n";
return undef;
}
if ($response->code() != GENIRESPONSE_SUCCESS) {
print STDERR "Could not get version for $self Error: ";
print STDERR " " . $response->output() . "\n";
return undef;
}
$self->{'version'} = $response->value();
return $response->value();
}
# #
# Does the uuid prefix match. # Does the uuid prefix match.
# #
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# GENIPUBLIC-COPYRIGHT # GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2009 University of Utah and the Flux Group. # Copyright (c) 2008-2010 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
package GeniComponent; package GeniComponent;
...@@ -23,6 +23,7 @@ use GeniRegistry; ...@@ -23,6 +23,7 @@ use GeniRegistry;
use GeniTicket; use GeniTicket;
use GeniCredential; use GeniCredential;
use GeniAuthority; use GeniAuthority;
use GeniHRN;
use emutil qw(TBGetUniqueIndex); use emutil qw(TBGetUniqueIndex);
use English; use English;
use overload ('""' => 'Stringify'); use overload ('""' => 'Stringify');
...@@ -54,7 +55,16 @@ sub Lookup($$) ...@@ -54,7 +55,16 @@ sub Lookup($$)
my $query_result; my $query_result;
my $uuid; my $uuid;
if ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) { if (GeniHRN::IsValid($token)) {
$query_result =
DBQueryWarn("select uuid from geni_certificates ".
"where urn='$token'");
return undef
if (!$query_result || !$query_result->numrows);
($uuid) = $query_result->fetchrow_array();
}
elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
$uuid = $token; $uuid = $token;
} }
elsif ($token =~ /^[-\w\.]*$/) { elsif ($token =~ /^[-\w\.]*$/) {
...@@ -120,9 +130,9 @@ sub Stringify($) ...@@ -120,9 +130,9 @@ sub Stringify($)
{ {
my ($self) = @_; my ($self) = @_;
my $uuid = $self->uuid(); my $urn = $self->urn();
return "[GeniComponent: $uuid]"; return "[GeniComponent: $urn]";
} }
# #
...@@ -168,6 +178,19 @@ sub cert($) { return $_[0]->{'CERT'}->cert(); } ...@@ -168,6 +178,19 @@ sub cert($) { return $_[0]->{'CERT'}->cert(); }
sub GetCertificate($) { return $_[0]->{'CERT'}; } sub GetCertificate($) { return $_[0]->{'CERT'}; }
sub GetManager($) { return $_[0]->{'MANAGER'}; } sub GetManager($) { return $_[0]->{'MANAGER'}; }
#
# Return the URN. This is complicated by the fact that the DB does not
# store the urn, but is in the certificate. Further, it might be a
# Component from a CM not doing URNs yet, in which case set it to the
# uuid and hope for the best.
#
sub urn($)
{
my ($self) = @_;
return $self->GetCertificate()->urn();
}
# #
# Delete a component from the DB. # Delete a component from the DB.
# #
...@@ -258,7 +281,13 @@ sub Update($$) ...@@ -258,7 +281,13 @@ sub Update($$)
# #
sub CreateFromRegistry($$) sub CreateFromRegistry($$)
{ {
my ($class, $uuid) = @_; my ($class, $token) = @_;
my $component = GeniComponent->Lookup($token);
# We want to reload if urn/uuid not set properly
return $component
if (defined($component) &&
$component->urn() && $component->manager_uuid());
my $clearinghouse = GeniRegistry::ClearingHouse->Create(); my $clearinghouse = GeniRegistry::ClearingHouse->Create();
return undef return undef
...@@ -266,17 +295,57 @@ sub CreateFromRegistry($$) ...@@ -266,17 +295,57 @@ sub CreateFromRegistry($$)
my $blob; my $blob;
return undef return undef
if ($clearinghouse->Resolve($uuid, "Component", \$blob) != 0); if ($clearinghouse->Resolve($token, "Component", \$blob) != 0);
my $certificate = GeniCertificate->LoadFromString($blob->{'gid'}); my $certificate = GeniCertificate->LoadFromString($blob->{'gid'});
return undef return undef
if (!defined($certificate)); if (!defined($certificate));
my $component = GeniComponent->Create($certificate); my $manager_certificate =
$certificate->Delete() GeniCertificate->LoadFromString($blob->{'manager_gid'});
if (!defined($component)); if (!defined($certificate)) {
goto bad;
}
#
# At this point, we do not support non-urn sites. They must re-register.
#
my $urn = $certificate->urn();
if (!defined($urn)) {
print STDERR "GeniComponent::CreateFromRegistry: ".
"$certificate does not have a urn.\n";
goto bad;
}
#
# 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 = GeniAuthority->CreateFromRegistry("CM", $manager_urn);
if (!defined($manager)) {
print STDERR "GeniComponent::CreateFromRegistry: ".
"could not create authority $manager_urn\n";
}
$component = GeniComponent->Create($certificate, $manager);
if (!defined($component)) {
print STDERR "GeniComponent::CreateFromRegistry: ".
"could not create component from $certificate\n";
goto bad;
}
return $component; return $component;
bad:
$certificate->Delete()
if (defined($certificate));
$manager_certificate->Delete()
if (defined($manager_certificate));
return undef;
} }
# #
...@@ -293,6 +362,61 @@ sub CreateFromCertificate($$;$) ...@@ -293,6 +362,61 @@ sub CreateFromCertificate($$;$)
return $component; return $component;
} }
#
# Resolve a component (at its CM).
#
sub Resolve($)
{
my ($self) = @_;
my $authority = GeniAuthority->Lookup($self->manager_uuid());
if (!defined($authority)) {
$authority =
GeniAuthority->CreateFromRegistry("CM", $self->manager_uuid());
if (!defined($authority)) {
print STDERR "Could not create registry credential for $self\n";
return undef;
}
}
my $manager_version = $authority->Version();
return undef
if (!defined($manager_version));
my $credential = GeniRegistry::Client->CreateCredential($self);
if (!defined($credential)) {
print STDERR "Could not create registry credential for $self\n";
return undef;
}
my $method_args;
if ($manager_version == 1.0) {
$method_args->{'credential'} = $credential->asString();
$method_args->{'uuid'} = $self->uuid();
$method_args->{'type'} = "node";
}
elsif ($manager_version == 2.0) {
$method_args->{'credentials'} = [$credential->asString()];
$method_args->{'urn'} = $self->urn();
}
else {
print STDERR "GeniComponent::Resolve: Unknown version at $authority\n";
return undef;
}
my $response =
Genixmlrpc::CallMethod($authority->url(),
undef, "Resolve", $method_args);
if (!defined($response)) {
print STDERR "*** Internal error Resolving $self at $authority\n";
return undef;
}
if ($response->code() != GENIRESPONSE_SUCCESS) {
print STDERR "Could not resolve $self at $authority Error:";
print STDERR " " . $response->output() . "\n";
return undef;
}
return $response->value();
}
# #
# Delete all components for a CM. # Delete all components for a CM.
# #
......
#!/usr/bin/perl -w #!/usr/bin/perl -w
# #
# GENIPUBLIC-COPYRIGHT # GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2009 University of Utah and the Flux Group. # Copyright (c) 2008-2010 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
package GeniEmulab; package GeniEmulab;
...@@ -185,13 +185,10 @@ sub CreatePhysNode($) ...@@ -185,13 +185,10 @@ sub CreatePhysNode($)
# #
Genixmlrpc->SetContext($context); Genixmlrpc->SetContext($context);
my $authority = GeniAuthority->Lookup($manager_urn); my $authority = GeniAuthority->CreateFromRegistry("CM", $manager_urn);
if (!defined($authority)) { if (!defined($authority)) {
$authority = GeniAuthority->CreateFromRegistry("cm", $manager_urn); print STDERR "Could not lookup $manager_urn at ClearingHouse\n";
if (!defined($authority)) { return undef;
print STDERR "Could not lookup $manager_urn at ClearingHouse\n";
return undef;
}
} }
# #
...@@ -202,19 +199,14 @@ sub CreatePhysNode($) ...@@ -202,19 +199,14 @@ sub CreatePhysNode($)
# print STDERR "$node_hrn\n"; # print STDERR "$node_hrn\n";
my $component = GeniComponent->Lookup($node_hrn); my $component = GeniComponent->CreateFromRegistry($node_urn);
if (defined($component)) { if (!defined($component)) {
my $node = Node->Lookup($component->uuid()); print STDERR "Could not lookup $node_urn at ClearingHouse\n";
return $node return undef;
if (defined($node));
}
else {
$component = GeniComponent->CreateFromRegistry($node_urn);
if (!defined($component)) {
print STDERR "Could not lookup $node_urn at ClearingHouse\n";
return undef;
}
} }
my $node = Node->Lookup($component->uuid());
return $node
if (defined($node));
print STDERR "Creating local node for $node_urn\n"; print STDERR "Creating local node for $node_urn\n";
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# GENIPUBLIC-COPYRIGHT # GENIPUBLIC-COPYRIGHT
# Copyright (c) 2009 University of Utah and the Flux Group. # Copyright (c) 2009-2010 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
package GeniHRN; package GeniHRN;
use strict; use strict;
use Exporter; use Exporter;
use Carp;
use vars qw(@ISA @EXPORT); use vars qw(@ISA @EXPORT);
@ISA = "Exporter"; @ISA = "Exporter";
...@@ -53,6 +54,11 @@ sub IsValid($) ...@@ -53,6 +54,11 @@ sub IsValid($)
{ {
my ($hrn) = @_; my ($hrn) = @_;
if (!defined($hrn)) {
carp("GeniHRN::IsValid: hrn is undefined");
return 0;
}
# Reject %00 sequences (see RFC 3986, section 7.3). # Reject %00 sequences (see RFC 3986, section 7.3).
return undef if $hrn =~ /%00/; return undef if $hrn =~ /%00/;
...@@ -146,6 +152,10 @@ sub Parse($) ...@@ -146,6 +152,10 @@ sub Parse($)
{ {
my ($hrn) = @_; my ($hrn) = @_;
if (!defined($hrn)) {
carp("GeniHRN::Parse: hrn is undefined");
return 0;
}
return undef if !IsValid( $hrn ); return undef if !IsValid( $hrn );
$hrn = Unescape( $hrn ); $hrn = Unescape( $hrn );
...@@ -238,6 +248,10 @@ sub ParseInterface($) ...@@ -238,6 +248,10 @@ sub ParseInterface($)
{ {
my ($urn) = @_; my ($urn) = @_;
if (!defined($urn)) {
carp("GeniHRN::ParseInterface: urn is undefined");
return 0;
}
my ($authority,$type,$id) = Parse( $urn ); my ($authority,$type,$id) = Parse( $urn );
return undef if $type ne "interface"; return undef if $type ne "interface";
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# GENIPUBLIC-COPYRIGHT # GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2009 University of Utah and the Flux Group. # Copyright (c) 2008-2010 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
package GeniResource; package GeniResource;
...@@ -388,13 +388,10 @@ sub GetTicket($$$$) ...@@ -388,13 +388,10 @@ sub GetTicket($$$$)
# #
Genixmlrpc->SetContext($context); Genixmlrpc->SetContext($context);
my $authority = GeniAuthority->Lookup($manager_urn);