Commit 27340905 authored by Leigh Stoller's avatar Leigh Stoller

Three changes:

1. Fix up multi architecture code wrt auxtypes (say, pvcm). I was
   failing to treat "d710-vm" as a node with a specified type, and so
   were doing multiple mapper runs with different architectures. This is
   cause an auxtype is not really a first class type object, but it is
   now, enough to recognize it as such.

   Aside; vtypes are still a potential problem, need to give this more
   thought.

2. Use the reservation MaxSwapInMap() to determine if the request is
   asking for more nodes of a specific type then allowed; do not bother
   to run assign, bail right away. We can do this we now track how many
   nodes of a specific type have been requested, for the multi
   architecture stuff. So might as well put to another good use.
   This close issue #236.

3. Add reservation system information dump to resinfo.log for post
   mortem debugging.
parent c41adae1
......@@ -90,6 +90,7 @@ sub LookupRow($$$)
$self->{"DBROW"} = $row;
$self->{"CLASS"} = ($type eq $row->{"class"} ? $type : undef);
$self->{"ATTRS"} = undef;
$self->{"ISAUX"} = 0;
bless($self, $class);
......@@ -103,6 +104,7 @@ sub field($$) { return ((! ref($_[0])) ? -1 : $_[0]->{'DBROW'}->{$_[1]}); }
# Do not use the embedded type field, cause of auxtypes.
sub type($) { return $_[0]->{'TYPE'}; }
sub class($) { return field($_[0], 'class'); }
sub IsAuxType($) { return $_[0]->{'ISAUX'}; }
sub architecture($) { return field($_[0], 'architecture'); }
sub isvirtnode($) { return field($_[0], 'isvirtnode'); }
sub isjailed($) { return field($_[0], 'isjailed'); }
......@@ -156,16 +158,8 @@ sub LookupAny($$)
return $obj;
}
$query_result =
DBQueryWarn("select type from node_types_auxtypes ".
"where auxtype='$type' limit 1");
return undef
if (!$query_result);
if ($query_result->numrows) {
my ($ntype) = $query_result->fetchrow_array();
return NodeType->Lookup($ntype);
}
return undef;
# Try for an auxtype.
return NodeType->LookupAuxType($type);
}
#
......@@ -220,6 +214,56 @@ sub LookupArchitectureTypes($$)
return @alltypes;
}
#
# Lookup an auxtype.
#
sub LookupAuxType($$)
{
my ($class, $auxtype) = @_;
my $query_result =
DBQueryWarn("select nt.type from node_types_auxtypes as at ".
"left join node_types as nt on nt.type=at.type ".
"where at.auxtype='$auxtype'");
return undef
if (!$query_result || !$query_result->numrows);
my ($type) = $query_result->fetchrow_array();
my $typeinfo = Lookup($class, $type);
# Something went wrong?
return undef
if (!defined($typeinfo));
#
# Generate a new type entry, but named by the auxtype instead.
# Underlying data is shared; might need to change that.
#
my $newtype = {};
$newtype->{"TYPE"} = $auxtype;
$newtype->{"DBROW"} = $typeinfo->{"DBROW"};
$newtype->{"ATTRS"} = $typeinfo->{"ATTRS"};
$newtype->{"ISAUX"} = 1;
$newtype->{"BASE"} = $typeinfo;
bless($newtype, $class);
# Add to cache.
$nodetypes{$auxtype} = $newtype;
return $newtype;
}
sub BaseType($)
{
my ($self) = @_;
return undef
if (!$self->IsAuxType());
return $self->{'BASE'};
}
#
# Return list of all auxtypes.
#
sub AuxTypes($)
{
my ($class) = @_;
......@@ -234,26 +278,13 @@ sub AuxTypes($)
if (!$query_result || !$query_result->numrows);
while (my ($auxtype, $type) = $query_result->fetchrow_array()) {
my $typeinfo = Lookup($class, $type);
my $typeinfo = LookupAuxType($class, $auxtype);
# Something went wrong?
return undef
if (!defined($typeinfo));
#
# Generate a new type entry, but named by the auxtype instead.
# Underlying data is shared; might need to change that.
#
my $newtype = {};
$newtype->{"TYPE"} = $auxtype;
$newtype->{"DBROW"} = $typeinfo->{"DBROW"};
$newtype->{"ATTRS"} = $typeinfo->{"ATTRS"};
bless($newtype, $class);
# Add to cache.
$nodetypes{$auxtype} = $newtype;
push(@auxtypes, $newtype);
push(@auxtypes, $typeinfo);
}
return @auxtypes;
}
......
......@@ -1151,20 +1151,25 @@ sub LoadVirtNodes($)
$nodetype = NodeType->LookupAny($type);
if (!defined($nodetype)) {
my $vtype = $self->virttypeisvtype($type);
if (!defined($vtype)) {
warn("Improper type $type for node $vnode!\n");
return -1;
if (defined($vtype)) {
# For now, just pick the first member type.
my @memberlist = split(" ", $vtype->members());
my $vtypename = $memberlist[0];
$nodetype = NodeType->Lookup($vtypename);
if (!defined($nodetype)) {
warn("Improper type $vtypename in vtype $type ".
"for node $vnode!\n");
return -1;
}
}
#
# For now, just pick the first member type.
#
my @memberlist = split(" ", $vtype->members());
my $vtypename = $memberlist[0];
$nodetype = NodeType->LookupAny($vtypename);
if (!defined($nodetype)) {
warn("Improper type $vtypename in vtypes for node $vnode!\n");
else {
my @memberlist = NodeType->GlobalVtypeTypes($type);
if (!@memberlist) {
warn("Improper type $type for node $vnode!\n");
return -1;
}
# For now, just pick the first member type.
$nodetype = $memberlist[0];
}
$isvtyped = 1;
}
......@@ -5886,7 +5891,14 @@ sub AllocVirtNodes($)
if ($virtnode->_isdynamic()) {
# Always use the base type ... node type system sucks.
my $basetype = $virtnode->_typeinfo()->type();
my $basetype;
if ($virtnode->_typeinfo()->IsAuxType()) {
$basetype = $virtnode->_typeinfo()->BaseType()->type();
}
else {
$basetype = $virtnode->_typeinfo()->type();
}
#
# We might be expecting to allocate a shared vnode on
......
......@@ -24,6 +24,7 @@
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
use POSIX qw(setsid ceil);
use POSIX ":sys_wait_h";
......@@ -117,6 +118,7 @@ my $PTOPGEN = "$TB/libexec/ptopgen";
my $PTOPGEN_NEW = "$TB/libexec/ptopgen_new";
my $VTOPGEN = "$TB/bin/vtopgen";
my $NFREE = "$TB/bin/nfree";
my $PREDICT = "$TB/sbin/predict";
my $XERCES = "@HAVE_XERCES@";
#
......@@ -124,6 +126,7 @@ my $XERCES = "@HAVE_XERCES@";
#
use lib "@prefix@/lib";
use libdb;
use emutil;
use libtestbed;
use libtblog;
use libvtop;
......@@ -142,6 +145,7 @@ sub FinalizeRegression($);
sub AssignLoop();
sub MapperWrapper(;$);
sub PrintSolution();
sub DumpReservationInfo($$);
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
......@@ -668,7 +672,8 @@ sub RunAssign($$)
$vtopfile .= ".xml";
}
my $assignexitcode = 0;
my $assignlog = "assign.log";
my $assignlog = "assign.log";
my $resinfolog = "resinfo.log";
#
# Now generate a vtop file and dump it to a file.
......@@ -733,14 +738,39 @@ sub RunAssign($$)
# Bound the results to avoid future reservation conflicts.
Reservation->FlushAll();
my $reservation_bounds = Reservation->MaxSwapInMap( $experiment );
foreach my $type ( keys( %$reservation_bounds ) ) {
if( exists( $admission_control{ $type } ) ) {
if( $reservation_bounds->{ $type } < $admission_control{ $type } ) {
$admission_control{ $type } = $reservation_bounds->{ $type };
my $reservation_bounds = Reservation->MaxSwapInMap($experiment);
# Dump to file.
DumpReservationInfo($resinfolog, $reservation_bounds);
foreach my $type (keys(%$reservation_bounds)) {
if (exists($admission_control{$type})) {
if ($reservation_bounds->{$type} < $admission_control{$type}) {
$admission_control{$type} = $reservation_bounds->{$type};
}
}
else {
$admission_control{$type} = $reservation_bounds->{$type};
}
#
# Look to see if topology specifies nodes with this specific
# type. If so, we can tell right away that the user is asking for
# more then is available.
#
# This only works for nodes with hard types. Auxtypes and vtypes
# will still need to go through assign. Might be able to handle
# auxtypes though.
#
if (exists($vtop->types()->{$type})) {
my $bound = $reservation_bounds->{$type};
my $wanted = $vtop->types()->{$type};
if ($wanted > $bound) {
print "*** Resource reservation violation: ".
"$wanted nodes of type $type, but only $bound ".
"avaiable because of existing resource reservations ".
"to other projects.\n";
# Unretriable error
return -1;
}
} else {
$admission_control{ $type } = $reservation_bounds->{ $type };
}
}
......@@ -912,11 +942,13 @@ sub RunAssign($$)
#
system("/bin/cp -fp $assignlog ${prefix}.assign");
system("/bin/cp -fp $assignlog ${pid}-${eid}.assign") if ($debug);
system("/bin/cp -fp $resinfolog ${prefix}-${resinfolog}");
if ($assignexitcode) {
print "Assign exited with $assignexitcode\n" if ($debug);
system("/bin/cat $assignlog");
#
# assign returns two positive error codes (that we care about).
# The distinction between them is somewhat murky. An exitval of
......@@ -1153,3 +1185,25 @@ sub chat($)
print $_[0];
}
}
sub DumpReservationInfo($$)
{
my ($file, $bounds) = @_;
if (!open(RES, ">$file")) {
print STDERR "Could not open $file for writing: $!\n";
return;
}
if (! scalar(keys(%$bounds))) {
close(RES);
return;
}
foreach my $type (keys(%$bounds)) {
my $bound = $bounds->{$type};
print RES "Running predict for $type:$bound\n";
my $output = emutil::ExecQuiet("$PREDICT $type");
print RES $output;
print RES "--------\n";
}
close(RES);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment