Commit 7a82778e authored by Leigh B Stoller's avatar Leigh B Stoller

A slew of new support for cooked mode. Swapmod now works pretty well,

although the default is currently to do cooked mode in "basic" mode,
rather then "full" mode.
parent 99c6c7c4
This diff is collapsed.
...@@ -239,6 +239,17 @@ sub GetCertificate($) { return $_[0]->{'CERTIFICATE'}; } ...@@ -239,6 +239,17 @@ sub GetCertificate($) { return $_[0]->{'CERTIFICATE'}; }
# An alias so that slivers look like aggregates. # An alias so that slivers look like aggregates.
sub resource_type($) { return field($_[0], "type"); } sub resource_type($) { return field($_[0], "type"); }
# A place to stash a temporary rspec.
sub rspec($;$)
{
my ($self, $rspec) = @_;
if (defined($rspec)) {
$self->{'RSPEC'} = $rspec;
}
return $self->{'RSPEC'};
}
# Return the URN. # Return the URN.
sub urn($) sub urn($)
{ {
...@@ -770,6 +781,8 @@ sub Start($$$) ...@@ -770,6 +781,8 @@ sub Start($$$)
return -1; return -1;
} }
if ($reservation->SameExperiment($experiment)) { if ($reservation->SameExperiment($experiment)) {
my $vnode;
# #
# Since this is an aggregate, some slivers may already be # Since this is an aggregate, some slivers may already be
# in the started state. Skip those, unless doing a restart. # in the started state. Skip those, unless doing a restart.
...@@ -778,14 +791,28 @@ sub Start($$$) ...@@ -778,14 +791,28 @@ sub Start($$$)
if ($sliver->state() eq "started" && !$restart); if ($sliver->state() eq "started" && !$restart);
if ($node->isvirtnode()) { if ($node->isvirtnode()) {
$vnodes{$node->node_id} = $node; # A virtnode on a shared physical node needs reboot or setup
if ($node->sharing_mode()) {
# A virtnode on a shared physical node needs nothing else. if ($restart && $sliver->state() eq "started") {
next $reboots{$node->node_id} = $node;
if ($node->sharing_mode()); }
else {
# But if non-shared, have to make sure that the phys node $vnodes{$node->node_id} = $node;
# gets loaded. }
next;
}
# See below.
$vnode = $node;
#
# Now it gets messy. Do not want to mess with the physnode
# if its running other vnodes, and we just need to fire up
# a new one. But if the physnode is going to get rebooted,
# then there is no need to do anything with the vnodes; they
# will boot up with the physnode.
#
# But, have to make sure that the phys node gets setup.
#
my $physnodeid = $node->phys_nodeid(); my $physnodeid = $node->phys_nodeid();
next next
if (exists($poweron{$physnodeid}) || if (exists($poweron{$physnodeid}) ||
...@@ -798,21 +825,22 @@ sub Start($$$) ...@@ -798,21 +825,22 @@ sub Start($$$)
} }
} }
# #
# Look to see if local physical node was stopped (powered off). # If the node is not imageable, then there is not much to
# do except turn it on or reboot it. I am assuming that a
# a non imageable node is always in raw mode.
# #
if (!$node->isremotenode() && if (!$node->imageable()) {
($sliver->state() eq "stopped")) { if ($sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node; $poweron{$node->node_id} = $node;
} }
else { else {
# node_reboot is smart enough to know that if a pnode $reboots{$node->node_id} = $node;
# is rebooted it can ignore the vnodes on it, so do }
# not optimize this here. next;
$reboots{$node->node_id} = $node;
} }
next #
if (!$node->imageable()); # See if the node is running the requested OS.
#
my $osinfo = OSinfo->Lookup($node->def_boot_osid()); my $osinfo = OSinfo->Lookup($node->def_boot_osid());
if (!defined($osinfo)) { if (!defined($osinfo)) {
print STDERR "Could not get osinfo for $node\n"; print STDERR "Could not get osinfo for $node\n";
...@@ -852,6 +880,14 @@ sub Start($$$) ...@@ -852,6 +880,14 @@ sub Start($$$)
$reloads{$image->imageid()} = [ ]; $reloads{$image->imageid()} = [ ];
} }
push(@{ $reloads{$image->imageid()} }, $node); push(@{ $reloads{$image->imageid()} }, $node);
# Reload means reboot or power on.
if (!defined($vnode) && $sliver->state() eq "stopped") {
$poweron{$node->node_id} = $node;
}
else {
$reboots{$node->node_id} = $node;
}
} }
else { else {
# #
...@@ -861,6 +897,33 @@ sub Start($$$) ...@@ -861,6 +897,33 @@ sub Start($$$)
print STDERR " Could not os_select $node to $osinfo\n"; print STDERR " Could not os_select $node to $osinfo\n";
return -1; return -1;
} }
#
# If the node is going to get rebooted, then do not need
# to worry about the vnodes on it. But if the node is ready
# to go, then we have to do the vnodes. Remember, we do not
# reboot the physnode since we might only be adding a new node
# in which case, a full reboot is wrong.
#
if (! $node->IsUp()) {
if ($sliver->state() eq "stopped" && !defined($vnode)) {
$poweron{$node->node_id} = $node;
}
else {
$reboots{$node->node_id} = $node;
}
}
elsif ($restart && !defined($vnode)) {
# Just a physnode that needs restarting.
$reboots{$node->node_id} = $node;
}
elsif (defined($vnode)) {
if ($sliver->state() eq "started") {
$reboots{$vnode->node_id} = $vnode;
}
else {
$vnodes{$vnode->node_id} = $vnode;
}
}
} }
} }
else { else {
......
...@@ -150,7 +150,7 @@ sub Resolve($) ...@@ -150,7 +150,7 @@ sub Resolve($)
undef, "Nothing here by that name"); undef, "Nothing here by that name");
} }
my $rspec = GetAdvertisement(0, $node->node_id(), "0.1"); my $rspec = GetAdvertisement(0, $node->node_id(), "0.1", undef);
if (! defined($rspec)) { if (! defined($rspec)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start avail"); "Could not start avail");
...@@ -237,10 +237,29 @@ sub DiscoverResourcesAux($$$) ...@@ -237,10 +237,29 @@ sub DiscoverResourcesAux($$$)
} }
} }
#
# See if one of the credentials is a slice credential. If it is, and
# that slice is active, pass it to ptopgen so that it includes the current
# resources as available.
#
my $experiment = undef;
foreach my $credential (@$credentials) {
my ($auth, $type, $id) = GeniHRN::Parse($credential->target_urn());
if ($type eq "slice") {
# Might not exist here yet.
my $slice = GeniSlice->Lookup($credential->target_urn());
if (defined($slice)) {
# See if the local experiment exists yet.
$experiment = Experiment->Lookup($slice->uuid());
}
last;
}
}
# #
# Acquire the advertisement from ptopgen and compress it if requested. # Acquire the advertisement from ptopgen and compress it if requested.
# #
my $xml = GetAdvertisement($available, undef, "0.2"); my $xml = GetAdvertisement($available, undef, "0.2", $experiment);
if (! defined($xml)) { if (! defined($xml)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not start avail"); "Could not start avail");
...@@ -258,12 +277,16 @@ sub DiscoverResourcesAux($$$) ...@@ -258,12 +277,16 @@ sub DiscoverResourcesAux($$$)
# #
# Use ptopgen in xml mode to spit back an xml file. # Use ptopgen in xml mode to spit back an xml file.
# #
sub GetAdvertisement($$$) sub GetAdvertisement($$$$)
{ {
my ($available, $pc, $version) = @_; my ($available, $pc, $version, $experiment) = @_;
my $xml = undef; my $xml = undef;
my $invocation = "$PTOPGEN -x -g $version -r -p GeniSlices"; my $invocation = "$PTOPGEN -x -g $version -r -p GeniSlices";
if (defined($experiment)) {
my $eid = $experiment->eid();
$invocation .= " -e $eid";
}
$invocation .= " -a" unless $available; $invocation .= " -a" unless $available;
if (defined($pc)) { if (defined($pc)) {
$invocation .= " -1 $pc"; $invocation .= " -1 $pc";
...@@ -1535,6 +1558,7 @@ sub SliverWorkAux($$$$$$$) ...@@ -1535,6 +1558,7 @@ sub SliverWorkAux($$$$$$$)
my $response; my $response;
my $ticket; my $ticket;
my $rspec; my $rspec;
my $oldmanifest;
require Interface; require Interface;
# V2 API support. # V2 API support.
...@@ -1665,10 +1689,18 @@ sub SliverWorkAux($$$$$$$) ...@@ -1665,10 +1689,18 @@ sub SliverWorkAux($$$$$$$)
print GeniXML::Serialize($rspec); print GeniXML::Serialize($rspec);
# The Manifest starts out as a copy of the rspec.
my $manifest = $rspec->cloneNode(1);
# #
# Find current slivers and save. # Find current slivers and save.
# #
if (defined($aggregate)) { if (defined($aggregate)) {
$oldmanifest = $aggregate->GetManifest(0);
if (!defined($oldmanifest)) {
$message = "Internal error getting manifest";
goto bad;
}
my @slivers; my @slivers;
if ($aggregate->SliverList(\@slivers) != 0) { if ($aggregate->SliverList(\@slivers) != 0) {
$message = "Could not get sliverlist for $aggregate"; $message = "Could not get sliverlist for $aggregate";
...@@ -2040,8 +2072,22 @@ sub SliverWorkAux($$$$$$$) ...@@ -2040,8 +2072,22 @@ sub SliverWorkAux($$$$$$$)
} }
# Already in the aggregate? # Already in the aggregate?
next if (grep {$_ eq $virtual_id} keys(%nodemap)) {
if (grep {$_ eq $virtual_id} keys(%nodemap)); #
# Need to find the old manifest entry and make sure it
# gets into the new manifest.
#
if (defined($oldmanifest)) {
my $oldnode = GeniXML::GetNodeByVirtualId($virtual_id,
$oldmanifest);
my $curnode = GeniXML::GetNodeByVirtualId($virtual_id,
$manifest);
if (defined($oldnode) && defined($curnode)) {
GeniXML::ReplaceNode($curnode, $oldnode);
}
}
next;
}
my $node = GeniUtil::LookupNode($resource_id); my $node = GeniUtil::LookupNode($resource_id);
if (!defined($node)) { if (!defined($node)) {
...@@ -2080,6 +2126,13 @@ sub SliverWorkAux($$$$$$$) ...@@ -2080,6 +2126,13 @@ sub SliverWorkAux($$$$$$$)
} }
push(@plabnodes, $vnode); push(@plabnodes, $vnode);
} }
# Store the updated rspec for later.
goto bad
if ($sliver->UpdateRspec($ref));
# And store into the new manifest.
my $oldnode = GeniXML::GetNodeByVirtualId($virtual_id, $manifest);
GeniXML::ReplaceNode($oldnode, $ref);
} }
# #
...@@ -2126,8 +2179,22 @@ sub SliverWorkAux($$$$$$$) ...@@ -2126,8 +2179,22 @@ sub SliverWorkAux($$$$$$$)
# Do not worry about modifying a link that is setup, unless a tunnel. # Do not worry about modifying a link that is setup, unless a tunnel.
# Need to deal with this later. # Need to deal with this later.
if (grep {$_ eq $linkname} keys(%linkmap)) { if (grep {$_ eq $linkname} keys(%linkmap)) {
next if (!$is_tunnel) {
if ($is_tunnel); #
# Need to find the old manifest entry and make sure it
# gets into the new manifest.
#
if (defined($oldmanifest)) {
my $oldlink = GeniXML::GetLinkByVirtualId($linkname,
$oldmanifest);
my $curlink = GeniXML::GetLinkByVirtualId($linkname,
$manifest);
if (defined($oldlink) && defined($curlink)) {
GeniXML::ReplaceNode($curlink, $oldlink);
}
}
next;
}
# #
# Gack, we have to recreate all the tunnel physical state, but # Gack, we have to recreate all the tunnel physical state, but
...@@ -2201,7 +2268,7 @@ sub SliverWorkAux($$$$$$$) ...@@ -2201,7 +2268,7 @@ sub SliverWorkAux($$$$$$$)
$message = "Could not set aggregate for $tunnel to $aggregate"; $message = "Could not set aggregate for $tunnel to $aggregate";
goto bad; goto bad;
} }
next; goto manifest;
} }
my $linkaggregate = GeniAggregate::Link->Create($slice, $owner, my $linkaggregate = GeniAggregate::Link->Create($slice, $owner,
...@@ -2340,6 +2407,11 @@ sub SliverWorkAux($$$$$$$) ...@@ -2340,6 +2407,11 @@ sub SliverWorkAux($$$$$$$)
goto bad; goto bad;
} }
} }
manifest:
# And store into the new manifest.
my $oldlink = GeniXML::GetLinkByVirtualId($linkname, $manifest);
GeniXML::ReplaceNode($oldlink, $linkref);
} }
skiplinks: skiplinks:
# #
...@@ -2445,14 +2517,12 @@ sub SliverWorkAux($$$$$$$) ...@@ -2445,14 +2517,12 @@ sub SliverWorkAux($$$$$$$)
} }
} }
# The Manifest.
my $manifest = GeniXML::Serialize($rspec);
# #
# Move this elsewhere. # Move this elsewhere.
# #
my $manifest_string = GeniXML::Serialize($manifest);
DBQueryWarn("replace into geni_manifests set ". DBQueryWarn("replace into geni_manifests set ".
" manifest=". DBQuoteSpecial($manifest) . ", " . " manifest=". DBQuoteSpecial($manifest_string) . ", " .
" idx=NULL, slice_uuid='$slice_uuid', created=now()"); " idx=NULL, slice_uuid='$slice_uuid', created=now()");
if (GeniUsage->NewManifest($aggregate, $rspec)) { if (GeniUsage->NewManifest($aggregate, $rspec)) {
...@@ -2485,7 +2555,7 @@ sub SliverWorkAux($$$$$$$) ...@@ -2485,7 +2555,7 @@ sub SliverWorkAux($$$$$$$)
$slice->UnLock(); $slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_SUCCESS, return GeniResponse->Create(GENIRESPONSE_SUCCESS,
[$sliver_credential->asString(), [$sliver_credential->asString(),
$manifest]); $manifest_string]);
} }
# #
# Free any slivers that were no longer wanted. # Free any slivers that were no longer wanted.
...@@ -2505,9 +2575,9 @@ sub SliverWorkAux($$$$$$$) ...@@ -2505,9 +2575,9 @@ sub SliverWorkAux($$$$$$$)
if ($v2) { if ($v2) {
return GeniResponse->Create(GENIRESPONSE_SUCCESS, return GeniResponse->Create(GENIRESPONSE_SUCCESS,
[$sliver_credential->asString(), [$sliver_credential->asString(),
$manifest]); $manifest_string]);
} else { } else {
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $manifest); return GeniResponse->Create(GENIRESPONSE_SUCCESS, $manifest_string);
} }
bad: bad:
......
...@@ -125,7 +125,7 @@ sub Resolve($) ...@@ -125,7 +125,7 @@ sub Resolve($)
if ($type eq "node") { if ($type eq "node") {
my $node = $object; my $node = $object;
my $rspec = GeniCM::GetAdvertisement(0, $node->node_id(), "0.1"); my $rspec = GeniCM::GetAdvertisement(0, $node->node_id(), "0.1", undef);
if (! defined($rspec)) { if (! defined($rspec)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error getting advertisement"); "Error getting advertisement");
...@@ -585,6 +585,8 @@ sub SliverAction($$$$$) ...@@ -585,6 +585,8 @@ sub SliverAction($$$$$)
{ {
my ($action, $slice_urn, $sliver_urns, $credentials, $manifest) = @_; my ($action, $slice_urn, $sliver_urns, $credentials, $manifest) = @_;
my $response; my $response;
print STDERR "fooey\n";
if (! (defined($credentials) && if (! (defined($credentials) &&
(defined($slice_urn) || defined($sliver_urns)))) { (defined($slice_urn) || defined($sliver_urns)))) {
......
This diff is collapsed.
...@@ -321,6 +321,26 @@ sub GetManifest($$) ...@@ -321,6 +321,26 @@ sub GetManifest($$)
return $xml; return $xml;
} }
#
# Store the rspec/manifest string.
#
sub UpdateRspec($$)
{
my ($self, $rspec) = @_;
my $idx = $self->idx();
my $rspec_string = GeniXML::Serialize($rspec);
my $safe_rspec = DBQuoteSpecial($rspec_string);
return -1
if (!DBQueryWarn("update geni_slivers set ".
" rspec_string=$safe_rspec ".
"where idx='$idx'"));
$self->{'RSPEC'} = $rspec;
return 0;
}
# #
# Set the aggregate for a sliver. # Set the aggregate for a sliver.
# #
......
...@@ -1645,14 +1645,45 @@ sub LightUpNodes($@) ...@@ -1645,14 +1645,45 @@ sub LightUpNodes($@)
my $experiment = $parent->experiment(); my $experiment = $parent->experiment();
my $pid = $experiment->pid(); my $pid = $experiment->pid();
my $eid = $experiment->eid(); my $eid = $experiment->eid();
my @rebootlist = ();
#
# What nodes need reboot.
#
foreach my $node (@nodelist) {
push (@rebootlist, $node)
if ($node->allocstate() eq TBDB_ALLOCSTATE_RES_REBOOT());
}
TBDebugTimeStamp("Starting Geni setup."); TBDebugTimeStamp("Starting Geni setup.");
#
# This will start newly added slivers, but not existing.
#
if (libGeni::StartSlivers($experiment, if (libGeni::StartSlivers($experiment,
$parent->user(), 0, $parent->debug())) { $parent->user(), $parent->debug())) {
print STDERR "*** Could not start Geni slivers\n"; print STDERR "*** Could not start Geni slivers\n";
return 1; return 1;
} }
TBDebugTimeStamp("Geni slivers have been started."); TBDebugTimeStamp("Geni slivers have been started.");
# Now reboot the rest.
if (@rebootlist) {
if (libGeni::RestartNodes($parent->user(), $parent->debug(), @rebootlist)) {
tbdie("Could not restart protogeni nodes\n");
}
#
# We always do a wait for geni nodes since for nodes in "basic"
# cooked mode, nothing will be reporting a state change from the
# node. We have to go poll it to make sure that the node is alive,
# and so we can report ISUP for it. This is a bit of a violation of
# the default reboot model, which is fire and forget when waitmode
# is not set, but no way around it.
#
if (libGeni::WaitForNodes($parent->user(),
$parent->debug(), undef, @rebootlist)) {
tbdie("Error in waiting for protogeni nodes\n");
}
}
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -321,9 +321,9 @@ sub AssignLoop() ...@@ -321,9 +321,9 @@ sub AssignLoop()
TBDebugTimeStamp("mapper loop started"); TBDebugTimeStamp("mapper loop started");
while (1) { while (1) {
chat("Assign run $currentrun\n"); chat("Mapper loop $currentrun\n");
my $prefix = ($debug || $regression ? "$pid-$eid" : "$pid-$eid-$$"); my $prefix = "$pid-$eid-$$";
# #
# When precheck is on, we only do one run in impotent mode and exit. # When precheck is on, we only do one run in impotent mode and exit.
...@@ -469,9 +469,24 @@ sub RunAssign($$) ...@@ -469,9 +469,24 @@ sub RunAssign($$)
return -1; return -1;
} }
close(VTOPFILE); close(VTOPFILE);
system("/bin/cp -fp $vtopfile ${pid}-${eid}.vtop") if ($debug);
return 0 return 0
if ($toponly); if ($toponly);
if (! ($impotent || $regression || $alloconly)) {
if ($experiment->Update({"maximum_nodes" => $vtop->maximum_nodes(),
"minimum_nodes" => $vtop->minimum_nodes(),
"virtnode_count"=> $vtop->virtnodecount() })){
tberror("Could not update min/max/virt nodes for $experiment\n");
return -1;
}
}
# New solution each time.
$vtop->ClearSolution();
goto skipassign
if ($vtop->nodecount() == $vtop->genicount());
# Debugging hack for regression mode. Avoid really long assign runs. # Debugging hack for regression mode. Avoid really long assign runs.
if ($regression && $noassign) { if ($regression && $noassign) {
if (! -e "assign.log") { if (! -e "assign.log") {
...@@ -550,17 +565,9 @@ sub RunAssign($$) ...@@ -550,17 +565,9 @@ sub RunAssign($$)
tberror("Failure in ptopgen\n"); tberror("Failure in ptopgen\n");
return -1; return -1;
} }
system("/bin/cp -fp $ptopfile ${pid}-${eid}.ptop") if ($debug);
TBDebugTimeStamp("ptopgen finished"); TBDebugTimeStamp("ptopgen finished");
if (! ($impotent || $regression || $alloconly)) {
if ($experiment->Update({"maximum_nodes" => $vtop->maximum_nodes(),
"minimum_nodes" => $vtop->minimum_nodes(),
"virtnode_count"=> $vtop->virtnodecount() })){
tberror("Could not update min/max/virt nodes for $experiment\n");
return -1;
}
}
# Run assign # Run assign
my $cmd = "assign"; my $cmd = "assign";
$cmd .= "-new" $cmd .= "-new"
...@@ -650,7 +657,8 @@ sub RunAssign($$) ...@@ -650,7 +657,8 @@ sub RunAssign($$)
# purposes We do not call it .log though, since we do not want it # purposes We do not call it .log though, since we do not want it
# copied out to the user directory every swapin. See Experiment.pm # copied out to the user directory every swapin. See Experiment.pm
# #
system("/bin/cp assign.log ${prefix}.assign"); system("/bin/cp -fp assign.log ${prefix}.assign");
system("/bin/cp -fp assign.log ${pid}-${eid}.assign") if ($debug);
if ($assignexitcode) { if ($assignexitcode) {
print "Assign exited with $assignexitcode\n" if ($debug); print "Assign exited with $assignexitcode\n" if ($debug);
...@@ -680,9 +688,6 @@ sub RunAssign($$) ...@@ -680,9 +688,6 @@ sub RunAssign($$)
print("Could not open assign logfile! $!\n"); print("Could not open assign logfile! $!\n");
return -1; return -1<