Skip to content

Commit

Permalink
Unblock remote MySQL blocker by temporarily disabling during upgrade.
Browse files Browse the repository at this point in the history
Case RE-34:

Changelog: Unblock remote MySQL blocker by temporarily disabling the
 remote profile during the upgrade.
  • Loading branch information
Stephen Bee authored and troglodyne committed Jul 25, 2024
1 parent 5294d94 commit 5ef8705
Show file tree
Hide file tree
Showing 6 changed files with 610 additions and 88 deletions.
203 changes: 175 additions & 28 deletions elevate-cpanel
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,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 @@ -607,7 +606,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 @@ -680,21 +678,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 @@ -5456,6 +5439,20 @@ 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}); }

Expand All @@ -5465,13 +5462,161 @@ EOS

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

$self->_ensure_localhost_mysql_profile_is_active(1);

Elevate::Database::upgrade_database_server();

return;
}

sub post_leapp ($self) {

if ( -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;
}

return;
}

sub _ensure_localhost_mysql_profile_is_active ( $self, $should_create_localhost_profile ) {

if ( Cpanel::MysqlUtils::MyCnf::Basic::is_local_mysql() ) {
return;
}

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

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

catch {
if ($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);
}
else {
die "Unable to generate/enable localhost MySQL profile: $_\n";
}
};

return;
}

sub _create_new_localhost_profile ( $self, $profile_manager ) {

my $active_profile = $profile_manager->get_active_profile('dont_die');
File::Slurper::write_text( MYSQL_PROFILE_FILE, $active_profile );

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 @@ -9065,17 +9210,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( 'MySQL' => 'post_leapp' );
$self->run_component_once( 'PerlXS' => 'post_leapp' );
$self->run_component_once( 'DatabaseUpgrade' => '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( 'Imunify' => 'post_leapp' );
$self->run_component_once( 'NixStats' => 'post_leapp' );
$self->run_component_once( 'LiteSpeed' => '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 5ef8705

Please sign in to comment.