sched_reload.in 5.15 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#!/usr/bin/perl -wT
use English;
   
#
# XXX Paper and plastic IP addresses wired into the kernel choice.
#     Paths to the images are wired in.
#     Path to netdisk is wired in.
#     Need to reset the partitions when reloading the entire disk.
# 

#
# 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.
# 
# usage: sched_reload <imageid> <imagepart> <imagepath> <node> [node ...]
#
19 20 21 22

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

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
my $rsh		= "sshtb -q";
my $ssh		= "sshtb -q";
my $NETDISK     = "/tftpboot/netdisk";
my $power	= "$TB/power";
my $osload      = "$TB/os_load";
my $ping	= "/sbin/ping";
my $dbg		= 1;
my %waitfor     = ();
my $SAVEUID	= $UID;
my @row;
my $name        = "";
my $mereuser    = 0;

# 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

#
# Set up for querying the database.
# 
use Mysql;
49
my $DB = Mysql->connect("localhost", $DBNAME, "script", "none");
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

if ( $#ARGV < 3) {
    die("Usage: sched_reload <imageid> <imagepart> <imagepath> <node> [node ...]\n".
	"Schedules the loading of an OS image to a node partition.\n");
}
my $imageid   = shift;
my $imagepart = shift;
my $imagepath = shift;
my @nodes     = @ARGV;

#
# 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)
67
	or die "$UID not in passwd file\n";
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

    $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");
}

#
# Check to make sure that mere user is allowed to muck with nodes
#
#if ($mereuser) {
#    foreach my $node (@nodes) {
#	$db_result = $DB->query("select reserved.node_id from reserved ".
#				"left join proj_memb on ".
#				"reserved.pid=proj_memb.pid and ".
#				"reserved.node_id='$node' ".
#				"where proj_memb.uid='$name'");
#	if ($db_result->numrows < 1) {
#	    die("You do not have permission to load images on $node\n");
#	}
#    }
#}

#
# We only support 0 or 4 right now.
#
if ($imagepart != 0 && $imagepart != 4) {
103
    die("Only the entire disk or partition 4 can be loaded.\n");
104 105 106 107 108 109
}

#
# The image has to be accessible, and it must reside in the right places.
#
if (! -e $imagepath) {
110
    die("Cannot access $imagepath.\n");
111 112
}
if (! -f $imagepath) {
113
    die("$imagepath is not a plain file.\n");
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
}

#
# 0 means load the entire disk. 
#
my $diskpart = "";
if ($imagepart) {
    $diskpart = "wd0 s${imagepart}";
}
else {
    $diskpart = "wd0";
}

#
# 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;
    }

158 159
    $sth = $DB->query("select * from nodes where node_id='$pc'");
    if ($sth == 0) {
160
	die("Database lookup failed (exists). Aborted...\n");
161 162 163 164 165 166 167
    }
    if ($sth->num_rows() != 1) {
      print STDERR "Node $pc doesn't exist. Skipping $pc.\n";
      next;
    }
    

168 169 170 171 172 173 174 175 176 177 178 179
    # Always 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");
    }

    print STDERR "Checking if $pc is reserved...";
180
    $sth = $DB->query("select * from reserved where node_id='$pc'");
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
    if ($sth == 0) {
	die("Database lookup failed (reserved). Aborted...\n");
    }
    
    if ( ($sth->num_rows()) < 1) {
        print STDERR "Available.\nReserving and adding to list.\n";
	my $cmd = "$TB/nalloc testbed reloading $pc";
        if ( system($cmd) != 0 ) {
	    print STDERR "WARNING: Could not reserve $pc!\n";
	} else {
	    push (@load_list,$pc);
	}
    } else {
        print STDERR "Reserved.\n";      
    }
}

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";
exit 0;