diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 2f579d46f1..6a65e22674 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.740-191113 +Version: 7.0NG.740-191118 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 74a6e96001..775e895a8e 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.740-191113" +pandora_version="7.0NG.740-191118" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 0dfcf8848a..1423f42e01 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -55,7 +55,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.740'; -use constant AGENT_BUILD => '191113'; +use constant AGENT_BUILD => '191118'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; @@ -296,6 +296,77 @@ sub load_libraries() { } } +################################################################################ +# Erase blank spaces before and after the string +################################################################################ +sub trim { + my $string = shift; + if (empty($string)){ + return ""; + } + + $string =~ s/\r//g; + + chomp($string); + $string =~ s/^\s+//g; + $string =~ s/\s+$//g; + + return $string; +} + +################################################################################ +# Mix hashses +################################################################################ +sub merge_hashes { + my $_h1 = shift; + my $_h2 = shift; + + if (ref($_h1) ne "HASH") { + return \%{$_h2} if (ref($_h2) eq "HASH"); + } + + if (ref($_h2) ne "HASH") { + return \%{$_h1} if (ref($_h1) eq "HASH"); + } + + if ((ref($_h1) ne "HASH") && (ref($_h2) ne "HASH")) { + return {}; + } + + my %ret = (%{$_h1}, %{$_h2}); + + return \%ret; +} + +################################################################################ +# Empty +################################################################################ +sub empty { + my $str = shift; + + if (!(defined($str)) ){ + return 1; + } + + if(looks_like_number($str)){ + return 0; + } + + if (ref($str) eq "ARRAY") { + return (($#{$str}<0)?1:0); + } + + if (ref($str) eq "HASH") { + my @tmp = keys %{$str}; + return (($#tmp<0)?1:0); + } + + if ($str =~ /^\ *[\n\r]{0,2}\ *$/) { + return 1; + } + return 0; +} + ################################################################################ # Check a regular expression. Returns 1 if its valid, 0 otherwise. ################################################################################ @@ -731,13 +802,6 @@ sub parse_conf_modules($) { # Macros } elsif ($line =~ /^\s*module_macro(\S+)\s+(.*)\s*$/) { $module->{'macros'}{$1} = $2; - # Commands - } elsif ($line =~ /^\s*cmd_file\s+(.+)$/) { - if (ref ($Conf{'commands'}) ne "HASH") { - $Conf{'commands'} = {}; - } - # Initialize empty command hash. - $Conf{'commands'}->{$1} = {}; } } return; @@ -832,7 +896,21 @@ sub read_config (;$) { next if ($line =~ /^module\s*\w*/); #Configuration token - if ($line =~ /^\s*(\S+)\s+(.*)$/) { + if ($line =~ /^\s*(\S+)\s+(.*)$/) { + # Reserved keyword. + next if ($1 eq "commands"); + + if ($1 eq "cmd_file") { + # Commands + if (ref ($Conf{'commands'}) ne "HASH") { + $Conf{'commands'} = {}; + } + # Initialize empty command hash. + $Conf{'commands'}->{$2} = {}; + log_message('setup', "Command required $2"); + next; + } + log_message ('setup', "$1 is $2"); $Conf{$1} = $2; @@ -979,6 +1057,7 @@ sub read_config (;$) { $Conf{'secondary_server_opts'} = '-x \'' . $Conf{'secondary_server_pwd'} . '\' ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_pwd'} ne ''); $Conf{'secondary_server_opts'} = '-c ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_ssl'} eq '1'); } + } ################################################################################# @@ -1289,6 +1368,10 @@ sub check_remote_config () { %Collections = (); %Conf = %DefaultConf; + # Supposed to discard current configuration but not. + # Cleanup old commands configuration. + $Conf{'commands'} = {}; + # Reload the new configuration read_config (); @@ -1421,7 +1504,7 @@ sub check_collections () { ################################################################################ # Check for remote commands defined. ################################################################################ -sub prepare_remote_commands { +sub prepare_commands { if ($YAML == 0) { log_message( 'error', @@ -1430,13 +1513,27 @@ sub prepare_remote_commands { return; } + # Force configuration file read. + my @commands = read_config('cmd_file'); + + if (empty(\@commands)) { + $Conf{'commands'} = {}; + } else { + foreach my $rcmd (@commands) { + $Conf{'commands'}->{trim($rcmd)} = {}; + } + } + + # Cleanup old commands. Not registered. + cleanup_old_commands(); + foreach my $ref (keys %{$Conf{'commands'}}) { my $file_content; my $download = 0; my $rcmd_file = $ConfDir.'/commands/'.$ref.'.rcmd'; # Check for local .rcmd.done files - if (-e $Conf{'temporal'}.'/'.$ref.'.rcmd.done') { + if (-e $rcmd_file.'.done') { # Ignore. delete $Conf{'commands'}->{$ref}; next; @@ -1531,19 +1628,101 @@ sub report_command { return $return; } +################################################################################ +# Cleanup unreferenced rcmd and rcmd.done files. +################################################################################ +sub cleanup_old_commands { + # Cleanup old .rcmd and .rcmd.done files. + my %registered = map { $_.'.rcmd' => 1 } keys %{$Conf{'commands'}}; + if(opendir(my $dir, $ConfDir.'/commands/')) { + while (my $item = readdir($dir)) { + + # Skip other files. + next if ($item !~ /\.rcmd$/); + + # Clean .rcmd.done file if its command is not referenced in conf. + if (!defined($registered{$item})) { + if (-e $ConfDir.'/commands/'.$item) { + unlink($ConfDir.'/commands/'.$item); + } + if (-e $ConfDir.'/commands/'.$item.'.done') { + unlink($ConfDir.'/commands/'.$item.'.done'); + } + } + } + + # Close dir. + closedir($dir); + } + +} + ################################################################################ # Executes a command using defined timeout. ################################################################################ sub execute_command_timeout { - my ($command, $timeout) = @_; + my ($cmd, $timeout) = @_; - if (!looks_like_number($timeout)) { - `$command`; - } else { - `$command`; + if (!defined($timeout) + || !looks_like_number($timeout) + || $timeout <= 0 + ) { + `$cmd`; + return $?>>8; } - return $?>>8; + my $remaining_timeout = $timeout; + + my $RET; + my $output; + + my $pid = open ($RET, "-|"); + if (!defined($pid)) { + # Failed to fork. + log_message('error', '[command] Failed to fork.'); + return undef; + } + if ($pid == 0) { + # Child. + my $ret; + eval { + local $SIG{ALRM} = sub { die "timeout\n" }; + alarm $timeout; + `$cmd`; + alarm 0; + }; + + my $result = ($?>>8); + print $result; + + # Exit child. + # Child finishes. + exit; + + } else { + # Parent waiting. + while( --$remaining_timeout > 0 ){ + if (wait == -1) { + last; + } + # Wait child up to timeout seconds. + sleep 1; + } + } + + if ($remaining_timeout > 0) { + # Retrieve output from child. + $output = do { local $/; <$RET> }; + $output = $output>>8; + } + else { + # Timeout expired. + return 124; + } + + close($RET); + + return $output; } ################################################################################ @@ -1552,28 +1731,48 @@ sub execute_command_timeout { # $std_files = ' >> /tmp/stdout 2>> /tmp/stderr ################################################################################ sub execute_command_block { - my ($commands, $std_files, $timeout) = @_; + my ($commands, $std_files, $timeout, $retry) = @_; return 0 unless defined($commands); + my $retries = $retry; + + $retries = 1 unless looks_like_number($retries) && $retries > 0; + my $err_level = 0; $std_files = '' unless defined ($std_files); if (ref($commands) ne "ARRAY") { return 0 if $commands eq ''; - $err_level = execute_command_timeout( - "($commands) $std_files", - $timeout - ); + + do { + $err_level = execute_command_timeout( + "($commands) $std_files", + $timeout + ); + + # Do not retry if success. + last if looks_like_number($err_level) && $err_level == 0; + } while ((--$retries) > 0); } else { foreach my $comm (@{$commands}) { next unless defined($comm); - $err_level = execute_command_timeout( - "($comm) $std_files", - $timeout - ); + $retries = $retry; + $retries = 1 unless looks_like_number($retries) && $retries > 0; + do { + $err_level = execute_command_timeout( + "($comm) $std_files", + $timeout + ); + + # Do not retry if success. + last if looks_like_number($err_level) && $err_level == 0; + + } while ((--$retries) > 0); + + # Do not continue evaluating block if failed. last unless ($err_level == 0); } } @@ -3271,24 +3470,8 @@ while (1) { # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); - if ($Conf{'debug'} ne '1') { - # Check remote commands - prepare_remote_commands (); - - # Cleanup old .rcmd.done files. - my %registered = map { $_.'.rcmd.done' => 1 } keys %{$Conf{'commands'}}; - if(opendir(my $dir, $ConfDir.'/commands/')) { - while (my $item = readdir($dir)) { - # Skip other files. - next if ($item !~ /\.rcmd\.done$/); - - # Clean .rcmd.done file if its command is not referenced in conf. - if (!defined($registered{$item})) { - unlink ($item); - } - } - } - } + # Check scheduled commands + prepare_commands() unless ($Conf{'debug'} eq '1'); # Launch broker agents @BrokerPid = (); diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 05f8c89559..8707f0cea4 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.740 -%define release 191113 +%define release 191118 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 18ac2f32c0..624fe728fc 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.740 -%define release 191113 +%define release 191118 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index bf85762a39..19e2eac0ea 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.740" -PI_BUILD="191113" +PI_BUILD="191118" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index be5a498d11..04238d3924 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{191113} +{191118} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index b268f7f436..157d2ebe66 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.740(Build 191113)") +#define PANDORA_VERSION ("7.0NG.740(Build 191118)") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index e2707bff53..de7973252d 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.740(Build 191113))" + VALUE "ProductVersion", "(7.0NG.740(Build 191118))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 45e4ec20f1..6a00d319d9 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.740-191113 +Version: 7.0NG.740-191118 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index cf617bb4e3..aa35237934 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.740-191113" +pandora_version="7.0NG.740-191118" package_pear=0 package_pandora=1 diff --git a/pandora_console/extensions/quick_shell.php b/pandora_console/extensions/quick_shell.php index 13924f56e2..a8cce0b8de 100644 --- a/pandora_console/extensions/quick_shell.php +++ b/pandora_console/extensions/quick_shell.php @@ -218,7 +218,8 @@ function quickShell() if (empty($config['gotty_user']) === false && empty($config['gotty_pass']) === false ) { - $auth_str = $config['gotty_user'].':'.$config['gotty_pass']; + $auth_str = io_safe_output($config['gotty_user']); + $auth_str .= ':'.io_output_password($config['gotty_pass']); $gotty_url = $auth_str.'@'.$host.':'.$port; } @@ -381,7 +382,12 @@ function quickShellSettings() } // Interface. - ui_print_page_header(__('QuickShell settings')); + ui_print_page_header( + __('QuickShell settings'), + '', + false, + 'quickshell_settings' + ); if ($changes > 0) { $msg = __('%d Updated', $changes); @@ -442,25 +448,31 @@ function quickShellSettings() ], ], [ - 'label' => __('Gotty user').ui_print_help_tip( - __('Optional, set a user to access gotty service'), - true - ), - 'arguments' => [ - 'type' => 'text', - 'name' => 'gotty_user', - 'value' => $config['gotty_user'], - ], - ], - [ - 'label' => __('Gotty password').ui_print_help_tip( - __('Optional, set a password to access gotty service'), - true - ), - 'arguments' => [ - 'type' => 'password', - 'name' => 'gotty_pass', - 'value' => io_output_password($config['gotty_pass']), + 'toggle' => true, + 'toggle_name' => 'Advanced', + 'block_content' => [ + [ + 'label' => __('Gotty user').ui_print_help_tip( + __('Optional, set a user to access gotty service'), + true + ), + 'arguments' => [ + 'type' => 'text', + 'name' => 'gotty_user', + 'value' => $config['gotty_user'], + ], + ], + [ + 'label' => __('Gotty password').ui_print_help_tip( + __('Optional, set a password to access gotty service'), + true + ), + 'arguments' => [ + 'type' => 'password', + 'name' => 'gotty_pass', + 'value' => io_output_password($config['gotty_pass']), + ], + ], ], ], [ diff --git a/pandora_console/extras/mr/33.sql b/pandora_console/extras/mr/33.sql index 84e1d4edb0..e7396397d5 100644 --- a/pandora_console/extras/mr/33.sql +++ b/pandora_console/extras/mr/33.sql @@ -30,12 +30,16 @@ CREATE TABLE `tremote_command_target` ( `rcmd_id` bigint unsigned NOT NULL, `id_agent` int(10) unsigned NOT NULL, `utimestamp` int(20) unsigned NOT NULL default 0, - `stdout` text, - `stderr` text, + `stdout` MEDIUMTEXT, + `stderr` MEDIUMTEXT, `errorlevel` int(10) unsigned NOT NULL default 0, PRIMARY KEY (`id`), FOREIGN KEY (`rcmd_id`) REFERENCES `tremote_command`(`id`) ON UPDATE CASCADE ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO `tconfig`(`token`, `value`) VALUES ('welcome_state', -1); + +ALTER TABLE `tcredential_store` MODIFY COLUMN `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE', 'SAP') default 'CUSTOM'; + COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 7ec1e1d562..9fcd845c6e 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -2249,7 +2249,7 @@ CREATE TABLE `tvisual_console_elements_cache` ( CREATE TABLE IF NOT EXISTS `tcredential_store` ( `identifier` varchar(100) NOT NULL, `id_group` mediumint(4) unsigned NOT NULL DEFAULT 0, - `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE') default 'CUSTOM', + `product` enum('CUSTOM', 'AWS', 'AZURE', 'GOOGLE', 'SAP') default 'CUSTOM', `username` text, `password` text, `extra_1` text, @@ -2327,8 +2327,8 @@ CREATE TABLE `tremote_command_target` ( `rcmd_id` bigint unsigned NOT NULL, `id_agent` int(10) unsigned NOT NULL, `utimestamp` int(20) unsigned NOT NULL default 0, - `stdout` text, - `stderr` text, + `stdout` MEDIUMTEXT, + `stderr` MEDIUMTEXT, `errorlevel` int(10) unsigned NOT NULL default 0, PRIMARY KEY (`id`), FOREIGN KEY (`rcmd_id`) REFERENCES `tremote_command`(`id`) diff --git a/pandora_console/general/sap_view.php b/pandora_console/general/sap_view.php new file mode 100644 index 0000000000..58ee50e563 --- /dev/null +++ b/pandora_console/general/sap_view.php @@ -0,0 +1,77 @@ + '[sap_views]'.$e->getMessage() ]); + exit; + } else { + echo '[sap_views]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; +} + +// Ajax controller. +if (is_ajax()) { + $method = get_parameter('method', ''); + + if (method_exists($sap_views, $method) === true) { + if ($sap_views->ajaxMethod($method) === true) { + $sap_views->{$method}(); + } else { + $sap_views->error('Unavailable method.'); + } + } else { + $sap_views->error('Method not found. ['.$method.']'); + } + + + // Stop any execution. + exit; +} else { + // Run. + $sap_views->run(); +} diff --git a/pandora_console/godmode/agentes/configurar_agente.php b/pandora_console/godmode/agentes/configurar_agente.php index 61d33193d3..4f6c3e463e 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -486,6 +486,20 @@ if ($id_agente) { $agent_wizard['active'] = false; } + $is_sap = agents_get_sap_agents($id_agente); + if ($is_sap) { + $saptab['text'] = ''.html_print_image('images/sap_icon.png', true, ['title' => __('SAP view')]).''; + + if ($tab == 'sap_view') { + $saptab['active'] = true; + } else { + $saptab['active'] = false; + } + } else { + $saptab = ''; + } + + $total_incidents = agents_get_count_incidents($id_agente); // Incident tab. @@ -531,6 +545,7 @@ if ($id_agente) { 'group' => $grouptab, 'gis' => $gistab, 'agent_wizard' => $agent_wizard, + 'sap_view' => $saptab, ]; } else { $onheader = [ @@ -546,6 +561,8 @@ if ($id_agente) { 'group' => $grouptab, 'gis' => $gistab, 'agent_wizard' => $agent_wizard, + 'sap_view' => $saptab, + ]; } @@ -691,6 +708,12 @@ if ($id_agente) { } break; + case 'sap_view': + $tab_description = '- '.__('SAP view'); + $help_header = 'sap_view'; + $tab_name = 'SAP View'; + break; + default: // Default. break; @@ -2346,6 +2369,10 @@ switch ($tab) { include 'agent_wizard.php'; break; + case 'sap_view': + include 'general/sap_view.php'; + break; + default: if (enterprise_hook('switch_agent_tab', [$tab])) { // This will make sure that blank pages will have at least some diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 3a9e3de9c0..af09d9ff0d 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -28,7 +28,7 @@ if (check_acl($config['id_user'], 0, 'AR') || check_acl($config['id_user'], 0, 'PM') ) { $sub = []; - $sub['godmode/servers/discovery&wiz=main']['text'] = __('Main'); + $sub['godmode/servers/discovery&wiz=main']['text'] = __('Start'); $sub['godmode/servers/discovery&wiz=main']['id'] = 'Discovery'; $sub['godmode/servers/discovery&wiz=tasklist']['text'] = __('Task list'); $sub['godmode/servers/discovery&wiz=tasklist']['id'] = 'tasklist'; diff --git a/pandora_console/godmode/servers/discovery.php b/pandora_console/godmode/servers/discovery.php index 2d0fcec8a1..7215ee7dfb 100755 --- a/pandora_console/godmode/servers/discovery.php +++ b/pandora_console/godmode/servers/discovery.php @@ -54,7 +54,7 @@ function get_wiz_class($str) __('Discovery'), '', false, - '', + 'discovery', true, '', false, diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 9b12f2ee36..da6f4e572e 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -773,6 +773,9 @@ class DiscoveryTaskList extends Wizard case DISCOVERY_CLOUD_AWS_RDS: return 'wiz=cloud&mode=amazonws&ki='.$task['auth_strings'].'&sub=rds&page=0'; + case DISCOVERY_APP_SAP: + return 'wiz=app&mode=SAP&page=0'; + default: if ($task['description'] == 'console_task') { return 'wiz=ctask'; diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index 6f1d59d56b..30b0706342 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -458,6 +458,7 @@ class Wizard if (is_array($input['block_content']) === true) { $direct = (bool) $input['direct']; + $toggle = (bool) $input['toggle']; // Print independent block of inputs. $output .= '
'.$str.'', @@ -1673,7 +1711,7 @@ class Diagnostics extends Wizard 'status' => 0, ]; - if (is_file($path) === true) { + if (file_exists($path) === true) { $fileSize = filesize($path); $sizeServerLog = number_format($fileSize); $sizeServerLog = (0 + str_replace(',', '', $sizeServerLog)); @@ -1730,7 +1768,17 @@ class Diagnostics extends Wizard // of objects, making a post-process of certain fields. if (isset($items[$key]['status']) === true) { $acumValue = $items[$key]['value']; - if ($items[$key]['status'] === 1) { + + if ($items[$key]['status'] === 2) { + $items[$key]['value'] = html_print_image( + 'images/icono-warning.png', + true, + [ + 'title' => __('Warning'), + 'style' => 'width:15px;', + ] + ); + } else if ($items[$key]['status'] === 1) { $items[$key]['value'] = html_print_image( 'images/exito.png', true, @@ -1872,7 +1920,7 @@ class Diagnostics extends Wizard $mail_feedback = 'feedback@artica.es'; $email = $mail_feedback; - $subject = 'PandoraFMS Report '.$config['pandora_uid']; + $subject = $this->product_name.' Report '.$config['pandora_uid']; $text = get_parameter('what-happened', ''); $attachment = get_parameter_switch('include_installation_data', 0); $email_from = get_parameter_switch('email', ''); diff --git a/pandora_console/include/class/HelpFeedBack.class.php b/pandora_console/include/class/HelpFeedBack.class.php index 825d3c923f..e97e84ddd9 100644 --- a/pandora_console/include/class/HelpFeedBack.class.php +++ b/pandora_console/include/class/HelpFeedBack.class.php @@ -93,12 +93,13 @@ class HelpFeedBack extends Wizard ui_require_css_File('discovery'); ui_require_css_file('help_feedback'); - $help_url = get_parameter('url', null); + $help_url = get_parameter('b', null); + $help_url = base64_decode($help_url); if ($help_url === null) { echo __('Page not found'); } else { ?> - @@ -143,7 +144,7 @@ class HelpFeedBack extends Wizard 'block_content' => [ [ 'arguments' => [ - 'label' => __('Sugesstion'), + 'label' => __('Suggestion'), 'type' => 'radio_button', 'attributes' => 'class="btn"', 'name' => 'suggestion', @@ -154,7 +155,7 @@ class HelpFeedBack extends Wizard ], [ 'arguments' => [ - 'label' => __('Something is not quite right'), + 'label' => __('Something is wrong'), 'type' => 'radio_button', 'attributes' => 'class="btn"', 'name' => 'report', diff --git a/pandora_console/include/config_process.php b/pandora_console/include/config_process.php index ff5f365d5e..82515500d2 100644 --- a/pandora_console/include/config_process.php +++ b/pandora_console/include/config_process.php @@ -20,7 +20,7 @@ /** * Pandora build version and version */ -$build_version = 'PC191113'; +$build_version = 'PC191118'; $pandora_version = 'v7.0NG.740'; // Do not overwrite default timezone set if defined. diff --git a/pandora_console/include/constants.php b/pandora_console/include/constants.php index df171efbca..318496cfa8 100644 --- a/pandora_console/include/constants.php +++ b/pandora_console/include/constants.php @@ -537,7 +537,7 @@ define('NODE_GENERIC', 3); define('STATUS_OK', 0); define('STATUS_ERROR', 1); -// Maps (new networkmaps and new visualmaps). +// Maps new networkmaps and new visualmaps. define('MAP_TYPE_NETWORKMAP', 0); define('MAP_TYPE_VISUALMAP', 1); @@ -590,6 +590,7 @@ define('DISCOVERY_CLOUD_AWS_EC2', 6); define('DISCOVERY_CLOUD_AWS_RDS', 7); define('DISCOVERY_CLOUD_AZURE_COMPUTE', 8); define('DISCOVERY_DEPLOY_AGENTS', 9); +define('DISCOVERY_APP_SAP', 10); // Discovery types matching definition. diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index a7d94d43bc..720caefc58 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -5416,6 +5416,14 @@ function get_help_info($section_name) } break; + case 'omnishell': + if ($es) { + $result .= 'Omnishell&printable=yes'; + } else { + $result .= 'Omnishell&printable=yes'; + } + break; + case 'module_type_tab': if ($es) { $result .= 'Operacion&printable=yes#Tipos_de_m.C3.B3dulos'; @@ -5431,6 +5439,22 @@ function get_help_info($section_name) $result .= 'GIS&printable=yes#Operation'; } break; + + case 'quickshell_settings': + if ($es) { + $result .= 'Configuracion_Consola&printable=yes#Websocket_Engine'; + } else { + $result .= 'Console_Setup&printable=yes#Websocket_engine'; + } + break; + + case 'discovery': + if ($es) { + $result .= 'Discovery&printable=yes'; + } else { + $result .= 'Discovery&printable=yes'; + } + break; } return $result; diff --git a/pandora_console/include/functions_agents.php b/pandora_console/include/functions_agents.php index 826ca971c5..e85798cfde 100644 --- a/pandora_console/include/functions_agents.php +++ b/pandora_console/include/functions_agents.php @@ -132,6 +132,32 @@ function agents_get_agent_id_by_alias($alias) } +/** + * Return seconds left to contact again with agent. + * + * @param integer $id_agente Target agent + * + * @return integer|null Seconds left. + */ +function agents_get_next_contact_time_left(int $id_agente) +{ + $last_contact = false; + + if ($id_agente > 0) { + $last_contact = db_get_value_sql( + sprintf( + 'SELECT format(intervalo,2) - (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(IF(ultimo_contacto > ultimo_contacto_remoto, ultimo_contacto, ultimo_contacto_remoto))) as "val" + FROM `tagente` + WHERE id_agente = %d ', + $id_agente + ) + ); + } + + return $last_contact; +} + + /** * Creates an agent. * @@ -3481,3 +3507,66 @@ function agents_get_status_animation($up=true) ); } } + + +/** + * Return if an agent is SAP or or an a agent SAP list. + * If function receive false, you will return all SAP agents, + * but if you receive an id agent, check if it is a sap agent + * and return true or false. + * + * @param integer $id_agent + * @return boolean + */ +function agents_get_sap_agents($id_agent) +{ + // Available modules. + // If you add more modules, please update SAP.pm. + $sap_modules = [ + 160 => __('SAP Login OK'), + 109 => __('SAP Dumps'), + 111 => __('SAP List lock'), + 113 => __('SAP Cancel Jobs'), + 121 => __('SAP Batch input erroneus'), + 104 => __('SAP Idoc erroneus'), + 105 => __('SAP IDOC OK'), + 150 => __('SAP WP without active restart'), + 151 => __('SAP WP stopped'), + 102 => __('Average time of SAPGUI response '), + 180 => __('Dialog response time'), + 103 => __('Dialog Logged users '), + 192 => __('SYSFAIL, delivery attempts tRFC wrong entries number'), + 195 => __('SYSFAIL, queue qRFC INPUT, wrong entries number '), + 116 => __('Number of Update WPs in error'), + ]; + + $array_agents = []; + foreach ($sap_modules as $module => $key) { + $array_agents = array_merge( + $array_agents, + db_get_all_rows_sql( + 'SELECT ta.id_agente,ta.alias + FROM tagente ta + INNER JOIN tagente_modulo tam + ON tam.id_agente = ta.id_agente + WHERE tam.nombre + LIKE "%SAP%" + GROUP BY ta.id_agente' + ) + ); + } + + $indexed_agents = index_array($array_agents, 'id_agente', false); + + if ($id_agent === false) { + return $indexed_agents; + } + + foreach ($indexed_agents as $agent => $key) { + if ($agent === $id_agent) { + return true; + } + } + + return false; +} diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 89b3c03de2..4ee9e682b8 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -455,6 +455,10 @@ function config_update_config() $error_update[] = __('Ipam Ocuppied Manager Warning'); } + if (!config_update_value('sap_license', get_parameter('sap_license'))) { + $error_update[] = __('Deset SAP license'); + } + $inventory_changes_blacklist = get_parameter('inventory_changes_blacklist', []); if (!config_update_value('inventory_changes_blacklist', implode(',', $inventory_changes_blacklist))) { $error_update[] = __('Inventory changes blacklist'); diff --git a/pandora_console/include/functions_events.php b/pandora_console/include/functions_events.php index 9563732c68..5fd0ae3481 100644 --- a/pandora_console/include/functions_events.php +++ b/pandora_console/include/functions_events.php @@ -4580,7 +4580,7 @@ function events_page_comments($event, $ajax=false) continue; } - $comments_array[] = json_decode(io_safe_output($comm), true); + $comments_array[] = io_safe_output(json_decode($comm, true)); } } else { // If comments are not stored in json, the format is old. diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 0ad31cf931..a1414f4d7c 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -1404,14 +1404,19 @@ function ui_print_help_icon( } $url = get_help_info($help_id); + $b = base64_encode($url); + $help_handler = 'index.php?sec=view&sec2=general/help_feedback'; + // Needs to use url encoded to avoid anchor lost. + $help_handler .= '&b='.$b; + $help_handler .= '&pure=1&url='.$url; $output = html_print_image( $image, true, [ 'class' => 'img_help', 'title' => __('Help'), - 'onclick' => "open_help ('".ui_get_full_url('index.php?sec=view&sec2=general/help_feedback&pure=1&url='.$url)."')", + 'onclick' => "open_help ('".ui_get_full_url($help_handler)."')", 'id' => $id, ], false, @@ -2915,119 +2920,73 @@ function ui_progress( * Generates a progress bar CSS based. * Requires css progress.css * - * @param array $progress Progress. - * @param string $width Width. - * @param integer $height Height in 'em'. - * @param array $color status color. - * @param boolean $return Return or paint (if false). - * @param boolean $text Text to be displayed,by default progress %. - * @param array $ajax Ajax: [ 'page' => 'page', 'data' => 'data' ] Sample: - * [ - * 'page' => 'operation/agentes/ver_agente', Target page. - * 'interval' => 100 / $agent["intervalo"], Ask every interval seconds. - * 'data' => [ Data to be sent to target page. - * 'id_agente' => $id_agente, - * 'refresh_contact' => 1, - * ], - * ]. + * @param array $data With following content: + * + * 'slices' => [ + * 'label' => [ // Name of the slice + * 'value' => value + * 'color' => color of the slice. + * ] + * ], + * 'width' => Width + * 'height' => Height in 'em' + * 'return' => Boolean, return or paint. * * @return string HTML code. */ function ui_progress_extend( - $progress, - $width='100%', - $height='2.5', - $color='#82b92e', - $return=true, - $text='', - $ajax=false + array $data ) { - if (!$progress['total']) { - $progress = 0; + if (is_array($data) === false) { + // Failed. + return false; } - $totalW = ($progress['total'] * 100); - if ($totalW > 100) { - $totalW = 100; + if (is_array($data['slices']) === false) { + // Failed. + return false; } - if ($totalW < 0) { - $totalW = 0; + if (isset($data['width']) === false) { + $data['width'] = '100'; } - if (empty($text)) { - $text = $totalW.'%'; + if (isset($data['height']) === false) { + $data['height'] = '1.3'; + } + + $total = array_reduce( + $data['slices'], + function ($carry, $item) { + $carry += $item['value']; + return $carry; + } + ); + if ($total == 0) { + return null; } - $badW = (($progress['bad'] * 100 ) / $progress['total']); - $goodW = (($progress['good'] * 100 ) / $progress['total']); - $unknownW = (($progress['unknown'] * 100 ) / $progress['total']); ui_require_css_file('progress'); - $output .= '