mostly complete upgrade system
This commit is contained in:
parent
cf92cb5a4f
commit
1a79d607af
13 changed files with 399 additions and 698 deletions
438
sbin/upgrade.pl
438
sbin/upgrade.pl
|
|
@ -11,47 +11,38 @@
|
|||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use Cwd ();
|
||||
use File::Path ();
|
||||
use File::Spec;
|
||||
use warnings;
|
||||
use WebGUI::Paths -inc;
|
||||
use WebGUI::Upgrade;
|
||||
use Getopt::Long ();
|
||||
use Pod::Usage ();
|
||||
use WebGUI::Paths -inc;
|
||||
|
||||
use WebGUI::Config;
|
||||
use WebGUI::Session;
|
||||
|
||||
my $help;
|
||||
my $history;
|
||||
my $override;
|
||||
my $quiet;
|
||||
my $mysql = "mysql";
|
||||
my $mysqldump = "mysqldump";
|
||||
my $backupDir = "/tmp/backups";
|
||||
my $skipBackup;
|
||||
my $skipDelete;
|
||||
my $skipMaintenance;
|
||||
my $doit;
|
||||
|
||||
Getopt::Long::GetOptions(
|
||||
'help'=>\$help,
|
||||
'history'=>\$history,
|
||||
'override'=>\$override,
|
||||
'quiet'=>\$quiet,
|
||||
'mysql=s'=>\$mysql,
|
||||
'doit'=>\$doit,
|
||||
'skipDelete' =>\$skipDelete,
|
||||
'skipMaintenance' =>\$skipMaintenance,
|
||||
'mysqldump=s'=>\$mysqldump,
|
||||
'backupDir=s'=>\$backupDir,
|
||||
'skipbackup'=>\$skipBackup
|
||||
);
|
||||
'help' => \( my $help ),
|
||||
'history' => \( my $history ),
|
||||
'override' => \( my $override ),
|
||||
'quiet' => \( my $quiet ),
|
||||
'doit' => \( my $doit ),
|
||||
'skipDelete' => \( my $skipDelete ),
|
||||
'skipMaintenance' => \( my $skipMaintenance ),
|
||||
'skipbackup' => \( my $skipBackup ),
|
||||
'backupDir=s' => \( my $backupDir ),
|
||||
'mysql=s' => \( my $mysql ),
|
||||
'mysqldump=s' => \( my $mysqldump ),
|
||||
) or Pod::Usage::pod2usage(2);
|
||||
|
||||
Pod::Usage::pod2usage( verbose => 2 ) if $help;
|
||||
Pod::Usage::pod2usage() unless $doit;
|
||||
|
||||
unless ($doit) {
|
||||
print <<STOP;
|
||||
if ($help) {
|
||||
Pod::Usage::pod2usage(
|
||||
-verbosity => 1,
|
||||
-exitval => 1,
|
||||
);
|
||||
}
|
||||
elsif ($history) {
|
||||
print "print site history\n";
|
||||
exit;
|
||||
}
|
||||
elsif ( ! $doit ) {
|
||||
my $message = <<'END_MESSAGE';
|
||||
|
||||
+--------------------------------------------------------------------+
|
||||
| |
|
||||
|
|
@ -75,197 +66,38 @@ unless ($doit) {
|
|||
| |
|
||||
+--------------------------------------------------------------------+
|
||||
|
||||
STOP
|
||||
exit;
|
||||
END_MESSAGE
|
||||
Pod::Usage::pod2usage($message);
|
||||
}
|
||||
|
||||
|
||||
if (!($^O =~ /^Win/i) && $> != 0 && !$override) {
|
||||
print "You must be the super user to use this utility.\n";
|
||||
exit;
|
||||
if ( $^O ne 'MSWin32' && $> != 0 && !$override ) {
|
||||
print "You must be the super user to use this utility.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
## Globals
|
||||
|
||||
$| = 1;
|
||||
our $perl = $^X;
|
||||
our $slash;
|
||||
if ($^O =~ /^Win/i) {
|
||||
$slash = "\\";
|
||||
} else {
|
||||
$slash = "/";
|
||||
}
|
||||
our $upgradesPath = WebGUI::Paths->upgrades;
|
||||
our (%upgrade, %config);
|
||||
|
||||
my $upgrade = WebGUI::Upgrade->new(
|
||||
quiet => $quiet,
|
||||
clearCache => !$skipDelete,
|
||||
createBackups => !$skipBackup,
|
||||
useMaintenanceMode => !$skipMaintenance,
|
||||
$mysql ? (
|
||||
mysql => $mysql,
|
||||
) : (),
|
||||
$mysqldump ? (
|
||||
mysqldump => $mysqldump,
|
||||
) : (),
|
||||
$backupDir ? (
|
||||
backupPath => $backupDir,
|
||||
) : (),
|
||||
);
|
||||
|
||||
## Find site configs.
|
||||
$upgrade->upgradeSites;
|
||||
|
||||
print "\nGetting site configs...\n" unless ($quiet);
|
||||
my $configs = WebGUI::Config->readAllConfigs;
|
||||
foreach my $filename (keys %{$configs}) {
|
||||
print "\tProcessing $filename.\n" unless ($quiet);
|
||||
$config{$filename}{configFile} = $filename;
|
||||
$config{$filename}{dsn} = $configs->{$filename}->get("dsn");
|
||||
my $temp = _parseDSN($config{$filename}{dsn}, ['database', 'host', 'port']);
|
||||
if ($temp->{'driver'} eq "mysql") {
|
||||
$config{$filename}{db} = $temp->{'database'};
|
||||
$config{$filename}{host} = $temp->{'host'};
|
||||
$config{$filename}{port} = $temp->{'port'};
|
||||
$config{$filename}{dbuser} = $configs->{$filename}->get("dbuser");
|
||||
$config{$filename}{dbpass} = $configs->{$filename}->get("dbpass");
|
||||
$config{$filename}{mysqlCLI} = $configs->{$filename}->get("mysqlCLI");
|
||||
$config{$filename}{mysqlDump} = $configs->{$filename}->get("mysqlDump");
|
||||
$config{$filename}{backupPath} = $configs->{$filename}->get("backupPath");
|
||||
my $session = WebGUI::Session->open($filename);
|
||||
($config{$filename}{version}) = $session->db->quickArray("select webguiVersion from webguiVersion order by
|
||||
dateApplied desc, length(webguiVersion) desc, webguiVersion desc limit 1");
|
||||
unless ($history) {
|
||||
print "\tPreparing site for upgrade.\n" unless ($quiet);
|
||||
unless ($skipMaintenance) {
|
||||
$session->setting->remove('specialState');
|
||||
$session->setting->add('specialState','upgrading');
|
||||
}
|
||||
unless ($skipDelete) {
|
||||
print "\tDeleting temp files.\n" unless ($quiet);
|
||||
my $path = File::Spec->catdir($configs->{$filename}->get("uploadsPath"), 'temp');
|
||||
File::Path::rmtree($path) unless ($path eq "" || $path eq "/" || $path eq "/data");
|
||||
print "\tDeleting file cache.\n" unless ($quiet);
|
||||
$path = $configs->{$filename}->get("fileCacheRoot") || "/tmp/WebGUICache";
|
||||
File::Path::rmtree($path) unless ($path eq "" || $path eq "/" || $path eq "/data");
|
||||
}
|
||||
}
|
||||
$session->close();
|
||||
} else {
|
||||
delete $config{$filename};
|
||||
print "\tSkipping non-MySQL database.\n" unless ($quiet);
|
||||
}
|
||||
}
|
||||
|
||||
if ($history) {
|
||||
print "\nDisplaying upgrade history for each site.\n";
|
||||
foreach my $file (keys %config) {
|
||||
print "\n".$file."\n";
|
||||
my $session = WebGUI::Session->open($file);
|
||||
my $sth = $session->db->read("select * from webguiVersion order by dateApplied asc, webguiVersion asc");
|
||||
while (my $data = $sth->hashRef) {
|
||||
print "\t".sprintf("%-8s %-15s %-15s",
|
||||
$data->{webguiVersion},
|
||||
$session->datetime->epochToHuman($data->{dateApplied},"%y-%m-%d"),
|
||||
$data->{versionType})."\n";
|
||||
}
|
||||
$sth->finish;
|
||||
$session->close;
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
## Find upgrade files.
|
||||
|
||||
print "\nLooking for upgrade files...\n" unless ($quiet);
|
||||
opendir(DIR,$upgradesPath) or die "Couldn't open $upgradesPath\n";
|
||||
my @files = readdir(DIR);
|
||||
closedir(DIR);
|
||||
foreach my $file (@files) {
|
||||
if ($file =~ /^upgrade_(\d+\.\d+\.\d+)-(\d+\.\d+\.\d+)\.(pl|sql)$/) {
|
||||
if (checkVersion($1)) {
|
||||
if ($3 eq "sql") {
|
||||
print "\tFound upgrade script from $1 to $2.\n" unless ($quiet);
|
||||
$upgrade{$1}{sql} = $file;
|
||||
} elsif ($3 eq "pl") {
|
||||
print "\tFound upgrade executable from $1 to $2.\n" unless ($quiet);
|
||||
$upgrade{$1}{pl} = $file;
|
||||
}
|
||||
$upgrade{$1}{from} = $1;
|
||||
$upgrade{$1}{to} = $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "\nREADY TO BEGIN UPGRADES\n" unless ($quiet);
|
||||
|
||||
my $notRun = 1;
|
||||
|
||||
|
||||
my $currentPath = Cwd::getcwd();
|
||||
my $totalConfigs = scalar keys %config;
|
||||
my $configCounter = 0;
|
||||
foreach my $filename (keys %config) {
|
||||
chdir($upgradesPath);
|
||||
my $clicmd = $config{$filename}{mysqlCLI} || $mysql;
|
||||
my $dumpcmd = $config{$filename}{mysqlDump} || $mysqldump;
|
||||
my $backupTo = $config{$filename}{backupPath} || $backupDir;
|
||||
mkdir($backupTo);
|
||||
++$configCounter;
|
||||
while ($upgrade{$config{$filename}{version}}{sql} ne "" || $upgrade{$config{$filename}{version}}{pl} ne "") {
|
||||
my $upgrade = $upgrade{$config{$filename}{version}}{from};
|
||||
print "\n".$config{$filename}{db}." ".$upgrade{$upgrade}{from}."-".$upgrade{$upgrade}{to}."\n" unless ($quiet);
|
||||
print "Processing $configCounter out of $totalConfigs configs\n" unless ($quiet);
|
||||
unless ($skipBackup) {
|
||||
print "\tBacking up $config{$filename}{db} ($upgrade{$upgrade}{from})..." unless ($quiet);
|
||||
my $cmd = qq!$dumpcmd -u"$config{$filename}{dbuser}" -p"$config{$filename}{dbpass}"!;
|
||||
$cmd .= " --host=".$config{$filename}{host} if ($config{$filename}{host});
|
||||
$cmd .= " --port=".$config{$filename}{port} if ($config{$filename}{port});
|
||||
$cmd .= " --add-drop-table ".$config{$filename}{db}." --result-file="
|
||||
.File::Spec->catfile($backupTo, $config{$filename}{db}."_".$upgrade{$upgrade}{from}."_".time.".sql");
|
||||
unless (system($cmd)) {
|
||||
print "OK\n" unless ($quiet);
|
||||
} else {
|
||||
print "Failed!\n" unless ($quiet);
|
||||
fatalError();
|
||||
}
|
||||
}
|
||||
if ($upgrade{$upgrade}{sql} ne "") {
|
||||
print "\tUpgrading to ".$upgrade{$upgrade}{to}."..." unless ($quiet);
|
||||
my $cmd = qq!$clicmd -u"$config{$filename}{dbuser}" -p"$config{$filename}{dbpass}"!;
|
||||
$cmd .= " --host=".$config{$filename}{host} if ($config{$filename}{host});
|
||||
$cmd .= " --port=".$config{$filename}{port} if ($config{$filename}{port});
|
||||
$cmd .= " --database=".$config{$filename}{db}." < ".$upgrade{$upgrade}{sql};
|
||||
unless (system($cmd)) {
|
||||
print "OK\n" unless ($quiet);
|
||||
} else {
|
||||
print "Failed!\n" unless ($quiet);
|
||||
fatalError();
|
||||
}
|
||||
}
|
||||
if ($upgrade{$upgrade}{pl} ne "") {
|
||||
my $pid = fork;
|
||||
if (!$pid) {
|
||||
local @ARGV = ("--configFile=$filename", $quiet ? ('--quiet') : ());
|
||||
local $0 = $upgrade{$upgrade}{pl};
|
||||
local $@;
|
||||
do $0;
|
||||
if ($@) {
|
||||
warn $@;
|
||||
exit 255;
|
||||
};
|
||||
exit;
|
||||
}
|
||||
waitpid $pid, 0;
|
||||
if ($?) {
|
||||
print "\tProcessing upgrade executable failed!\n";
|
||||
fatalError();
|
||||
}
|
||||
##Do a dummy load of the config
|
||||
WebGUI::Config->clearCache();
|
||||
}
|
||||
$config{$filename}{version} = $upgrade{$upgrade}{to};
|
||||
$notRun = 0;
|
||||
sleep 1; # Sleep a second to avoid adding asset revisions too quickly
|
||||
}
|
||||
chdir($currentPath);
|
||||
my $session = WebGUI::Session->open($filename);
|
||||
print "\tSetting site upgrade completed..." unless ($quiet);
|
||||
$session->setting->remove('specialState');
|
||||
$session->close();
|
||||
print "OK\n" unless ($quiet);
|
||||
}
|
||||
|
||||
if ($notRun) {
|
||||
print "\nNO UPGRADES NECESSARY\n\n" unless ($quiet);
|
||||
} else {
|
||||
unless ($quiet) {
|
||||
print <<STOP;
|
||||
print <<STOP;
|
||||
|
||||
UPGRADES COMPLETE
|
||||
Please restart your web server and test your sites.
|
||||
|
|
@ -278,111 +110,6 @@ NOTE: If you have not already done so, please consult
|
|||
docs/gotcha.txt for possible upgrade complications.
|
||||
|
||||
STOP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------
|
||||
# checkVersion($versionNumber)
|
||||
#-----------------------------------------
|
||||
# Version number must be 7.3.22 or greater
|
||||
# in order to be upgraded by this utility.
|
||||
#-----------------------------------------
|
||||
sub checkVersion {
|
||||
$_[0] =~ /(\d+)\.(\d+)\.(\d+)/;
|
||||
my $goal = 7;
|
||||
my $feature = 3;
|
||||
my $fix = 22;
|
||||
if ($1 > $goal) {
|
||||
return 1;
|
||||
}
|
||||
elsif ($1 == $goal) {
|
||||
if ($2 > $feature) {
|
||||
return 1;
|
||||
}
|
||||
elsif ($2 == $feature) {
|
||||
if ($3 >= $fix) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-----------------------------------------
|
||||
sub fatalError {
|
||||
print <<STOP;
|
||||
|
||||
The upgrade process failed and has stopped so you can either restore
|
||||
from backup, or attempt to fix the problem and continue.
|
||||
|
||||
STOP
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------
|
||||
sub _parseDSN {
|
||||
my($dsn, $args) = @_;
|
||||
my($var, $val, $hash);
|
||||
$hash = {};
|
||||
|
||||
if (!defined($dsn)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dsn =~ s/^dbi:(\w*?)(?:\((.*?)\))?://i
|
||||
or '' =~ /()/; # ensure $1 etc are empty if match fails
|
||||
$hash->{driver} = $1;
|
||||
|
||||
while (length($dsn)) {
|
||||
if ($dsn =~ /([^:;]*)[:;](.*)/) {
|
||||
$val = $1;
|
||||
$dsn = $2;
|
||||
} else {
|
||||
$val = $dsn;
|
||||
$dsn = '';
|
||||
}
|
||||
if ($val =~ /([^=]*)=(.*)/) {
|
||||
$var = $1;
|
||||
$val = $2;
|
||||
if ($var eq 'hostname' || $var eq 'host') {
|
||||
$hash->{'host'} = $val;
|
||||
} elsif ($var eq 'db' || $var eq 'dbname') {
|
||||
$hash->{'database'} = $val;
|
||||
} else {
|
||||
$hash->{$var} = $val;
|
||||
}
|
||||
} else {
|
||||
foreach $var (@$args) {
|
||||
if (!defined($hash->{$var})) {
|
||||
$hash->{$var} = $val;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub readLines {
|
||||
my $file = shift;
|
||||
my @lines;
|
||||
if (open(my $fh, '<', $file)) {
|
||||
while (my $line = <$fh>) {
|
||||
$line =~ s/#.*//;
|
||||
$line =~ s/^\s+//;
|
||||
$line =~ s/\s+$//;
|
||||
next if !$line;
|
||||
push @lines, $line;
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
return @lines;
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
|
|
@ -392,34 +119,33 @@ upgrade - Upgrade WebGUI database to the latest revision.
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
upgrade --doit
|
||||
[--backupDir path]
|
||||
[--history]
|
||||
[--mysql pathname]
|
||||
[--mysqldump pathname]
|
||||
[--override]
|
||||
[--skipBackup]
|
||||
[--skipDelete]
|
||||
[--skipMaintenance]
|
||||
[--quiet]
|
||||
upgrade --doit
|
||||
[--backupDir path]
|
||||
[--mysql pathname]
|
||||
[--mysqldump pathname]
|
||||
[--override]
|
||||
[--skipBackup]
|
||||
[--skipDelete]
|
||||
[--skipMaintenance]
|
||||
[--quiet]
|
||||
upgrade --history
|
||||
|
||||
upgrade --help
|
||||
upgrade --help
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This WebGUI utility script is able to upgrade B<any> WebGUI database
|
||||
from 7.3.22 upward to the currently installed version. The WebGUI
|
||||
software distribution includes a set of upgrade scripts that
|
||||
perform the necessary database changes (schema and data) to bring
|
||||
the database up-to-date in order to match the currently installed
|
||||
WebGUI libraries and programs.
|
||||
to the currently installed version. The WebGUI software distribution
|
||||
includes a set of upgrade scripts that perform the necessary database
|
||||
changes (schema and data) to bring the database up-to-date in order
|
||||
to match the currently installed WebGUI libraries and programs.
|
||||
|
||||
This utility is designed to be run as a superuser on Linux systems,
|
||||
since it needs to be able to access several system directories
|
||||
and change ownership of files. If you want to run this utility without
|
||||
superuser privileges, use the B<--override> option described below.
|
||||
superuser privileges, use the C<--override> option described below.
|
||||
|
||||
=head1 WARNING
|
||||
=head2 WARNING
|
||||
|
||||
There are B<NO> guarantees of any kind provided with this software.
|
||||
This utility has been tested rigorously, and has performed without
|
||||
|
|
@ -431,62 +157,64 @@ B<BEFORE YOU UPGRADE> you should definitely read docs/gotcha.txt to
|
|||
find out what things you should know about that will affect your
|
||||
upgrade.
|
||||
|
||||
=over
|
||||
=head1 OPTIONS
|
||||
|
||||
=item B<--doit>
|
||||
=over 4
|
||||
|
||||
=item C<--doit>
|
||||
|
||||
You B<MUST> include this flag in the command line or the script
|
||||
will refuse to run. This is to force you to read this documentation
|
||||
at least once and be sure that you B<REALLY> want to perform the
|
||||
upgrade.
|
||||
|
||||
=item B<--backupDir path>
|
||||
=item C<--backupDir path>
|
||||
|
||||
Specify a path where database backups should be created during the
|
||||
upgrade procedure. If left unspecified, it defaults to B</tmp/backups>.
|
||||
upgrade procedure. If left unspecified, it defaults to C</tmp/backups>.
|
||||
|
||||
=item B<--history>
|
||||
=item C<--history>
|
||||
|
||||
Displays the upgrade history for each of your sites. Running with this
|
||||
flag will B<NOT> perform the upgrade.
|
||||
|
||||
=item B<--mysql pathname>
|
||||
=item C<--mysql pathname>
|
||||
|
||||
The full pathname to your mysql client executable. If left unspecified,
|
||||
it defaults to B</usr/bin/mysql>.
|
||||
it defaults to C</usr/bin/mysql>.
|
||||
|
||||
=item B<--mysqldump pathname>
|
||||
=item C<--mysqldump pathname>
|
||||
|
||||
The full pathname to your mysqldump executable. If left unspecified,
|
||||
it defaults to B</usr/bin/mysqldump>.
|
||||
it defaults to C</usr/bin/mysqldump>.
|
||||
|
||||
=item B<--override>
|
||||
=item C<--override>
|
||||
|
||||
This flag will allow you to run this utility without being the super user,
|
||||
but note that it may not work as intended.
|
||||
|
||||
=item B<--skipBackup>
|
||||
=item C<--skipBackup>
|
||||
|
||||
Use this if you B<DO NOT> want database backups to be performed
|
||||
during the upgrade procedure.
|
||||
|
||||
=item B<--skipDelete>
|
||||
=item C<--skipDelete>
|
||||
|
||||
The upgrade procedure normally deletes WebGUI's cache and temporary files
|
||||
created as part of the upgrade. This cleanup is very important during
|
||||
large upgrades, but can make the procedure quite slow. This option
|
||||
skips the deletion of these files.
|
||||
|
||||
=item B<--skipMaintenance>
|
||||
=item C<--skipMaintenance>
|
||||
|
||||
The upgrade procedure normally puts up a simple maintenance page on all
|
||||
the sites while running, but this option will skip that step.
|
||||
|
||||
=item B<--quiet>
|
||||
=item C<--quiet>
|
||||
|
||||
Disable all output unless there's an error.
|
||||
|
||||
=item B<--help>
|
||||
=item C<--help>
|
||||
|
||||
Shows this documentation, then exits.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue