Commit 649a0107 authored by Jonathon Duerig's avatar Jonathon Duerig

Checkpoint. All the conversion is done, but I need to refactor the xpaths to...

Checkpoint. All the conversion is done, but I need to refactor the xpaths to account for brittleness in the xpath specification.
parent e25f7049
......@@ -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 GeniResource.pm
GeniSES.pm GeniResource.pm GeniXML.pm
SBIN_SCRIPTS = plabnodewrapper plabslicewrapper
SCRIPTS = addnode.pl genischemacheck.pl
......
......@@ -26,6 +26,7 @@ use GeniRegistry;
use GeniUtil;
use GeniUser;
use GeniHRN;
use GeniXML;
use emutil;
use Lan;
use Data::Dumper;
......@@ -646,29 +647,22 @@ sub GetManifest($$)
}
my ($xml) = $query_result->fetchrow_array();
my $manifest =
eval { XMLin($xml, KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints"]) };
if ($@) {
print STDERR "XMLin error reading manifest: $@\n";
my $manifest = GeniXML::Parse($xml);
if (!defined($manifest)) {
return undef;
}
#
# Update the manifest ticket to reflect the current expiration time.
#
$manifest->{'valid_until'} =
POSIX::strftime("20%y-%m-%dT%H:%M:%S",
gmtime(str2time($slice->expires())));
my $valid_date = POSIX::strftime("20%y-%m-%dT%H:%M:%S",
gmtime(str2time($slice->expires())));
GeniXML::SetText("valid_until", $manifest, $valid_date);
return $manifest
if (!$asxml);
$xml = eval { XMLout($manifest, "NoAttr" => 1, RootName => "manifest") };
if ($@) {
print STDERR "XMLout error on manifest: $@\n";
return undef;
}
$xml = $manifest->toString();
return $xml;
}
......@@ -1235,10 +1229,12 @@ sub Create($$$$$$)
$linkrspec, $node1rspec, $node2rspec) = @_;
my $clearinghouse;
my $linkname = $linkrspec->{"nickname"} || $linkrspec->{"virtual_id"};
my $linkname = GeniXML::GetText("./n:nickname | ".
"./n:virtual_id", $linkrspec);
return undef
if (!defined($linkname));
my @interfaces = @{ $linkrspec->{'interface_ref'} };
my @interfaces = GeniXML::FindNodes("./n:interface_ref",
$linkrspec)->get_nodelist();
my $experiment = Experiment->Lookup($slice->uuid());
if (!defined($experiment)) {
......@@ -1269,8 +1265,8 @@ sub Create($$$$$$)
my $iface2ref = $interfaces[1];
# These are the ips of the tunnel.
my $ip1 = $iface1ref->{'tunnel_ip'};
my $ip2 = $iface2ref->{'tunnel_ip'};
my $ip1 = GeniXML::GetText("./n:tunnel_ip", $iface1ref);
my $ip2 = GeniXML::GetText("./n:tunnel_ip", $iface2ref);
my $ctrlip1;
my $ctrlip2;
my $iface1;
......@@ -1295,7 +1291,8 @@ sub Create($$$$$$)
}
}
else {
my $component = GeniComponent->Lookup($node1rspec->{'component_uuid'});
my $component_name = GeniXML::GetNodeId($node1rspec);
my $component = GeniComponent->Lookup($component_name);
my $blob;
if (!defined($component)) {
......@@ -1304,10 +1301,10 @@ sub Create($$$$$$)
#
$clearinghouse = GeniRegistry::ClearingHouse->Create();
if ($clearinghouse->Resolve($node1rspec->{'component_uuid'},
if ($clearinghouse->Resolve($component_name,
"Component", \$blob) != 0) {
print STDERR "Could not lookup node at clearinghouse\n";
print STDERR Dumper($node1rspec);
print STDERR $node1rspec->toString();
goto bad;
}
my $certificate = GeniCertificate->LoadFromString($blob->{'gid'});
......@@ -1332,13 +1329,13 @@ sub Create($$$$$$)
print STDERR "Could not create a registry client for $component\n";
goto bad;
}
$registry->Resolve($node1rspec->{'component_uuid'}, "Node", \$blob);
$registry->Resolve($component_name, "Node", \$blob);
$ctrlip1 = $blob->{'physctrl'}
if (defined($blob) && exists($blob->{'physctrl'}));
if (!defined($ctrlip1)) {
print STDERR "Could not get control IP for ".
"$node1rspec->{'component_uuid'} at $component\n";
"$component_name at $component\n";
goto bad;
}
}
......@@ -1360,17 +1357,18 @@ sub Create($$$$$$)
}
else {
my $blob;
my $component = GeniComponent->Lookup($node2rspec->{'component_uuid'});
my $component_name = GeniXML::GetNodeId($node2rspec);
my $component = GeniComponent->Lookup($component_name);
if (!defined($component)) {
#
# Need to ask the clearinghouse where this node comes from.
#
$clearinghouse = GeniRegistry::ClearingHouse->Create();
if ($clearinghouse->Resolve($node2rspec->{'component_uuid'},
if ($clearinghouse->Resolve($component_name,
"Component", \$blob) != 0) {
print STDERR "Could not lookup node at clearinghouse\n";
print STDERR Dumper($node2rspec);
print STDERR $node2rspec->toString();
goto bad;
}
my $certificate = GeniCertificate->LoadFromString($blob->{'gid'});
......@@ -1395,13 +1393,13 @@ sub Create($$$$$$)
print STDERR "Could not create a registry client for $component\n";
goto bad;
}
$registry->Resolve($node2rspec->{'component_uuid'}, "Node", \$blob);
$registry->Resolve($component_name, "Node", \$blob);
$ctrlip2 = $blob->{'physctrl'}
if (defined($blob) && exists($blob->{'physctrl'}));
if (!defined($ctrlip2)) {
print STDERR "Could not get control IP for ".
"$node2rspec->{'component_uuid'} at $component\n";
"$component_name at $component\n";
goto bad;
}
}
......
This diff is collapsed.
......@@ -19,6 +19,7 @@ use vars qw(@ISA @EXPORT);
use GeniDB;
use GeniCertificate;
use GeniUtil;
use GeniXML;
use emutil qw(TBGetUniqueIndex);
use English;
use XML::Simple;
......@@ -122,7 +123,7 @@ sub Create($$$)
$self->{'owner_cert'} = $owner->GetCertificate();
$self->{'string'} = undef;
$self->{'capabilities'} = undef;
$self->{'extensions'} = undef;
$self->{'extensions'} = XML::LibXML::NodeList->new();
$self->{'idx'} = undef; # Only set when stored to DB.
bless($self, $class);
......@@ -184,11 +185,8 @@ sub AddExtension($$$)
return -1
if (!ref($self));
if (!defined($self->extensions())) {
$self->{'extensions'} = {};
}
$self->{'extensions'}->{$key} = $value;
my $newNode = XML::LibXML::Element->new($key);
$newNode->appendText($value);
return 0;
}
......@@ -249,7 +247,7 @@ sub CreateFromSigned($$;$)
unlink($filename);
}
# Use XML::Simple to convert to something we can mess with.
# Use XML::LibXML to convert to something we can mess with.
my $parser = XML::LibXML->new;
my $doc;
eval {
......@@ -259,28 +257,10 @@ sub CreateFromSigned($$;$)
print STDERR "Failed to parse credential string: $@\n";
return undef;
}
# Dig out the capabilities
my ($cap_node) = $doc->getElementsByTagName("privileges");
return undef
if (!defined($cap_node));
my $rawcapabilities =
eval { XMLin($cap_node->toString(),
ForceArray => [ "privilege" ] ) };
if ($@) {
print STDERR "XMLin error on capabilities: $@\n";
return undef;
}
my $capabilities = $rawcapabilities->{ "privilege" };
my $root = $doc->documentElement();
# Dig out the extensions
my ($extensions_node) = $doc->getElementsByTagName("extensions");
my $extensions = eval { XMLin($extensions_node->toString()) }
if (defined($extensions_node));
if ($@) {
print STDERR "XMLin error on extensions: $@\n";
return undef;
}
my $extensions = GeniXML::FindNodes('//n:extensions/*', $root);
# UUID of the credential.
my ($uuid_node) = $doc->getElementsByTagName("uuid");
......@@ -351,7 +331,7 @@ sub CreateFromSigned($$;$)
}
my $self = {};
$self->{'capabilities'} = $capabilities;
$self->{'capabilities'} = undef;
$self->{'extensions'} = $extensions;
$self->{'uuid'} = $this_uuid;
$self->{'valid_until'} = $expires;
......@@ -363,9 +343,44 @@ sub CreateFromSigned($$;$)
$self->{'idx'} = undef; # Only set when stored to DB.
bless($self, $class);
# Dig out the capabilities
foreach my $cap (GeniXML::FindNodes('.//n:privileges/n:privilege',
$root)->get_nodelist()) {
my $name = GeniXML::FindElement('./n:name', $cap);
my $delegate = GeniXML::FindElement('./n:can_delegate', $cap);
if (defined($name) && defined($delegate)) {
$self->AddCapability($name->textContent(),
$delegate->textContent());
}
}
return $self;
}
# Returns a NodeList for a given XPath using a given node as
# context. 'n' is defined to be the prefix for the namespace of the
# node.
#sub findnodes_n($$)
#{
# my ($path, $node) = @_;
# my $xc = XML::LibXML::XPathContext->new();
# my $ns = $node->namespaceURI();
# if (defined($ns)) {
# $xc->registerNs('ns', $node->namespaceURI());
# } else {
# $path =~ s/\bn://g;
# }
# return $xc->findnodes($path, $node);
#}
# Returns the first Node which matches a given XPath against a given
# node. Works like findnodes_n.
#sub findfirst_n($$)
#{
# my ($path, $node) = @_;
# return findnodes_n($path, $node)->pop();
#}
#
# Might have to delete this from the DB.
#
......@@ -413,11 +428,10 @@ sub Sign($$)
}
$cap_xml .= "</privileges>\n";
if (defined($self->extensions())) {
if ($self->extensions()->size() > 0) {
$cap_xml .= "<extensions>\n";
foreach my $key (keys(%{ $self->extensions() })) {
my $value = $self->extensions()->{$key};
$cap_xml .= "<$key>$value</$key>\n";
foreach my $node ($self->extensions()->get_nodelist()) {
$cap_xml .= $node->toString();
}
$cap_xml .= "</extensions>\n";
}
......
......@@ -31,6 +31,7 @@ use GeniSlice;
use GeniSliver;
use GeniUser;
use GeniHRN;
use GeniXML;
use libtestbed;
use User;
use Node;
......@@ -305,20 +306,26 @@ sub CreatePhysNode($)
}
}
elsif (exists($blob->{'rspec'})) {
my $rspec = XMLin($blob->{'rspec'}, KeyAttr => [],
ForceArray => ["interface"]);
foreach my $noderef (@{ $rspec->{'node'} }) {
my $rspec = GeniXML::Parse($blob->{'rspec'});
if (!defined($rspec)) {
goto bad;
}
foreach my $noderef (GeniXML::FindNodes("./n:node",
$rspec)->get_nodelist()) {
next
if ($noderef->{'component_uuid'} ne $node_urn);
if (GeniXML::GetNodeId($noderef) ne $node_urn);
next
if (! exists($noderef->{'interface'}));
if (! defined(GeniXML::FindFirst("./n:interface", $noderef)));
my $count = 0;
foreach my $ref (@{ $noderef->{'interface'} }) {
my $component_id = $ref->{'component_id'};
my $role = (exists($ref->{'role'}) ? $ref->{'role'} : "expt");
foreach my $ref (GeniXML::FindNodes("./n:interface",
$noderef)->get_nodelist()) {
my $component_id = GeniXML::GetText("./n:component_id", $ref);
my $role = GeniXML::GetText("./n:role", $ref);
if (! defined($role)) {
$role = "expt";
}
my $MAC = "00000000000" . $count;
my ($auth,$id,$iface) = GeniHRN::ParseInterface($component_id);
......
......@@ -26,6 +26,7 @@ use GeniAuthority;
use GeniComponent;
use GeniUser;
use GeniHRN;
use GeniXML;
use emutil qw(TBGetUniqueIndex);
use User;
use Project;
......@@ -303,9 +304,7 @@ sub Manifest($)
return undef;
}
my ($manifest_string) = $query_result->fetchrow_array();
my $manifest = XMLin($manifest_string, KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints"]);
my $manifest = GeniXML::Parse($manifest_string);
$self->{'MANIFEST'} = $manifest;
$self->{'MANIFESTSTR'} = $manifest_string;
......@@ -321,13 +320,8 @@ sub UpdateManifest($$)
return -1;
}
my $manifest_idx = $self->manifest_idx();
my $manifest_string =
eval { XMLout($manifest, "NoAttr" => 1, RootName => "manifest") };
if ($@) {
print STDERR "UpdateManifest: XMLout error: $@\n";
print STDERR Dumper($manifest);
return -1;
}
my $manifest_string = $manifest->toString();
my $query_result =
DBQueryWarn("update geni_manifests set ".
" manifest=". DBQuoteSpecial($manifest_string) . ", " .
......@@ -362,13 +356,14 @@ sub GetTicket($$$$)
#
# Lets give it a reasonable default time.
#
if (!exists($rspec->{'valid_until'})) {
$rspec->{'valid_until'} =
POSIX::strftime("20%y-%m-%dT%H:%M:%S", gmtime(time() + (3600*6)));
my $valid_until = GeniXML::FindFirst("./n:valid_until", $rspec);
if (! defined($valid_until)) {
GeniXML::SetText("valid_until",
POSIX::strftime("20%y-%m-%dT%H:%M:%S",
gmtime(time() + (3600*6))));
}
my $rspec_string = XMLout($rspec, "NoAttr" => 1);
$rspec_string =~ s/opt\>/rspec\>/g;
my $rspec_string = $rspec_nodes->toString();
#
# Load the SA cert to act as caller context.
......
......@@ -22,6 +22,7 @@ use GeniCertificate;
use GeniAggregate;
use GeniUsage;
use GeniHRN;
use GeniXML;
use emutil;
use Experiment;
use OSinfo;
......@@ -105,12 +106,8 @@ sub Lookup($$)
my $rspec_string = $self->{'SLIVER'}->{'rspec_string'};
if (defined($rspec_string) && $rspec_string ne "") {
my $rspec =
eval { XMLin($rspec_string, KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints"]) };
if ($@) {
print STDERR "XMLin error reading rspec: $@\n";
my $rspec = GeniXML::Parse($rspec_string);
if (!defined($rspec)) {
return undef;
}
$self->{'RSPEC'} = $rspec;
......@@ -200,7 +197,7 @@ sub Create($$$$$$$$$)
push(@insert_data, "slice_uuid='$slice_uuid'");
if (defined($rspec)) {
my $rspec_string = XMLout($rspec, RootName => "rspec");
my $rspec_string = $rspec->toString();
my $safe_rspec = DBQuoteSpecial($rspec_string);
push(@insert_data, "rspec_string=$safe_rspec");
......@@ -304,12 +301,7 @@ sub GetManifest($$)
return $manifest
if (!$asxml);
my $xml =
eval { XMLout($manifest, "NoAttr" => 1, RootName => "manifest") };
if ($@) {
print STDERR "XMLout error on manifest: $@\n";
return undef;
}
my $xml = $self->rspec()->toString();
return $xml;
}
......@@ -594,8 +586,14 @@ sub component_urn($)
sub Create($$$$$$)
{
# $rspec is a LibXML element representing a single node.
my ($class, $slice, $user, $resource_uuid, $rspec) = @_;
my $virtualization_type = $rspec->{'virtualization_type'};
my $virt_xml = GeniXML::FindFirst("./n:virtualization_type", $rspec);
if (!defined($virt_xml)) {
print STDERR "Node does not contain a virtualization_type\n";
return undef;
}
my $virtualization_type = $virt_xml->textContent();
my $experiment = $slice->GetExperiment();
if (!defined($experiment)) {
......@@ -631,7 +629,12 @@ sub Create($$$$$$)
return undef;
}
}
my $nickname = $rspec->{'virtual_id'};
my $virtual_id_xml = GeniXML::FindFirst("./n:virtual_id", $rspec);
if (!defined($virtual_id_xml)) {
print STDERR "Node does not contain a virtual_id\n";
return undef;
}
my $nickname = $virtual_id_xml->textContent();
my $hrn;
my $sshdport;
my $hostname;
......@@ -665,10 +668,10 @@ sub Create($$$$$$)
#
# Add this stuff to the rspec (which becomes the manifest).
#
$rspec->{'sliver_uuid'} = $sliver_uuid;
$rspec->{'hostname'} = $hostname;
$rspec->{'sshdport'} = $sshdport if (defined($sshdport));
$rspec->{'component_urn'} = $component_urn;
$rspec->setAttribute("sliver_uuid", $sliver_uuid);
$rspec->setAttribute("hostname", $hostname);
$rspec->setAttribute("sshdport", $sshdport) if (defined($sshdport));
$rspec->setAttribute("component_urn", $component_urn);
return GeniSliver->Create($slice, $user, $sliver_uuid, $resource_uuid,
"Node", $resource_id, $hrn, $nickname, $rspec);
......@@ -717,9 +720,11 @@ sub Provision($;$)
my $pid = $experiment->pid();
my $eid = $experiment->eid();
my $virt_type = GeniXML::FindFirst("./n:virtualization_type",
$self->rspec());
if (!$node->isremotenode() &&
exists($self->rspec()->{'virtualization_type'}) &&
$self->rspec()->{'virtualization_type'} eq "emulab-vnode") {
defined($virt_type) &&
$virt_type->textContent() eq "emulab-vnode") {
my $pnode = Node->Lookup($node->phys_nodeid());
if (!defined($pnode)) {
print STDERR "Could not get pnode object for $node\n";
......@@ -729,8 +734,10 @@ sub Provision($;$)
# Mark
$node->ModifyReservation({"genisliver_idx" => $self->idx()});
if (exists($self->rspec()->{'virtualization_subtype'})) {
my $subtype = $self->rspec()->{'virtualization_subtype'};
my $virt_subtype_xml = GeniXML::FindFirst("./n:virtualization_subtype",
$self->rspec());
if (defined($virt_subtype_xml)) {
my $subtype = $virt_subtype_xml->textContent();
if (!$pnode->sharing_mode()) {
$pnode->ModifyReservation({"genisliver_idx" => $self->idx()});
......@@ -808,8 +815,11 @@ sub UnProvision($;$)
}
}
my $virt_type = GeniXML::FindFirst("./n:virtualization_type",
$self->rspec());
if (!$node->isremotenode() &&
$self->rspec()->{'virtualization_type'} eq "emulab-vnode") {
defined($virt_type) &&
$virt_type->textContent() eq "emulab-vnode") {
my $pnode_id = $node->phys_nodeid();
my $pnode = Node->Lookup($pnode_id);
if (!defined($pnode)) {
......@@ -902,12 +912,15 @@ sub ProcessManifest($$)
#
# Find the corresponding node in the manifest.
#
foreach my $ref (@{$manifest->{'node'}}) {
if ($ref->{'sliver_uuid'} eq $uuid) {
foreach my $ref (GeniXML::FindNodes("./n:node",
$manifest)->get_nodelist()) {
my $sliver_xml = GeniXML::FindFirst("./n:sliver_uuid", $ref);
if (defined($sliver_xml) && $sliver_xml->textContent() eq $uuid) {
# startup command.
if (exists($ref->{'startup_command'})) {
my $startupcmd = $ref->{'startup_command'};
my $startup = GeniXML::FindFirst("./n:startup_command", $ref);
if (defined($startup)) {
my $startupcmd = $startup->textContent();
if (! TBcheck_dbslot($startupcmd, "virt_nodes",
"startupcmd",
TBDB_CHECKDBSLOT_WARN|
......@@ -1127,8 +1140,8 @@ sub Create()
#
# Add this stuff to the rspec (which becomes the manifest).
#
$rspec->{'sliver_uuid'} = $interface_uuid;
$rspec->{'component_urn'} = $component_urn;
GeniXML::SetText("sliver_uuid", $rspec, $interface_uuid);
GeniXML::SetText("component_urn", $rspec, $component_urn);
return GeniSliver->Create($slice, $user, $interface_uuid,
$interface_uuid, "Interface", $resource_id,
......
......@@ -23,6 +23,7 @@ use GeniCertificate;
use emutil qw(TBGetUniqueIndex);
use GeniUtil;
use GeniHRN;
use GeniXML;
use English;
use XML::Simple;
use XML::LibXML;
......@@ -137,13 +138,24 @@ sub Lookup($$)
#
sub Create($$$$)
{
# $rspec is an XML string.
my ($class, $target, $owner, $rspec) = @_;
my $parser = XML::LibXML->new;
my $doc;
eval {
$doc = $parser->parse_string($rspec);
};
if ($@) {
print STDERR "Failed to parse ticket string: $@\n";
return undef;
}
# Every Ticket gets a new unique index (sequence number).
my $seqno = TBGetUniqueIndex('next_ticket', 1);
my $self = {};
$self->{'rspec'} = $rspec;
$self->{'rspec'} = $doc->documentElement();
$self->{'ticket_uuid'} = undef;
$self->{'owner_uuid'} = $owner->uuid();
$self->{'owner_hrn'} = $owner->hrn();
......@@ -282,21 +294,13 @@ sub CreateFromSignedTicket($$;$$)
}
# Dig out the rspec.
my ($rspec_node) = $doc->getElementsByTagName("rspec");
if (!defined($rspec_node)) {
my $rspec = GeniXML::FindFirst("//*[local-name()='rspec']",
$doc->documentElement());
if (!defined($rspec)) {
print STDERR "Ticket is missing rspec node\n";
return undef;
}
my $rspec =
eval { XMLin($rspec_node->toString(), KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints"]) };
if ($@) {
print STDERR "XMLin error on ticket rspec: $@\n";
return undef;
}
# Dig out the ticket uuid.
my ($uuid_node) = $doc->getElementsByTagName("uuid");
if (!defined($uuid_node)) {
......@@ -573,14 +577,7 @@ sub rspecXML($)
return undef
if (!defined($self->rspec()));
my $rspec_xml =
eval { XMLout($self->rspec(),
"NoAttr" => 1, RootName => "rspec") };
if ($@) {
print STDERR "XMLout error on rspec: $@\n";
return undef;
}
return $rspec_xml;
return $self->rspec()->toString();
}
#
......@@ -712,18 +709,7 @@ sub RunSigner($$)
my $target_cert = $self->target_cert()->cert();
my $owner_cert = $self->owner_cert()->cert();
my $ticket_uuid = $self->{'ticket_uuid'};
my $rspec_xml = $self->rspec();