sched_reload.in 5.07 KB
Newer Older
1 2
#!/usr/bin/perl -wT
use English;
3
use Getopt::Std;
4 5 6 7 8 9 10
   
#
# Schedule the reloading of a disk partition on a node. If the node is
# currently not reserved, start the loading now after reserving it to 
# testbed:reloading. Otherwise, put the right info into the database, and 
# nfree will do it when the node gets freed.
# 
11 12 13 14 15 16 17 18 19 20
# usage: sched_reload [-f] <imageid> <imagepart> <imagepath> <node> [node ...]
#
sub usage()
{
    print STDOUT "Usage: sched_reload [-f] <imageid> <imagepart> <imagepath> ".
	"<node> [node ...]\n".
	"Use the -f to force reload. Fail if node cannot be reserved.\n";
    exit(-1);
}
my  $optlist = "f";
21 22 23 24

#
# Configure variables
#
25
my $TB     = "@prefix@/bin";
26 27
my $DBNAME = "@TBDBNAME@";

28 29 30
my $osload      = "$TB/os_load";
my $name        = "";
my $mereuser    = 0;
31 32 33 34
my $error       = 0;
my $debug       = 0;
my $force	= 0;
my @row;
35 36 37 38 39 40 41 42

# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

$| = 1; #Turn off line buffering on output

#
43 44 45 46 47 48 49 50 51
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (@ARGV != 4) {
    usage();
52
}
53 54 55 56
if (defined($options{"f"})) {
    $force = $options{"f"};
}

57 58 59 60 61
my $imageid   = shift;
my $imagepart = shift;
my $imagepath = shift;
my @nodes     = @ARGV;

62 63 64 65 66 67
#
# Set up for querying the database.
# 
use Mysql;
my $DB = Mysql->connect("localhost", $DBNAME, "script", "none");

68 69 70 71 72 73 74
#
# Figure out who called us. Root and admin types can do whatever they
# want. Normal users can only change nodes in experiments in their
# own projects.
#
if ($UID != 0) {
    ($name) = getpwuid($UID)
75
	or die "$UID not in passwd file\n";
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

    $db_result = $DB->query("select admin from users where uid='$name'");
    @row = $db_result->fetchrow_array();
    if ($row[0] != 1) {
	$mereuser = 1;
    }
}

#
# Mere Users cannot schedule reloads.
#
if ($mereuser) {
    die("Only root or TB administrators can schedule disk reloads.\n");
}

#
# We only support 0 or 4 right now.
#
if ($imagepart != 0 && $imagepart != 4) {
95
    die("Only the entire disk or partition 4 can be loaded.\n");
96 97 98 99 100 101
}

#
# The image has to be accessible, and it must reside in the right places.
#
if (! -e $imagepath) {
102
    die("Cannot access $imagepath.\n");
103 104
}
if (! -f $imagepath) {
105
    die("$imagepath is not a plain file.\n");
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
}

#
# Do the best we can
# 
my @load_list=();
foreach my $node (@nodes) {
    my $pc = $node;

    # Untaint the arguments. Sheer idiocy.
    #
    if ($pc =~ /^([-\@\w.]+)$/) {
	$pc = $1;
    }
    if ($imageid =~ /^([-\@\w.]+)$/) {
	$imageid = $1;
    } else {
        print STDERR "Imageid contains invalid characters. Skipping $pc.\n";
	next;
    }
    if ($imagepart =~ /^([-\@\w.]+)$/) {
	$imagepart = $1;
    } else {
        print STDERR "Imagepart contains invalid characters. Skipping $pc.\n";
	next;
    }
    if ($imagepath =~ /^([-\@\w.\/]+)$/) {
	$imagepath = $1;
    } else {
        print STDERR "Imagepath contains invalid characters. Skipping $pc.\n";
	next;
    }

139 140
    $sth = $DB->query("select * from nodes where node_id='$pc'");
    if ($sth == 0) {
141
	die("Database lookup failed (exists). Aborted...\n");
142 143 144 145 146 147
    }
    if ($sth->num_rows() != 1) {
      print STDERR "Node $pc doesn't exist. Skipping $pc.\n";
      next;
    }
    
148
    print STDERR "Checking if $pc is reserved...";
149
    $sth = $DB->query("select * from reserved where node_id='$pc'");
150 151 152
    if ($sth == 0) {
	die("Database lookup failed (reserved). Aborted...\n");
    }
153 154 155

    my $allocated = 0;
   
156 157
    if ( ($sth->num_rows()) < 1) {
        print STDERR "Available.\nReserving and adding to list.\n";
158 159 160 161
	#
	# XXX If you change testbed/reloading, be sure to update the
	#     test in doreboot() in tmcd/tmcd.c.
	# 
162 163 164 165
	my $cmd = "$TB/nalloc testbed reloading $pc";
        if ( system($cmd) != 0 ) {
	    print STDERR "WARNING: Could not reserve $pc!\n";
	} else {
166 167 168 169 170 171
	    #
	    # Kill the last_reservation so that whoever gets the node next
	    # won't be fooled into thinking a reload is required.
	    #
	    $sth = $DB->query("delete from last_reservation ".
			      "where node_id='$pc'");
172
	    push (@load_list,$pc);
173
	    $allocated = 1;
174 175 176 177
	}
    } else {
        print STDERR "Reserved.\n";      
    }
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

    #
    # If force and not able to reserve, do not pend a reload.
    # 
    if ($force && !$allocated) {
	$error++;
	next;
    }

    # Put it in the reloads table so TMCD knows to free it.
    print STDERR "Scheduling reload for $pc:\n".
      "Load OS $imageid to partition $imagepart from $imagepath\n";
    $sth = $DB->query("replace into reloads ".
		      "(node_id, partition, image_id, path)".
		      "values ('$pc', '$imagepart',".
		      "'$imageid', '$imagepath')");
    if ($sth == 0) {
      die("Database update failed (reloads). Aborted...\n");
    }
197 198 199 200 201 202 203 204 205 206 207 208
}

if (@load_list > 0) {
  print STDERR "Running os_load on ",join(", ",@load_list),":\n";
  $cmd = "$osload $imageid $imagepart $imagepath @load_list";
  print STDERR "Calling '$cmd'\n";
  if ( system($cmd) != 0 ) {
    print STDERR "WARNING: OS_LOAD FAILED ON @load_list!\n";
  }
}

print STDOUT "Reload Scheduling Done!\n";
209
exit $error;