Commit 9b37d0a4 authored by Jonathon Duerig's avatar Jonathon Duerig
Browse files

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents 51e4c143 6198efe1
......@@ -108,6 +108,9 @@ if (@ARGV) {
if (defined($options{"d"})) {
$debug++;
}
if (defined($options{"f"})) {
$force = 1;
}
if (defined($options{"a"})) {
$all = 1;
}
......
......@@ -31,6 +31,7 @@ use Lan;
use GeniEmulab;
use GeniResource;
use GeniResponse;
use GeniXML;
use English;
use Socket;
use XML::Simple;
......@@ -103,7 +104,12 @@ sub MapResources($$$$)
$fragments{$cm} = {
'generated_by' => 'libvtop',
'type' => 'request',
'xmlns' => 'http://www.protogeni.net/resources/rspec/0.1',
'xmlns' => 'http://www.protogeni.net/resources/rspec/0.2',
# Assign now wants this stuff. I have no clue what it means!
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
'xsi:schemaLocation' =>
"http://www.protogeni.net/resources/rspec/0.2 ".
"http://www.protogeni.net/resources/rspec/0.2/request.xsd",
'node' => [] };
}
push(@{ $fragments{$cm}->{'node'} }, $copy);
......@@ -204,7 +210,7 @@ sub MapResources($$$$)
$ptopfh->close();
system("nice $ASSIGN -uod -c .75 ".
"-q $ptop -w $vtop -W $soln > $log 2>&1");
"-f rspec/rspec -W $soln $ptop $vtop > $log 2>&1");
if ($?) {
print STDERR "Could not map to physical resources on $resource\n";
......@@ -284,13 +290,20 @@ sub MapResources($$$$)
if ($verbose) {
print STDERR "Final rspec:\n";
print STDERR Dumper($rspec);
if (1) {
my $rspecdoc = GeniResource::ConvertRspec($rspec);
my $rspecstr = GeniXML::Serialize($rspecdoc);
print STDERR "In XML:\n";
print STDERR "$rspecstr\n";
}
}
return 0;
}
sub GetTickets($$$$)
{
my ($experiment, $impotent, $user, $rspec) = @_;
my ($experiment, $verbose, $user, $rspec) = @_;
my %cm_urns = ();
Register($experiment, $user) == 0
......@@ -335,6 +348,17 @@ sub GetTickets($$$$)
$cm_urns{$cm} = $resource;
}
#
# XXX Convert to a proper XML looking thing. This is just a temporay
# hack for now.
#
my $rspecdoc = GeniResource::ConvertRspec($rspec);
my $rspecstr = GeniXML::Serialize($rspecdoc);
if ($verbose) {
print STDERR "In XML:\n";
print STDERR "$rspecstr\n";
}
#
# Get Tickets in parallel.
#
......@@ -344,7 +368,7 @@ sub GetTickets($$$$)
my ($resource) = @_;
print STDERR "Asking for ticket from $resource\n";
if ($resource->GetTicket($user, $rspec, $impotent)) {
if ($resource->GetTicket($user, $rspecstr, 0)) {
#
# Print this here since we do not save this in the
# DB, and the parent side of the fork will not have
......@@ -487,19 +511,22 @@ sub MapNodes($$)
my $manifest = $resource->Manifest();
return -1
if (!defined($manifest));
my $manifest_string = $resource->manifest_string();
print STDERR Dumper($manifest)
print STDERR "$manifest_string\n"
if ($verbose);
foreach my $ref (@{ $manifest->{'node'} }) {
my $sliver_urn = $ref->{'sliver_urn'};
my $vname = $ref->{'virtual_id'};
foreach my $ref (GeniXML::FindNodes("n:node",
$manifest)->get_nodelist()) {
my $sliver_urn = GeniXML::GetSliverId($ref);
my $vname = GeniXML::GetVirtualId($ref);
my $sshdport = GeniXML::GetText("sshdport", $ref);
#
# The manifest can include nodes from other CMs. There will not
# be a sliver urn in that case.
#
my $component_manager_urn = $ref->{'component_manager_urn'};
my $component_manager_urn = GeniXML::GetManagerId($ref);
next
if (!defined($sliver_urn) && !defined($component_manager_urn));
......@@ -515,9 +542,7 @@ sub MapNodes($$)
$sliver_urn})
== 0 or return -1;
if (exists($ref->{'sshdport'})) {
my $sshdport = $ref->{'sshdport'};
if (defined($sshdport)) {
$node->Update({'sshdport' => $sshdport});
}
#
......@@ -527,29 +552,38 @@ sub MapNodes($$)
"-s $BOSSNODE -k $eventkey,$keyhash -u '$sliver_urn'";
$cmd .= " -j " . $node->node_id()
if ($node->isvirtnode());
$ref->{'startup_command'} = "$cmd boot";
GeniXML::SetText("startup_command", $ref, "$cmd boot");
# Interface map for loop below.
if (exists($ref->{'interface'})) {
foreach my $ifaceref (@{ $ref->{'interface'} }) {
my $virtid = $ifaceref->{'virtual_id'};
my $compid = $ifaceref->{'component_id'};
if (defined(GeniXML::FindFirst("n:interface", $ref))) {
foreach my $ifaceref (GeniXML::FindNodes("n:interface",
$ref)->get_nodelist()) {
my $virtid = GeniXML::GetText("virtual_id", $ifaceref);
my $compid = GeniXML::GetText("component_id", $ifaceref);
$ifacemap{$virtid} = [$node, $compid];
}
}
}
foreach my $ref (@{ $manifest->{'link'} }) {
my $linkname = $ref->{"virtual_id"};
my $interfaces = $ref->{'interface_ref'};
my %managers = map { $_->{'id'} => $_->{'id'} }
@{ $ref->{'component_manager'} };
foreach my $ref (GeniXML::FindNodes("n:link",
$manifest)->get_nodelist()) {
my $linkname = GeniXML::GetVirtualId($ref);
my $link_type = GeniXML::GetText("link_type", $ref);
my $vlantag = GeniXML::GetText("vlantag", $ref);
my @ifacerefs = GeniXML::FindNodes("n:interface_ref",
$ref)->get_nodelist();
my %managers = ();
if (GeniXML::FindNodes("n:component_manager", $ref)) {
%managers = map { GeniXML::GetText("id", $_) => $_ }
GeniXML::FindNodes("n:component_manager",
$ref)->get_nodelist();
}
# Skip tunnels in this loop for now.
next
if (exists($ref->{'link_type'}) &&
$ref->{'link_type'} eq "tunnel");
if (defined($link_type) && $link_type eq "tunnel");
#
# The manifest can include links for other CMs. Skip those
......@@ -558,13 +592,13 @@ sub MapNodes($$)
next
if (!exists($managers{$resource->manager_urn()}));
if (exists($ref->{'vlantag'})) {
my $TAG = $ref->{'vlantag'};
if (defined($vlantag)) {
my $TAG = $vlantag;
if (defined($TAG)) {
if (!($TAG =~ /^[\w]*$/)) {
print STDERR "Bad vlantag '$TAG' for $linkname\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
my $lan = Lan->Lookup($experiment, $linkname, 1);
......@@ -590,11 +624,12 @@ sub MapNodes($$)
}
}
foreach my $ifaceref (@{ $interfaces }) {
my $vname = $ifaceref->{'virtual_node_id'};
my $iface_id = $ifaceref->{'virtual_interface_id'};
my $MAC = $ifaceref->{'MAC'};
my $VMAC = $ifaceref->{'VMAC'};
foreach my $ifaceref (@ifacerefs) {
my $vname = GeniXML::GetText("virtual_node_id", $ifaceref);
my $iface_id = GeniXML::GetText("virtual_interface_id",
$ifaceref);
my $MAC = GeniXML::GetText("MAC", $ifaceref);
my $VMAC = GeniXML::GetText("VMAC", $ifaceref);
my ($node, $compid) = @{ $ifacemap{$iface_id} };
my $iface;
......@@ -607,7 +642,7 @@ sub MapNodes($$)
if (!defined($iface)) {
print STDERR "Could not determine iface for" .
"$vname,$iface_id\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
#
......@@ -619,7 +654,7 @@ sub MapNodes($$)
my $pnode = $node->GetPhysHost();
if (!defined($pnode)) {
print STDERR "Could not physical node for $node\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
$node = $pnode;
......@@ -628,22 +663,22 @@ sub MapNodes($$)
my $interface = Interface->LookupByIface($node,$iface);
if (!defined($interface)) {
print STDERR "Could not map iface for $node,$iface\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
if (!defined($MAC)) {
print STDERR "No mac (or vmac) for $node,$iface\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
if (! ($MAC =~ /^[\w]*$/)) {
print STDERR "Bad mac '$MAC' for $node,$iface\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
if ($interface->Update({"mac" => "$MAC"})) {
print STDERR "Could not update $node,$iface\n";
print Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
if (defined($VMAC)) {
......@@ -659,12 +694,12 @@ sub MapNodes($$)
}
if (! ($VMAC =~ /^[\w]*$/)) {
print STDERR "Bad vmac '$VMAC' for $linkname,$vname\n";
print STDERR Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
if ($vinterface->Update({"mac" => "$VMAC"})) {
print STDERR "Could not update $linkname,$vname\n";
print Dumper($manifest);
print STDERR "$manifest_string\n";
return -1;
}
}
......@@ -797,16 +832,17 @@ sub WaitForSlivers($$$@)
return -1
if (!defined($manifest));
foreach my $ref (@{ $manifest->{'node'} }) {
my $vname = $ref->{'virtual_id'};
my $urn = $ref->{'component_urn'};
foreach my $ref (GeniXML::FindNodes("n:node",
$manifest)->get_nodelist()) {
my $vname = GeniXML::GetVirtualId($ref);
my $urn = GeniXML::GetNodeId($ref);
my $node = $experiment->VnameToNode($vname);
#
# The manifest can include nodes from other CMs. There will not
# be a sliver urn in that case.
#
my $sliver_urn = $ref->{'sliver_urn'};
my $sliver_urn = GeniXML::GetSliverId($ref);
next
if (!defined($sliver_urn));
......@@ -945,8 +981,9 @@ sub WaitForSlivers($$$@)
next
if (!defined($manifest));
foreach my $ref (@{ $manifest->{'node'} }) {
my $vname = $ref->{'virtual_id'};
foreach my $ref (GeniXML::FindNodes("n:node",
$manifest)->get_nodelist()) {
my $vname = GeniXML::GetVirtualId($ref);
my $node = $experiment->VnameToNode($vname);
next
if (!defined($node));
......
......@@ -167,6 +167,8 @@ if ($verify) {
print " this is resolved. Typically, you can resolve this by:\n\n";
print " boss> cd /your/object/dir\n";
print " boss> gmake update-testbed\n\n";
print " More information is available at:\n";
print " https://users.emulab.net/trac/emulab/wiki/install/update-testbed-v2\n\n";
exit($exitval);
}
......
......@@ -27,6 +27,7 @@ use English;
use overload ('""' => 'Stringify');
use XML::Simple;
use Date::Parse;
use Data::Dumper;
# Configure variables
my $TB = "@prefix@";
......@@ -327,8 +328,13 @@ sub Version($)
print STDERR " " . $response->output() . "\n";
return undef;
}
$self->{'version'} = $response->value();
return $response->value();
if (ref($response->value())) {
$self->{'version'} = $response->value()->{'api'};
}
else {
$self->{'version'} = $response->value();
}
return $self->{'version'};
}
#
......
......@@ -26,6 +26,7 @@ use GeniAuthority;
use GeniComponent;
use GeniUser;
use GeniHRN;
use GeniXML;
use emutil qw(TBGetUniqueIndex);
use User;
use Project;
......@@ -218,6 +219,7 @@ sub manager_version($) { return $_[0]->{'manager_version'}; }
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'}; }
sub manifest_string($) { return $_[0]->{'MANIFESTSTR'}; }
#
# Delete a resource record from the DB.
......@@ -378,11 +380,11 @@ sub Manifest($)
return undef;
}
my ($manifest_string) = $query_result->fetchrow_array();
my $manifest = XMLin($manifest_string, KeyAttr => [],
ForceArray => ["node", "link", "interface",
"interface_ref", "linkendpoints",
"component_manager"]);
my $manifest = GeniXML::Parse($manifest_string);
if (!defined($manifest)) {
print STDERR "Could not getmanifest for $self\n";
return undef;
}
$self->{'MANIFEST'} = $manifest;
$self->{'MANIFESTSTR'} = $manifest_string;
return $manifest;
......@@ -397,14 +399,7 @@ 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 = GeniXML::Serialize($manifest);
my $query_result =
DBQueryWarn("update geni_manifests set ".
......@@ -461,13 +456,81 @@ sub ManagerVersion($)
return $self->{'manager_version'};
}
#
# Convert an rspec structure (as from libvtop) into proper format.
# This is horrible.
#
sub ConvertRspec($)
{
my ($rspec) = @_;
my $template =
"<rspec xmlns=\"http://protogeni.net/resources/rspec/0.2\" ".
" type=\"request\" generated_by=\"libvtop\">".
"</rspec>";
my $new = GeniXML::Parse($template);
if (!defined($new)) {
print STDERR "ConvertRspec: Could not create new document\n";
return undef;
}
# ???
my $root = $new;
foreach my $ref (@{ $rspec->{'node'} }) {
my $node = GeniXML::AddElement("node", $root);
foreach my $key ('virtual_id', 'component_urn', 'exclusive',
'virtualization_type', 'virtualization_subtype',
'startup_command', 'tarfiles') {
GeniXML::SetText($key, $node, $ref->{$key})
if (exists($ref->{$key}));
}
foreach my $ifaceref (@{ $ref->{'interface'} }) {
my $iface = GeniXML::AddElement("interface", $node);
foreach my $key ('virtual_id', 'component_id') {
GeniXML::SetText($key, $iface, $ifaceref->{$key})
if (exists($ifaceref->{$key}));
}
}
}
if (exists($rspec->{'link'})) {
foreach my $linkref (@{ $rspec->{'link'} }) {
my $link = GeniXML::AddElement("link", $root);
foreach my $key ('virtual_id', 'link_type',
'virtualization_type') {
GeniXML::SetText($key, $link, $linkref->{$key})
if (exists($linkref->{$key}));
}
# These are special; see libvtop.
foreach my $key ('bandwidth', 'latency', 'packet_loss') {
if (exists($linkref->{$key})) {
my ($val) = @{ $linkref->{$key} };
GeniXML::SetText($key, $link, $val);
}
}
foreach my $ifaceref (@{ $linkref->{'interface_ref'} }) {
my $iface = GeniXML::AddElement("interface_ref", $link);
foreach my $key ('virtual_node_id', 'virtual_interface_id',
'tunnel_ip') {
GeniXML::SetText($key, $iface, $ifaceref->{$key})
if (exists($ifaceref->{$key}));
}
}
}
}
return $new;
}
#
# Add Resources. We get an rspec to replace the current rspec.
# Ask for a ticket, and then redeem it.
#
sub GetTicket($$$$)
{
my ($self, $user, $rspec, $impotent) = @_;
my ($self, $user, $rspec_string, $impotent) = @_;
my $ticket;
my $response;
......@@ -483,15 +546,6 @@ sub GetTicket($$$$)
}
my $manager_urn = $self->manager_urn();
my $rspec_string = eval { XMLout($rspec, "NoAttr" => 1) };
if ($@) {
print STDERR "GetTicket: XMLout error: $@\n";
print STDERR Dumper($rspec);
return -1;
}
$rspec_string =~ s/opt\>/rspec\>/g;
#
# Load the SA cert to act as caller context.
#
......
......@@ -204,6 +204,12 @@ sub GetVirtualId($)
GetText("nickname", $node);
}
sub GetSliverId($)
{
my ($node) = @_;
return GetText("sliver_urn", $node);
}
sub GetManagerId($)
{
my ($node) = @_;
......
......@@ -3294,6 +3294,23 @@ CREATE TABLE `table_regex` (
UNIQUE KEY `table_name` (`table_name`,`column_name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `template_stamps`
--
CREATE TABLE `template_stamps` (
`guid` varchar(16) NOT NULL default '',
`vers` smallint(5) unsigned NOT NULL default '0',
`id` smallint(5) unsigned NOT NULL auto_increment,
`instance` int(10) unsigned default NULL,
`stamp_type` varchar(32) NOT NULL default '',
`modifier` varchar(32) default NULL,
`stamp` int(10) unsigned default NULL,
`aux_type` varchar(32) default NULL,
`aux_data` float default '0',
PRIMARY KEY (`guid`,`vers`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Table structure for table `testbed_stats`
--
......
#
# Add missing table.
#
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
if (!DBTableExists("template_stamps")) {
DBQueryFatal("CREATE TABLE `template_stamps` ( ".
" `guid` varchar(16) NOT NULL default '', ".
" `vers` smallint(5) unsigned NOT NULL default '0', ".
" `id` smallint(5) unsigned NOT NULL auto_increment, ".
" `instance` int(10) unsigned default NULL, ".
" `stamp_type` varchar(32) NOT NULL default '', ".
" `modifier` varchar(32) default NULL, ".
" `stamp` int(10) unsigned default NULL, ".
" `aux_type` varchar(32) default NULL, ".
" `aux_data` float default '0', ".
" PRIMARY KEY (`guid`,`vers`,`id`) ".
") ENGINE=MyISAM DEFAULT CHARSET=latin1");
}
return 0;
}
1;
......@@ -8,10 +8,16 @@ package libossetup;
use strict;
use Exporter;
use vars qw(@ISA @EXPORT $AUTOLOAD $NOSTATE $RELOAD $RECONFIG $REBOOT);
use vars qw(@EXPORT $AUTOLOAD
$NOSTATE $RELOAD $RECONFIG $REBOOT
$RELOAD_FAILED $RECONFIG_FAILED $REBOOT_FAILED $SETUP_FAILED
$SETUP_OKAY);
use base qw( Exporter );
@ISA = "Exporter";
@EXPORT = qw (die_noretry $NOSTATE $RELOAD $RECONFIG $REBOOT);
@EXPORT = qw(&die_noretry
$NOSTATE $RELOAD $RECONFIG $REBOOT
$RELOAD_FAILED $RECONFIG_FAILED $REBOOT_FAILED $SETUP_FAILED
$SETUP_OKAY);
use libdb;
use libtestbed;
......@@ -28,12 +34,19 @@ my $TBOPS = "@TBOPSEMAIL@";
my $NODEREBOOT = "$TB/bin/node_reboot";
my $VNODESETUP = "$TB/sbin/vnode_setup";
# Flags
# Setup Operation Flags
$NOSTATE = 0x00;
$RELOAD = 0x01;
$RELOAD = 0x01;
$RECONFIG = 0x02;
$REBOOT = 0x04;
# Setup Result Flags
$SETUP_OKAY = 0x00;
$RELOAD_FAILED = 0x01;
$RECONFIG_FAILED = 0x02;
$REBOOT_FAILED = 0x04;
$SETUP_FAILED = 0x08;
#
# Used to die with a -1 return code, to indicate to caller (tbswap)
# that the failure is not likely to be fixed with another attempt.
......@@ -78,6 +91,7 @@ sub New($$$@)
# Init some per-node stuff.
$node->_rebooted(0);
$node->_vnodecount(0);
}
bless($self, $class);
......@@ -399,10 +413,11 @@ sub SetOS($$)
#
$self->SetupReload($node, $osinfo);
}
# Remember this for later.
$node->_bootosinfo($osinfo);
}
}
# Remember this for later.
$node->_bootosinfo($osinfo);
print STDERR "$node_id - $osinfo\n"
if ($self->debug());