Commit b4bde6d6 authored by Leigh Stoller's avatar Leigh Stoller

Checkpoint more install changes.

parent c5f9978b
......@@ -13,7 +13,7 @@ include $(OBJDIR)/Makeconf
ifeq ($(STANDALONE_CLEARINGHOUSE),0)
TARGETS = libinstall.pm boss-install ops-install fs-install dump-descriptors \
load-descriptors update-install update-testbed
load-descriptors update-install update-testbed testbed-version
else
TARGETS = clrhouse-install
endif
......@@ -28,7 +28,8 @@ include $(TESTBED_SRCDIR)/GNUmakerules
install: $(INSTALL_LIBDIR)/libinstall.pm \
$(INSTALL_SBINDIR)/update-install \
$(INSTALL_SBINDIR)/update-testbed
$(INSTALL_SBINDIR)/update-testbed \
$(INSTALL_SBINDIR)/testbed-version
clean:
rm -f boss-install ops-install fs-install update-install
......
......@@ -108,8 +108,10 @@ sub Phase($$$) {
my $isSubPhase = ($depth > 1);
my $descrstring = "| " x ($depth -1) . $descr;
if ($firstSubPhase && !$updatemode) {
if ($firstSubPhase) {
print "\n";
printf $logfp "\n"
if ($impotent);
}
printf "%-50s", $descrstring;
printf $logfp "%-50s", $descrstring
......@@ -578,6 +580,31 @@ sub HUPDaemon($) {
SignalDaemon($name, 'HUP');
}
#
# Restart a daemon if running. Do not start if not running.
#
sub RestartDaemon($) {
my ($name) = @_;
my $pidfile = "$VARRUN/${name}.pid";
if (! -e "$VARRUN/stated.pid") {
PhaseSkip("Testbed not running");
}
if (!-e $pidfile) {
PhaseSkip("$name not running");
}
if ($impotent) {
PhaseWouldHave("restart $name");
return 1;
}
SignalDaemon($name, 'TERM');
if (ExecQuiet("$TBROOT/sbin/$name")) {
PhaseSucceed("$name started");
}
PhaseFail("Could not start $name");
}
#
# Fetch a file from the network, using any protocol supported by fetch(1).
# Arguments are URL and a local filename. Retunrns 1 if succesful, 0 if not.
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2010 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
#
# Update DB.
#
sub usage()
{
print STDERR "Usage: testbed-version\n";
exit(-1);
}
my $optlist = "v";
my $verbose = 0;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $DBNAME = "@TBDBNAME@";
# Protos
sub Fatal($);
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/site/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Do not modify the include path if it was specified when invoked.
# This allows update to run from the build tree.
#
BEGIN
{
eval "require emdbi";
if ($@) {
unshift(@INC, "@prefix@/lib");
}
}
use emdb;
use libtestbed;
#
# Parse command arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"v"})) {
$verbose = 1;
}
my $query_result =
DBQueryFatal("select * from version_info order by name");
while (my ($name, $value) = $query_result->fetchrow_array()) {
printf("%-20s %s\n", $name . ":" , $value);
}
exit(0);
sub Fatal($)
{
my ($msg) = @_;
Restart();
die("*** $0:\n".
" $msg\n");
}
......@@ -13,10 +13,10 @@ use Getopt::Std;
#
sub usage()
{
print STDERR "Usage: update-install [-v] [-s] [-f] [<version>]\n";
print STDERR "Usage: update-install [-v | -n] [-s] [-f] [<version>]\n";
exit(-1);
}
my $optlist = "dsfvp:qa:ci";
my $optlist = "dsfvp:qa:cin";
my $debug = 0;
my $force = 0;
my $single = 0;
......@@ -86,7 +86,7 @@ if (defined($options{"d"})) {
if (defined($options{"c"})) {
$check = 1;
}
if (defined($options{"i"})) {
if (defined($options{"i"}) || defined($options{"n"})) {
$impotent = 1;
}
if (defined($options{"f"})) {
......@@ -120,6 +120,21 @@ if ($UID && !($impotent || $check || $verify)) {
Fatal("This script must be run as root! Maybe use sudo?")
}
#
# This is a utility routine that callee scripts can use to set a DB
# flag to indicate that a reboot is require.
#
sub MarkForReboot($)
{
my ($version) = @_;
print "*** $version says reboot is (will be) required!\n";
emdbi::DBQueryFatal("replace into version_info set ".
" value='1', name='needreboot'");
return 0;
}
if ($impotent) {
open(LOGFP, "> $logfile")
or Fatal("Could not open $logfile");
......@@ -140,6 +155,8 @@ if (!defined($version)) {
DBQueryFatal("insert into version_info ".
"values ('install', '$version')");
DBQueryFatal("insert into version_info ".
"values ('needreboot', '0')");
}
else {
($version) = $query_result->fetchrow_array();
......@@ -148,6 +165,9 @@ if (!defined($version)) {
if (! ($version =~ /^[\d\.]+$/)) {
Fatal("'$version' does not look like a reasonable starting version.");
}
# Start off with reboots not needed.
DBQueryFatal("replace into version_info ".
"values ('needreboot', '0')");
#
# Split apart the version number. Assumed to be in dotted notation.
......
......@@ -7,6 +7,7 @@
use strict;
use English;
use Getopt::Std;
use Data::Dumper;
#
# Update DB.
......@@ -16,12 +17,17 @@ sub usage()
print STDERR "Usage: update-testbed [-v] [-f]\n";
exit(-1);
}
my $optlist = "idsvf";
my $debug = 0;
my $force = 0;
my $verify = 0;
my $install = 0;
my $forceopt= "";
my $optlist = "idsvfn";
my $debug = 0;
my $force = 0;
my $verify = 0;
my $install = 0;
my $stopbed = 0;
my $stopped = 0;
my $nologins = 0;
my $committed = 0;
my $impotent = 0;
my $forceopt = "";
#
# Configure variables
......@@ -34,10 +40,13 @@ my $SQLUPDATEDIR = "$SRCDIR/sql/updates";
my $UPDATEDIR = "$SRCDIR/install/updates";
my $DBUPDATE = "$TB/sbin/dbupdate";
my $INSTALLUPDATE= "$TB/sbin/update-install";
my $SETSITEVAR = "$TB/sbin/setsitevar";
my $STARTUP = "/usr/local/etc/rc.d/3.testbed.sh";
my $tempfile = "/var/tmp/update.$$";
# Protos
sub Fatal($);
sub CheckForReboot();
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/site/bin';
......@@ -54,19 +63,15 @@ $| = 1;
#
BEGIN
{
eval "require emdbi";
if ($@) {
if (-e "../Makeconf") {
# Prior to first install or running from object dir.
unshift(@INC, "../db");
unshift(@INC, "@top_srcdir@/install");
unshift(@INC, "@top_srcdir@/tbsetup");
unshift(@INC, "../tbsetup");
}
require emdbi;
if (-e "../Makeconf") {
# Prior to first install or running from object dir.
unshift(@INC, "../db");
unshift(@INC, "@top_srcdir@/install");
unshift(@INC, "@top_srcdir@/tbsetup");
unshift(@INC, "../tbsetup");
}
}
use emdbi;
use emdb;
use libtestbed;
#
......@@ -89,11 +94,17 @@ if (defined($options{"i"})) {
if (defined($options{"v"})) {
$verify = 1;
}
if (defined($options{"s"})) {
$stopbed = 1;
}
if (defined($options{"n"})) {
$impotent = 1;
}
#
# Must be root if actually doing this.
#
if (!$verify && $UID) {
if (!($verify || $impotent) && $UID) {
Fatal("This script must be run as root! Maybe use sudo?")
}
......@@ -104,6 +115,24 @@ if (! (-e "../db/dbupdate" && -e "./update-install")) {
my @INCDIRS = ("-I.", "-I../tbsetup", "-I../db",
"-I${SRCDIR}/tbsetup", "-I${SRCDIR}/install");
#
# Dump the testbed version numbers in all modes.
#
print "Testbed version info:\n";
system("perl @INCDIRS ./testbed-version");
#
# Impotent mode, just runs the install scripts.
#
if ($impotent) {
system("perl @INCDIRS ./update-install -n -p $UPDATEDIR");
if ($?) {
exit(1);
}
CheckForReboot();
exit(0);
}
#
# In verify mode, just run the update scripts in verify.
#
......@@ -131,6 +160,107 @@ if ($verify) {
exit($exitval);
}
#
# Cleanup handler when stopping the testbed.
#
sub Restart()
{
if ($committed) {
print "*** Update has progressed too far; you must renable by hand\n";
return;
}
if ($stopped) {
print "Starting up testbed daemons.\n";
system("$STARTUP start");
if ($?) {
print "*** Could not restart testbed daemons.\n";
exit(1);
}
}
if ($nologins) {
print "Turning on the web interface and allowing swaps\n";
if (system("$SETSITEVAR web/nologins -") ||
system("$SETSITEVAR web/message -")) {
print "*** Could not renable the web interface and swapping!\n";
exit(1);
}
}
}
sub Handler()
{
Restart();
exit(1);
}
if ($stopbed) {
$SIG{INT} = \&Handler;
#
# Stop the testbed before doing the update.
#
print "** Putting the testbed to sleep before updating ...\n";
print "-> Turning off the web interface and disallowing swaps.\n";
my $msg = "Testbed software update in progress; back in a little while";
$msg =~ s|\&|&amp;|g;
$msg =~ s|\<|&lt;|g;
system("$SETSITEVAR","web/message", $msg);
if ($?) {
Fatal("Could not update web message");
}
system("$SETSITEVAR web/nologins 1");
if ($?) {
Fatal("Could not disable web logins and experiment swaps");
}
$nologins = 1;
print "-> Waiting a few seconds for testbed to quiet down ...\n";
sleep(5);
print "-> Looking for experiments still in transition.\n";
#
# Look for any experiments in transition, and wait for them to stop.
# This could take an arbitrarily long time of course, but its the only
# safe way to do it. Don't worry about any experiments that are older
# then 24 hours though; they are likely stuck and not going anywhere.
#
while (1) {
my $query_result =
emdb::DBQueryWarn("select pid,eid,idx,state,expt_locked ".
" from experiments ".
"where expt_locked is not null and ".
" DATE_SUB(NOW(),INTERVAL 1 DAY) <= expt_locked");
if (!$query_result) {
Fatal("Error getting info from the DB. Stopping.");
}
last
if (!$query_result->numrows());
print "-> Experiments still in transition:\n";
while (my ($pid,$eid,$idx,$state,$expt_locked) =
$query_result->query_result()) {
print " $pid,$eid,$idx -- $state, $expt_locked\n";
}
print "-> Waiting 30 seconds before trying again. ^C is okay\n\n";
sleep(30);
}
print "** Testbed is quiet; stopping testbed daemons ... \n";
system("$STARTUP stop >/dev/null 2>&1");
if ($?) {
Fatal("Could not stop testbed daemons. Stopping.");
}
$stopped = 1;
print "** Testbed is stopped. Proceeding to update\n";
#
# No going back; we do not want to re-enable the testbed if things fail
# from this point on.
#
$committed = 1;
}
print "Running DB updates ...\n";
system("perl @INCDIRS ../db/dbupdate -q -p $SQLUPDATEDIR $DBNAME");
exit(1)
......@@ -156,12 +286,48 @@ system("perl @INCDIRS ./update-install $forceopt -q -a post -p $UPDATEDIR");
exit(1)
if ($?);
if (CheckForReboot()) {
exit(0);
}
# So we can turn the testbed back on.
elsif ($stopbed) {
$committed = 0;
Restart();
}
exit(0);
sub Fatal($)
{
my ($msg) = @_;
Restart();
die("*** $0:\n".
" $msg\n");
}
#
# See if a reboot is needed. Typically not, but sometimes it might.
#
sub CheckForReboot()
{
my $reboot_query =
emdb::DBQueryWarn("select value from version_info ".
"where name='needreboot'");
if ($reboot_query->numrows) {
my ($needreboot) = $reboot_query->fetchrow_array();
if ($needreboot) {
print "********************************************************\n";
print "*\n";
if ($impotent) {
print "* THESE UPDATES WILL REQUIRE BOSS REBOOT!\n";
}
else {
print "* YOU MUST NOW REBOOT BOSS!\n";
}
print "*\n";
print "********************************************************\n";
return 1;
}
}
return 0;
}
......@@ -21,6 +21,7 @@ sub InstallUpdate($$)
if ($phase eq "pre") {
Phase "startupfile", "Updating testbed startup file", sub {
DoneIfIdentical("$TOP_OBJDIR/rc.d/3.testbed.sh", $TESTBED_STARTUP);
main::MarkForReboot($version);
DiffFiles("$TOP_OBJDIR/rc.d/3.testbed.sh", $TESTBED_STARTUP);
ExecQuietFatal("$GMAKE -C $TOP_OBJDIR/rc.d install");
};
......
......@@ -27,6 +27,7 @@ sub InstallUpdate($$)
};
Phase "startupfile", "Updating testbed startup file", sub {
DoneIfIdentical("$TOP_OBJDIR/rc.d/3.testbed.sh", $TESTBED_STARTUP);
main::MarkForReboot($version);
DiffFiles("$TOP_OBJDIR/rc.d/3.testbed.sh", $TESTBED_STARTUP);
ExecQuietFatal("$GMAKE -C $TOP_OBJDIR/rc.d install");
};
......@@ -38,7 +39,13 @@ sub InstallUpdate($$)
if ($phase eq "post") {
Phase "checknodes_daemon", "Starting up checknodes daemon", sub {
# Testbed not running.
DoneIfDoesntExist("$VARRUN/stated.pid");
if (! -e "$VARRUN/stated.pid") {
PhaseSkip("Testbed not running");
}
if (ExecQuiet("$TBROOT/sbin/checknodes_daemon")) {
PhaseSucceed("checknodes_daemon started");
}
PhaseFail("Could not start checknodes_daemon");
};
}
return 0;
......
......@@ -20,13 +20,28 @@ sub InstallUpdate($$)
Phase "newsyslog", "Updating $NEWSYSLOG_CONF", sub {
DoneIfEdited($NEWSYSLOG_CONF);
BackUpFileFatal($NEWSYSLOG_CONF);
# Kill any old lines; they were hand jobs.
ExecQuietFatal("sed -i .orig -e '/reloadlog/d' $NEWSYSLOG_CONF");
ExecQuietFatal("sed -i .orig -e '/checkuplog/d' $NEWSYSLOG_CONF");
ExecQuietFatal("sed -i .orig -e '/poollog/d' $NEWSYSLOG_CONF");
ExecQuietFatal("sed -i .orig -e '/expire_dae/d' $NEWSYSLOG_CONF");
ExecQuietFatal("sed -i .orig -e '/sa_daemon/d' $NEWSYSLOG_CONF");
#
# The ProtoGeni entries are okay; they might not be running.
#
AppendToFileFatal($NEWSYSLOG_CONF,
"$LOGDIR/reloadlog 640 9 1000 * Z ".
"/var/run/reload_daemon.pid",
"$LOGDIR/checkuplog 640 9 1000 * Z ".
"/var/run/checkup_daemon.pid",
"$LOGDIR/poollog 640 9 1000 * Z ".
"/var/run/pool_daemon.pid");
"/var/run/pool_daemon.pid",
"$LOGDIR/expire_daemon.log 640 9 1000 * Z ".
"/var/run/expire_daemon.pid",
"$LOGDIR/sa_daemon.log 640 9 1000 * Z ".
"/var/run/sa_daemon.pid");
};
}
......@@ -34,6 +49,24 @@ sub InstallUpdate($$)
# If something should run in the post-install phase.
#
if ($phase eq "post") {
Phase "daemons", "Restarting daemons", sub {
Phase "reload_daemon", "Restarting reload_daemon", sub {
RestartDaemon("reload_daemon");
};
Phase "checkup_daemon", "Restarting checkup_daemon", sub {
RestartDaemon("checkup_daemon");
};
Phase "pool_daemon", "Restarting pool_daemon", sub {
RestartDaemon("pool_daemon");
};
Phase "expire_daemon", "Restarting expire_daemon", sub {
RestartDaemon("expire_daemon");
};
Phase "sa_daemon", "Restarting sa_daemon", sub {
RestartDaemon("sa_daemon");
};
PhaseSucceed("Daemons Restarted");
};
}
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment