sched_reload.in 5.76 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.
# 
Leigh B. Stoller's avatar
Leigh B. Stoller committed
11
# usage: sched_reload [-f | -p] [-r] [-i <imageid>] <node> [node ...]
12 13 14
#
sub usage()
{
Leigh B. Stoller's avatar
Leigh B. Stoller committed
15 16 17 18 19 20
    print STDOUT "Usage: sched_reload [-f | -p] [-r] [-i <imageid>] ".
	         "<node> [node ...]\n".
	"Use -i to specify an imageid. Use node default otherwise.\n".
	"Use -f to force reload. Fail if node cannot be reserved.\n".
	"Use -p to pend reload for the reload daemon.\n".
	"Use -r to use Frisbee rather than netdisk (experimental).\n";
21 22
    exit(-1);
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
23
my  $optlist = "fpri:";
24 25 26 27

#
# Configure variables
#
28
my $TB     = "@prefix@";
29

30 31 32
#
# Load the Testbed support stuff. 
#
33 34
use lib "@prefix@/lib";
use libdb;
35

36
#
37
# These come from the library.
38
# 
39 40 41
my $RELOADPID	= NODERELOADING_PID;
my $RELOADEID	= NODERELOADING_EID;
my $PENDINGEID	= NODERELOADPENDING_EID;
42

43 44
my $osload      = "$TB/bin/os_load";
my $nalloc      = "$TB/bin/nalloc";
45
my $name        = "";
46 47 48
my $error       = 0;
my $debug       = 0;
my $force	= 0;
49
my $pend	= 0;
50
my $frisbee	= 0;
51
my @nodes       = ();
Leigh B. Stoller's avatar
Leigh B. Stoller committed
52 53 54
my $usedefault  = 1;
my $imageid;
my %imagenodes  = ();
55
my @row;
56 57 58 59 60 61 62 63

# 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

#
64 65 66 67 68 69 70
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
71
if (@ARGV < 1) {
72
    usage();
73
}
74 75 76
if (defined($options{"f"})) {
    $force = $options{"f"};
}
77 78 79
if (defined($options{"p"})) {
    $pend = $options{"p"};
}
80 81 82 83
if (defined($options{"r"})) {
    $frisbee = 1;
	$osload .= " -r ";
}
84 85 86
if ($pend and $force) {
    usage();
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
87 88 89 90 91 92 93 94 95 96 97
if (defined($options{"i"})) {
    $imageid    = $options{"i"};
    $usedefault = 0;

    if ($imageid =~ /^([-\@\w.\+]+)$/) {
	$imageid = $1;
    }
    else {
	die("Bad data in $imageid.");
    }
}
98

99
# This type will be put into the database, to allow programs 
Leigh B. Stoller's avatar
Leigh B. Stoller committed
100
# such as nfree to figure out what kind of reload is supposed
101 102 103 104 105 106 107
# to occur
if ($frisbee) {
	$type = "frisbee";
} else {
	$type = "netdisk";
}

108
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
109
# Untaint nodes.
110 111 112 113 114 115 116 117 118 119 120
#
foreach my $node ( @ARGV ) {
    if ($node =~ /^([-\@\w]+)$/) {
	$node = $1;
    }
    else {
	die("Bad node name: $node.");
    }
    
    push(@nodes, $node);
}
121

122
#
123 124
# Root and admin types can do whatever they want.
# Mere users cannot schedule reloads.
125
#
126
if ($UID && !TBAdmin($UID)) {
127 128 129 130
    die("*** Only root or TB administrators can schedule disk reloads.\n");
}

#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
131 132
# Confirm a valid imageid if one was specified. Otherwise we are going
# to pull it out of the DB for each node.
133
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
134 135 136
if (defined($imageid)) {
    my $query_result =
	DBQueryFatal("select * from images where imageid='$imageid'");
137
    
Leigh B. Stoller's avatar
Leigh B. Stoller committed
138 139 140
    if ($query_result->numrows < 1) {
	die("*** No such imageid $imageid is registered in the DB!");
    }
141 142 143
}

#
144
# A loop.
145 146 147 148
# 
my @load_list=();
foreach my $node (@nodes) {
    my $pc = $node;
149
    my $allocated = 0;
150

151
    $sth = DBQueryFatal("select * from nodes where node_id='$pc'");
152 153 154 155
    if ($sth->num_rows() != 1) {
      print STDERR "Node $pc doesn't exist. Skipping $pc.\n";
      next;
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
156 157 158 159 160 161 162 163 164

    #
    # Get default imageid for this node if none specified on comand line.
    #
    if ($usedefault) {
	if (! ($imageid = DefaultImageID($node))) {
	    die("*** No default imageid is defined for $node!\n");
	}
    }
165
    
166
    print STDERR "Checking if $pc is reserved...";
167
    $sth = DBQueryFatal("select * from reserved where node_id='$pc'");
168
   
169 170
    if ( ($sth->num_rows()) < 1) {
        print STDERR "Available.\nReserving and adding to list.\n";
171 172 173 174 175 176 177 178 179
	my $eid;
	if ($pend) {
	    $eid = $PENDINGEID;
	}
	else {
	    $eid = $RELOADEID;
	}
	my $cmd = "$nalloc $RELOADPID $eid $pc";

180 181 182
        if ( system($cmd) != 0 ) {
	    print STDERR "WARNING: Could not reserve $pc!\n";
	} else {
183 184 185 186
	    #
	    # Kill the last_reservation so that whoever gets the node next
	    # won't be fooled into thinking a reload is required.
	    #
187
	    DBQueryFatal("delete from last_reservation where node_id='$pc'");
188
	    $allocated = 1;
189 190 191 192
	}
    } else {
        print STDERR "Reserved.\n";      
    }
193 194 195 196 197 198 199 200 201 202

    #
    # 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.
203
    print STDERR "Scheduling reload of $imageid for $pc:\n";
204
    DBQueryFatal("replace into scheduled_reloads ".
205 206
		 "(node_id, image_id, reload_type) values ".
		 "('$pc', '$imageid','$type')");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

    #
    # The point of this hash table is so that we can gather up all the
    # nodes per imageid and issue single requests to os_load, so that it
    # can optimize things (say, for Frisbee). It is possible to get multiple
    # imageids when using the node defaults instead of a command line imageid.
    #
    # Note that building up a hashed array of lists is a mighty odd operation
    # in PERL, hence this funny looking code!
    #
    if ($allocated) {
	if (! defined($imagenodes{$imageid})) {
	    $imagenodes{$imageid} = [ $node ];
	}
	else {
	    push(@{ $imagenodes{$imageid} }, $node);
	}
    }
225 226
}

227
if ($pend) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
228
    print STDOUT "Reload Scheduling Done! There were $error failures!\n";
229 230 231
    exit $error;
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245
#
# Now issue the reloads, one per imageid. The hash table we created above
# stores a list of nodes for each imageid.
#
foreach my $id ( keys(%imagenodes) ) {
    my @nodelist = @{ $imagenodes{$imageid} };

    my $cmd = "$osload -i $id @nodelist";

    print "Issuing $cmd\n";
    if (system($cmd)) {
	print STDERR "*** WARNING: Failed $cmd\n";
	$error++;
    }
246 247
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
248
print STDOUT "Reload Scheduling Done! There were $error failures!\n";
249
exit $error;