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 \
tmcd/netbsd/GNUmakefile \
tmcd/tmcd.restart \
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 \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
......
......@@ -240,7 +240,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/netbsd/GNUmakefile \
tmcd/tmcd.restart \
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 \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
......
......@@ -64,7 +64,7 @@ use Exporter;
TB_EXPTPRIORITY_LOW TB_EXPTPRIORITY_HIGH
TB_ASSIGN_TOOFEWNODES
TB_ASSIGN_TOOFEWNODES TB_OPSPID
TBAdmin TBProjAccessCheck TBNodeAccessCheck TBOSIDAccessCheck
TBImageIDAccessCheck TBExptAccessCheck ExpLeader MarkNodeDown
......@@ -74,7 +74,7 @@ use Exporter;
ExpNodes DBDateTime DefaultImageID GroupLeader TBGroupUnixInfo
TBValidNodeLogType TBValidNodeName TBSetNodeLogEntry
TBSetSchedReload MapNodeOSID TBLockExp TBUnLockExp TBSetExpSwapTime
TBUnixGroupList
TBUnixGroupList TBOSID TBImageID
);
# Must come after package declaration!
......@@ -86,6 +86,7 @@ require Mysql;
my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBOPSPID = "emulab-ops";
#
# Set up for querying the database. Note that fork causes a reconnect
......@@ -219,6 +220,9 @@ sub TB_EXPTPRIORITY_HIGH() { 20; }
# Assign exit status for too few nodes.
sub TB_ASSIGN_TOOFEWNODES() { 2; }
# System PID.
sub TB_OPSPID() { $TBOPSPID; }
#
# We should list all of the DB limits.
#
......@@ -553,18 +557,19 @@ sub TBOSIDAccessCheck($$$)
# No GIDs yet.
#
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) {
return 0;
}
my @row = $query_result->fetchrow_array();
my $pid = $row[0];
my $shared = $row[1];
#
# Global OSIDs can be read by anyone.
#
if (!$pid) {
if ($shared) {
if ($access_type == TB_OSID_READINFO) {
return 1;
}
......@@ -612,18 +617,19 @@ sub TBImageIDAccessCheck($$$)
# No GIDs yet.
#
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) {
return 0;
}
my @row = $query_result->fetchrow_array();
my $pid = $row[0];
my $shared = $row[1];
#
# Global ImageIDs can be read by anyone.
#
if (!$pid) {
if ($shared) {
if ($access_type == TB_IMAGEID_READINFO) {
return 1;
}
......@@ -1051,6 +1057,50 @@ sub DefaultImageID ($) {
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.
#
......
......@@ -851,9 +851,9 @@ foreach $pnode (keys(%p2vmap)) {
}
foreach $pair (@nodepairs) {
($pnode,$vnode) = @$pair;
my $result = DBQueryFatal("SELECT osid,cmd_line,rpms,deltas,startupcmd," .
"tarfiles,failureaction,routertype from virt_nodes" .
" where pid=\"$pid\"" .
my $result = DBQueryFatal("SELECT osname,cmd_line,rpms,deltas," .
" startupcmd,tarfiles,failureaction,routertype " .
" from virt_nodes where pid=\"$pid\"" .
" and eid=\"$eid\" and vname=\"$vnode\"");
# The if statement will cause us to skip nodes that belong to
# the experiment but aren't virtual. I.e. delay nodes.
......@@ -862,11 +862,21 @@ foreach $pair (@nodepairs) {
" where node_id=\"$pnode\"");
my ($type) = $result2->fetchrow_array;
$result2->finish;
if (($osid,$cmdline,$rpms,$deltas,$startupcmd,$tarfiles,
if (($osname,$cmdline,$rpms,$deltas,$startupcmd,$tarfiles,
$failureaction,$routertype) = $result->fetchrow_array) {
if (!defined($osid) || $osid eq "") {
my $osid;
if (!defined($osname) || $osname eq "") {
$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\"," .
" def_boot_cmd_line='$cmdline'," .
" startstatus='none'," .
......
......@@ -6,6 +6,8 @@ use Getopt::Std;
# usage: node_control [options] node [node ...]
# node_control [options] -e pid,eid
#
# XXX def_boot_osid and virt_nodes osname are not handled properly.
#
sub usage()
{
print("Usage: node_control name=value [name=value ...] node [node ...]\n".
......@@ -29,7 +31,7 @@ my %controlset =
#
# 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_cmdline => [0, 0, "def_boot_cmd_line", "cmd_line"],
startup_command => [0, 0, "startupcmd", "startupcmd"],
......
......@@ -101,7 +101,7 @@ Node instproc updatedb {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
......
......@@ -54,12 +54,15 @@ namespace eval TBCOMPAT {
}
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.
if {!${GLOBALS::anonymous}} {
variable osids
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]] != ""} {
set osids($row) 1
}
......
#!/usr/bin/perl -wT
use English;
use Getopt::Std;
#
# XXX boss.emulab.net and users.emulab.net wired in.
# wd0 wired in. Should come from node_types table in DB
......@@ -15,18 +15,19 @@ use Getopt::Std;
sub usage()
{
print STDOUT
"Usage: os_load [-s] [-r | -n] [-i <imageid>] <node> [node ...]\n".
" os_load [-s] [-r | -n] [-i <imageid>] -e pid,eid\n".
"Usage: os_load [-s] [[-p <pid>] -i <imagename>] [-m <imageid>] ".
"<node> [node ...]\n".
" os_load [-s] [[-p <pid>] -i <imagename>] [-m <imageid>] ".
"-e pid,eid\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 -e to reboot all the nodes in an experiment\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";
"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";
exit(-1);
}
my $optlist = "sldrni:e:";
my $optlist = "sldrni:e:p:m:b";
#
# Configure variables
......@@ -64,7 +65,9 @@ my $ping = "/sbin/ping";
my $dbg = 0;
my @row;
my $usedefault = 1;
my $imagename;
my $imageid;
my $imagepid = TB_OPSPID;
my %imageid_row;
my @nodes = ();
my %retries = ();
......@@ -89,6 +92,9 @@ $| = 1; #Turn off line buffering on output
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$dbg++;
}
if (defined($options{"l"})) {
dolisting();
exit(0);
......@@ -105,15 +111,41 @@ if (defined($options{"r"})) {
if (defined($options{"n"})) {
$type = TB_RELOADTYPE_NETDISK;
}
if (defined($options{"i"}) && defined($options{"m"})) {
usage();
}
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;
if ($imageid =~ /^([-\@\w.\+]+)$/) {
if ($imageid =~ /^([-\w\.\+]+)$/) {
$imageid = $1;
}
else {
die("*** Bad $imageid name.\n");
die("*** Bad data in $imageid\n");
}
}
if (defined($options{"e"})) {
......@@ -161,17 +193,29 @@ if ($UID && !TBAdmin($UID)) {
$mereuser = 1;
if (! TBNodeAccessCheck($UID, TB_NODEACCESS_LOADIMAGE, @nodes)) {
die("*** You do not have permission to load images on one (or more) ".
"of the nodes!\n");
die("*** $0:\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 &&
! TBImageIDAccessCheck($UID, $imageid, TB_IMAGEID_READINFO)) {
die("*** You do not have permission to load imageid $imageid!\n");
if (defined($imagename)) {
if (! ($imageid = TBImageID($imagepid, $imagename))) {
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) {
if ($usedefault) {
$imageid = $default_imageid;
}
print STDERR "Using $imageid for for $node\n" if $dbg;
my $db_result =
DBQueryFatal("select * from images where imageid='$imageid'");
......@@ -208,6 +254,7 @@ foreach my $node (@nodes) {
my $loadlen = $imageid_row{'loadlength'};
my $imagepath = $imageid_row{'path'};
my $defosid = $imageid_row{'default_osid'};
my $shared = $imageid_row{'shared'};
#
# 0 means load the entire disk.
......@@ -224,7 +271,7 @@ foreach my $node (@nodes) {
# For now, all testbed default images come from paper and all pid specific
# images come from plastic:/proj.
#
if (defined($imageid_row{'pid'})) {
if (! $shared) {
if (! ($imagepath =~ /^\/proj\//)) {
die("*** $0:\n".
" Your image must reside in /proj\n");
......@@ -248,12 +295,12 @@ foreach my $node (@nodes) {
"(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
# it will get a fresh default image before getting reallocated to
# another experiment.
#
if ($mereuser && $imageid ne $default_imageid) {
if ($imageid ne $default_imageid) {
if (! TBSetSchedReload($node, $default_imageid)) {
print "*** $0:\n".
" WARNING: Could not schedule default reload for $node!";
......
......@@ -18,7 +18,7 @@ sub usage()
print STDOUT "Usage: os_setup <pid> <eid>\n";
exit(-1);
}
my $optlist = "";
my $optlist = "d";
#
# Configure variables
......@@ -37,8 +37,10 @@ use libdb;
use libtestbed;
my $nodereboot = "$TB/bin/node_reboot";
my $os_load = "$TB/bin/os_load";
my $ping = "/sbin/ping";
my $dbg = 0;
my $failed = 0;
my @nodes = ();
my %osids = ();
my %waitfor = ();
......@@ -47,12 +49,13 @@ my $db_result;
my @row;
#
# This stuff is BOGUS! Quick hack for paper deadline to make Jay happy.
# If Frisbee works, this might be appropriate.
# Ah, Frisbee works so lets do auto reloading for nodes that do not have
# 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 $forcereload = 0;
my %reload = ();
my %reloads = ();
my %reboots = ();
my $doautoload = 1;
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
......@@ -71,6 +74,10 @@ if (! getopts($optlist, \%options)) {
if (@ARGV != 2) {
usage();
}
if (defined($options{"d"})) {
$dbg = 1;
}
my $pid = $ARGV[0];
my $eid = $ARGV[1];
......@@ -117,14 +124,15 @@ if ($db_result->numrows < 1) {
die("There are no nodes assigned to experiment '$eid' in project '$pid'.");
}
for ($i = 0; $i < $db_result->numrows; $i++) {
my %row = $db_result->fetchhash();
while (my %row = $db_result->fetchhash()) {
my $node = $row{'node_id'};
my $osid = $row{'def_boot_osid'};
my $type = $row{'type'};
my $bootpath = 0;
push(@nodes, $node);
$osids{$node} = $osid;
$reboots{$node} = 1;
#
# Make sure the files specified in the paths exist. We mount the
......@@ -253,39 +261,58 @@ for ($i = 0; $i < $db_result->numrows; $i++) {
#
if ($p_result->numrows == 0) {
#
# If its a specific Version, and its not loaded on the machine,
# 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");
}
# Check to see if a non specific version specified.
#
# A non-specific version. Try to map it.
#
my $o_result =
DBQueryFatal("select o1.* from os_info as o1 ".
"left join partitions as p ".
" on o1.osid=p.osid ".
"left join os_info as o2 ".
" on o2.OS=o1.OS ".
"where p.node_id='$node' ".
" and o2.osid='$osid'");
if ($o_result->numrows == 0) {
die("*** $0:\n".
" No mapping can be made for $osid on $node!\n".
" Perhaps the disk needs reloading?\n");
if (! defined($osid_row{'version'}) ||
$osid_row{'version'} eq "") {
#
# A non-specific version. Try to map it.
#
my $o_result =
DBQueryFatal("select o1.* from os_info as o1 ".
"left join partitions as p ".
" on o1.osid=p.osid ".
"left join os_info as o2 ".
" on o2.OS=o1.OS ".
"where p.node_id='$node' ".
" and o2.osid='$osid'");
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 {
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;
#
# User wants a specific version of an OS, but its not
# loaded on the machine. Issue a load if we can find
# an image. This goo constructs a hashed array of lists.
#
if ((my $imageid = TBMapOSIDtoImageID($osid, $type))) {
if (! defined($reloads{$imageid})) {
$reloads{$imageid} = [ $node ];
}
else {
push(@{ $reloads{$imageid} }, $node);
}
delete $reboots{$node};
}
else {
die("*** $0:\n".
" No image can be found for $osid on $node!\n");
}
}
}
}
......@@ -312,23 +339,45 @@ for ($i = 0; $i < $db_result->numrows; $i++) {
$canfail{$node} = 0;
}
print STDOUT "$node - $osids{$node} - $waitfor{$node} - $canfail{$node}\n"
print STDERR "$node - $osids{$node} - $waitfor{$node} - $canfail{$node}\n"
if $dbg;
}
#
# Fire off a mass reboot. The reboot script does this in parallel, so
# no need to create any new children here. We just wait until it exits,
# which means all the nodes are actually rebooting.
# We need to issue the reboots and the reloads in parallel.
#
if (!$TESTMODE) {
if (system("$nodereboot @nodes")) {
die("*** Failed to reboot some nodes!");
}
my %pids = ();
my $count = 0;
my $cmd;
if (keys(%reboots)) {
$cmd = "$nodereboot " . join(" ", keys(%reboots));
$pids{$cmd} = ForkCmd($cmd);
}
foreach my $imageid ( keys(%reloads) ) {
my @list = @{ $reloads{$imageid} };
sleep(5);
$pids{"$os_load -m $imageid @list"} =
ForkCmd("$os_load -m $imageid @list");
}
foreach $cmd ( keys(%pids) ) {
my $pid = $pids{$cmd};
waitpid($pid, 0);
if ($?) {
$failed++;
print STDERR "*** Failed: $cmd\n";
}
}
}
print STDOUT "Waiting for testbed nodes to finish rebooting ...\n";
sleep(2);
my $waitstart = time;
#
......@@ -389,12 +438,13 @@ foreach my $node ( @nodes ) {
"Thanks\n".
"Testbed Operations\n");
die("*** Experiment will be now be terminated automatically.");
print STDERR "*** Experiment will be terminated automatically.\n";
$failed++;
}
}
print STDOUT "OS Setup Done!\n";
exit 0;
exit $failed;
#
# Wait for a node to come back alive.
......@@ -407,10 +457,7 @@ sub WaitTillAlive {
#
# Seems like a long time to wait, but it ain't!
#
my $maxwait = (60 * 6);
if ($reload{$pc}) {
$maxwait += (60 * 5);
}
my $maxwait = (60 * 5);
#
# Start a counter going, relative to the time we rebooted the first
......@@ -440,7 +487,7 @@ sub WaitTillAlive {
$waittime = time - $waitstart;
if ($waittime > $maxwait) {
print "$pc appears dead; its been ",
(int ($waittime / 60))," minutes since reload started.\n";
(int ($waittime / 60))," minutes since rebooted.\n";
return 1;
}
if (int($waittime / 60) > $minutes) {
......@@ -449,3 +496,42 @@ sub WaitTillAlive {
}
}
}
#
# Map an OSID to an imageid for a node type.
#
sub TBMapOSIDtoImageID($$)
{
my ($osid, $type) = @_;
my $query_result =
DBQueryFatal("select imageid from osidtoimageid ".
"where type='$type' and osid='$osid'");
if ($query_result->numrows == 0) {
return 0;
}
my ($imageid) = $query_result->fetchrow_array();
return $imageid;
}
#
# Fork a process to exec a command. Return the pid to wait on.
#
sub ForkCmd($) {
my ($cmd) = @_;
my($mypid);
$mypid = fork();
if ($mypid) {
return $mypid;
}
if ($dbg) {
print STDERR "Forking command: $cmd\n";
}
system($cmd);
exit($? >> 8);
}
......@@ -126,8 +126,8 @@ while (1) {
}
#
# We can pull out all nodes that were not 'touched' (matched by the select above)
# during this pass
# We can pull out all nodes that were not 'touched' (matched by the
# select above) during this pass
#
foreach $node (keys %retried) {
if ($retried{$node} != $time) {
......@@ -153,8 +153,8 @@ while (1) {
}
#
# We can pull out all nodes that were not 'touched' (matched by the select above)
# during this pass
# We can pull out all nodes that were not 'touched' (matched by the
# select above) during this pass
#
foreach $node (keys %warned) {
if ($warned{$node} != $time) {
......@@ -163,7 +163,7 @@ while (1) {
}
#
# Find all of the free node that have not been reloaded (no pid entry
# Find all of the free nodes that have not been reloaded (no pid entry
# in last_reservation, which is reset anytime a node is reloaded by
# the system).
#
......@@ -253,12 +253,12 @@ while (1) {
}
#
# We only add the -i flag to os_load if we found a specific image
# We only add the -m flag to os_load if we found a specific image
# above. Omitting it causes os_load to pick the default image for
# the node's type
#
if ($imageid) {
$os_load_flags .= " -i $imageid ";
$os_load_flags .= " -m $imageid ";
}
if (system("$os_load $os_load_flags $node")) {
......@@ -351,7 +351,7 @@ while (1) {