Skip to content

Commit

Permalink
Merge pull request #483 from troglodyne/RE-34
Browse files Browse the repository at this point in the history
RE-34: Unblock the Elevate Blocker when remote MySQL is enabled by disabling remote Mysql during upgrade
  • Loading branch information
toddr authored Aug 6, 2024
2 parents e70ed7e + cb3d98a commit 11f8db1
Show file tree
Hide file tree
Showing 6 changed files with 625 additions and 90 deletions.
199 changes: 170 additions & 29 deletions elevate-cpanel
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,6 @@ BEGIN { # Suppress load of all of these at earliest point.
use Cpanel::SafeRun::Simple ();
use Cpanel::DB::Map::Collection::Index ();
use Cpanel::Exception ();
use Cpanel::MysqlUtils::MyCnf::Basic ();

# use Elevate::Blockers::Base();
our @ISA;
Expand All @@ -619,7 +618,6 @@ BEGIN { # Suppress load of all of these at earliest point.
my $ok = 1;
$self->_warning_if_postgresql_installed;
$ok = 0 unless $self->_blocker_acknowledge_postgresql_datadir;
$ok = 0 unless $self->_blocker_remote_mysql;
$ok = 0 unless $self->_blocker_old_mysql;
$ok = 0 unless $self->_blocker_mysql_upgrade_in_progress;
$self->_warning_mysql_not_enabled();
Expand Down Expand Up @@ -692,21 +690,6 @@ BEGIN { # Suppress load of all of these at earliest point.
return ( keys %user_hash );
}

sub _blocker_remote_mysql ($self) {

my $pretty_distro_name = $self->upgrade_to_pretty_name();

if ( Cpanel::MysqlUtils::MyCnf::Basic::is_remote_mysql() ) {
return $self->has_blocker( <<~"EOS" );
The system is currently setup to use a remote database server.
We cannot elevate the system to $pretty_distro_name
unless the system is configured to use the local database server.
EOS
}

return 0;
}

sub _blocker_old_mysql ($self) {

my $mysql_is_provided_by_cloudlinux = Elevate::Database::is_database_provided_by_cloudlinux(0);
Expand Down Expand Up @@ -5580,13 +5563,29 @@ EOS
our @ISA;
BEGIN { push @ISA, qw(Elevate::Components::Base); }

use Cpanel::MysqlUtils::RemoteMySQL::ProfileManager ();

use File::Slurper;
use Try::Tiny;

use Cpanel::MysqlUtils::MyCnf::Basic ();
use Cpanel::MysqlUtils::RemoteMySQL::ProfileManager ();
use Cpanel::PasswdStrength::Generate ();
use Cpanel::JSON ();
use Cpanel::SafeRun::Simple ();
use Cpanel::Encoder::URI ();

use constant MYSQL_PROFILE_FILE => '/var/cpanel/elevate-mysql-profile';

# use Log::Log4perl qw(:easy);
INIT { Log::Log4perl->import(qw{:easy}); }

sub pre_leapp ($self) {

return if Elevate::Database::is_database_provided_by_cloudlinux();

$self->_ensure_localhost_mysql_profile_is_active(1);

return if Elevate::Database::is_database_version_supported( Elevate::Database::get_local_database_version() );

Elevate::Database::upgrade_database_server();
Expand All @@ -5595,6 +5594,147 @@ EOS
}

sub post_leapp ($self) {
return unless -e MYSQL_PROFILE_FILE;

my $original_profile = File::Slurper::read_text(MYSQL_PROFILE_FILE) // 'localhost';
INFO(qq{Reactivating "$original_profile" MySQL profile});

my $output = $self->ssystem_capture_output( '/usr/local/cpanel/scripts/manage_mysql_profiles', '--activate', "$original_profile" );
my $stdout = join qq{\n}, @{ $output->{'stdout'} };

unless ( $stdout =~ m{MySQL profile activation done} ) {
die <<~"EOS";
Unable to reactivate the original remote MySQL profile "$original_profile":
$stdout
Please resolve the reported problems then run this script again with:
/scripts/elevate-cpanel --continue
EOS
}

unlink MYSQL_PROFILE_FILE or WARN( "Could not delete " . MYSQL_PROFILE_FILE . ": $!" );

return;
}

sub _ensure_localhost_mysql_profile_is_active ( $self, $should_create_localhost_profile ) {
return if Cpanel::MysqlUtils::MyCnf::Basic::is_local_mysql();

my $profile_manager = Cpanel::MysqlUtils::RemoteMySQL::ProfileManager->new();

my $profile = $profile_manager->get_active_profile('dont_die') || 'localhost';
if ($should_create_localhost_profile) {
INFO( "Saving the currently active MySQL Profile ($profile) to " . MYSQL_PROFILE_FILE );
File::Slurper::write_text( MYSQL_PROFILE_FILE, $profile );
}

try {
$profile_manager->validate_profile('localhost');
$self->_activate_localhost_profile($profile_manager);
}

catch {
die "Unable to generate/enable localhost MySQL profile: $_\n" unless $should_create_localhost_profile;
INFO("Attempting to create new localhost MySQL profile...");
$self->_create_new_localhost_profile($profile_manager);
$self->_ensure_localhost_mysql_profile_is_active(0);
};

return;
}

sub _create_new_localhost_profile ( $self, $profile_manager ) {

my $password = Cpanel::PasswdStrength::Generate::generate_password( 16, no_othersymbols => 1 );

try {
$profile_manager->create_profile(
{
'name' => 'localhost',
'mysql_user' => 'root',
'mysql_pass' => $password,
'mysql_host' => 'localhost',
'mysql_port' => Cpanel::MysqlUtils::MyCnf::Basic::getmydbport('root') || 3306,
'setup_via' => 'Auto-generated localhost profile during elevate.',
},
{ 'overwrite' => 1 },
);
}
catch {
die <<~"EOS";
Unable to generate a functioning MySQL DB profile for the local MySQL server.
The following error was encountered:
$@
EOS
};

$self->_set_local_mysql_root_password($password);

$profile_manager->save_changes_to_disk();

$self->_activate_localhost_profile($profile_manager);

return;
}

sub _set_local_mysql_root_password ( $self, $password ) {
INFO("Resetting password for local root MySQL user...");

my $encoded_password = Cpanel::Encoder::URI::uri_encode_str($password);

my $output = Cpanel::SafeRun::Simple::saferunnoerror( q{/bin/sh}, q{-c}, qq{/usr/local/cpanel/bin/whmapi1 --output=json set_local_mysql_root_password password='$encoded_password'} );
my $result = eval { Cpanel::JSON::Load($output); } // {};

unless ( $result->{metadata}{result} ) {

my $errors = join qq{\n\n}, @{ $result->{'metadata'}{'errors'} };

die <<~"EOS";
Unable to set root password for the localhost MySQL server.
The following errors occurred:
$errors
Please resolve the reported problems then run this script again with:
/scripts/elevate-cpanel --continue
EOS
}

return;
}

sub _activate_localhost_profile {
my ( $self, $profile_manager ) = @_;

if ($profile_manager) {
$profile_manager->{'_transaction_obj'}->close_or_die();
}

INFO("Activating “localhost” MySQL profile");

my $output = $self->ssystem_capture_output(qw{/usr/local/cpanel/scripts/manage_mysql_profiles --activate localhost});
my $stdout = join qq{\n}, @{ $output->{'stdout'} };

if ( $stdout !~ m{MySQL profile activation done} ) {
die <<~"EOS";
Unable to activate a MySQL DB profile for "localhost":
$stdout
Please resolve the reported problems then run this script again with:
/scripts/elevate-cpanel --continue
EOS
}

return;
}
Expand Down Expand Up @@ -9358,18 +9498,19 @@ sub post_leapp_update_restore ($self) {
}

# plugins can use MySQL - restore database earlier
$self->run_component_once( 'MySQL' => 'post_leapp' );
$self->run_component_once( 'PerlXS' => 'post_leapp' );
$self->run_component_once( 'cPanelPlugins' => 'post_leapp' );
$self->run_component_once( 'PECL' => 'post_leapp' );
$self->run_component_once( 'WPToolkit' => 'post_leapp' );
$self->run_component_once( 'InfluxDB' => 'post_leapp' );
$self->run_component_once( 'JetBackup' => 'post_leapp' );
$self->run_component_once( 'Kernel' => 'post_leapp' );
$self->run_component_once( 'KernelCare' => 'post_leapp' );
$self->run_component_once( 'NixStats' => 'post_leapp' );
$self->run_component_once( 'LiteSpeed' => 'post_leapp' );
$self->run_component_once( 'R1Soft' => 'post_leapp' );
$self->run_component_once( 'MySQL' => 'post_leapp' );
$self->run_component_once( 'PerlXS' => 'post_leapp' );
$self->run_component_once( 'cPanelPlugins' => 'post_leapp' );
$self->run_component_once( 'DatabaseUpgrade' => 'post_leapp' );
$self->run_component_once( 'PECL' => 'post_leapp' );
$self->run_component_once( 'WPToolkit' => 'post_leapp' );
$self->run_component_once( 'InfluxDB' => 'post_leapp' );
$self->run_component_once( 'JetBackup' => 'post_leapp' );
$self->run_component_once( 'Kernel' => 'post_leapp' );
$self->run_component_once( 'KernelCare' => 'post_leapp' );
$self->run_component_once( 'NixStats' => 'post_leapp' );
$self->run_component_once( 'LiteSpeed' => 'post_leapp' );
$self->run_component_once( 'R1Soft' => 'post_leapp' );

return;
}
Expand Down
19 changes: 0 additions & 19 deletions lib/Elevate/Blockers/Databases.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use Cpanel::JSON ();
use Cpanel::SafeRun::Simple ();
use Cpanel::DB::Map::Collection::Index ();
use Cpanel::Exception ();
use Cpanel::MysqlUtils::MyCnf::Basic ();

use parent qw{Elevate::Blockers::Base};

Expand All @@ -34,7 +33,6 @@ sub check ($self) {
my $ok = 1;
$self->_warning_if_postgresql_installed;
$ok = 0 unless $self->_blocker_acknowledge_postgresql_datadir;
$ok = 0 unless $self->_blocker_remote_mysql;
$ok = 0 unless $self->_blocker_old_mysql;
$ok = 0 unless $self->_blocker_mysql_upgrade_in_progress;
$self->_warning_mysql_not_enabled();
Expand Down Expand Up @@ -107,23 +105,6 @@ sub _has_mapped_postgresql_dbs ($self) {
return ( keys %user_hash );
}

sub _blocker_remote_mysql ($self) {

my $pretty_distro_name = $self->upgrade_to_pretty_name();

# If we are setup to use remote MySQL, then attempting an upgrade will fail
# TODO: Temporarily disable remote MySQL to allow the database upgrade
if ( Cpanel::MysqlUtils::MyCnf::Basic::is_remote_mysql() ) {
return $self->has_blocker( <<~"EOS" );
The system is currently setup to use a remote database server.
We cannot elevate the system to $pretty_distro_name
unless the system is configured to use the local database server.
EOS
}

return 0;
}

sub _blocker_old_mysql ($self) {

my $mysql_is_provided_by_cloudlinux = Elevate::Database::is_database_provided_by_cloudlinux(0);
Expand Down
Loading

0 comments on commit 11f8db1

Please sign in to comment.