sched_reserve.in 4.1 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2 3

#
4
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
24 25
#

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
use English;

# Schedule the reservation of a node. If the node is not currently in use,
# nalloc will be called to reserve the node immediately. If the node is 
# currently reserved, an entry will be added to the next_reserve table, and
# when the node is freed it will be reserved to the given experiment.
#
# usage: sched_reserve <pid> <eid> <node> [<node> ...]

sub usage() {
  die("Usage: sched_reserve <pid> <eid> <node> [<node> ...]\n".
      "Reserves nodes to eid when the are free.\n");
}

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

# Load the Testbed support stuff.
44 45
use lib "@prefix@/lib";
use libdb;
46
use Experiment;
47 48 49 50 51 52 53 54 55 56 57

my $nalloc      = "$TB/bin/nalloc";
my $debug       = 0;
my @nodes       = ();

# 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

58
if (@ARGV < 3) {
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  usage();
}

# Untaint args.
my $pid   = shift;
if ($pid =~ /^([-\@\w.\+]+)$/) {
  $pid = $1;
} else {
  die("Bad data in pid '$pid'.");
}

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

foreach my $node ( @ARGV ) {
  if ($node =~ /^([-\@\w]+)$/) {
    $node = $1;
  } else {
    die("Bad node name '$node'.");
  }
  push(@nodes, $node);
}

# Root and admin types can do whatever they want.
# Mere users cannot schedule reservations (yet?)
if ($UID && !TBAdmin($UID)) {
  die("Only root or TB administrators can schedule reservations.\n");
}

92 93 94 95
my $experiment = Experiment->Lookup($pid, $eid);
if (! $experiment) {
    die("*** $0:\n".
	"    No such experiment $pid/$eid in the Emulab Database.\n");
96
}
97
my $exptidx = $experiment->idx();
98

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
#
# Use the awesome power of left join:
#
# - if we get no row returned, then the node does not exist,
# - if we get a nodes entry but no reserved entry, the node is free,
# - if we get both, then it is allocated and pid/eid is where it is now.
#
# This single query on all nodes replaces the three queries per-node
# we used to do.
#
my $nlist = "(" . join(",", map("'$_'", @nodes)) . ")";
my $sth = DBQueryFatal("SELECT n.node_id AS nt,r.node_id AS rt,r.pid,r.eid".
		       " FROM nodes AS n LEFT JOIN reserved AS r".
		       " ON n.node_id=r.node_id WHERE n.node_id in $nlist");
#
# Make a list of the nodes we got nodes table info for, others don't exist
#
my %nmap = ();
while (my $rref = $sth->fetchrow_hashref()) {
  $nmap{$rref->{'nt'}} = $rref;
}

121 122 123
foreach my $node (@nodes) {
  my $pc = $node;
  my $allocated = 0;
124
  my $nref = $nmap{$node};
125

126
  if (!defined($nref)) {
127 128 129 130 131
    print STDERR "Node $pc doesn't exist. Skipping $pc.\n";
    next;
  }

  print "Checking if $pc is reserved...";
132
  if (!$nref->{'rt'}) {
133
    print "Available - Reserving...\n";
134
    #print STDERR "Using proj $pid, expt $eid, I am ",`whoami`;
135 136 137 138 139
    my $cmd = "$nalloc $pid $eid $pc";
    if ( system($cmd) != 0 ) {
      print STDERR "WARNING: Could not reserve $pc!\n";
    }
  } else {
140
    if (!($pid eq $nref->{'pid'} && $eid eq $nref->{'eid'})) {
141
      print "Reserved  - Scheduling next reservation...\n";
142
      $sth = DBQueryFatal("REPLACE INTO next_reserve ".
143
			  " (node_id,exptidx,pid,eid) ".
144
			  "VALUES ('$pc','$exptidx','$pid','$eid')");
145 146 147 148 149 150 151 152
    } else {
      print "Reserved  - Already reserved to $pid/$eid\n";
    }
  }
}

# If I haven't died yet, then this was successful.
exit 0;