Commit c27b24d0 authored by Ryan Jackson's avatar Ryan Jackson
Browse files

Modified versions of client-side tmcd stuff. All changes are simply to make...

Modified versions of client-side tmcd stuff.  All changes are simply to make it handle the new XML format.
parent 3a64e4d0
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
#
# XXX ONLY RUN THIS INSTALL ON A TESTBED NODE!
#
# These things need to be installed into the right place on a testbed
# node before cutting an image. This directory is installed first,
# followed by the system-specific directory.
#
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = tmcd/common
include $(OBJDIR)/Makeconf
all:
include $(TESTBED_SRCDIR)/GNUmakerules
DESTDIR =
ETCDIR = $(DESTDIR)$(CLIENT_ETCDIR)
BINDIR = $(DESTDIR)$(CLIENT_BINDIR)
VARDIR = $(DESTDIR)$(CLIENT_VARDIR)
RCDIR = $(BINDIR)/rc
SYSRCDIR = $(DESTDIR)/usr/local/etc/rc.d
TBBINDIR = $(DESTDIR)/usr/testbed/bin
TBLIBDIR = $(DESTDIR)/usr/testbed/lib
INSTALL = /usr/bin/install -c
install client-install:
@echo "You should probably not run this install directly!"
@echo "If you do, be sure to install from the system specific "
@echo "directory afterwards."
local-install: path-install local-script-install symlinks
remote-install: path-install remote-script-install
control-install: path-install control-script-install
other-install:
(cd ../../os; $(MAKE) DESTDIR=$(DESTDIR) client-install)
(cd ../../event; $(MAKE) DESTDIR=$(DESTDIR) client-install)
(cd ../../sensors/slothd; $(MAKE) DESTDIR=$(DESTDIR) client-install)
(cd ../../tools; $(MAKE) DESTDIR=$(DESTDIR) client-install)
dir-install:
$(INSTALL) -m 755 -o root -d $(ETCDIR)
$(INSTALL) -m 755 -o root -d $(BINDIR)
$(INSTALL) -m 755 -o root -d $(RCDIR)
$(INSTALL) -m 755 -o root -d $(VARDIR)
$(INSTALL) -m 755 -o root -d $(VARDIR)/db
$(INSTALL) -m 755 -o root -d $(VARDIR)/jails
$(INSTALL) -m 755 -o root -d $(VARDIR)/logs
$(INSTALL) -m 755 -o root -d $(VARDIR)/boot
$(INSTALL) -m 755 -o root -d $(VARDIR)/lock
$(INSTALL) -m 755 -o root -d $(TBBINDIR)
path-install: dir-install
$(INSTALL) -m 755 $(SRCDIR)/paths.pm $(ETCDIR)/paths.pm
$(INSTALL) -m 755 $(SRCDIR)/paths.sh $(ETCDIR)/paths.sh
common-script-install: dir-install
$(INSTALL) -m 755 $(SRCDIR)/libsetup.pm $(BINDIR)/libsetup.pm
$(INSTALL) -m 755 $(SRCDIR)/libtmcc.pm $(BINDIR)/libtmcc.pm
$(INSTALL) -m 755 $(SRCDIR)/libtestbed.pm $(BINDIR)/libtestbed.pm
$(INSTALL) -m 755 $(SRCDIR)/tmcc.pl $(BINDIR)/tmcc
$(INSTALL) -m 755 $(SRCDIR)/logboot $(BINDIR)/logboot
$(INSTALL) -m 755 $(SRCDIR)/watchdog $(BINDIR)/watchdog
$(INSTALL) -m 755 $(SRCDIR)/ntpstart $(BINDIR)/ntpstart
$(INSTALL) -m 755 $(SRCDIR)/runstartup $(BINDIR)/runstartup
$(INSTALL) -m 755 $(SRCDIR)/runcvsup.sh $(BINDIR)/runcvsup.sh
$(INSTALL) -m 755 $(SRCDIR)/update $(BINDIR)/update
$(INSTALL) -m 755 $(SRCDIR)/ifsetup $(BINDIR)/ifsetup
$(INSTALL) -m 755 $(SRCDIR)/ifdynconfig $(BINDIR)/ifdynconfig
$(INSTALL) -m 755 $(SRCDIR)/vnodesetup $(BINDIR)/vnodesetup
$(INSTALL) -m 755 $(SRCDIR)/bootsubnodes $(BINDIR)/bootsubnodes
$(INSTALL) -m 755 $(SRCDIR)/bootvnodes $(BINDIR)/bootvnodes
$(INSTALL) -m 755 $(SRCDIR)/startcmddone $(BINDIR)/startcmddone
(cd config; $(MAKE) DESTDIR=$(DESTDIR) script-install)
symlinks: dir-install
rm -f $(TBBINDIR)/tevc$(EXE)
ln -s $(CLIENT_BINDIR)/tevc$(EXE) $(TBBINDIR)/tevc$(EXE)
rm -f $(TBBINDIR)/emulab-sync$(EXE)
ln -s $(CLIENT_BINDIR)/emulab-sync$(EXE) $(TBBINDIR)/emulab-sync$(EXE)
rm -f $(TBLIBDIR)
ln -s $(CLIENT_BINDIR) $(TBLIBDIR)
local-script-install: common-script-install
$(INSTALL) -m 755 $(SRCDIR)/sendevent $(BINDIR)/sendevent
$(INSTALL) -m 755 $(SRCDIR)/rc.testbed $(RCDIR)/rc.testbed
$(INSTALL) -m 755 $(SRCDIR)/rc.bootsetup $(RCDIR)/rc.bootsetup
$(INSTALL) -m 755 $(SRCDIR)/rc.slothd $(RCDIR)/rc.slothd
$(INSTALL) -m 755 $(SRCDIR)/rc.canaryd $(RCDIR)/rc.canaryd
$(INSTALL) -m 755 $(SRCDIR)/rc.linktest $(RCDIR)/rc.linktest
$(INSTALL) -m 755 $(SRCDIR)/rc.inelab $(RCDIR)/rc.inelab
# Symlink this cause we invoke it from boss, and its too much
# of a hassle to worry about right now.
rm -f $(ETCDIR)/update
-ln -s $(CLIENT_BINDIR)/update $(ETCDIR)/update
remote-script-install: common-script-install
-chown root $(BINDIR)/vnodesetup
-chmod u+s $(BINDIR)/vnodesetup
control-script-install: dir-install bossnode
$(INSTALL) -m 755 $(SRCDIR)/libsetup.pm $(BINDIR)/libsetup.pm
$(INSTALL) -m 755 $(SRCDIR)/libtmcc.pm $(BINDIR)/libtmcc.pm
$(INSTALL) -m 755 $(SRCDIR)/tmcc.pl $(BINDIR)/tmcc
$(INSTALL) -m 755 $(SRCDIR)/ctrlnode.sh $(SYSRCDIR)/ctrlnode.sh
$(INSTALL) -m 755 $(SRCDIR)/rc.ctrlnode $(RCDIR)/rc.ctrlnode
$(INSTALL) -m 755 $(SRCDIR)/config/librc.pm $(BINDIR)/librc.pm
$(INSTALL) bossnode $(ETCDIR)/bossnode
bossnode: GNUmakefile
echo >$@ "$(BOSSNODE)"
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use Getopt::Std;
use English;
use Errno;
use POSIX qw(strftime);
#
# Startup subnodes, if there are any!
#
# NB: This script should not be run in foreground mode on a remote node
# when booting; if boss is down the boot will hang. On local nodes, its
# okay to hang.
#
sub usage()
{
print "Usage: bootsubnodes [-d] [-f]\n";
exit(1);
}
my $optlist = "df";
#
# Turn off line buffering on output
#
$| = 1;
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
#
use libsetup;
use libtmcc;
# Locals
my $logname = "$LOGDIR/bootsubnodes.debug";
my $debug = 0;
my $daemon = 1;
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"f"})) {
$daemon = 0;
}
if (@ARGV) {
usage();
}
#
# Must be root.
#
if ($UID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
#
# Put this into the background and log its output. We *must* do this cause
# we do not want to halt the boot if the testbed is down!
#
if ($daemon && TBBackGround($logname)) {
#
# Parent exits normally
#
exit(0);
}
my %subnodelist;
#
# Get the current set of subnodes that are supposed to be running on
# this node.
#
my %tmccresults;
if (tmcc(TMCCCMD_SUBNODELIST, undef, \%tmccresults) < 0) {
die("*** WARNING: Could not get subnode list from server!\n");
}
if (!$tmccresults{'subnode'}) {
print "No subnodes. Exiting gracefully ...\n";
exit(0);
}
foreach my $node (@{$tmccresults{'subnode'}}) {
my $nodeid = $$node{'nodeid'};
my $type = $$node{'type'};
if ($node =~ /^([-\w]+)$/ && $type =~ /^([-\w]+)$/) {
$subnodelist{$nodeid} = $type;
}
else {
warn("*** WARNING: Skipping bad subnodeid: 'NODEID=$nodeid TYPE=$type'\n");
}
}
print "subnodelist is @{[keys(%subnodelist)]}\n";
# Pause to give hardware settle time.
sleep(2);
foreach my $subnode (keys(%subnodelist)) {
my $type = $subnodelist{$subnode};
print "Setting up subnode $subnode ($type) ...\n";
# These should not return until the subnode is fully running.
SWITCH: for ($type) {
/^IXP$/i && do {
system("ixpboot $subnode");
if ($?) {
print STDERR "$subnode boot failed with $?\n";
}
last SWITCH;
};
/^mote$/i && do {
libsetup_setvnodeid($subnode);
configtmcc("subnode", $subnode);
tmcc(TMCCCMD_STATE, "BOOTING");
tmcc(TMCCCMD_SUBCONFIG, undef, \%tmccresults) == 0
or die("*** $0:\n".
" Could not get subnode config from server!\n");
my $BAUD = 0;
my $CAPSERVER = "";
my $CAPPORT = 0;
if ($tmccresults{'type'} eq 'mica2') {
$BAUD = 57600;
}
$CAPSERVER = $tmccresults{'capserver'};
$CAPPORT = $tmccresults{'capport'};
if (-x "$BINDIR/capture") {
system("$BINDIR/capture -a -s $BAUD -u '/usr/local/bin/uisp ".
"-dprog=sggpio -dpart=ATmega128 --wr_fuse_e=ff ".
"--erase --upload if=%s' $CAPSERVER:$CAPPORT tts/2");
}
tmcc(TMCCCMD_STATE, "ISUP");
last SWITCH;
};
/^netfpga$/i && do {
system("netfpgactl $subnode boot");
if ($?) {
print STDERR "$subnode boot failed with $?\n";
}
last SWITCH;
};
print "Invalid subnode type: $type\n";
}
sleep(1);
}
exit(0);
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2008 University of Utah and the Flux Group.
# All rights reserved.
#
use Getopt::Std;
use English;
use Errno;
use POSIX qw(strftime);
#
# Startup vnodes, if there are any!
#
# NB: This script should not be run in foreground mode on a remote node
# when booting; if boss is down the boot will hang. On local nodes, its
# okay to hang.
#
sub usage()
{
print "Usage: bootvnodes [-d] [-f] [-k | -h | -r | -b | -c]\n";
exit(1);
}
my $optlist = "kdfhrcb";
#
# Turn off line buffering on output
#
$| = 1;
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
#
use libsetup;
use libtmcc;
# Locals
my $logname = "$LOGDIR/bootvnodes.debug";
my $vndir = "$VARDIR/jails";
my $debug = 0;
my $daemon = 1;
my $reconfig= 0;
my $action;
# Prototypes
sub prebootvnodes($$);
sub postbootvnodes($$);
sub bootvnode($$$);
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"f"})) {
$daemon = 0;
}
if (defined($options{"r"})) {
$action = "reboot";
}
if (defined($options{"k"})) {
$action = "kill";
}
if (defined($options{"h"})) {
$action = "halt";
}
if (defined($options{"b"})) {
$action = "boot";
}
if (defined($options{"c"})) {
$reconfig = 1;
}
if (@ARGV) {
usage();
}
#
# Must be root.
#
if ($UID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
# We need to know this below.
my $sysname = `uname -s`;
chomp($sysname);
my $islinux = ($sysname eq "Linux");
#
# Put this into the background and log its output. We *must* do this cause
# we do not want to halt the boot if the testbed is down!
#
if ($daemon && TBBackGround($logname)) {
#
# Parent exits normally
#
exit(0);
}
#
# This applies to whatever vnodes are running. Do it and exit.
#
if (defined($action) && !$reconfig) {
opendir(DIR, "$vndir") or
die("Cannot opendir $vndir: $!\n");
my @files = readdir(DIR);
closedir(DIR);
foreach my $file (@files) {
if ($file =~ /^((?:pc|homenet)vm[-\w]*)$/) {
bootvnode($1, $action, (-e "$vndir/$file/fakejail" ? 0 : 1));
}
}
exit(0);
}
my %newvnodelist = ();
my %curvnodelist = ();
my $fakejails = 0;
#
# Get the current set of vnodes that are supposed to be running on
# this node.
#
my %tmccresults;
if (tmcc(TMCCCMD_VNODELIST, undef, \%tmccresults) < 0) {
die("*** WARNING: Could not get vnode list from server!\n");
}
my $rptr = $tmccresults{'vnode'};
if (ref $rptr ne 'ARRAY') {
$rptr = [ $ref ];
}
foreach my $vnode (@$rptr) {
my $vnodeid = $$vnode{'vnodeid'};
my $jailed = $$vnode{'jailed'};
if ($vnodeid =~ /^VNODEID=([-\w]+)$/ && $jailed =~ /^JAILED=(\d)$/) {
$newvnodelist{$vnodeid} = $jailed;
$fakejails++ if ($jailed eq "0");
}
else {
warn("*** WARNING: Skipping bad subnodeid: 'VNODEID=$vnodeid JAILED=$jailed'\n");
}
}
#
# If doing a reconfig, get the current set of vnodes that are running.
# We want to compare that list against the list we just got from tmcd.
#
if ($reconfig) {
opendir(DIR, "$vndir") or
die("Cannot opendir $vndir: $!\n");
my @files = readdir(DIR);
closedir(DIR);
foreach my $file (@files) {
if ($file =~ /^((?:pc|homenet)vm[-\w]*)$/) {
if (-e "$vndir/$file/fakejail") {
$fakejails++;
$curvnodelist{$1} = 0;
} else {
$curvnodelist{$1} = 1;
}
}
}
#
# Reboot nodes that are running and in the current list from tmcd.
# Kill nodes that are running but not in the current list from tmcd.
#
foreach my $vnode (sort(keys(%curvnodelist))) {
if (exists($newvnodelist{$vnode})) {
bootvnode($vnode,
(defined($action) ? $action : "reboot"),
$newvnodelist{$vnode});
delete($newvnodelist{$vnode});
}
else {
bootvnode($vnode, "kill", $curvnodelist{$vnode});
}
}
}
# XXX Exit if specific action requested, and it was not "boot"
exit(0)
if (defined($action) && $action ne "boot");
# Exit if nothing left to do (no new vnodes).
exit(0)
if (! scalar(keys(%newvnodelist)));
prebootvnodes(\%curvnodelist, \%newvnodelist)
if (!$fakejails);
foreach my $vnode (sort(keys(%newvnodelist))) {
# Blocks until mostly setup.
bootvnode($vnode, "boot", $newvnodelist{$vnode});
}
postbootvnodes(\%curvnodelist, \%newvnodelist)
if (!$fakejails);
exit(0);
#
# Prepare the vnode host prior to individual vnode setup
# Takes references to the current and new vnode hashes.
#
sub prebootvnodes($$)
{
my ($cvn, $nvn) = @_;
#
# For local vnodes, create the extra FS for filesystems and other state.
# This will fail if it already exists, so just keep going.
#
if (!REMOTE()) {
my $mntdir = $islinux ? "/vservers" : $vndir;
system("mkextrafs.pl $mntdir");
}
#
# Symlink /local into it.
#
if (! -e "/local") {
system("ln -s " . LOCALROOTFS() . " /local");
}
#
# XXX OS dependent stuff. Should move elsewhere
#
if ($islinux) {
return;
}
#
# Make sure enough vn devices exist
#
for (my $i = 0; $i < scalar(keys(%$nvn)) + scalar(keys(%$cvn)); $i++) {
my $dev = "vn${i}";
if (! -e "/dev/${dev}c") {
system("(cd /dev; ./MAKEDEV $dev)");
}
}
#
# XXX tweak IP interrupt queue size to accomodate up to 8 x 100Mb
# trivial links XXX turn on local hack to retry on NFS EACCES
# errors (thanks mountd!)
#
system("sysctl net.inet.ip.intr_queue_maxlen=128 >/dev/null 2>&1");
system("sysctl vfs.nfs.eacces_retry_enable=1 >/dev/null 2>&1");
#
# XXX grossed out yet? Try this one: the mount command will HUP mountd
# after every successful mount. Thus if mounts in one jail overlap NFS
# activity in another, the latter may be randomly killed off.
#
# Elegant solution: rename the mountd.pid file so mount cannot find it!
# XXX hmm...mountd_sux hack above should take care of this, and we need
# to hup mountd when we modify the exports file.
#
rename("/var/run/mountd.pid", "/var/run/mountd.thisreallysux")
if (-e "/var/run/mountd.pid");
}
#
# Final setup of vnode host after individual vnode setup
# Takes references to the current and new vnode hashes.
#
sub postbootvnodes($$)
{
my ($cvn, $nvn) = @_;
#
# XXX OS dependent stuff. Should move elsewhere
#
if ($islinux) {
return;
}
my $PIDFILE = "/var/run/progagent.pid";
foreach my $vnode (keys(%$nvn)) {
system("rtprio 15 -`cat $vndir/$vnode/root/$PIDFILE`")
if (-e "$vndir/$vnode/root/$PIDFILE");
}
}
#
# Helper function to boot/kill/halt/reboot a specific vnode.
#
sub bootvnode($$$)
{
my ($vnode, $action, $jailed) = @_;
my $opt;
my $act;
if ($action eq "halt") {
$opt = "-h";
$act = "Halting";
}
elsif ($action eq "reboot") {
$opt = "-r";
$act = "Rebooting";
}
elsif ($action eq "kill") {
$opt = "-k";
$act = "Killing";
}
else {
$opt = "-b";
$act = "Booting";
}
$opt .= ($jailed ? " -jVt" : " -i");
print "$act vnode $vnode ...\n";
system("vnodesetup $opt $vnode");
return($?);
}
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004-2008 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use POSIX ":sys_wait_h";
use POSIX qw(setsid);
sub usage()
{
print "Usage: " .
scriptname() . " [-j vnodeid] boot|shutdown|reconfig|reset\n";