Skip to content

Commit

Permalink
Merge pull request #496 from sloanebernstein/RE-102
Browse files Browse the repository at this point in the history
Upgrade PostgreSQL during ELevate
  • Loading branch information
toddr authored Aug 21, 2024
2 parents eb218fe + 2acb77e commit 827714a
Show file tree
Hide file tree
Showing 10 changed files with 947 additions and 401 deletions.
469 changes: 362 additions & 107 deletions elevate-cpanel

Large diffs are not rendered by default.

70 changes: 0 additions & 70 deletions lib/Elevate/Blockers/Databases.pm
Original file line number Diff line number Diff line change
Expand Up @@ -27,84 +27,14 @@ use parent qw{Elevate::Blockers::Base};

use Log::Log4perl qw(:easy);

use constant POSTGRESQL_ACK_TOUCH_FILE => q[/var/cpanel/acknowledge_postgresql_for_elevate];

sub check ($self) {
my $ok = 1;
$self->_warning_if_postgresql_installed;
$ok = 0 unless $self->_blocker_acknowledge_postgresql_datadir;
$ok = 0 unless $self->_blocker_old_mysql;
$ok = 0 unless $self->_blocker_mysql_upgrade_in_progress;
$self->_warning_mysql_not_enabled();
return $ok;
}

sub _warning_if_postgresql_installed ($self) {
return 0 unless Cpanel::Pkgr::is_installed('postgresql-server');

my $pg_full_ver = Cpanel::Pkgr::get_package_version('postgresql-server');
my ($old_version) = $pg_full_ver =~ m/^(\d+\.\d+)/a;
return 1 if !$old_version || $old_version >= 10;

my $pretty_distro_name = $self->upgrade_to_pretty_name();
WARN("You have postgresql-server version $old_version installed. This will be upgraded irreversibly to version 10.0 when you switch to $pretty_distro_name");

return 2;
}

sub _blocker_acknowledge_postgresql_datadir ($self) {

return 0 unless Cpanel::Pkgr::is_installed('postgresql-server');

my $touch_file = POSTGRESQL_ACK_TOUCH_FILE;
return 0 if -e $touch_file;

my @users_with_dbs = $self->_has_mapped_postgresql_dbs();
return 0 unless scalar @users_with_dbs;

my $message = <<~"EOS";
One or more users on your system have associated PostgreSQL databases.
ELevate may upgrade the software packages associated with PostgreSQL
automatically, but if it does, it will *NOT* automatically update the
PostgreSQL data directory to work with the new version. Without an update
to the data directory, the upgraded PostgreSQL software will not start, in
order to ensure that your data does not become corrupted.
For more information about PostgreSQL upgrades, please consider the
following resources:
https://cpanel.github.io/elevate/blockers/#postgresql
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/deploying_different_types_of_servers/using-databases#migrating-to-a-rhel-8-version-of-postgresql_using-postgresql
https://www.postgresql.org/docs/10/pgupgrade.html
When you are ready to acknowledge that you have prepared to update the
PostgreSQL data directory, or that this warning does not apply to you,
please touch the following file to continue with the ELevate process:
> touch $touch_file
The following user(s) have PostgreSQL databases associated with their cPanel accounts:
EOS

$message .= join "\n", sort(@users_with_dbs);

return $self->has_blocker($message);
}

sub _has_mapped_postgresql_dbs ($self) {

my $dbindex = eval { Cpanel::DB::Map::Collection::Index->new( { db => 'PGSQL' } ); };
if ( my $exception = $@ ) {
ERROR( 'Unable to read the database index file: ' . Cpanel::Exception::get_string($exception) );
$self->has_blocker("Unable to read the database index file; you may need to rebuild it by running: /usr/local/cpanel/bin/dbindex");
return ();
}

my %user_hash = map { $dbindex->{dbindex}{$_} => 1 } keys %{ $dbindex->{dbindex} };

return ( keys %user_hash );
}

sub _blocker_old_mysql ($self) {

my $mysql_is_provided_by_cloudlinux = Elevate::Database::is_database_provided_by_cloudlinux(0);
Expand Down
114 changes: 64 additions & 50 deletions lib/Elevate/Components/CCS.pm
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ sub pre_leapp ($self) {
}

sub clean_up_pkg_cruft ($self) {
$self->move_pgsql_directory();
$self->remove_cpanel_ccs_home_directory();
return;
}
Expand All @@ -79,60 +78,12 @@ sub remove_cpanel_ccs_home_directory ($self) {
return;
}

=head1 move_pgsql_directory
Removing the PKG will leave this directory in place
This results in PostGreSQL/CCS failing to start after leapp completes
=cut

sub move_pgsql_directory ($self) {
my $pg_dir = '/var/lib/pgsql';
my $pg_backup_dir = '/var/lib/pgsql_pre_elevate';

# Remove the backup path if it exists as a directory
File::Path::remove_tree($pg_backup_dir) if -e $pg_backup_dir && -d $pg_backup_dir;

# If we were unable to remove the backup path above, then change it to something that
# should be unique
$pg_backup_dir .= '_' . time() . '_' . $$ if -e $pg_backup_dir;

# Make sure the path that should be unique does not exist
File::Path::remove_tree($pg_backup_dir) if -e $pg_backup_dir && -d $pg_backup_dir;

# Give it up if we still do not have a candidate to back the data up to
if ( -e $pg_backup_dir ) {
die <<~"EOS";
Unable to ensure a valid backup path for $pg_dir.
Please ensure that '/var/lib/pgsql_pre_elevate' does not exist on your system and execute this script again with
/scripts/elevate-cpanel --continue
EOS
}

INFO( <<~"EOS" );
Moving the PostgreSQL data dir located at $pg_dir to $pg_backup_dir
to ensure a functioning PostgreSQL server after the elevation completes.
EOS

File::Copy::move( $pg_dir, $pg_backup_dir ) if -d $pg_dir;

return;
}

sub remove_ccs_and_dependencies ($self) {

my $zpush_installed = Cpanel::Pkgr::is_installed(ZPUSH_PACKAGE);
Elevate::StageFile::update_stage_file( { zpush_installed => $zpush_installed } );

# There are other dependencies but these are the 3 that we are concerned with
my @ccs_dependencies = qw{
postgresql
postgresql-devel
postgresql-server
};

my @ccs_dependencies;
push @ccs_dependencies, ZPUSH_PACKAGE();

$self->yum->remove( CCS_PACKAGE(), @ccs_dependencies );
Expand Down Expand Up @@ -324,6 +275,8 @@ sub _ensure_export_directory ($self) {
sub post_leapp ($self) {
return unless Elevate::StageFile::read_stage_file('ccs_installed');

$self->run_once('move_pgsql_directory');

$self->_install_ccs_and_dependencies();

# This needs to happen before verifying that the service is up
Expand All @@ -334,6 +287,8 @@ sub post_leapp ($self) {
$self->_ensure_ccs_service_is_up();
$self->run_once('import_ccs_data');

$self->move_pgsql_directory_back();

return;
}

Expand Down Expand Up @@ -458,4 +413,63 @@ sub _import_data_for_single_user ( $self, $user ) {
return;
}

=head1 move_pgsql_directory
Because CCS re-uses scripts originally intended for use with the system
Postgres, leaving the system Postgres data directory in place sometimes results
in failure to apply schema updates to CCS, causing failures in importing user
data. This is technically a bug in CCS, but we will not be issuing a fix for
that. Instead, when needed, the system Postgres database shall be moved aside,
ensuring that all and only CCS processes apply to that instance of Postgres.
=cut

sub move_pgsql_directory ($self) {
my $pg_dir = '/var/lib/pgsql';
my $pg_backup_dir = '/var/lib/pgsql_pre_elevate';

return unless -d $pg_dir;

# Remove the backup path if it exists as a directory
File::Path::remove_tree($pg_backup_dir) if -e $pg_backup_dir && -d $pg_backup_dir;

INFO( <<~"EOS" );
Temporarily moving the PostgreSQL data dir located at $pg_dir to $pg_backup_dir
due to issues with the CCS upgrade process. This script will attempt to move the directory
back to $pg_dir after CCS is upgraded.
EOS

# Using rename instead of File::Copy::move, because allowing copy+delete behavior introduces too many points of failure:
my $success = rename( $pg_dir, $pg_backup_dir );
LOGDIE(qq[The system failed to move $pg_dir to $pg_backup_dir (reason: $!)!]) unless $success;

return;
}

sub move_pgsql_directory_back ($self) {
my $pg_dir = '/var/lib/pgsql';
my $pg_backup_dir = '/var/lib/pgsql_pre_elevate';

return unless -e $pg_backup_dir;

INFO(qq[Restoring system PostgreSQL instance...]);

Elevate::SystemctlService->new( name => 'postgresql' )->stop(); # just in case
File::Path::remove_tree($pg_dir) if -e $pg_dir;

my $result = rename( $pg_backup_dir, $pg_dir );
if ( !$result ) {
my $msg = <<~"EOS";
The system could not fully restore $pg_backup_dir to $pg_dir (reason: $!).
Restore this manually, and perform the update as recommended.
EOS

LOGDIE($msg);
return;
}

INFO(qq[The system returned the PostgreSQL data directory to $pg_dir.]);
return;
}

1;
Loading

0 comments on commit 827714a

Please sign in to comment.