Skip to content

Commit

Permalink
Move logic to gather and store php usage to a component
Browse files Browse the repository at this point in the history
Case RE-611: With the changes to the logic to support Imunify 360 on
CentOS 7, it was found that sites using older hardened PHP versions no
longer had the correct version of PHP set after elevate completed.  This
was because the changes to the Imunify 360 logic made it so that the
code path that gathered and stored this information was no longer
reachable.  As such, this logic has been refactored to only check for
PHP versions that would otherwise be dropped after the upgrade to
AlmaLinux 8 that are not in use and the logic to gather and store the
current PHP usage has been moved to the EA4 component so that it always
gets executed and thus the logic to set the PHP version after the
elevation will always get executed now too.

Changelog: Move logic to gather and store php usage to a component
  • Loading branch information
cPholloway committed Aug 6, 2024
1 parent b569eac commit 7e80a15
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 68 deletions.
91 changes: 61 additions & 30 deletions elevate-cpanel
Original file line number Diff line number Diff line change
Expand Up @@ -1114,43 +1114,30 @@ EOS
}

sub _php_version_is_in_use ( $self, $php ) {
my $current_php_usage = $self->_get_php_versions_in_use();
my $current_php_usage = $self->_get_php_usage();

return 1 if $current_php_usage->{api_fail};

return $current_php_usage->{$php} ? 1 : 0;
}

our $php_versions_in_use;
our $php_usage;

sub _get_php_versions_in_use ($self) {
return $php_versions_in_use if defined $php_versions_in_use && ref $php_versions_in_use eq 'HASH';
sub _get_php_usage ($self) {
return $php_usage if defined $php_usage && ref $php_usage eq 'HASH';

my $out = Cpanel::SafeRun::Simple::saferunnoerror(qw{/usr/local/cpanel/bin/whmapi1 --output=json php_get_vhost_versions});
my $result = eval { Cpanel::JSON::Load($out); } // {};

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

WARN( <<~"EOS" );
Unable to determine if PHP versions that will be dropped are in use by
a domain. Assuming that they are in use and blocking to be safe.
EOS

$php_versions_in_use->{api_fail} = 1;
return $php_versions_in_use;
my $php_get_vhost_versions = Elevate::EA4::php_get_vhost_versions();
if ( !defined $php_get_vhost_versions ) {
$php_usage->{api_fail} = 1;
return $php_usage;
}

my $data = $result->{data}{versions};
Elevate::StageFile::remove_from_stage_file('php_get_vhost_versions');
Elevate::StageFile::update_stage_file( { php_get_vhost_versions => $data } );

foreach my $domain_info (@$data) {
foreach my $domain_info (@$php_get_vhost_versions) {
my $php_version = $domain_info->{version};
$php_versions_in_use->{$php_version} = 1;
$php_usage->{$php_version} = 1;
}

return $php_versions_in_use;
return $php_usage;
}

1;
Expand Down Expand Up @@ -3358,12 +3345,15 @@ EOS
our @ISA;
BEGIN { push @ISA, qw(Elevate::Components::Base); }

sub pre_leapp ($self) { # run to perform the backup

sub pre_imunify ($self) {
$self->run_once('_gather_php_usage');
$self->run_once('_backup_ea4_profile');
$self->run_once('_backup_config_files');
$self->run_once('_cleanup_rpm_db');
return;
}

sub pre_leapp ($self) {
$self->run_once('_cleanup_rpm_db');
return;
}

Expand Down Expand Up @@ -3516,6 +3506,13 @@ EOS
return;
}

sub _gather_php_usage ($self) {
my $php_get_vhost_versions = Elevate::EA4::php_get_vhost_versions();
Elevate::StageFile::remove_from_stage_file('php_get_vhost_versions');
Elevate::StageFile::update_stage_file( { php_get_vhost_versions => $php_get_vhost_versions } );
return;
}

1;

} # --- END lib/Elevate/Components/EA4.pm
Expand Down Expand Up @@ -6348,6 +6345,29 @@ EOS
return;
}

my $php_get_vhost_versions;

sub php_get_vhost_versions () {
return $php_get_vhost_versions if defined $php_get_vhost_versions && ref $php_get_vhost_versions eq 'HASH';

my $out = Cpanel::SafeRun::Simple::saferunnoerror(qw{/usr/local/cpanel/bin/whmapi1 --output=json php_get_vhost_versions});
my $result = eval { Cpanel::JSON::Load($out); } // {};

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

WARN( <<~"EOS" );
The php_get_vhost_versions API call failed. Unable to determine current
PHP usage by domain.
EOS

return;
}

my $php_get_vhost_versions = $result->{data}{versions};
return $php_get_vhost_versions;
}

1;

} # --- END lib/Elevate/EA4.pm
Expand Down Expand Up @@ -8988,6 +9008,20 @@ sub run_stage_2 ($self) {
$self->run_component_once( 'Grub2' => 'pre_leapp' );
$self->run_component_once( 'NICs' => 'pre_leapp' );

# Imunify depends on EA4 so the Imunify component needs to
# run before EA4 is removed. However, Imunify 360 can provide
# hardened PHP so the EA4 profile backup needs to run before
# Imunify is removed, so I split some of the EA4 logic out
# to be executed before Imunify and left the removal until
# after Imunify
$self->run_component_once( 'EA4' => 'pre_imunify' );
$self->run_component_once( 'Imunify' => 'pre_leapp' );
$self->run_component_once( 'PECL' => 'pre_leapp' );
$self->run_component_once( 'EA4' => 'pre_leapp' );

# This reboot will invalidate the cPanel license causing
# further whmapi1 calls to fail until stage 4
# if the NICs need to be renamed
return ACTION_REBOOT_NEEDED;
}

Expand Down Expand Up @@ -9320,9 +9354,6 @@ sub run_final_components_pre_leapp ($self) {

# order matters
$self->run_component_once( 'RmMod' => 'pre_leapp' );
$self->run_component_once( 'Imunify' => 'pre_leapp' );
$self->run_component_once( 'PECL' => 'pre_leapp' );
$self->run_component_once( 'EA4' => 'pre_leapp' );
$self->run_component_once( 'MySQL' => 'pre_leapp' );
$self->run_component_once( 'Repositories' => 'pre_leapp' );
$self->run_component_once( 'cPanelPlugins' => 'pre_leapp' );
Expand Down
35 changes: 11 additions & 24 deletions lib/Elevate/Blockers/EA4.pm
Original file line number Diff line number Diff line change
Expand Up @@ -84,44 +84,31 @@ sub _get_incompatible_packages ($self) {
}

sub _php_version_is_in_use ( $self, $php ) {
my $current_php_usage = $self->_get_php_versions_in_use();
my $current_php_usage = $self->_get_php_usage();

# Always return true if the api call failed
return 1 if $current_php_usage->{api_fail};

return $current_php_usage->{$php} ? 1 : 0;
}

our $php_versions_in_use;
our $php_usage;

sub _get_php_versions_in_use ($self) {
return $php_versions_in_use if defined $php_versions_in_use && ref $php_versions_in_use eq 'HASH';
sub _get_php_usage ($self) {
return $php_usage if defined $php_usage && ref $php_usage eq 'HASH';

my $out = Cpanel::SafeRun::Simple::saferunnoerror(qw{/usr/local/cpanel/bin/whmapi1 --output=json php_get_vhost_versions});
my $result = eval { Cpanel::JSON::Load($out); } // {};

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

WARN( <<~"EOS" );
Unable to determine if PHP versions that will be dropped are in use by
a domain. Assuming that they are in use and blocking to be safe.
EOS

$php_versions_in_use->{api_fail} = 1;
return $php_versions_in_use;
my $php_get_vhost_versions = Elevate::EA4::php_get_vhost_versions();
if ( !defined $php_get_vhost_versions ) {
$php_usage->{api_fail} = 1;
return $php_usage;
}

my $data = $result->{data}{versions};
Elevate::StageFile::remove_from_stage_file('php_get_vhost_versions');
Elevate::StageFile::update_stage_file( { php_get_vhost_versions => $data } );

foreach my $domain_info (@$data) {
foreach my $domain_info (@$php_get_vhost_versions) {
my $php_version = $domain_info->{version};
$php_versions_in_use->{$php_version} = 1;
$php_usage->{$php_version} = 1;
}

return $php_versions_in_use;
return $php_usage;
}

1;
16 changes: 13 additions & 3 deletions lib/Elevate/Components/EA4.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ use Log::Log4perl qw(:easy);

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

sub pre_leapp ($self) { # run to perform the backup

sub pre_imunify ($self) {
$self->run_once('_gather_php_usage');
$self->run_once('_backup_ea4_profile');
$self->run_once('_backup_config_files');
$self->run_once('_cleanup_rpm_db');
return;
}

sub pre_leapp ($self) {
$self->run_once('_cleanup_rpm_db');
return;
}

Expand Down Expand Up @@ -193,4 +196,11 @@ sub _ensure_sites_use_correct_php_version ($self) {
return;
}

sub _gather_php_usage ($self) {
my $php_get_vhost_versions = Elevate::EA4::php_get_vhost_versions();
Elevate::StageFile::remove_from_stage_file('php_get_vhost_versions');
Elevate::StageFile::update_stage_file( { php_get_vhost_versions => $php_get_vhost_versions } );
return;
}

1;
23 changes: 23 additions & 0 deletions lib/Elevate/EA4.pm
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,27 @@ sub _backup_ea_addons () {
return;
}

my $php_get_vhost_versions;

sub php_get_vhost_versions () {
return $php_get_vhost_versions if defined $php_get_vhost_versions && ref $php_get_vhost_versions eq 'HASH';

my $out = Cpanel::SafeRun::Simple::saferunnoerror(qw{/usr/local/cpanel/bin/whmapi1 --output=json php_get_vhost_versions});
my $result = eval { Cpanel::JSON::Load($out); } // {};

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

WARN( <<~"EOS" );
The php_get_vhost_versions API call failed. Unable to determine current
PHP usage by domain.
EOS

return;
}

my $php_get_vhost_versions = $result->{data}{versions};
return $php_get_vhost_versions;
}

1;
17 changes: 14 additions & 3 deletions script/elevate-cpanel.PL
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,20 @@ sub run_stage_2 ($self) {
$self->run_component_once( 'Grub2' => 'pre_leapp' );
$self->run_component_once( 'NICs' => 'pre_leapp' );

# Imunify depends on EA4 so the Imunify component needs to
# run before EA4 is removed. However, Imunify 360 can provide
# hardened PHP so the EA4 profile backup needs to run before
# Imunify is removed, so I split some of the EA4 logic out
# to be executed before Imunify and left the removal until
# after Imunify
$self->run_component_once( 'EA4' => 'pre_imunify' );
$self->run_component_once( 'Imunify' => 'pre_leapp' );
$self->run_component_once( 'PECL' => 'pre_leapp' );
$self->run_component_once( 'EA4' => 'pre_leapp' );

# This reboot will invalidate the cPanel license causing
# further whmapi1 calls to fail until stage 4
# if the NICs need to be renamed
return ACTION_REBOOT_NEEDED;
}

Expand Down Expand Up @@ -1305,9 +1319,6 @@ sub run_final_components_pre_leapp ($self) {

# order matters
$self->run_component_once( 'RmMod' => 'pre_leapp' );
$self->run_component_once( 'Imunify' => 'pre_leapp' );
$self->run_component_once( 'PECL' => 'pre_leapp' );
$self->run_component_once( 'EA4' => 'pre_leapp' );
$self->run_component_once( 'MySQL' => 'pre_leapp' );
$self->run_component_once( 'Repositories' => 'pre_leapp' );
$self->run_component_once( 'cPanelPlugins' => 'pre_leapp' );
Expand Down
16 changes: 8 additions & 8 deletions t/blocker-ea4.t
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Please remove these packages before continuing the update.
$mock_ea4->unmock('_php_version_is_in_use');

$mock_ea4->redefine(
_get_php_versions_in_use => sub ($self) {
_get_php_usage => sub ($self) {
return {
api_fail => 1,
};
Expand All @@ -217,7 +217,7 @@ Please remove these packages before continuing the update.

my $is_installed = 1;
$mock_ea4->redefine(
_get_php_versions_in_use => sub ($self) {
_get_php_usage => sub ($self) {
return {
'ea-php42' => $is_installed,
};
Expand All @@ -234,7 +234,7 @@ Please remove these packages before continuing the update.
{
note 'Testing _get_php_versions_in_use';

$mock_ea4->unmock('_get_php_versions_in_use');
$mock_ea4->unmock('_get_php_usage');

my $mock_result = 'nope';
my @saferun_calls;
Expand All @@ -252,16 +252,16 @@ Please remove these packages before continuing the update.
remove_from_stage_file => 1,
);

is( $ea4->_get_php_versions_in_use(), { api_fail => 1, }, 'api_fail is set when the API call does not return valid JSON' );
is( $ea4->_get_php_usage(), { api_fail => 1, }, 'api_fail is set when the API call does not return valid JSON' );

is( \@saferun_calls, [qw{/usr/local/cpanel/bin/whmapi1 --output=json php_get_vhost_versions}], 'The expected API call is made' );

message_seen( WARN => qr/Unable to determine if PHP versions that will be dropped are in use/ );
message_seen( WARN => qr/The php_get_vhost_versions API call failed/ );

$ea4->_get_php_versions_in_use();
$ea4->_get_php_usage();
is( \@saferun_calls, [qw{/usr/local/cpanel/bin/whmapi1 --output=json php_get_vhost_versions}], 'The API call is only made one time' );

local $Elevate::Blockers::EA4::php_versions_in_use = undef;
local $Elevate::Blockers::EA4::php_usage = undef;
$mock_result = {
metadata => {
result => 1,
Expand All @@ -284,7 +284,7 @@ Please remove these packages before continuing the update.
$mock_result = Cpanel::JSON::Dump($mock_result);

is(
$ea4->_get_php_versions_in_use(),
$ea4->_get_php_usage(),
{
'ea-php1' => 1,
'ea-php2' => 1,
Expand Down

0 comments on commit 7e80a15

Please sign in to comment.