Commit 0763d8ce authored by Kevin Atkinson's avatar Kevin Atkinson

Generalize node_usage plots to work on other sits, after some initial

setup, see http://users.emulab.net/trac/emulab/wiki/NodeUsageInstall.
parent b063af94
......@@ -31,7 +31,7 @@ include Makeconf
SUBDIRS = lib db assign www @optional_subdirs@ ipod security sensors \
pxe tbsetup account tmcd utils backend tip capture ipod vis \
sensors os xmlrpc install/newnode_sshkeys mote tools/whol \
tools/svn wiki bugdb collab tools/rmanage protogeni
tools/svn wiki bugdb collab tools/rmanage protogeni node_usage
all: all-subdirs
......@@ -77,6 +77,9 @@ endif
@$(MAKE) -C bugdb post-install
@$(MAKE) -C collab post-install
@$(MAKE) -C utils post-install
ifeq ($(NODE_USAGE_SUPPORT),1)
@$(MAKE) -C node_usage post-install
endif
#
# For installation on the 'ops' or 'users' node (okay, plastic)
......
......@@ -88,3 +88,5 @@ host_cpu = @host_cpu@
HAVE_ULXMLRPCPP = @HAVE_ULXMLRPCPP@
STANDALONE_CLEARINGHOUSE = @STANDALONE_CLEARINGHOUSE@
NODE_USAGE_SUPPORT = @NODE_USAGE_SUPPORT@
......@@ -1458,6 +1458,7 @@ done
#
......@@ -1541,6 +1542,7 @@ PROTOGENI_SUPPORT=0
PROTOGENI_CLEARINGHOUSE=0
PROTOGENI_DOMAIN="unknown"
STANDALONE_CLEARINGHOUSE=0
NODE_USAGE_SUPPORT=0
#
# XXX You really don't want to change these!
......@@ -2143,17 +2145,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2147: checking for $ac_hdr" >&5
echo "configure:2149: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2152 "configure"
#line 2154 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2157: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2159: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2192,17 +2194,17 @@ for ac_hdr in linux/videodev.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2196: checking for $ac_hdr" >&5
echo "configure:2198: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2201 "configure"
#line 2203 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2206: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2208: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2235,7 +2237,7 @@ done
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2239: checking for $ac_word" >&5
echo "configure:2241: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2292,7 +2294,7 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
echo "configure:2296: checking how to run the C++ preprocessor" >&5
echo "configure:2298: checking how to run the C++ preprocessor" >&5
if test -z "$CXXCPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2305,12 +2307,12 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
CXXCPP="${CXX-g++} -E"
cat > conftest.$ac_ext <<EOF
#line 2309 "configure"
#line 2311 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2314: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2316: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
......@@ -2336,17 +2338,17 @@ echo "$ac_t""$CXXCPP" 1>&6
ac_safe=`echo "xercesc/dom/DOM.hpp" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for xercesc/dom/DOM.hpp""... $ac_c" 1>&6
echo "configure:2340: checking for xercesc/dom/DOM.hpp" >&5
echo "configure:2342: checking for xercesc/dom/DOM.hpp" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2345 "configure"
#line 2347 "configure"
#include "confdefs.h"
#include <xercesc/dom/DOM.hpp>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2350: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2410,7 +2412,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:2414: checking for a BSD compatible install" >&5
echo "configure:2416: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2471,7 +2473,7 @@ esac
# Extract the first word of "rsync", so it can be a program name with args.
set dummy rsync; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2475: checking for $ac_word" >&5
echo "configure:2477: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2716,7 +2718,13 @@ outfiles="$outfiles Makeconf GNUmakefile \
collab/mailman/mailmanproxy collab/mailman/setmmpasswd \
collab/cvstools/cvs.proxy collab/cvstools/cvs_ctrl \
collab/cvstools/cvsrepo_ctrl.proxy collab/cvstools/cvsrepo_ctrl \
collab/cvstools/webcvsrepo_ctrl "
collab/cvstools/webcvsrepo_ctrl \
node_usage/GNUmakefile node_usage/mk-plots \
node_usage/analy node_usage/publish \
node_usage/analy2 node_usage/refresh \
node_usage/from_ptop node_usage/sanity \
node_usage/gather node_usage/mk-php-pages \
node_usage/get-start-date"
#
# Do this for easy distclean.
......@@ -2994,6 +3002,7 @@ s%@PROTOGENI_CLEARINGHOUSE@%$PROTOGENI_CLEARINGHOUSE%g
s%@PROTOGENI_DOMAIN@%$PROTOGENI_DOMAIN%g
s%@STANDALONE_CLEARINGHOUSE@%$STANDALONE_CLEARINGHOUSE%g
s%@GMAP_API_KEY@%$GMAP_API_KEY%g
s%@NODE_USAGE_SUPPORT@%$NODE_USAGE_SUPPORT%g
s%@TBOPSEMAIL@%$TBOPSEMAIL%g
s%@TBOPSEMAIL_NOSLASH@%$TBOPSEMAIL_NOSLASH%g
s%@TBROBOCOPSEMAIL@%$TBROBOCOPSEMAIL%g
......
......@@ -212,6 +212,7 @@ AC_SUBST(PROTOGENI_CLEARINGHOUSE)
AC_SUBST(PROTOGENI_DOMAIN)
AC_SUBST(STANDALONE_CLEARINGHOUSE)
AC_SUBST(GMAP_API_KEY)
AC_SUBST(NODE_USAGE_SUPPORT)
#
# Offer both versions of the email addresses that have the @ escaped
......@@ -294,6 +295,7 @@ PROTOGENI_SUPPORT=0
PROTOGENI_CLEARINGHOUSE=0
PROTOGENI_DOMAIN="unknown"
STANDALONE_CLEARINGHOUSE=0
NODE_USAGE_SUPPORT=0
#
# XXX You really don't want to change these!
......@@ -998,7 +1000,13 @@ outfiles="$outfiles Makeconf GNUmakefile \
collab/mailman/mailmanproxy collab/mailman/setmmpasswd \
collab/cvstools/cvs.proxy collab/cvstools/cvs_ctrl \
collab/cvstools/cvsrepo_ctrl.proxy collab/cvstools/cvsrepo_ctrl \
collab/cvstools/webcvsrepo_ctrl "
collab/cvstools/webcvsrepo_ctrl \
node_usage/GNUmakefile node_usage/mk-plots \
node_usage/analy node_usage/publish \
node_usage/analy2 node_usage/refresh \
node_usage/from_ptop node_usage/sanity \
node_usage/gather node_usage/mk-php-pages \
node_usage/get-start-date"
#
# Do this for easy distclean.
......
......@@ -12,3 +12,4 @@ TBSTATEDEMAIL=kevina@fast.cs.utah.edu
TBTESTSUITEEMAIL=kevina@fast.cs.utah.edu
WWW=www.emulab.net/dev/kevina
THISHOMEBASE=Kevina.Emulab.Net
NODE_USAGE_SUPPORT=1
\ No newline at end of file
SCRIPTS = analy from_ptop mk-plots refresh analy2 gather publish sanity
all:
node_usage-install:
cp index.php /usr/testbed/www/node_usage/
cp -p $(SCRIPTS) /usr/testbed/data/node_usage/scripts
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ..
SUBDIR = node_usage
include $(OBJDIR)/Makeconf
LIBEXEC_NODE_USAGE = analy mk-plots refresh analy2 gather publish mk-php-pages get-start-date
#
# These are Utah emulab specific
#
NODE_USAGE_OTHER = from_ptop sanity
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(LIBEXEC_NODE_USAGE)
include $(TESTBED_SRCDIR)/GNUmakerules
install: \
$(addprefix $(INSTALL_LIBEXECDIR)/node_usage/, $(LIBEXEC_NODE_USAGE))
post-install:
$(INSTALL_LIBEXECDIR)/node_usage/%: %
@echo "Installing $<"
-mkdir -p @prefix@/data/node_usage
-mkdir -p $(INSTALL_LIBEXECDIR)/node_usage
$(INSTALL) $< $@
clean:
......@@ -4,21 +4,26 @@ use strict;
use warnings;
use POSIX qw(strftime ceil);
chdir "/usr/testbed/data/node_usage/data";
sub any (@) { $_ && return 1 for @_; 0 }
my $TOLERANCE_ALL = 0.05;
my $TOLERANCE_PC3000 = 0.05;
our ($START, @to_plot);
require "@prefix@/etc/node_usage.conf";
chdir "@prefix@/data/node_usage";
my $TOLERANCE = 0.05;
my $TOLERANCE_INTERVAL = 1/3;
my $START = 1125727200;
my $interval = 60*60;
my $interval_name = "hourly";
my $start = ceil($START / $interval) * $interval;
my @idxs = (0 .. $#to_plot);
my $prev_time = 0;
my @prev_data = (0,0);
my @total_so_far = (0,0);
my @prev_data = map {0} @idxs;
my @total_so_far = map {0} @idxs;
my $next_cutoff = $start;
my $error_frac = 0;
......@@ -26,28 +31,40 @@ my $error_frac = 0;
open F, "node_usage.raw";
open O, ">node_usage-$interval_name.dat";
our %d;
sub sum_usage_stats ($) {
my ($n) = @_;
my @res;
foreach my $row (@to_plot) {
my $r = 0;
my $pcs = $row->[1];
foreach (@$pcs) {
$r += $d{$_}[$n] if defined $d{$_}[$n];
}
push @res, $r;
}
return @res;
}
while (<F>) {
chop;
s/^(\d+) (\d+) // or die;
my $time = $2;
my %d;
undef %d;
while (s/^ ([\w\d\-\?]+): (\d+) (\d+) (\d+) //) {
$d{$1} = [$2, $3, $4];
}
no warnings 'uninitialized';
my @num = ($d{pc850}[0] + $d{pc600}[0] + $d{pc2000}[0] + $d{pc3000}[0],
$d{pc3000}[0]);
die unless $time <= $start || $num[0] == 160 + 128 + 40 + 8;
die unless $time <= $start || $num[1] == 160;
my @data = ($d{pc850}[1] + $d{pc600}[1] + $d{pc2000}[1] + $d{pc3000}[1],
$d{pc3000}[1]);
my @error = ($d{pc850}[2] + $d{pc600}[2] + $d{pc2000}[2] + $d{pc3000}[2],
$d{pc3000}[2]);
$data[0] = $data[0] + $error[0]/2;
$data[1] = $data[1] + $error[1]/2;
if ($error[0] > $num[0]*$TOLERANCE_ALL || $error[1] > $num[1]*$TOLERANCE_PC3000) {
my @num = sum_usage_stats(0);
#die unless $time <= $start || $num[0] == 128 + 40;
#die unless $time <= $start || $num[1] == 128;
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 = ('NaN', 'NaN');
@data = map {'NaN'} @idxs;
}
use warnings;
......@@ -57,26 +74,30 @@ while (<F>) {
if ($prev_data[0] != $prev_data[0]) { # ie NaN
$error_frac += $frac;
} else {
$total_so_far[0] += $prev_data[0] * $frac;
$total_so_far[1] += $prev_data[1] * $frac;
}
foreach my $i (@idxs) {
$total_so_far[$i] += $prev_data[$i] * $frac;
}
}
};
while ($time >= $next_cutoff) {
&$combine($next_cutoff);
my @free = @total_so_far;
if ($error_frac > $TOLERANCE_INTERVAL) {
$free[0] = 'NaN';
$free[1] = 'Nan';
foreach my $i (@idxs) {
$free[0] = 'NaN';
}
} else {
$free[0] /= (1 - $error_frac);
$free[1] /= (1 - $error_frac);
foreach my $i (@idxs) {
$free[$i] /= (1 - $error_frac);
}
}
my @alloc = ($num[0] - $free[0], $num[1] - $free[1]);
my @alloc = map {$num[$_] - $free[$_]} @idxs;
my $dtime = $next_cutoff - $interval;
printf O ("%d %.1f %.1f %.1f %.1f\n", $dtime, @free, @alloc) if $dtime >= $start;
print O join(' ', $dtime, map {sprintf("%.1f", $_)} (@free, @alloc)),"\n"
if $dtime >= $start;
$error_frac = 0;
@total_so_far = (0,0);
@total_so_far = map {0} @idxs;
$prev_time = $next_cutoff;
$next_cutoff += $interval;
......@@ -88,3 +109,14 @@ while (<F>) {
}
......@@ -7,10 +7,15 @@ use strict;
use warnings;
no warnings 'uninitialized';
chdir "/usr/testbed/data/node_usage/data";
our (@to_plot);
require "@prefix@/etc/node_usage.conf";
chdir "@prefix@/data/node_usage";
my $TOLERANCE_INTERVAL = 1/3;
my @idxs = (0 .. (@to_plot * 2 - 1));
my %res;
sub tally ($$@) {
......@@ -19,7 +24,7 @@ sub tally ($$@) {
$res{$what}{data}{$str}{invalid}++;
} else {
$res{$what}{data}{$str}{count}++;
foreach my $i (0 .. 3) {
foreach my $i (@idxs) {
$res{$what}{data}{$str}{data}[$i] += $d[$i];
}
}
......@@ -29,7 +34,7 @@ sub tally_mod ($$@) {
my ($bin, $what, @d) = @_;
return if $d[0] != $d[0]; # ie NaN
$res{$what}{data}[$bin]{count}++;
foreach my $i (0 .. 3) {
foreach my $i (@idxs) {
$res{$what}{data}[$bin]{data}[$i] += $d[$i];
}
}
......@@ -84,13 +89,13 @@ foreach my $k (keys %res) {
my $invalid = $d->{invalid};
my $count = $d->{count};
if ($invalid / ($invalid + $count) > $TOLERANCE_INTERVAL) {
@r = ('NaN', 'NaN', 'NaN', 'NaN');
@r = map {'NaN'} @idxs;
} else {
foreach my $j (0 .. 3) {
foreach my $j (@idxs) {
$r[$j] = $d->{data}[$j]/$count;
}
}
printf F ("%s %5.1f %5.1f %5.1f %5.1f\n", $i, @r);
print F join(' ', "$i ", map {sprintf("%5.1f", $_)} @r),"\n"
}
} else {
my $div = $res{$k}{div};
......@@ -99,10 +104,10 @@ foreach my $k (keys %res) {
my @r;
my $d = $res{$k}{data}[$i];
my $count = $d->{count};
foreach my $j (0 .. 3) {
foreach my $j (@idxs) {
$r[$j] = $d->{data}[$j]/$count;
}
printf F ("%6.3f %5.1f %5.1f %5.1f %5.1f\n", $i/$div, @r);
print F join(' ', sprintf("%6.3f ", $i/$div), map {sprintf("%5.1f", $_)} @r),"\n"
}
}
}
......@@ -13,22 +13,17 @@ use Carp;
use strict;
use warnings;
#
# Configure variables
#
my $TB = "/usr/testbed/";
#
# Turn off line buffering on output
#
$| = 1;
# Load the Testbed support stuff.
use lib "/usr/testbed/lib";
use lib "@prefix@/lib";
use libdb;
use libtestbed;
chdir "/usr/testbed/data/node_usage/data";
chdir "@prefix@/data/node_usage";
my $qr = DBQueryFatal("select t.idx,action,t.exptidx,eid,pid,UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time) from testbed_stats as t left join experiment_stats as e on t.exptidx = e.exptidx where (t.action='swapin' or t.action='start') and exitcode=0 and start_time >= '2005-09-03' order by t.idx");
......
......@@ -15,21 +15,22 @@ $Data::Dumper::Indent = 1;
use strict;
use warnings;
our $NODE_USAGE_DB;
require "@prefix@/etc/node_usage.conf";
my $prep = 1;
my $results = 1;
my $fresh = 0;
my $TB = "/usr/testbed/";
# Turn off line buffering on output
$| = 1;
# Load the Testbed support stuff.
use lib "/usr/testbed/lib";
use lib "@prefix@/lib";
use libdb;
use libtestbed;
chdir "/usr/testbed/data/node_usage/data";
chdir "@prefix@/data/node_usage";
$fresh = 1 unless -e "gather.state.1" && "gather.state.2";
......@@ -55,11 +56,17 @@ our $last_history_id = -1;
if ($prep) {
DBQueryFatal("insert into node_usage.node_history_copy select * from node_history where history_id > (select max(history_id) from node_usage.node_history_copy)");
if ($fresh) {
DBQueryFatal("create database if not exists $NODE_USAGE_DB");
DBQueryFatal("drop table if exists $NODE_USAGE_DB.node_history_copy");
DBQueryFatal("create table $NODE_USAGE_DB.node_history_copy like node_history");
}
DBQueryFatal("insert into $NODE_USAGE_DB.node_history_copy select * from node_history where history_id > IFNULL((select max(history_id) from $NODE_USAGE_DB.node_history_copy), 0)");
if ($fresh) {
DBQueryFatal("drop table if exists node_usage.node_trans");
DBQueryFatal("create table node_usage.node_trans (".
DBQueryFatal("drop table if exists $NODE_USAGE_DB.node_trans");
DBQueryFatal("create table $NODE_USAGE_DB.node_trans (".
" history_id int unsigned not null primary key,".
" stamp int unsigned not null, ".
" node_id char(8) not null, ".
......@@ -74,7 +81,7 @@ if ($prep) {
do "gather.state.1";
}
$qr = DBQueryFatal("select history_id,node_id,op,stamp from node_usage.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");
local $last_history_id;
......@@ -92,9 +99,9 @@ if ($prep) {
}
if ($invalid) {
#print STDERR "WARNING: $history_id ($stamp) $last_trans{$node_id}: $invalid\n";
DBQueryFatal("update node_usage.node_trans set op = 'invalid' where history_id=$last_trans{$node_id}");
DBQueryFatal("update $NODE_USAGE_DB.node_trans set op = 'invalid' where history_id=$last_trans{$node_id}");
} elsif (!defined $prev_state || $prev_state ne $node_state{$node_id}) {
DBQueryFatal("insert into node_usage.node_trans values ($history_id, $stamp, '$node_id', '$node_state{$node_id}')");
DBQueryFatal("insert into $NODE_USAGE_DB.node_trans values ($history_id, $stamp, '$node_id', '$node_state{$node_id}')");
$last_trans{$node_id} = $history_id;
}
$last_history_id = $history_id;
......@@ -121,7 +128,7 @@ if ($results) {
open F, ">>node_usage.raw";
$qr = DBQueryFatal("select history_id,stamp,node_id,op from node_usage.node_trans where history_id > $last_history_id order by history_id");
$qr = DBQueryFatal("select history_id,stamp,node_id,op from $NODE_USAGE_DB.node_trans where history_id > $last_history_id order by history_id");
while (my ($history_id,$stamp,$node_id,$op) = $qr->fetchrow()) {
my $type = $node_type{$node_id};
......@@ -155,3 +162,11 @@ if ($results) {
#!/usr/bin/perl
use strict;
use warnings;
our ($START);
require "@prefix@/etc/node_usage.conf";
chdir "@prefix@/data/node_usage";
open F, "node_usage.raw" or die;
my @hunt_for;
if (@ARGV == 0 || @ARGV % 2 != 0) {
print "Usage: $0 <pc1> <num1> [<pc2> <num2> ...]\n";
exit 1;
}
while (@ARGV) {
push @hunt_for, [shift @ARGV, shift @ARGV];
}
while (<F>) {
chop;
s/^(\d+) (\d+) // or die;
my $time = $2;
my %d;
while (s/^ ([\w\d\-\?]+): (\d+) (\d+) (\d+) //) {
$d{$1} = [$2, $3, $4];
}
my $num_satisfied = 0;
foreach my $e (@hunt_for) {
$num_satisfied++ if defined $d{$e->[0]} && ($d{$e->[0]}[0]) == $e->[1];
}
if ($num_satisfied == @hunt_for) {
print "$time\n";
exit 0;
}
}
print STDERR "No sutable date found.\n";
exit 2;
......@@ -10,34 +10,7 @@ PAGEHEADER("Testbed Node Usage Stats");
?>
<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.
</p>
<p>
Hourly graphs show the average number of free nodes in the
given hour. Daily graphs show the average number of free nodes in the
given day, etc. All times are given in Mountain Time. Note that because
some data in these graphs is averaged over a very long time period (up to four
years), it may not reflect recent
trends.
</p>
$avail_header
<h2 align=center>Recent Availability</h2>
......@@ -89,8 +62,7 @@ trends.
<p align=center>
Note: The gap in the last two graphs represents periods when no data
was availabe due to bugs in our system.
$avail_footer
<?php
......
#!/usr/bin/perl
use warnings;
use POSIX qw(strftime);
our ($START);
require "@prefix@/etc/node_usage.conf";
chdir "@prefix@/data/node_usage";
$start_date_short = strftime("%b %G", localtime($START));
sub mk_page ($$$);
our $avail_link = << '---';
<center>
[<a href="usage.php">Show Node Usage by Percentage Utilization</a>]
</center>
---
our $usage_link = << '---';
<center>
[<a href="./">Show Node Usage by Available Nodes</a>]
</center>
---
mk_page ("index.php", "avail", "Availability");
mk_page ("usage.php", "usage", "Usage");
sub mk_page ($$$) {
my ($file, $tag, $desc) = @_;
open F, ">$file" or die "Unable to write index.php";
print F <<"---"
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# All rights reserved.
#
require("../defs.php3");
PAGEHEADER("Testbed Node $desc Stats");
?>
${"${tag}_link"}
${"${tag}_header"}
<h2 align=center>Recent $desc</h2>
<p align=center>
<b>Last 2 Weeks (hourly)</b>
<br>
<img src="node_${tag}-hourly_last2weeks.png">
<br>
<p align=center>
<b>Last 2 Months (daily)</b>