Commit a73e627e authored by Leigh Stoller's avatar Leigh Stoller

Big round of image/osid changes. This is the first cut (final cut?) at

supporting autocreating and autoloading images. The imageid form now
sports a field to specify a nodeid to create the image from; If set,
the backend create_image script is invoked. Thats the easy part.
Slightly harder is autoloading images based on the osid specified in
the NS file. To support this, I have added a new DB table called
osidtoimageid, which holds the mapping from osid/pctype to imageid.
When users create images, they must specify what node types that image
is good for. Obviously, the mappings have to be unique or it would be
impossible to figure it out! Anyway, once that image mapping is
in place and the image created, the user can specify that ID in the NS
file. I've changed os_setup to to look for IDs that are not loaded,
and to try and find one in the osidtoimageid. If found, it invokes
os_load. To keep things running in parallel as much as possible,
os_setup issues all the loads/reboots (could be more than a single set
of loads is multiple IDs are in the NS file) at once, and waits for
all the children to exit. I've hacked up os_load a bit to try and be
more robust in the face of PXE failures, which still happen and are
rather troublsesome. Need an event system!

Contained in this revision are unrelated changed to make the OS and
Image IDs per-project unique instead of globally unique, since thats a
pain for the users. This turns out to be very messy, since underneath
we do not want to pass around pid/ID in all the various places its
used. Rather, I create a globally unique name and extened the OS and
Image tables to include pid/name/ID. The user selects pid/name, and I
create the globally unique ID. For the most part this is invisible
throughout the system, except where we interface with the user, say in
the web pages; the user should see his chosen name where possible, and
the should invoke scripts (os_load, create_image, etc) using his/her
name not the internal ID. Also, in the front end the NS file should
use the user name not the ID. All in all, this accounted for a number
of annoying changes and some special cases that are unavoidable.
parent d3410f30
...@@ -1155,7 +1155,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -1155,7 +1155,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/netbsd/GNUmakefile \ tmcd/netbsd/GNUmakefile \
tmcd/tmcd.restart \ tmcd/tmcd.restart \
utils/GNUmakefile utils/vlandiff utils/vlansync utils/delay_config \ utils/GNUmakefile utils/vlandiff utils/vlansync utils/delay_config \
utils/sshtb utils/create_image utils/node_admin \ utils/sshtb utils/create_image utils/node_admin utils/webcreateimage \
www/GNUmakefile www/defs.php3 www/dbdefs.php3 \ www/GNUmakefile www/defs.php3 www/dbdefs.php3 \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \ vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \ rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
......
...@@ -240,7 +240,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -240,7 +240,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/netbsd/GNUmakefile \ tmcd/netbsd/GNUmakefile \
tmcd/tmcd.restart \ tmcd/tmcd.restart \
utils/GNUmakefile utils/vlandiff utils/vlansync utils/delay_config \ utils/GNUmakefile utils/vlandiff utils/vlansync utils/delay_config \
utils/sshtb utils/create_image utils/node_admin \ utils/sshtb utils/create_image utils/node_admin utils/webcreateimage \
www/GNUmakefile www/defs.php3 www/dbdefs.php3 \ www/GNUmakefile www/defs.php3 www/dbdefs.php3 \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \ vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \ rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
......
...@@ -64,7 +64,7 @@ use Exporter; ...@@ -64,7 +64,7 @@ use Exporter;
TB_EXPTPRIORITY_LOW TB_EXPTPRIORITY_HIGH TB_EXPTPRIORITY_LOW TB_EXPTPRIORITY_HIGH
TB_ASSIGN_TOOFEWNODES TB_ASSIGN_TOOFEWNODES TB_OPSPID
TBAdmin TBProjAccessCheck TBNodeAccessCheck TBOSIDAccessCheck TBAdmin TBProjAccessCheck TBNodeAccessCheck TBOSIDAccessCheck
TBImageIDAccessCheck TBExptAccessCheck ExpLeader MarkNodeDown TBImageIDAccessCheck TBExptAccessCheck ExpLeader MarkNodeDown
...@@ -74,7 +74,7 @@ use Exporter; ...@@ -74,7 +74,7 @@ use Exporter;
ExpNodes DBDateTime DefaultImageID GroupLeader TBGroupUnixInfo ExpNodes DBDateTime DefaultImageID GroupLeader TBGroupUnixInfo
TBValidNodeLogType TBValidNodeName TBSetNodeLogEntry TBValidNodeLogType TBValidNodeName TBSetNodeLogEntry
TBSetSchedReload MapNodeOSID TBLockExp TBUnLockExp TBSetExpSwapTime TBSetSchedReload MapNodeOSID TBLockExp TBUnLockExp TBSetExpSwapTime
TBUnixGroupList TBUnixGroupList TBOSID TBImageID
); );
# Must come after package declaration! # Must come after package declaration!
...@@ -86,6 +86,7 @@ require Mysql; ...@@ -86,6 +86,7 @@ require Mysql;
my $TB = "@prefix@"; my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@"; my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@"; my $TBOPS = "@TBOPSEMAIL@";
my $TBOPSPID = "emulab-ops";
# #
# Set up for querying the database. Note that fork causes a reconnect # Set up for querying the database. Note that fork causes a reconnect
...@@ -219,6 +220,9 @@ sub TB_EXPTPRIORITY_HIGH() { 20; } ...@@ -219,6 +220,9 @@ sub TB_EXPTPRIORITY_HIGH() { 20; }
# Assign exit status for too few nodes. # Assign exit status for too few nodes.
sub TB_ASSIGN_TOOFEWNODES() { 2; } sub TB_ASSIGN_TOOFEWNODES() { 2; }
# System PID.
sub TB_OPSPID() { $TBOPSPID; }
# #
# We should list all of the DB limits. # We should list all of the DB limits.
# #
...@@ -553,18 +557,19 @@ sub TBOSIDAccessCheck($$$) ...@@ -553,18 +557,19 @@ sub TBOSIDAccessCheck($$$)
# No GIDs yet. # No GIDs yet.
# #
my $query_result = my $query_result =
DBQueryFatal("SELECT pid FROM os_info WHERE osid='$osid'"); DBQueryFatal("SELECT pid,shared FROM os_info WHERE osid='$osid'");
if ($query_result->numrows == 0) { if ($query_result->numrows == 0) {
return 0; return 0;
} }
my @row = $query_result->fetchrow_array(); my @row = $query_result->fetchrow_array();
my $pid = $row[0]; my $pid = $row[0];
my $shared = $row[1];
# #
# Global OSIDs can be read by anyone. # Global OSIDs can be read by anyone.
# #
if (!$pid) { if ($shared) {
if ($access_type == TB_OSID_READINFO) { if ($access_type == TB_OSID_READINFO) {
return 1; return 1;
} }
...@@ -612,18 +617,19 @@ sub TBImageIDAccessCheck($$$) ...@@ -612,18 +617,19 @@ sub TBImageIDAccessCheck($$$)
# No GIDs yet. # No GIDs yet.
# #
my $query_result = my $query_result =
DBQueryFatal("SELECT pid FROM images WHERE imageid='$imageid'"); DBQueryFatal("SELECT pid,shared FROM images WHERE imageid='$imageid'");
if ($query_result->numrows == 0) { if ($query_result->numrows == 0) {
return 0; return 0;
} }
my @row = $query_result->fetchrow_array(); my @row = $query_result->fetchrow_array();
my $pid = $row[0]; my $pid = $row[0];
my $shared = $row[1];
# #
# Global ImageIDs can be read by anyone. # Global ImageIDs can be read by anyone.
# #
if (!$pid) { if ($shared) {
if ($access_type == TB_IMAGEID_READINFO) { if ($access_type == TB_IMAGEID_READINFO) {
return 1; return 1;
} }
...@@ -1051,6 +1057,50 @@ sub DefaultImageID ($) { ...@@ -1051,6 +1057,50 @@ sub DefaultImageID ($) {
return $row[0]; return $row[0];
} }
#
# Convert user pid/name to internal imageid.
#
# usage: TBImageID(char *pid, char *imagename)
# returns imageid if its valid.
# returns 0 if not valid.
#
sub TBImageID ($$) {
my($pid, $imagename) = @_;
my $query_result =
DBQueryFatal("select imageid from images ".
"where pid='$pid' and imagename='$imagename'");
if (! $query_result->num_rows) {
return 0;
}
my @row = $query_result->fetchrow_array();
return $row[0];
}
#
# Convert user pid/name to internal osid.
#
# usage: TBOSID(char *pid, char *isname)
# returns osid if its valid.
# returns 0 if not valid.
#
sub TBOSID ($$) {
my($pid, $osname) = @_;
my $query_result =
DBQueryFatal("select osid from os_info ".
"where pid='$pid' and osname='$osname'");
if (! $query_result->num_rows) {
return 0;
}
my @row = $query_result->fetchrow_array();
return $row[0];
}
# #
# Map login (db uid) to a user_name and user_email. # Map login (db uid) to a user_name and user_email.
# #
......
...@@ -851,9 +851,9 @@ foreach $pnode (keys(%p2vmap)) { ...@@ -851,9 +851,9 @@ foreach $pnode (keys(%p2vmap)) {
} }
foreach $pair (@nodepairs) { foreach $pair (@nodepairs) {
($pnode,$vnode) = @$pair; ($pnode,$vnode) = @$pair;
my $result = DBQueryFatal("SELECT osid,cmd_line,rpms,deltas,startupcmd," . my $result = DBQueryFatal("SELECT osname,cmd_line,rpms,deltas," .
"tarfiles,failureaction,routertype from virt_nodes" . " startupcmd,tarfiles,failureaction,routertype " .
" where pid=\"$pid\"" . " from virt_nodes where pid=\"$pid\"" .
" and eid=\"$eid\" and vname=\"$vnode\""); " and eid=\"$eid\" and vname=\"$vnode\"");
# The if statement will cause us to skip nodes that belong to # The if statement will cause us to skip nodes that belong to
# the experiment but aren't virtual. I.e. delay nodes. # the experiment but aren't virtual. I.e. delay nodes.
...@@ -862,11 +862,21 @@ foreach $pair (@nodepairs) { ...@@ -862,11 +862,21 @@ foreach $pair (@nodepairs) {
" where node_id=\"$pnode\""); " where node_id=\"$pnode\"");
my ($type) = $result2->fetchrow_array; my ($type) = $result2->fetchrow_array;
$result2->finish; $result2->finish;
if (($osid,$cmdline,$rpms,$deltas,$startupcmd,$tarfiles, if (($osname,$cmdline,$rpms,$deltas,$startupcmd,$tarfiles,
$failureaction,$routertype) = $result->fetchrow_array) { $failureaction,$routertype) = $result->fetchrow_array) {
if (!defined($osid) || $osid eq "") { my $osid;
if (!defined($osname) || $osname eq "") {
$osid = $defosids{$type}; $osid = $defosids{$type};
} }
#
# Map the user name into a specific OSID in the project or in
# the OPS project (a default image).
#
elsif (! ($osid = TBOSID($pid, $osname)) &&
! ($osid = TBOSID(TB_OPSPID, $osname))) {
print STDERR "$0: *** Invalid OS $osname in project $pid!\n";
exit(1);
}
DBQueryFatal("UPDATE nodes set def_boot_osid=\"$osid\"," . DBQueryFatal("UPDATE nodes set def_boot_osid=\"$osid\"," .
" def_boot_cmd_line='$cmdline'," . " def_boot_cmd_line='$cmdline'," .
" startstatus='none'," . " startstatus='none'," .
......
...@@ -6,6 +6,8 @@ use Getopt::Std; ...@@ -6,6 +6,8 @@ use Getopt::Std;
# usage: node_control [options] node [node ...] # usage: node_control [options] node [node ...]
# node_control [options] -e pid,eid # node_control [options] -e pid,eid
# #
# XXX def_boot_osid and virt_nodes osname are not handled properly.
#
sub usage() sub usage()
{ {
print("Usage: node_control name=value [name=value ...] node [node ...]\n". print("Usage: node_control name=value [name=value ...] node [node ...]\n".
...@@ -29,7 +31,7 @@ my %controlset = ...@@ -29,7 +31,7 @@ my %controlset =
# #
# Symbolic name => Admin, Multi args, nodes DB field, virt_nodes DB field # Symbolic name => Admin, Multi args, nodes DB field, virt_nodes DB field
# #
default_boot_osid => [0, 0, "def_boot_osid", "osid"], default_boot_osid => [0, 0, "def_boot_osid", undef],
default_boot_path => [0, 0, "def_boot_path", undef], default_boot_path => [0, 0, "def_boot_path", undef],
default_boot_cmdline => [0, 0, "def_boot_cmd_line", "cmd_line"], default_boot_cmdline => [0, 0, "def_boot_cmd_line", "cmd_line"],
startup_command => [0, 0, "startupcmd", "startupcmd"], startup_command => [0, 0, "startupcmd", "startupcmd"],
......
...@@ -101,7 +101,7 @@ Node instproc updatedb {DB} { ...@@ -101,7 +101,7 @@ Node instproc updatedb {DB} {
} }
# Update the DB # Update the DB
sql exec $DB "insert into virt_nodes (pid,eid,vname,type,ips,osid,cmd_line,rpms,deltas,startupcmd,tarfiles,failureaction,routertype,fixed) values (\"$pid\",\"$eid\",\"$self\",\"$type\",\"$ipraw\",\"$osid\",\"$cmdline\",\"$rpms\",\"$deltas\",\"$startup\",\"$tarfiles\",\"$failureaction\",\"$default_ip_routing_type\",\"$fixed\")"; sql exec $DB "insert into virt_nodes (pid,eid,vname,type,ips,osname,cmd_line,rpms,deltas,startupcmd,tarfiles,failureaction,routertype,fixed) values (\"$pid\",\"$eid\",\"$self\",\"$type\",\"$ipraw\",\"$osid\",\"$cmdline\",\"$rpms\",\"$deltas\",\"$startup\",\"$tarfiles\",\"$failureaction\",\"$default_ip_routing_type\",\"$fixed\")";
} }
# add_lanlink lanlink # add_lanlink lanlink
......
...@@ -54,12 +54,15 @@ namespace eval TBCOMPAT { ...@@ -54,12 +54,15 @@ namespace eval TBCOMPAT {
} }
sql endquery $DB sql endquery $DB
# And a os table with valid OSIDs # And a os table with valid OS Descriptor names. While we still call
# them "osids", we are using the user level name not the internal,
# globally unique name. We leave it to a later phase to deal with it.
#
# We omit this check in anonymous mode. # We omit this check in anonymous mode.
if {!${GLOBALS::anonymous}} { if {!${GLOBALS::anonymous}} {
variable osids variable osids
sql query $DB \ sql query $DB \
"select osid from os_info where pid is NULL or pid = \"$pid\"" "select osname from os_info where shared=1 or pid='$pid'"
while {[set row [sql fetchrow $DB]] != ""} { while {[set row [sql fetchrow $DB]] != ""} {
set osids($row) 1 set osids($row) 1
} }
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
use English; use English;
use Getopt::Std; use Getopt::Std;
# #
# XXX boss.emulab.net and users.emulab.net wired in. # XXX boss.emulab.net and users.emulab.net wired in.
# wd0 wired in. Should come from node_types table in DB # wd0 wired in. Should come from node_types table in DB
...@@ -15,18 +15,19 @@ use Getopt::Std; ...@@ -15,18 +15,19 @@ use Getopt::Std;
sub usage() sub usage()
{ {
print STDOUT print STDOUT
"Usage: os_load [-s] [-r | -n] [-i <imageid>] <node> [node ...]\n". "Usage: os_load [-s] [[-p <pid>] -i <imagename>] [-m <imageid>] ".
" os_load [-s] [-r | -n] [-i <imageid>] -e pid,eid\n". "<node> [node ...]\n".
" os_load [-s] [[-p <pid>] -i <imagename>] [-m <imageid>] ".
"-e pid,eid\n".
" os_load -l\n". " os_load -l\n".
"Use -i to specify an imageid. Use node default otherwise.\n". "Use -i to specify an image name. Use node default otherwise.\n".
"Use -m to specify an image ID (internal name, TB admins only!).\n".
"Use -s to start reload, but do not wait for it to complete.\n". "Use -s to start reload, but do not wait for it to complete.\n".
"Use -e to reboot all the nodes in an experiment\n" . "Use -e to reload all the nodes in an experiment.\n" .
"Use -l to get a list of images you are permitted to load.\n" . "Use -l to get a list of images you are permitted to load.\n";
"Use -r to use Frisbee to reload disks.\n" .
"Use -n to use netdisk to reload disks.\n";
exit(-1); exit(-1);
} }
my $optlist = "sldrni:e:"; my $optlist = "sldrni:e:p:m:b";
# #
# Configure variables # Configure variables
...@@ -64,7 +65,9 @@ my $ping = "/sbin/ping"; ...@@ -64,7 +65,9 @@ my $ping = "/sbin/ping";
my $dbg = 0; my $dbg = 0;
my @row; my @row;
my $usedefault = 1; my $usedefault = 1;
my $imagename;
my $imageid; my $imageid;
my $imagepid = TB_OPSPID;
my %imageid_row; my %imageid_row;
my @nodes = (); my @nodes = ();
my %retries = (); my %retries = ();
...@@ -89,6 +92,9 @@ $| = 1; #Turn off line buffering on output ...@@ -89,6 +92,9 @@ $| = 1; #Turn off line buffering on output
if (! getopts($optlist, \%options)) { if (! getopts($optlist, \%options)) {
usage(); usage();
} }
if (defined($options{"d"})) {
$dbg++;
}
if (defined($options{"l"})) { if (defined($options{"l"})) {
dolisting(); dolisting();
exit(0); exit(0);
...@@ -105,15 +111,41 @@ if (defined($options{"r"})) { ...@@ -105,15 +111,41 @@ if (defined($options{"r"})) {
if (defined($options{"n"})) { if (defined($options{"n"})) {
$type = TB_RELOADTYPE_NETDISK; $type = TB_RELOADTYPE_NETDISK;
} }
if (defined($options{"i"}) && defined($options{"m"})) {
usage();
}
if (defined($options{"i"})) { if (defined($options{"i"})) {
$imageid = $options{"i"}; $imagename = $options{"i"};
$usedefault = 0;
if ($imagename =~ /^([-\w\.\+]+)$/) {
$imagename = $1;
}
else {
die("*** Bad data in $imagename.\n");
}
if (defined($options{"p"})) {
$imagepid = $options{"p"};
if ($imagepid =~ /^([-\w\.\+]+)$/) {
$imagepid = $1;
}
else {
die("*** Bad data in $imagepid.\n");
}
}
}
if (defined($options{"m"})) {
$imageid = $options{"m"};
$usedefault = 0; $usedefault = 0;
if ($imageid =~ /^([-\@\w.\+]+)$/) { if ($imageid =~ /^([-\w\.\+]+)$/) {
$imageid = $1; $imageid = $1;
} }
else { else {
die("*** Bad $imageid name.\n"); die("*** Bad data in $imageid\n");
} }
} }
if (defined($options{"e"})) { if (defined($options{"e"})) {
...@@ -161,17 +193,29 @@ if ($UID && !TBAdmin($UID)) { ...@@ -161,17 +193,29 @@ if ($UID && !TBAdmin($UID)) {
$mereuser = 1; $mereuser = 1;
if (! TBNodeAccessCheck($UID, TB_NODEACCESS_LOADIMAGE, @nodes)) { if (! TBNodeAccessCheck($UID, TB_NODEACCESS_LOADIMAGE, @nodes)) {
die("*** You do not have permission to load images on one (or more) ". die("*** $0:\n".
"of the nodes!\n"); " You do not have permission to load images on one (or more) ".
"nodes!\n");
}
if (defined($imageid)) {
usage();
} }
} }
# #
# See if allowed to load this image! # Convert external name to internal (imageid), and check permission.
# #
if (defined($imageid) && $mereuser && if (defined($imagename)) {
! TBImageIDAccessCheck($UID, $imageid, TB_IMAGEID_READINFO)) { if (! ($imageid = TBImageID($imagepid, $imagename))) {
die("*** You do not have permission to load imageid $imageid!\n"); die("*** $0:\n".
" No such image $imagename in project $imagepid!\n");
}
if ($mereuser &&
! TBImageIDAccessCheck($UID, $imageid, TB_IMAGEID_READINFO)) {
die("*** $0:\n".
" You do not have permission to load this image!\n");
}
} }
# #
...@@ -194,6 +238,8 @@ foreach my $node (@nodes) { ...@@ -194,6 +238,8 @@ foreach my $node (@nodes) {
if ($usedefault) { if ($usedefault) {
$imageid = $default_imageid; $imageid = $default_imageid;
} }
print STDERR "Using $imageid for for $node\n" if $dbg;
my $db_result = my $db_result =
DBQueryFatal("select * from images where imageid='$imageid'"); DBQueryFatal("select * from images where imageid='$imageid'");
...@@ -208,6 +254,7 @@ foreach my $node (@nodes) { ...@@ -208,6 +254,7 @@ foreach my $node (@nodes) {
my $loadlen = $imageid_row{'loadlength'}; my $loadlen = $imageid_row{'loadlength'};
my $imagepath = $imageid_row{'path'}; my $imagepath = $imageid_row{'path'};
my $defosid = $imageid_row{'default_osid'}; my $defosid = $imageid_row{'default_osid'};
my $shared = $imageid_row{'shared'};
# #
# 0 means load the entire disk. # 0 means load the entire disk.
...@@ -224,7 +271,7 @@ foreach my $node (@nodes) { ...@@ -224,7 +271,7 @@ foreach my $node (@nodes) {
# For now, all testbed default images come from paper and all pid specific # For now, all testbed default images come from paper and all pid specific
# images come from plastic:/proj. # images come from plastic:/proj.
# #
if (defined($imageid_row{'pid'})) { if (! $shared) {
if (! ($imagepath =~ /^\/proj\//)) { if (! ($imagepath =~ /^\/proj\//)) {
die("*** $0:\n". die("*** $0:\n".
" Your image must reside in /proj\n"); " Your image must reside in /proj\n");
...@@ -248,12 +295,12 @@ foreach my $node (@nodes) { ...@@ -248,12 +295,12 @@ foreach my $node (@nodes) {
"(node_id, image_id) values ('$node', '$imageid')"); "(node_id, image_id) values ('$node', '$imageid')");
# #
# If a mereuser is loading an image (which is not the default) then # If loading an image (which is not the default) then
# schedule a reload for it so that when the experiment is terminated # schedule a reload for it so that when the experiment is terminated
# it will get a fresh default image before getting reallocated to # it will get a fresh default image before getting reallocated to
# another experiment. # another experiment.
# #
if ($mereuser && $imageid ne $default_imageid) { if ($imageid ne $default_imageid) {
if (! TBSetSchedReload($node, $default_imageid)) { if (! TBSetSchedReload($node, $default_imageid)) {
print "*** $0:\n". print "*** $0:\n".
" WARNING: Could not schedule default reload for $node!"; " WARNING: Could not schedule default reload for $node!";
......
...@@ -18,7 +18,7 @@ sub usage() ...@@ -18,7 +18,7 @@ sub usage()
print STDOUT "Usage: os_setup <pid> <eid>\n"; print STDOUT "Usage: os_setup <pid> <eid>\n";
exit(-1); exit(-1);
} }
my $optlist = ""; my $optlist = "d";
# #
# Configure variables # Configure variables
...@@ -37,8 +37,10 @@ use libdb; ...@@ -37,8 +37,10 @@ use libdb;
use libtestbed; use libtestbed;
my $nodereboot = "$TB/bin/node_reboot"; my $nodereboot = "$TB/bin/node_reboot";
my $os_load = "$TB/bin/os_load";
my $ping = "/sbin/ping"; my $ping = "/sbin/ping";
my $dbg = 0; my $dbg = 0;
my $failed = 0;
my @nodes = (); my @nodes = ();
my %osids = (); my %osids = ();
my %waitfor = (); my %waitfor = ();
...@@ -47,12 +49,13 @@ my $db_result; ...@@ -47,12 +49,13 @@ my $db_result;
my @row; my @row;
# #
# This stuff is BOGUS! Quick hack for paper deadline to make Jay happy. # Ah, Frisbee works so lets do auto reloading for nodes that do not have
# If Frisbee works, this might be appropriate. # the proper OS loaded on it. This will be a hash of lists; for each
# imageid, a list of the nodes to pass to os_load for that imageid.
# #
my $doreloading = 0; my %reloads = ();
my $forcereload = 0; my %reboots = ();
my %reload = (); my $doautoload = 1;
# un-taint path # un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin'; $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
...@@ -71,6 +74,10 @@ if (! getopts($optlist, \%options)) { ...@@ -71,6 +74,10 @@ if (! getopts($optlist, \%options)) {
if (@ARGV != 2) { if (@ARGV != 2) {
usage(); usage();
} }
if (defined($options{"d"})) {
$dbg = 1;
}
my $pid = $ARGV[0]; my $pid = $ARGV[0];
my $eid = $ARGV[1]; my $eid = $ARGV[1];
...@@ -117,14 +124,15 @@ if ($db_result->numrows < 1) { ...@@ -117,14 +124,15 @@ if ($db_result->numrows < 1) {
die("There are no nodes assigned to experiment '$eid' in project '$pid'."); die("There are no nodes assigned to experiment '$eid' in project '$pid'.");
} }
for ($i = 0; $i < $db_result->numrows; $i++) { while (my %row = $db_result->fetchhash()) {
my %row = $db_result->fetchhash();
my $node = $row{'node_id'}; my $node = $row{'node_id'};
my $osid = $row{'def_boot_osid'}; my $osid = $row{'def_boot_osid'};
my $type = $row{'type'};
my $bootpath = 0; my $bootpath = 0;
push(@nodes, $node); push(@nodes, $node);
$osids{$node} = $osid; $osids{$node} = $osid;
$reboots{$node} = 1;
# #
# Make sure the files specified in the paths exist. We mount the # Make sure the files specified in the paths exist. We mount the
...@@ -253,39 +261,58 @@ for ($i = 0; $i < $db_result->numrows; $i++) { ...@@ -253,39 +261,58 @@ for ($i = 0; $i < $db_result->numrows; $i++) {
# #
if ($p_result->numrows == 0) { if ($p_result->numrows == 0) {
# #
# If its a specific Version, and its not loaded on the machine, # Check to see if a non specific version specified.
# its currently an error. Later we might reload.
#
if (defined($osid_row{'version'}) &&
$osid_row{'version'} ne "") {
die("*** OSID $osid is not currently loaded on $node!\n");
}
# #
# A non-specific version. Try to map it. if (! defined($osid_row{'version'}) ||
# $osid_row{'version'} eq "") {
my $o_result =
DBQueryFatal("select o1.* from os_info as o1 ". #
"left join partitions as p ". # A non-specific version. Try to map it.
" on o1.osid=p.osid ". #
"left join os_info as o2 ". my $o_result =
" on o2.OS=o1.OS ". DBQueryFatal("select o1.* from os_info as o1 ".
"where p.node_id='$node' ". "left join partitions as p ".
" and o2.osid='$osid'"); " on o1.osid=p.osid ".
"left join os_info as o2 ".
if ($o_result->numrows == 0) { " on o2.OS=o1.OS ".
die("*** $0:\n". "where p.node_id='$node' ".
" No mapping can be made for $osid on $node!\n". " and o2.osid='$osid'");
" Perhaps the disk needs reloading?\n");
if ($o_result->numrows == 0) {
die("*** $0:\n".
" No mapping can be made for $osid on $node!\n".
" Perhaps the disk needs reloading?\n");
}
else {
my %o_row = $o_result->fetchhash();
my $n_osid = $o_row{'osid'};
print "Mapping $osid on $node to $n_osid.\n";
DBQueryFatal("update nodes ".
"set def_boot_osid='$n_osid' ".
"where node_id='$node'");
$osids{$node} = $n_osid;
}
} }
else { else {
my %o_row = $o_result->fetchhash(); #
my $n_osid = $o_row{'osid'}; # User wants a specific version of an OS, but its not
# loaded on the machine. Issue a load if we can find
print "Mapping $osid on $node to $n_osid.\n"; # an image. This goo constructs a hashed array of lists.
DBQueryFatal("update nodes set def_boot_osid='$n_osid' ". #
"where node_id='$node'"); if ((my $imageid = TBMapOSIDtoImageID($osid, $type))) {
$osids{$node} = $n_osid; if (! defined($reloads{$imageid})) {
$reloads{$imageid} = [ $node ];
}
else {
push(@{ $reloads{$imageid} }, $node);
}
delete $reboots{$node};
}
else {
die("*** $0:\n".