Commit f08acc14 authored by Leigh B Stoller's avatar Leigh B Stoller
Browse files

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents 9364606d 63198ae5
......@@ -6145,6 +6145,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/linux9/GNUmakefile tmcd/linux9/supfile \
tmcd/fedora/GNUmakefile tmcd/fedora/supfile \
tmcd/linux-sg/GNUmakefile tmcd/ubuntu7/GNUmakefile \
tmcd/ubuntu10/GNUmakefile \
tmcd/freebsd5/GNUmakefile tmcd/freebsd5/supfile \
tmcd/freebsd6/GNUmakefile tmcd/freebsd6/supfile tmcd/freebsd6/netif-emulab \
tmcd/freebsd7/GNUmakefile tmcd/freebsd7/supfile tmcd/freebsd7/netif-emulab \
......
......@@ -935,6 +935,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/linux9/GNUmakefile tmcd/linux9/supfile \
tmcd/fedora/GNUmakefile tmcd/fedora/supfile \
tmcd/linux-sg/GNUmakefile tmcd/ubuntu7/GNUmakefile \
tmcd/ubuntu10/GNUmakefile \
tmcd/freebsd5/GNUmakefile tmcd/freebsd5/supfile \
tmcd/freebsd6/GNUmakefile tmcd/freebsd6/supfile tmcd/freebsd6/netif-emulab \
tmcd/freebsd7/GNUmakefile tmcd/freebsd7/supfile tmcd/freebsd7/netif-emulab \
......
......@@ -37,6 +37,14 @@ if [ ! -d $dir/iperf-$version/src ]; then
echo "ERROR: iperf-fetch.sh: tar failed"
exit 1
}
# XXX hack to deal with relative paths...argh!
case $srcdir in
/*)
;;
*)
srcdir="../$srcdir"
;;
esac
cd iperf-$version && patch -p0 < $srcdir/iperf-patch || {
echo "ERROR: iperf-fetch.sh: patch failed"
exit 1
......
......@@ -40,6 +40,15 @@ if [ ! -d $dir/rude-$version/src ]; then
if [ -d rude -a ! -d rude-$version ]; then
mv rude rude-$version
fi
# XXX hack to deal with relative paths...argh!
case $srcdir in
/*)
;;
*)
srcdir="../$srcdir"
;;
esac
cd rude-$version && patch -p0 < $srcdir/rude-patch || {
echo "ERROR: rude-fetch.sh: patch failed"
exit 1
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2008 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -1767,7 +1767,7 @@ parse_configfile(char *filename)
while (fgets(buf, sizeof(buf), fp)) {
int cc = strlen(buf);
if (buf[cc-1] == '\n')
buf[cc-1] = (char) NULL;
buf[cc-1] = '\0';
if (!strncmp(buf, "UID=", 4)) {
if (user) {
......@@ -1896,7 +1896,7 @@ parse_configfile_env(char *filename)
FILE *file;
if (buf[cc-1] == '\n')
buf[cc-1] = (char) NULL;
buf[cc-1] = '\0';
if (isops)
bp = buf;
......
......@@ -42,16 +42,16 @@ PFLAGS = -pthread
PFLAGS += -DDEBUG
PFLAGS += -O2 -g -Wall
PFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
PFLAGS += -L/usr/local/lib -lpubsub_r -lm
PFLAGS += -L/usr/local/lib -lpubsub_r -ltb -lm
PLDFLAGS += -L$(OBJDIR)/lib -L$(OBJDIR)/lib/libtb -L../lib
PLIBS = -levent_r -ltb -lcrypto
PLIBS += -L/usr/local/lib -lpubsub_r -lm
PLIBS += -L/usr/local/lib -lpubsub_r -ltb -lm
PLDFLAGS += $(LDSTATIC)
LDFLAGS += -L$(OBJDIR)/lib -L$(OBJDIR)/lib/libtb -L../lib
LIBS = -levent -ltb -lcrypto
LIBS += -L/usr/local/lib -lpubsub -lm
LIBS += -L/usr/local/lib -lpubsub -ltb -lm
LDFLAGS += $(LDSTATIC)
# Deal with the presence/absence of kerberos in the linux ssl library
......@@ -89,7 +89,7 @@ evproxyplab-debug: evproxyplab.o ../lib/libevent.a ../lib/event.h
version0_gateway: version0_gateway.c
$(CC) $(CFLAGS) $(PLDFLAGS) -pthread -o $@ $< -L/usr/local/lib \
-lpubsub_r -lm
-lpubsub_r -ltb -lm
eventping-debug: eventping.o
$(CC) $(LDFLAGS) -o $@ eventping.o -pthread $(LIBS)
......
......@@ -207,6 +207,7 @@ main(int argc, char **argv)
static char notify_debug_string[2*BUFSIZ];
#if 0
static int
pubsub_notify_traverse_debug(void *arg, char *name,
pubsub_type_t type, pubsub_value_t value,
......@@ -258,6 +259,7 @@ pubsub_notify_traverse_debug(void *arg, char *name,
return 1;
}
#endif
static void
pubsub_callback(pubsub_handle_t *handle,
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2007 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -209,7 +209,7 @@ main(int argc, char **argv)
if ((bp = strchr(temp, '/')) == NULL)
fatal("Malformed pid/eid: %s", myeid);
*bp++ = (char) NULL;
*bp++ = '\0';
sprintf(keyfilebuf, "/proj/%s/exp/%s/tbdata/eventkey",
temp, bp);
......@@ -292,7 +292,7 @@ main(int argc, char **argv)
* XXX For now, uppercase the strings, and remove trailing _.
*/
if (argc) {
buf[0] = (char) NULL;
buf[0] = '\0';
while (argc) {
if (strlen(*argv) + strlen(buf) >= sizeof(buf)-2)
fatal("Too many event argument strings!");
......@@ -309,8 +309,8 @@ main(int argc, char **argv)
bp++;
}
if (*(bp-1) == '_')
*(bp-1) = (char) NULL;
*bp++ = (char) NULL;
*(bp-1) = '\0';
*bp++ = '\0';
sprintf(&buf[strlen(buf)], "%s=%s ", *argv, bp);
}
......
......@@ -11,3 +11,5 @@ if ! [ -f "$target_dir/bin/tcsh" ]; then
ln -sf /bin/tcsh.fake "$target_dir/bin/tcsh"
ln -sf /bin/tcsh.fake "$target_dir/bin/csh"
fi
touch "$target_dir/etc/mtab"
......@@ -17,6 +17,7 @@ require "@prefix@/etc/node_usage.conf";
chdir "@prefix@/data/node_usage";
my $TOLERANCE = 0.05;
#my $TOLERANCE = 0.10;
my $TOLERANCE_INTERVAL = 1/3;
my $interval = 60*60;
......@@ -26,12 +27,21 @@ my $start = ceil($START / $interval) * $interval;
my @idxs = (0 .. $#to_plot);
my @start;
foreach (@idxs) {
if (defined $to_plot[$_][2]) {
$start[$_] = ceil($to_plot[$_][2] / $interval) * $interval;
} else {
$start[$_] = $start;
}
}
my $prev_time = 0;
my @prev_data = map {0} @idxs;
my @total_so_far = map {0} @idxs;
my $next_cutoff = $start;
my $error_frac = 0;
my @error_frac = map {0} @idxs;
open F, "node_usage.raw";
open O, ">node_usage-$interval_name.dat";
......@@ -52,6 +62,11 @@ sub sum_usage_stats ($) {
return @res;
}
sub filter_w_start ($@) {
my $time = shift @_;
return map {$time >= $start[$_] ? $_[$_] : 'NaN'} @idxs;
}
while (<F>) {
chop;
s/^(\d+) (\d+) // or die;
......@@ -67,19 +82,20 @@ while (<F>) {
my @data = sum_usage_stats(1);
my @error = sum_usage_stats(2);
@data = map {$data[$_] + $error[$_]/2} @idxs;
if (any map {$error[$_] > $num[$_]*$TOLERANCE} @idxs) {
#print STDERR "ERROR $time: $error\n";
@data = map {'NaN'} @idxs;
}
@data = map {$error[$_] > $num[$_]*$TOLERANCE
? 'NaN' : $data[$_]} @idxs;
# if (any map {$error[$_] > $num[$_]*$TOLERANCE} @idxs) {
# print STDERR "ERROR $time: ", join (' ', map {"$error[$_] > ".$num[$_]*$TOLERANCE} @idxs), "\n";
# }
use warnings;
my $combine = sub {
my ($t) = (@_);
my $frac = ($t - $prev_time)/$interval;
if ($prev_data[0] != $prev_data[0]) { # ie NaN
$error_frac += $frac;
} else {
foreach my $i (@idxs) {
foreach my $i (@idxs) {
if ($prev_data[$i] != $prev_data[$i]) { # ie NaN
$error_frac[$i] += $frac;
} else {
$total_so_far[$i] += $prev_data[$i] * $frac;
}
}
......@@ -88,20 +104,20 @@ while (<F>) {
while ($time >= $next_cutoff) {
&$combine($next_cutoff);
my @free = @total_so_far;
if ($error_frac > $TOLERANCE_INTERVAL) {
foreach my $i (@idxs) {
$free[0] = 'NaN';
}
} else {
foreach my $i (@idxs) {
$free[$i] /= (1 - $error_frac);
foreach my $i (@idxs) {
if ($error_frac[$i] > $TOLERANCE_INTERVAL) {
$free[$i] = 'NaN';
} else {
$free[$i] /= (1 - $error_frac[$i]);
}
}
my @alloc = map {$num[$_] - $free[$_]} @idxs;
my $dtime = $next_cutoff - $interval;
@free = filter_w_start $dtime, @free;
@alloc = filter_w_start $dtime, @alloc;
print O join(' ', $dtime, map {sprintf("%.1f", $_)} (@free, @alloc)),"\n"
if $dtime >= $start;
$error_frac = 0;
@error_frac = map {0} @idxs;
@total_so_far = map {0} @idxs;
$prev_time = $next_cutoff;
$next_cutoff += $interval;
......
......@@ -25,11 +25,11 @@ my %res;
sub tally ($$@) {
my ($str, $what, @d) = @_;
if ($d[0] != $d[0]) { # ie NaN
$res{$what}{data}{$str}{invalid}++;
} else {
$res{$what}{data}{$str}{count}++;
foreach my $i (@idxs) {
foreach my $i (@idxs) {
if ($d[$i] != $d[$i]) { # ie NaN
$res{$what}{data}{$str}{invalid}[$i]++;
} else {
$res{$what}{data}{$str}{count}[$i]++;
$res{$what}{data}{$str}{data}[$i] += $d[$i];
}
}
......@@ -37,9 +37,9 @@ sub tally ($$@) {
sub tally_mod ($$@) {
my ($bin, $what, @d) = @_;
return if $d[0] != $d[0]; # ie NaN
$res{$what}{data}[$bin]{count}++;
foreach my $i (@idxs) {
next if $d[$i] != $d[$i]; # ie NaN
$res{$what}{data}[$bin]{count}[$i]++;
$res{$what}{data}[$bin]{data}[$i] += $d[$i];
}
}
......@@ -91,13 +91,14 @@ foreach my $k (keys %res) {
foreach my $i (sort keys %{$res{$k}{data}}) {
my @r;
my $d = $res{$k}{data}{$i};
my $invalid = $d->{invalid};
my $count = $d->{count};
if ($invalid / ($invalid + $count) > $TOLERANCE_INTERVAL) {
@r = map {'NaN'} @idxs;
} else {
foreach my $j (@idxs) {
foreach my $j (@idxs) {
my $invalid = $d->{invalid}[$j];
my $count = $d->{count}[$j];
if ($invalid / ($invalid + $count) > $TOLERANCE_INTERVAL) {
$r[$j] = 'NaN';
} else {
$r[$j] = $d->{data}[$j]/$count;
die "Unexpected NaN" if $r[$j] != $r[$j];
}
}
print F join(' ', "$i ", map {sprintf("%5.1f", $_)} @r),"\n"
......@@ -108,9 +109,8 @@ foreach my $k (keys %res) {
foreach my $i (0 .. $#{$res{$k}{data}}) {
my @r;
my $d = $res{$k}{data}[$i];
my $count = $d->{count};
foreach my $j (@idxs) {
$r[$j] = $d->{data}[$j]/$count;
$r[$j] = $d->{data}[$j] ? $d->{data}[$j]/$d->{count}[$j] : 0;
}
print F join(' ', sprintf("%6.3f ", $i/$div), map {sprintf("%5.1f", $_)} @r),"\n"
}
......
......@@ -10,6 +10,8 @@ use POSIX qw(strftime floor ceil);
use Data::Dumper;
use Carp;
my $LIMIT = 3000000;
$Data::Dumper::Indent = 1;
use strict;
......@@ -54,6 +56,8 @@ our $prev;
our $prev_line;
our $last_history_id = -1;
my $again = 0;
if ($prep) {
if ($fresh) {
......@@ -81,7 +85,11 @@ if ($prep) {
do "gather.state.1";
}
$qr = DBQueryFatal("select history_id,node_id,op,stamp from $NODE_USAGE_DB.node_history_copy where history_id > $last_history_id order by history_id");
$qr = DBQueryFatal("select history_id,node_id,op,stamp from $NODE_USAGE_DB.node_history_copy where history_id > $last_history_id order by history_id limit $LIMIT");
if ($qr->num_rows() == $LIMIT) {
$again = 1;
}
my $prev_history_id = $last_history_id;
......@@ -162,13 +170,7 @@ if ($results) {
close F;
}
if ($again) {
printf STDERR "Too many rows to handle at once, running again...\n";
exec "@prefix@/libexec/node_usage/gather";
}
......@@ -23,8 +23,11 @@ $NODE_USAGE_DB = 'node_usage';
# ...
#
@to_plot = (
["pc600 pc850 pc2000 pc3000s", [qw(pc600 pc850 pc2000 pc3000)]],
["pc3000s", [qw(pc3000)]]
["pc600 pc850 pc2000 pc3000s d710s", [qw(pc600 pc850 pc2000 pc3000 d710)]],
["pc3000s", [qw(pc3000)]],
# ["d710s", [qw(d710)], 1282575600] # latter start data:
# # when nodes were announced
["d710s", [qw(d710)], 1269466000]
);
#
......@@ -34,19 +37,16 @@ $avail_header = <<'---';
<p>
These graphs show the average number of free nodes over various time
periods. Nodes are broken down into two classes: The first class are the
<a href="http://users.emulab.net/trac/emulab/wiki/pc3000">pc3000</a>s,
which are the most numerous, and are fairly modern. They are
most experimenters' nodes of choice. For many experimenters, the number of
free pc3000s limits the size of the experiments they can run.
The second class includes other, older PCs (along with the pc3000s) to give
a sense for how many nodes are available if one is willing to use some
slower nodes.
</p>
<p>
Emulab currently includes around 350 PC nodes. As you can see, most of those
are in use even during our periods of &quot;light&quot; usage.
periods. Nodes are broken down into three classes: The first class includes
all "pc" node types, from the slowest to the fastest. The other two classes
show the most numerous and desirable node types, the
<a href="http://users.emulab.net/trac/emulab/wiki/pc3000">pc3000</a>s
and the
<a href="http://users.emulab.net/trac/emulab/wiki/d710">d710</a>s
which both have Gb Ethernet interfaces.
For many experimenters, the number of
free pc3000s and d710s limit the size of the experiments they can run.
Emulab currently includes around 500 PC nodes.
</p>
<p>
......@@ -58,6 +58,11 @@ years), it may not reflect recent
trends.
</p>
---
# Note removed:
# As you can see, most of those are in use even during our
# periods of "light" usage.
# After "Emulab currently includes around 500 PC nodes"
# from above for now since it probably not true.
$avail_footer = <<'---';
<p align=center>
......
......@@ -349,7 +349,7 @@ int init_slothd(void) {
return -1;
}
/* Try to get lock. If can't, then bail out. */
if ((pfd = open(PIDFILE, O_EXCL | O_CREAT | O_RDWR)) < 0) {
if ((pfd = open(PIDFILE, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
lerror("Can't create lock file.");
return -1;
}
......
......@@ -385,7 +385,7 @@ sub osload ($$) {
my ($pmbr) = $dbresult->fetchrow_array();
if ($pmbr != $rowref->{'mbr_version'}) {
# XXX: Is this right in the context of multiple images
tbwarn("$node: Existing partition $i inconsistent".
tbinfo("$node: Existing partition $i inconsistent".
" with new image partitioning,".
" invalidating existing partition");
$whackit = 1;
......
......@@ -27,6 +27,7 @@ my $WOL = "$TB/sbin/whol";
use lib "@prefix@/lib";
use libdb;
use libxmlrpc;
use power_ipmi;
use power_rpc27;
use power_sgmote;
use power_mail;
......@@ -324,7 +325,20 @@ foreach my $power_id (keys %outlets) {
# of object
#
my $errors = 0;
if ($type eq "APC") {
if ($type eq "IPMI") {
my $device = new power_ipmi($IP,$verbose);
if (!defined $device) {
warn "Unable to contact controller for $nodestr. Skipping...\n";
next;
} else {
print "Calling device->power($op,@outlets)\n" if $verbose > 1;
if ($device->power($op,@outlets)) {
print "Control of $nodestr failed.\n";
$errors++;
}
}
}
elsif ($type eq "APC") {
my $device = new snmpit_apc($IP,$verbose);
if (!defined $device) {
warn "Unable to contact controller for $nodestr. Skipping...\n";
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003, 2006-2007 University of Utah and the Flux Group.
# All rights reserved.
#
#
# module for controlling SuperMicro IPMI cards
# needs a working "/usr/local/bin/ipmitool" binary installed
# (try pkg_add -r ipmitool)
#
# supports new(ip), power(on|off|cyc[le]), status
#
package power_ipmi;
$| = 1; # Turn off line buffering on output
use strict;
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin'; # Required when using system() or backticks `` in combination with the perl -T taint checks
sub new($$;$) {
# The next two lines are some voodoo taken from perltoot(1)
my $proto = shift;
my $class = ref($proto) || $proto;
my $devicename = shift;
my $debug = shift;
if (!defined($debug)) {
$debug = 0;
}
if ($debug) {
print "power_ipmi module initializing... debug level $debug\n";
}
my $self = {};
$self->{DEBUG} = $debug;
$self->{DEVICENAME} = $devicename;
$self->{un} = "ADMIN"; # default username
$self->{pw} = "ADMIN"; # default password
# Do a quick query, to see if it works
system("ipmitool -H $self->{DEVICENAME} -U $self->{un} -P $self->{pw} power status >/dev/null 2>\&1");
if ( $? != 0 ) { # system() sets $? to a non-zero value in case of failure
warn "ERROR: Unable to connect to $devicename via IPMI\n";
return undef;
}
else {
bless($self,$class);
return $self;
}
}
sub power {
my $self = shift;
my $op = shift;
my @ports = @_; # Doesn't really matter, an IPMI card only has a single "outlet", which is for the node the card is installed in
my $errors = 0;
my ($retval, $output);
if ($op eq "on") { $op = "power on"; }
elsif ($op eq "off") { $op = "power off"; }
elsif ($op =~ /cyc/) { $op = "power reset"; }
($retval,$output) = $self->_execipmicmd($op);
if ( $retval != 0 ) { # increment $errors if return value was not 0
$errors++;
print STDERR $self->{DEVICENAME}, ": could not control power status of device\n";
}
return $errors;
}
sub status {
my $self = shift;
my $statusp = shift; # pointer to an associative (hashed) array (i.o.w. passed by reference)
my %status; # local associative array which we'll pass back through $statusp
my $errors = 0;
my ($retval, $output);
# Get power status (i.e. whether system is on/off)
($retval,$output) = $self->_execipmicmd("power status");
if ( $retval != 0 ) {
$errors++;
print STDERR $self->{DEVICENAME}, ": could not get power status from device\n";
}
else { $status{'outlet1'} = $output; print("Power status is: $output\n") if $self->{DEBUG}; } # there's only 1 "outlet" on an IPMI card
# Get Sensor Data Repository (sdr) entries and readings
($retval,$output) = $self->_execipmicmd("sdr");
if ( $retval != 0 ) {
$errors++;
print STDERR $self->{DEVICENAME}, ": could not get sensor data from device\n";
}
else { $status{'sdr'} = $output; print("SDR data is:\n$output\n") if $self->{DEBUG}; }
if ($statusp) { %$statusp = %status; } # update passed-by-reference array
return $errors;
}
sub _execipmicmd { # _ indicates that this is a private method (Perl convention)
my ($self,$op) = @_;
my $ipmicmd = "ipmitool -H $self->{DEVICENAME} -U $self->{un} -P $self->{pw} "; # ipmitool command syntax, to be completed
# with an operation to perform
my $cmd = $ipmicmd . $op;
my $output;
if ( $self->{DEBUG} > 1 ) {
print STDERR "**** Executing $cmd\n";
$output = `$cmd`; # get output of the $cmd, e.g. many lines of sensor readings or "Chassis power is on"
chomp ( $output ); # remove the \n at the end, if any
}
else { $output = `$cmd 2>/dev/null`; } # if there's any stderr output, silence it
# (system() and backticks `` execute the command using the /bin/sh shell)
return ($?, $output);
}
# End with true
1;