# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::System::Console::Command::Maint::Daemon::Summary;
use strict;
use warnings;
use Kernel::System::VariableCheck qw(IsArrayRefWithData);
use parent qw(Kernel::System::Console::BaseCommand);
our @ObjectDependencies = (
'Kernel::Config',
);
sub Configure {
my ( $Self, %Param ) = @_;
$Self->Description('Show a summary of one or all daemon modules.');
$Self->AddArgument(
Name => 'daemon-name',
Description => "The name of a registered daemon.",
Required => 0,
ValueRegex => qr/.*/smx,
);
$Self->AdditionalHelp(<<"EOF");
If no daemon-name is specified as:
otrs.console.pl $Self->{Name}
The command will get the summary of all daemon modules available.
EOF
return;
}
sub PreRun {
my ( $Self, %Param ) = @_;
my $DaemonName = $Self->GetArgument('daemon-name');
# do checks only if a particular daemon module is specified
if ($DaemonName) {
my $DaemonModuleConfig = $Kernel::OM->Get('Kernel::Config')->Get('DaemonModules') || {};
# check if configuration of the daemon is valid
if (
!$DaemonModuleConfig->{$DaemonName}
|| ref $DaemonModuleConfig->{$DaemonName} ne 'HASH'
|| !$DaemonModuleConfig->{$DaemonName}->{Module}
)
{
die "Daemon $DaemonName configuration is invalid";
}
my $DaemonObject;
# create daemon object
eval {
$DaemonObject = $Kernel::OM->Get( $DaemonModuleConfig->{$DaemonName}->{Module} );
};
# check if daemon object is valid
if ( !$DaemonObject || !$DaemonObject->can("Summary") ) {
die "Daemon $DaemonName is invalid";
}
}
return;
}
sub Run {
my ( $Self, %Param ) = @_;
my $DaemonName = $Self->GetArgument('daemon-name');
if ($DaemonName) {
$Self->Print("\nGathering summary for '$DaemonName'...\n\n");
}
else {
$Self->Print("\nGathering summary for all daemons...\n\n");
}
# get daemon modules from SysConfig
my $DaemonModuleConfig = $Kernel::OM->Get('Kernel::Config')->Get('DaemonModules') || {};
my @DaemonSummary;
MODULE:
for my $Module ( sort _DaemonSort keys %{$DaemonModuleConfig} ) {
# skip not well configured modules
next MODULE if !$Module;
next MODULE if !$DaemonModuleConfig->{$Module};
next MODULE if ref $DaemonModuleConfig->{$Module} ne 'HASH';
next MODULE if !$DaemonModuleConfig->{$Module}->{Module};
# if a module is specified skip all others
if ($DaemonName) {
next MODULE if $Module ne $DaemonName;
}
my $DaemonObject;
# create daemon object
eval {
$DaemonObject = $Kernel::OM->Get( $DaemonModuleConfig->{$Module}->{Module} );
};
# skip module if object could not be created or does not provide Summary()
next MODULE if !$DaemonObject;
next MODULE if !$DaemonObject->can("Summary");
# execute Summary
my @Summary;
eval {
@Summary = $DaemonObject->Summary();
};
# skip if the result is empty or in a wrong format;
next MODULE if !@Summary;
next MODULE if ref $Summary[0] ne 'HASH';
for my $SummaryItem (@Summary) {
push @DaemonSummary, $SummaryItem;
}
# if a module was specified skip all the rest
if ($DaemonName) {
last MODULE;
}
}
my $Output = $Self->_FormatOutput(
DaemonSummary => \@DaemonSummary,
);
$Self->Print("$Output");
$Self->Print("Done.\n");
return $Self->ExitCodeOk();
}
sub _FormatOutput {
my ( $Self, %Param ) = @_;
my @DaemonSummary = @{ $Param{DaemonSummary} };
my $Output;
SUMMARY:
for my $Summary (@DaemonSummary) {
# set header message
$Output .= ' ' . $Summary->{Header} . "\n";
# if there is no data to display, show empty message
if ( !IsArrayRefWithData( $Summary->{Data} ) ) {
$Output .= ' ' . ( $Summary->{NoDataMessage} || '' ) . "\n\n";
next SUMMARY;
}
my @TableHeader;
my @TableBody;
# generate table header
for my $Column ( @{ $Summary->{Column} } ) {
push @TableHeader, $Column->{DisplayName};
}
# generate table body
for my $DataRow ( @{ $Summary->{Data} } ) {
my @BodyRow;
for my $Column ( @{ $Summary->{Column} } ) {
my $Value = $DataRow->{ $Column->{Name} } // '';
if ( $Value eq 'Success' ) {
$Value = "$Value";
}
elsif ( $Value eq 'N/A' ) {
$Value = "$Value";
}
elsif ( $Value eq 'Fail' ) {
$Value = "$Value";
}
push @BodyRow, $Value;
}
push @TableBody, \@BodyRow;
}
my $TableOutput = $Self->TableOutput(
TableData => {
Header => \@TableHeader,
Body => \@TableBody,
},
Indention => 2,
);
$Output .= "$TableOutput\n";
}
return $Output // '';
}
sub _DaemonSort {
my %DefaultDaemons = (
SchedulerFutureTaskManager => 100,
SchedulerCronTaskManager => 110,
SchedulerGenericAgentTaskManager => 111,
SchedulerTaskWorker => 112,
);
# other daemons could not be in the DefaultDaemons sorting hash
# when comparing 2 external daemons sorting must be alphabetical
if ( !$DefaultDaemons{$a} && !$DefaultDaemons{$b} ) {
return $a cmp $b;
}
# when another daemon is compares to a framework one it must be lower
elsif ( !$DefaultDaemons{$a} ) {
return -1;
}
# when a framework daemon is compared to another one it must be higher
elsif ( !$DefaultDaemons{$b} ) {
return 1;
}
# otherwise do a numerical comparison with the framework daemons
return $DefaultDaemons{$a} <=> $DefaultDaemons{$b};
}
1;