From 960326b98089963b5e184fc4d92ffa0e7309c258 Mon Sep 17 00:00:00 2001 From: daniel Date: Thu, 21 Nov 2019 18:21:46 +0100 Subject: [PATCH] Add menu omnishell --- pandora_agents/pc/DEBIAN/make_deb_package.sh | 2 + pandora_agents/pc/pandora_agent_installer | 5 + .../unix/DEBIAN/make_deb_package.sh | 2 + pandora_agents/unix/pandora_agent | 498 ++++++++++++++++- pandora_agents/unix/pandora_agent.redhat.spec | 5 + pandora_agents/unix/pandora_agent.spec | 5 + pandora_agents/unix/pandora_agent_installer | 5 + pandora_console/extensions/agents_modules.php | 500 +++++++++-------- .../extensions/plugin_registration.php | 4 +- pandora_console/extensions/quick_shell.php | 54 +- pandora_console/extras/mr/33.sql | 32 ++ .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 36 +- .../HA_cluster_builder.php | 4 +- .../cluster_builder.php | 4 +- .../collections.php | 2 +- .../custom_fields.php | 4 +- .../custom_graphs.php | 4 +- .../fields_manager.php | 4 +- .../{firts_task => first_task}/incidents.php | 4 +- .../map_builder.php | 4 +- .../network_map.php | 4 +- .../general/first_task/omnishell.php | 56 ++ .../planned_downtime.php | 4 +- .../{firts_task => first_task}/recon_view.php | 4 +- .../service_list.php | 4 +- .../snmp_filters.php | 4 +- .../{firts_task => first_task}/tags.php | 4 +- .../transactional_list.php | 4 +- pandora_console/general/sap_view.php | 77 +++ .../godmode/agentes/configurar_agente.php | 43 +- .../godmode/agentes/fields_manager.php | 2 +- .../godmode/agentes/planned_downtime.list.php | 2 +- pandora_console/godmode/menu.php | 4 +- pandora_console/godmode/reporting/graphs.php | 2 +- .../godmode/reporting/map_builder.php | 2 +- pandora_console/godmode/servers/discovery.php | 2 +- .../godmode/servers/servers.build_table.php | 2 +- pandora_console/godmode/tag/tag.php | 2 +- .../wizards/DiscoveryTaskList.class.php | 5 +- .../godmode/wizards/Wizard.main.php | 57 +- .../icono-cluster-activo.png | Bin .../{firts_task => first_task}/icono_aws.png | Bin .../icono_grande_custom_reporting.png | Bin .../icono_grande_event_alerts.png | Bin .../icono_grande_export.png | Bin .../icono_grande_gestiondetags.png | Bin .../icono_grande_import.png | Bin .../icono_grande_incidencia.png | Bin .../icono_grande_inventario.png | Bin .../icono_grande_licencia.png | Bin .../icono_grande_reconserver.png | Bin .../icono_grande_registro_plugin.png | Bin .../icono_grande_servicios.png | Bin .../icono_grande_topology.png | Bin .../icono_grande_visualconsole.png | Bin .../icono_manage_agents.png | Bin .../images/first_task/omnishell.png | Bin 0 -> 3129 bytes .../op_workspace.menu.png | Bin .../{firts_task => first_task}/slave-mode.png | Bin pandora_console/images/sap_icon.png | Bin 0 -> 324 bytes .../include/class/CredentialStore.class.php | 11 +- .../include/class/Diagnostics.class.php | 32 +- .../include/class/HelpFeedBack.class.php | 9 +- pandora_console/include/constants.php | 3 +- pandora_console/include/functions.php | 24 + pandora_console/include/functions_agents.php | 89 +++ pandora_console/include/functions_config.php | 4 + pandora_console/include/functions_html.php | 121 +++- pandora_console/include/functions_menu.php | 2 +- pandora_console/include/functions_ui.php | 102 +++- pandora_console/include/javascript/alert.js | 174 ++++++ pandora_console/include/javascript/pandora.js | 53 +- .../include/lib/WebSocketServer.php | 22 + pandora_console/include/styles/alert.css | 128 +++++ pandora_console/include/styles/discovery.css | 3 +- .../styles/{firts_task.css => first_task.css} | 9 +- pandora_console/include/styles/omnishell.css | 515 ++++++++++++++++++ pandora_console/include/styles/pandora.css | 18 +- pandora_console/include/styles/progress.css | 10 + .../operation/agentes/ver_agente.php | 34 +- .../operation/incidents/incident.php | 2 +- pandora_console/operation/menu.php | 2 + pandora_console/operation/search_agents.php | 1 + .../operation/servers/recon_view.php | 2 +- pandora_console/pandoradb.sql | 37 +- pandora_console/pandoradb_data.sql | 4 +- pandora_console/tools/diagnostics.php | 2 +- pandora_server/DEBIAN/make_deb_package.sh | 4 +- pandora_server/conf/pandora_server.conf.new | 10 +- pandora_server/conf/tentacle_server.conf.new | 2 +- pandora_server/lib/PandoraFMS/Config.pm | 12 + pandora_server/lib/PandoraFMS/DataServer.pm | 6 +- .../lib/PandoraFMS/DiscoveryServer.pm | 45 +- pandora_server/lib/PandoraFMS/Recon/Base.pm | 211 ++++--- pandora_server/lib/PandoraFMS/Tools.pm | 28 + pandora_server/pandora_server.redhat.spec | 4 + pandora_server/pandora_server.spec | 2 + pandora_server/pandora_server_installer | 2 + 98 files changed, 2754 insertions(+), 447 deletions(-) rename pandora_console/general/{firts_task => first_task}/HA_cluster_builder.php (95%) rename pandora_console/general/{firts_task => first_task}/cluster_builder.php (96%) rename pandora_console/general/{firts_task => first_task}/collections.php (98%) rename pandora_console/general/{firts_task => first_task}/custom_fields.php (94%) rename pandora_console/general/{firts_task => first_task}/custom_graphs.php (94%) rename pandora_console/general/{firts_task => first_task}/fields_manager.php (94%) rename pandora_console/general/{firts_task => first_task}/incidents.php (95%) rename pandora_console/general/{firts_task => first_task}/map_builder.php (95%) rename pandora_console/general/{firts_task => first_task}/network_map.php (95%) create mode 100644 pandora_console/general/first_task/omnishell.php rename pandora_console/general/{firts_task => first_task}/planned_downtime.php (94%) rename pandora_console/general/{firts_task => first_task}/recon_view.php (95%) rename pandora_console/general/{firts_task => first_task}/service_list.php (95%) rename pandora_console/general/{firts_task => first_task}/snmp_filters.php (95%) rename pandora_console/general/{firts_task => first_task}/tags.php (94%) rename pandora_console/general/{firts_task => first_task}/transactional_list.php (95%) create mode 100644 pandora_console/general/sap_view.php rename pandora_console/images/{firts_task => first_task}/icono-cluster-activo.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_aws.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_custom_reporting.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_event_alerts.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_export.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_gestiondetags.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_import.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_incidencia.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_inventario.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_licencia.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_reconserver.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_registro_plugin.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_servicios.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_topology.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_grande_visualconsole.png (100%) rename pandora_console/images/{firts_task => first_task}/icono_manage_agents.png (100%) create mode 100644 pandora_console/images/first_task/omnishell.png rename pandora_console/images/{firts_task => first_task}/op_workspace.menu.png (100%) rename pandora_console/images/{firts_task => first_task}/slave-mode.png (100%) create mode 100644 pandora_console/images/sap_icon.png create mode 100644 pandora_console/include/javascript/alert.js create mode 100644 pandora_console/include/styles/alert.css rename pandora_console/include/styles/{firts_task.css => first_task.css} (88%) create mode 100644 pandora_console/include/styles/omnishell.css diff --git a/pandora_agents/pc/DEBIAN/make_deb_package.sh b/pandora_agents/pc/DEBIAN/make_deb_package.sh index f44dfec8f4..691918b54e 100644 --- a/pandora_agents/pc/DEBIAN/make_deb_package.sh +++ b/pandora_agents/pc/DEBIAN/make_deb_package.sh @@ -36,6 +36,8 @@ mkdir -p temp_package/usr/bin/ mkdir -p temp_package/usr/sbin/ mkdir -p temp_package/etc/pandora/plugins mkdir -p temp_package/etc/pandora/collections +mkdir -p temp_package/etc/pandora/trans +mkdir -p temp_package/etc/pandora/commands mkdir -p temp_package/etc/init.d/ mkdir -p temp_package/var/log/pandora/ mkdir -p temp_package/usr/share/man/man1/ diff --git a/pandora_agents/pc/pandora_agent_installer b/pandora_agents/pc/pandora_agent_installer index ab2a00877e..469364abf1 100644 --- a/pandora_agents/pc/pandora_agent_installer +++ b/pandora_agents/pc/pandora_agent_installer @@ -324,6 +324,11 @@ install () { cp -r collections $PANDORA_BASE$PANDORA_HOME chmod -R 700 $PANDORA_BASE$PANDORA_HOME/collections ln -s $PANDORA_BASE$PANDORA_HOME/collections $PANDORA_BASE$PANDORA_CFG + + echo "Copying Pandora FMS Agent commands to $PANDORA_BASE$PANDORA_HOME/commands..." + cp -r commands $PANDORA_BASE$PANDORA_HOME + chmod -R 700 $PANDORA_BASE$PANDORA_HOME/commands + ln -s $PANDORA_BASE$PANDORA_HOME/commands $PANDORA_BASE$PANDORA_CFG echo "Copying tentacle server to $PANDORA_BASE$TENTACLE_SERVER" cp tentacle_server $PANDORA_BASE$TENTACLE_SERVER diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index b77eaa48c4..d37d7c3751 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -36,6 +36,8 @@ mkdir -p temp_package/usr/bin/ mkdir -p temp_package/usr/sbin/ mkdir -p temp_package/etc/pandora/plugins mkdir -p temp_package/etc/pandora/collections +mkdir -p temp_package/etc/pandora/trans +mkdir -p temp_package/etc/pandora/commands mkdir -p temp_package/etc/init.d/ mkdir -p temp_package/lib/systemd/system/ mkdir -p temp_package/var/log/pandora/ diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 9625518306..ba2b7c264e 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -24,6 +24,7 @@ Version 6.0 use strict; use warnings; +use Scalar::Util qw(looks_like_number); use POSIX qw(strftime floor); use Sys::Hostname; use File::Basename; @@ -32,6 +33,18 @@ use IO::Socket; use Sys::Syslog; use Time::Local; +my $YAML = 0; +# Dynamic load. Avoid unwanted behaviour. +eval { + eval 'require YAML::Tiny;1' or die('YAML::Tiny lib not found, commands feature won\'t be available'); +}; +if ($@) { + $YAML = 0; + print STDERR $@; +} else { + $YAML = 1; +} + # Agent XML data my $Xml; @@ -187,6 +200,7 @@ my %DefaultConf = ( 'custom_id' => '', 'url_address' => '', 'standby' => 0, + 'cmd_file' => undef, ); my %Conf = %DefaultConf; @@ -268,6 +282,91 @@ sub error ($) { exit 1; } +################################################################################ +# Try to load extra libraries.c +################################################################################ +sub load_libraries() { + # Dynamic load. Avoid unwanted behaviour. + eval {eval 'require YAML::Tiny;1' or die('YAML::Tiny lib not found, commands feature won\'t be available');}; + if ($@) { + $YAML = 0; + print STDERR $@; + } else { + $YAML = 1; + } +} + +################################################################################ +# 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. ################################################################################ @@ -284,6 +383,27 @@ sub valid_regexp ($) { return 1; } +################################################################################ +# Reads a file and returns entire content or undef if error. +################################################################################ +sub read_file { + my $path = shift; + + my $_FILE; + if( !open($_FILE, "<", $path) ) { + # failed to open, return undef + return undef; + } + + # Slurp configuration file content. + my $content = do { local $/; <$_FILE> }; + + # Close file + close($_FILE); + + return $content; +} + ################################################################################ # Recursively delete files and directories. ################################################################################ @@ -776,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; @@ -923,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'); } + } ################################################################################# @@ -1157,14 +1292,14 @@ sub recv_file { }; if ($@) { - log_message ('error', "Error retrieving file: File transfer command is not responding."); + log_message ('error', "Error retrieving file: '.$file.' File transfer command is not responding."); exit 1; } # Get the errorlevel my $rc = $? >> 8; if ($rc != 0) { - log_message ('error', "Error retrieving file: $output"); + log_message ('error', "Error retrieving file: '$file' $output"); } exit $rc; } @@ -1233,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 (); @@ -1362,6 +1501,336 @@ sub check_collections () { } } +################################################################################ +# Check for remote commands defined. +################################################################################ +sub prepare_commands { + if ($YAML == 0) { + log_message( + 'error', + 'Cannot use commands without YAML dependency, please install it.' + ); + 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 $rcmd_file.'.done') { + # Ignore. + delete $Conf{'commands'}->{$ref}; + next; + } + + # Search for local .rcmd file + if (-e $rcmd_file) { + my $remote_md5_file = $Conf{'temporal'}.'/'.$ref.'.md5'; + + $file_content = read_file($rcmd_file); + if (recv_file($ref.'.md5', $remote_md5_file) != 0) { + # Remote file could not be retrieved, skip. + delete $Conf{'commands'}->{$ref}; + next; + } + + my $local_md5 = md5($file_content); + my $remote_md5 = md5(read_file($remote_md5_file)); + + if ($local_md5 ne $remote_md5) { + # Must be downloaded again. + $download = 1; + } + } else { + $download = 1; + } + + # Search for remote .rcmd file + if ($download == 1) { + # Download .rcmd file + if (recv_file($ref.'.rcmd') != 0) { + # Remote file could not be retrieved, skip. + delete $Conf{'commands'}->{$ref}; + next; + } else { + # Success + move($Conf{'temporal'}.'/'.$ref.'.rcmd', $rcmd_file); + } + } + + # Parse and prepare in memory skel. + eval { + $Conf{'commands'}->{$ref} = YAML::Tiny->read($rcmd_file); + }; + if ($@) { + # Failed. + log_message('error', 'Failed to decode command. ' . "\n".$@); + delete $Conf{'commands'}->{$ref}; + next; + } + + } +} + +################################################################################ +# Command report. +################################################################################ +sub report_command { + my ($ref, $err_level) = @_; + + # Retrieve content from .stdout and .stderr + my $stdout_file = $Conf{'temporal'}.'/'.$ref.'.stdout'; + my $stderr_file = $Conf{'temporal'}.'/'.$ref.'.stderr'; + + my $return; + eval { + $return = { + 'error_level' => $err_level, + 'stdout' => read_file($stdout_file), + 'stderr' => read_file($stderr_file), + }; + + $return->{'name'} = $Conf{'commands'}->{$ref}->[0]->{'name'}; + }; + if ($@) { + log_message('error', 'Failed to report command output. ' . $@); + } + + # Cleanup + unlink($stdout_file) if (-e $stdout_file); + unlink($stderr_file) if (-e $stderr_file); + + # Mark command as done. + open (my $R_FILE, '> '.$ConfDir.'/commands/'.$ref.'.rcmd.done'); + print $R_FILE $err_level; + close($R_FILE); + + + $return->{'stdout'} = '' unless defined ($return->{'stdout'}); + $return->{'stderr'} = '' unless defined ($return->{'stderr'}); + + 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 ($cmd, $timeout) = @_; + + if (!defined($timeout) + || !looks_like_number($timeout) + || $timeout <= 0 + ) { + `$cmd`; + 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; +} + +################################################################################ +# Executes a block of commands, returns error level, leaves output in +# redirection set by $std_files. E.g: +# $std_files = ' >> /tmp/stdout 2>> /tmp/stderr +################################################################################ +sub execute_command_block { + 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 ''; + + 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); + $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); + } + } + + return $err_level; +} + +################################################################################ +# Evalate given command. +################################################################################ +sub evaluate_command { + my ($ref) = @_; + + # Not found. + return unless defined $Conf{'commands'}->{$ref}; + + # Already completed. + return if (-e $ConfDir.'/commands/'.$ref.'.rcmd.done'); + + # [0] because how library works. + my $cmd = $Conf{'commands'}->{$ref}->[0]; + + my $std_files = ' >> '.$Conf{'temporal'}.'/'.$ref.'.stdout '; + $std_files .= ' 2>> '.$Conf{'temporal'}.'/'.$ref.'.stderr '; + + # Check preconditions + my $err_level; + + $err_level = execute_command_block( + $cmd->{'preconditions'}, + $std_files, + $cmd->{'timeout'} + ); + + # Precondition not satisfied. + return report_command($ref, $err_level) unless ($err_level == 0); + + # Main run. + $err_level = execute_command_block( + $cmd->{'script'}, + $std_files, + $cmd->{'timeout'} + ); + + # Script not success. + return report_command($ref, $err_level) unless ($err_level == 0); + + # Check postconditions + $err_level = execute_command_block( + $cmd->{'postconditions'}, + $std_files, + $cmd->{'timeout'} + ); + + # Return results. + return report_command($ref, $err_level); +} + ################################################################################ # Sleep function ################################################################################ @@ -2985,6 +3454,8 @@ my $iter_base_time = time(); $LogFileIdx = -1; # Loop while (1) { + load_libraries(); + if (-e $Conf{'logfile'} && (stat($Conf{'logfile'}))[7] > $Conf{'logsize'}) { rotate_log(); } @@ -2999,6 +3470,9 @@ while (1) { # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); + # Check scheduled commands + prepare_commands() unless ($Conf{'debug'} eq '1'); + # Launch broker agents @BrokerPid = (); my @broker_agents = read_config ('broker_agent'); @@ -3128,6 +3602,24 @@ while (1) { } } + if (ref ($Conf{'commands'}) eq "HASH") { + foreach my $command (keys %{$Conf{'commands'}}) { + my $result = evaluate_command($command); + if (ref($result) eq "HASH") { + # Process command result. + $Xml .= "\n"; + $Xml .= " \n"; + $Xml .= " {'name'}."]]>\n"; + $Xml .= " \n"; + $Xml .= " {'error_level'}."]]>\n"; + $Xml .= " {'stdout'}."]]>\n"; + $Xml .= " {'stderr'}."]]>\n"; + $Xml .= " \n"; + $Xml .= "\n"; + } + } + } + # Wait for all the threads $ThreadSem->down ($Conf{'agent_threads'}) if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); $ThreadSem->up ($Conf{'agent_threads'}) if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index a308bf9350..ed6e3d9af3 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -99,6 +99,11 @@ if [ ! -e /etc/pandora/collections ]; then ln -s /usr/share/pandora_agent/collections /etc/pandora fi +if [ ! -e /etc/pandora/commands ]; then + mkdir -p /usr/share/pandora_agent/commands + ln -s /usr/share/pandora_agent/commands /etc/pandora +fi + mkdir -p /var/spool/pandora/data_out if [ ! -d /var/log/pandora ]; then mkdir -p /var/log/pandora diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 6f71dee5b5..92394da731 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -90,6 +90,11 @@ fi if [ ! -e /etc/pandora/collections ]; then mkdir /etc/pandora/collections fi + +if [ ! -e /etc/pandora/commands ]; then + mkdir /etc/pandora/commands +fi + cp -aRf /usr/share/pandora_agent/pandora_agent_logrotate /etc/logrotate.d/pandora_agent # Enable the service on SystemD diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index 099ed7b6ca..e4e0431311 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -400,6 +400,11 @@ install () { mkdir -p $PANDORA_BASE$PANDORA_HOME/collections chmod -R 700 $PANDORA_BASE$PANDORA_HOME/collections ln -s $PANDORA_BASE_REAL$PANDORA_HOME/collections $PANDORA_BASE$PANDORA_CFG + + echo "Creating the commands directory in $PANDORA_BASE$PANDORA_HOME/commands..." + mkdir -p $PANDORA_BASE$PANDORA_HOME/commands + chmod -R 700 $PANDORA_BASE$PANDORA_HOME/commands + ln -s $PANDORA_BASE_REAL$PANDORA_HOME/commands $PANDORA_BASE$PANDORA_CFG if [ $WITHOUT_TENTACLE_SERVER -eq 0 ] then diff --git a/pandora_console/extensions/agents_modules.php b/pandora_console/extensions/agents_modules.php index 97657f5189..f492f5e437 100644 --- a/pandora_console/extensions/agents_modules.php +++ b/pandora_console/extensions/agents_modules.php @@ -13,7 +13,264 @@ * GNU General Public License for more details. */ +// Begin. + +/** + * Extra JS. + * + * @return void + */ +function agents_modules_load_js() +{ + $ignored_params['refresh'] = ''; + + ?> + + + + - - - diff --git a/pandora_console/extensions/plugin_registration.php b/pandora_console/extensions/plugin_registration.php index ef08e34bae..6cf20858ab 100644 --- a/pandora_console/extensions/plugin_registration.php +++ b/pandora_console/extensions/plugin_registration.php @@ -23,12 +23,12 @@ function pluginreg_extension_main() return; } - ui_require_css_file('firts_task'); + ui_require_css_file('first_task'); ui_print_page_header(__('Plugin registration'), 'images/extensions.png', false, '', true, ''); echo '
'; - echo html_print_image('images/firts_task/icono_grande_import.png', true, ['title' => __('Plugin Registration') ]); + echo html_print_image('images/first_task/icono_grande_import.png', true, ['title' => __('Plugin Registration') ]); echo '
'; echo '
'; echo '

'.__('Plugin registration').'

'; 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 755ec5f9c4..bfe1777e63 100644 --- a/pandora_console/extras/mr/33.sql +++ b/pandora_console/extras/mr/33.sql @@ -16,6 +16,38 @@ INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `ma INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `max`, `min`, `module_interval`, `tcp_port`, `tcp_send`, `tcp_rcv`, `snmp_community`, `snmp_oid`, `id_module_group`, `id_modulo`, `id_plugin`, `plugin_user`, `plugin_pass`, `plugin_parameter`, `max_timeout`, `max_retries`, `history_data`, `min_warning`, `max_warning`, `max_critical`, `str_warning`, `min_ff_event`, `min_critical`, `custom_string_2`, `str_critical`, `custom_integer_1`, `custom_string_1`, `post_process`, `custom_string_3`, `wizard_level`, `custom_integer_2`, `critical_instructions`, `unit`, `unknown_instructions`, `macros`, `warning_inverse`, `warning_instructions`, `tags`, `critical_inverse`, `module_macros`, `id_category`, `min_ff_event_warning`, `disabled_types_event`, `ff_type`, `min_ff_event_normal`, `dynamic_interval`, `min_ff_event_critical`, `dynamic_min`, `each_ff`, `dynamic_two_tailed`, `dynamic_max`, `dynamic_next`) VALUES ('Linux available memory percent','Available memory %',43,34,0,0,300,0,'free | grep Mem | awk '{print $NF/$2 * 100}'','','','',4,2,0,'','','',0,0,1,0.00,0.00,'',0.00,0.00,'',0,'','linux','',0,0,0.000000000000000,'%','nowizard','','','','',0,0,0,'','{\"going_unknown\":1}','',0,0,0,0,0,0,0,0,0,0); INSERT INTO `tnetwork_component` (`name`, `description`, `id_group`, `type`, `max`, `min`, `module_interval`, `tcp_port`, `tcp_send`, `tcp_rcv`, `snmp_community`, `snmp_oid`, `id_module_group`, `id_modulo`, `id_plugin`, `plugin_user`, `plugin_pass`, `plugin_parameter`, `max_timeout`, `max_retries`, `history_data`, `min_warning`, `max_warning`, `max_critical`, `str_warning`, `min_ff_event`, `min_critical`, `custom_string_2`, `str_critical`, `custom_integer_1`, `custom_string_1`, `post_process`, `custom_string_3`, `wizard_level`, `custom_integer_2`, `critical_instructions`, `unit`, `unknown_instructions`, `macros`, `warning_inverse`, `warning_instructions`, `tags`, `critical_inverse`, `module_macros`, `id_category`, `min_ff_event_warning`, `disabled_types_event`, `ff_type`, `min_ff_event_normal`, `dynamic_interval`, `min_ff_event_critical`, `dynamic_min`, `each_ff`, `dynamic_two_tailed`, `dynamic_max`, `dynamic_next`) VALUES ('Linux available disk /','Available free space in mountpoint /',43,34,0,0,300,0,'df / | tail -n +2 | awk '{print $(NF-1)}' | tr -d '%'','','','',4,2,0,'','','',0,0,1,0.00,0.00,'0.00',0.00,0.00,'',0,'','inherited','',0,0,0.000000000000000,'','nowizard','','nowizard','0','',0,0,0,'','{\"going_unknown\":1}','',0,0,0,0,0,0,0,0,0,0); +ALTER TABLE `tevent_rule` ADD COLUMN `log_content` TEXT; +ALTER TABLE `tevent_rule` ADD COLUMN `log_source` TEXT; +ALTER TABLE `tevent_rule` ADD COLUMN `log_agent` TEXT; + +CREATE TABLE `tremote_command` ( + `id` SERIAL, + `name` varchar(150) NOT NULL, + `timeout` int(10) unsigned NOT NULL default 30, + `retries` int(10) unsigned NOT NULL default 3, + `preconditions` text, + `script` text, + `postconditions` text, + `utimestamp` int(20) unsigned NOT NULL default 0, + `id_group` int(10) unsigned NOT NULL default 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `tremote_command_target` ( + `id` SERIAL, + `rcmd_id` bigint unsigned NOT NULL, + `id_agent` int(10) unsigned NOT NULL, + `utimestamp` int(20) unsigned NOT NULL default 0, + `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 44e73b2efa..9d182b0a54 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 @@ -1291,13 +1291,13 @@ ALTER TABLE `tmap` MODIFY COLUMN `id_user` varchar(250) NOT NULL DEFAULT ''; INSERT INTO `tconfig` (`token`, `value`) VALUES ('big_operation_step_datos_purge', '100'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('small_operation_step_datos_purge', '1000'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('days_autodisable_deletion', '30'); -INSERT INTO `tconfig` (`token`, `value`) VALUES ('MR', 32); +INSERT INTO `tconfig` (`token`, `value`) VALUES ('MR', 33); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_docs_logo', 'default_docs.png'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_support_logo', 'default_support.png'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_logo_white_bg_preview', 'pandora_logo_head_white_bg.png'); UPDATE tconfig SET value = 'https://licensing.artica.es/pandoraupdate7/server.php' WHERE token='url_update_manager'; DELETE FROM `tconfig` WHERE `token` = 'current_package_enterprise'; -INSERT INTO `tconfig` (`token`, `value`) VALUES ('current_package_enterprise', '739'); +INSERT INTO `tconfig` (`token`, `value`) VALUES ('current_package_enterprise', '741'); INSERT INTO `tconfig` (`token`, `value`) VALUES ('status_monitor_fields', 'policy,agent,data_type,module_name,server_type,interval,status,graph,warn,data,timestamp'); UPDATE `tconfig` SET `value` = 'mini_severity,evento,id_agente,estado,timestamp' WHERE `token` LIKE 'event_fields'; DELETE FROM `tconfig` WHERE `token` LIKE 'integria_api_password'; @@ -2411,6 +2411,38 @@ CREATE TABLE `tdeployment_hosts` ( ON UPDATE CASCADE ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- Table `tremote_command` +-- ---------------------------------------------------------------------- +CREATE TABLE `tremote_command` ( + `id` SERIAL, + `name` varchar(150) NOT NULL, + `timeout` int(10) unsigned NOT NULL default 30, + `retries` int(10) unsigned NOT NULL default 3, + `preconditions` text, + `script` text, + `postconditions` text, + `utimestamp` int(20) unsigned NOT NULL default 0, + `id_group` int(10) unsigned NOT NULL default 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- ---------------------------------------------------------------------- +-- Table `tremote_command_target` +-- ---------------------------------------------------------------------- +CREATE TABLE `tremote_command_target` ( + `id` SERIAL, + `rcmd_id` bigint unsigned NOT NULL, + `id_agent` int(10) unsigned NOT NULL, + `utimestamp` int(20) unsigned NOT NULL default 0, + `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; +========= -- --------------------------------------------------------------------- -- Table `trecon_script` -- --------------------------------------------------------------------- diff --git a/pandora_console/general/firts_task/HA_cluster_builder.php b/pandora_console/general/first_task/HA_cluster_builder.php similarity index 95% rename from pandora_console/general/firts_task/HA_cluster_builder.php rename to pandora_console/general/first_task/HA_cluster_builder.php index 6d82d94ad0..7ae56a4287 100644 --- a/pandora_console/general/firts_task/HA_cluster_builder.php +++ b/pandora_console/general/first_task/HA_cluster_builder.php @@ -33,13 +33,13 @@ if (! check_acl($config['id_user'], 0, 'PM')) { exit; } -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ui_print_info_message(['no_close' => true, 'message' => __('There are no HA clusters defined yet.') ]); ?>
- __('Clusters')]); ?> + __('Clusters')]); ?>

diff --git a/pandora_console/general/firts_task/cluster_builder.php b/pandora_console/general/first_task/cluster_builder.php similarity index 96% rename from pandora_console/general/firts_task/cluster_builder.php rename to pandora_console/general/first_task/cluster_builder.php index ba9d8c311a..e80d4e4b15 100644 --- a/pandora_console/general/firts_task/cluster_builder.php +++ b/pandora_console/general/first_task/cluster_builder.php @@ -24,7 +24,7 @@ if (! check_acl($config['id_user'], 0, 'AR') && ! check_acl($config['id_user'], return; } -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no clusters defined yet.') ]); @@ -32,7 +32,7 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no cluster
- __('Clusters')]); ?> + __('Clusters')]); ?>

diff --git a/pandora_console/general/firts_task/collections.php b/pandora_console/general/first_task/collections.php similarity index 98% rename from pandora_console/general/firts_task/collections.php rename to pandora_console/general/first_task/collections.php index 8e27ce6ee3..2ca4583bb9 100755 --- a/pandora_console/general/firts_task/collections.php +++ b/pandora_console/general/first_task/collections.php @@ -13,7 +13,7 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no collections defined yet.') ]); ?> diff --git a/pandora_console/general/firts_task/custom_fields.php b/pandora_console/general/first_task/custom_fields.php similarity index 94% rename from pandora_console/general/firts_task/custom_fields.php rename to pandora_console/general/first_task/custom_fields.php index 7d07ff9495..30f5b839c6 100644 --- a/pandora_console/general/firts_task/custom_fields.php +++ b/pandora_console/general/first_task/custom_fields.php @@ -13,7 +13,7 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no custom fields defined yet.') ]); @@ -21,7 +21,7 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no custom
- __('Custom Fields')]); ?> + __('Custom Fields')]); ?>

diff --git a/pandora_console/general/firts_task/custom_graphs.php b/pandora_console/general/first_task/custom_graphs.php similarity index 94% rename from pandora_console/general/firts_task/custom_graphs.php rename to pandora_console/general/first_task/custom_graphs.php index e22187c6f5..d49001449a 100644 --- a/pandora_console/general/firts_task/custom_graphs.php +++ b/pandora_console/general/first_task/custom_graphs.php @@ -13,7 +13,7 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no custom graphs defined yet.') ]); @@ -21,7 +21,7 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no custom

- __('Custom Graphs')]); ?> + __('Custom Graphs')]); ?>

diff --git a/pandora_console/general/firts_task/fields_manager.php b/pandora_console/general/first_task/fields_manager.php similarity index 94% rename from pandora_console/general/firts_task/fields_manager.php rename to pandora_console/general/first_task/fields_manager.php index f81de216db..2ef6e70f55 100755 --- a/pandora_console/general/firts_task/fields_manager.php +++ b/pandora_console/general/first_task/fields_manager.php @@ -13,13 +13,13 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no custom fields defined yet.') ]); ?>

- __('Fields Manager')]); ?> + __('Fields Manager')]); ?>

diff --git a/pandora_console/general/firts_task/incidents.php b/pandora_console/general/first_task/incidents.php similarity index 95% rename from pandora_console/general/firts_task/incidents.php rename to pandora_console/general/first_task/incidents.php index daa83588e3..20630ff5e3 100644 --- a/pandora_console/general/firts_task/incidents.php +++ b/pandora_console/general/first_task/incidents.php @@ -15,7 +15,7 @@ global $config; global $incident_w; global $incident_m; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no incidents defined yet.') ]); @@ -25,7 +25,7 @@ if ($incident_w || $incident_m) {

- __('Incidents')]); ?> + __('Incidents')]); ?>

diff --git a/pandora_console/general/firts_task/map_builder.php b/pandora_console/general/first_task/map_builder.php similarity index 95% rename from pandora_console/general/firts_task/map_builder.php rename to pandora_console/general/first_task/map_builder.php index 352f7374e5..509f967195 100755 --- a/pandora_console/general/firts_task/map_builder.php +++ b/pandora_console/general/first_task/map_builder.php @@ -15,7 +15,7 @@ global $config; global $vconsoles_write; global $vconsoles_manage; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ui_print_info_message( [ @@ -28,7 +28,7 @@ if ($vconsoles_write || $vconsoles_manage) {

- __('Visual Console')]); ?> + __('Visual Console')]); ?>

diff --git a/pandora_console/general/firts_task/network_map.php b/pandora_console/general/first_task/network_map.php similarity index 95% rename from pandora_console/general/firts_task/network_map.php rename to pandora_console/general/first_task/network_map.php index 0526f936aa..f1de76c08b 100755 --- a/pandora_console/general/firts_task/network_map.php +++ b/pandora_console/general/first_task/network_map.php @@ -13,7 +13,7 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no network map defined yet.') ]); @@ -23,7 +23,7 @@ $networkmap_types = networkmap_get_types($strict_user);

- __('Network Map')]); ?> + __('Network Map')]); ?>

diff --git a/pandora_console/general/first_task/omnishell.php b/pandora_console/general/first_task/omnishell.php new file mode 100644 index 0000000000..948204917c --- /dev/null +++ b/pandora_console/general/first_task/omnishell.php @@ -0,0 +1,56 @@ + + true, 'message' => __('There is no command defined yet.') ]); ?> + +

+
+ __('Omnishell')]); ?> +
+
+

+ '.__( + 'Omnishell is an enterprise feature which allows you to execute a structured command along any agent in your %s. The only requirement is to have remote configuration enabled in your agent.', + io_safe_output(get_product_name()) + ).'

'; + + echo '

'.__( + 'You can execute any command on as many agents you need, and check the execution on all of them using the Omnishell Command View' + ).'

'; + ?> +

+ +
+ +
+ +
+
diff --git a/pandora_console/general/firts_task/planned_downtime.php b/pandora_console/general/first_task/planned_downtime.php similarity index 94% rename from pandora_console/general/firts_task/planned_downtime.php rename to pandora_console/general/first_task/planned_downtime.php index 21bfb4b083..83c6cd9384 100644 --- a/pandora_console/general/firts_task/planned_downtime.php +++ b/pandora_console/general/first_task/planned_downtime.php @@ -13,13 +13,13 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no planned downtime defined yet.') ]); ?>
- __('Planned Downtime')]); ?> + __('Planned Downtime')]); ?>

diff --git a/pandora_console/general/firts_task/recon_view.php b/pandora_console/general/first_task/recon_view.php similarity index 95% rename from pandora_console/general/firts_task/recon_view.php rename to pandora_console/general/first_task/recon_view.php index 8c59b23f64..9eee373dec 100755 --- a/pandora_console/general/firts_task/recon_view.php +++ b/pandora_console/general/first_task/recon_view.php @@ -13,13 +13,13 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no discovery tasks defined yet.') ]); ?>

- __('Discovery server')]); ?> + __('Discovery server')]); ?>

diff --git a/pandora_console/general/firts_task/service_list.php b/pandora_console/general/first_task/service_list.php similarity index 95% rename from pandora_console/general/firts_task/service_list.php rename to pandora_console/general/first_task/service_list.php index 424bc60400..f4a56a826b 100755 --- a/pandora_console/general/firts_task/service_list.php +++ b/pandora_console/general/first_task/service_list.php @@ -15,14 +15,14 @@ global $config; global $agent_w; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no services defined yet.') ]); ?>

- __('Services')]); ?> + __('Services')]); ?>

diff --git a/pandora_console/general/firts_task/snmp_filters.php b/pandora_console/general/first_task/snmp_filters.php similarity index 95% rename from pandora_console/general/firts_task/snmp_filters.php rename to pandora_console/general/first_task/snmp_filters.php index 602702da69..724c9da31f 100755 --- a/pandora_console/general/firts_task/snmp_filters.php +++ b/pandora_console/general/first_task/snmp_filters.php @@ -13,13 +13,13 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no SNMP filter defined yet.') ]); ?>

- __('SNMP Filter')]); ?> + __('SNMP Filter')]); ?>

diff --git a/pandora_console/general/firts_task/tags.php b/pandora_console/general/first_task/tags.php similarity index 94% rename from pandora_console/general/firts_task/tags.php rename to pandora_console/general/first_task/tags.php index 38c006d3b2..ea8086357c 100755 --- a/pandora_console/general/firts_task/tags.php +++ b/pandora_console/general/first_task/tags.php @@ -13,13 +13,13 @@ // GNU General Public License for more details. global $config; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no tags defined yet.') ]); ?>

- __('Tags')]); ?> + __('Tags')]); ?>

diff --git a/pandora_console/general/firts_task/transactional_list.php b/pandora_console/general/first_task/transactional_list.php similarity index 95% rename from pandora_console/general/firts_task/transactional_list.php rename to pandora_console/general/first_task/transactional_list.php index 6edc964ad7..40381f2da8 100644 --- a/pandora_console/general/firts_task/transactional_list.php +++ b/pandora_console/general/first_task/transactional_list.php @@ -15,7 +15,7 @@ global $config; global $networkmaps_write; global $networkmaps_manage; check_login(); -ui_require_css_file('firts_task'); +ui_require_css_file('first_task'); ?> true, 'message' => __('There are no transactions defined yet.') ]); @@ -25,7 +25,7 @@ if ($networkmaps_write || $networkmaps_manage) {

- __('Transactions')]); ?> + __('Transactions')]); ?>

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..b48590074c 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -486,6 +486,7 @@ if ($id_agente) { $agent_wizard['active'] = false; } + $total_incidents = agents_get_count_incidents($id_agente); // Incident tab. @@ -546,6 +547,7 @@ if ($id_agente) { 'group' => $grouptab, 'gis' => $gistab, 'agent_wizard' => $agent_wizard, + ]; } @@ -696,25 +698,28 @@ if ($id_agente) { break; } - ui_print_page_header( - agents_get_alias($id_agente), - 'images/setup.png', - false, - $help_header, - true, - $onheader, - false, - '', - $config['item_title_size_text'], - '', - ui_print_breadcrums( - [ - __('Resources'), - __('Manage agents'), - ''.$tab_name.'', - ] - ) - ); + $pure = get_parameter('pure', 0); + if (!$pure) { + ui_print_page_header( + agents_get_alias($id_agente), + 'images/setup.png', + false, + $help_header, + true, + $onheader, + false, + '', + $config['item_title_size_text'], + '', + ui_print_breadcrums( + [ + __('Resources'), + __('Manage agents'), + ''.$tab_name.'', + ] + ) + ); + } } else { // Create agent. ui_print_page_header( diff --git a/pandora_console/godmode/agentes/fields_manager.php b/pandora_console/godmode/agentes/fields_manager.php index 20a9db547a..1536e5c278 100644 --- a/pandora_console/godmode/agentes/fields_manager.php +++ b/pandora_console/godmode/agentes/fields_manager.php @@ -126,7 +126,7 @@ if ($fields) { $table->size[3] = '8%'; $table->data = []; } else { - include_once $config['homedir'].'/general/firts_task/fields_manager.php'; + include_once $config['homedir'].'/general/first_task/fields_manager.php'; return; } diff --git a/pandora_console/godmode/agentes/planned_downtime.list.php b/pandora_console/godmode/agentes/planned_downtime.list.php index 01f30afba6..f116b2dcd8 100755 --- a/pandora_console/godmode/agentes/planned_downtime.list.php +++ b/pandora_console/godmode/agentes/planned_downtime.list.php @@ -352,7 +352,7 @@ if (!empty($groups)) { // No downtimes cause the user has not anyone. if (!$downtimes && !$filter_performed) { - include_once $config['homedir'].'/general/firts_task/planned_downtime.php'; + include_once $config['homedir'].'/general/first_task/planned_downtime.php'; } // No downtimes cause the user performed a search. else if (!$downtimes) { diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index edf7be1873..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'; @@ -346,6 +346,8 @@ if (check_acl($config['id_user'], 0, 'PM') || check_acl($config['id_user'], 0, ' $sub['godmode/setup/links']['id'] = 'Links'; $sub['tools/diagnostics']['text'] = __('Diagnostic info'); $sub['tools/diagnostics']['id'] = 'Diagnostic info'; + enterprise_hook('omnishell'); + $sub['godmode/setup/news']['text'] = __('Site news'); $sub['godmode/setup/news']['id'] = 'Site news'; $sub['godmode/setup/file_manager']['text'] = __('File manager'); diff --git a/pandora_console/godmode/reporting/graphs.php b/pandora_console/godmode/reporting/graphs.php index e9f1aef011..155eb560db 100644 --- a/pandora_console/godmode/reporting/graphs.php +++ b/pandora_console/godmode/reporting/graphs.php @@ -337,7 +337,7 @@ $table_aux = new stdClass(); echo '

'; } else { - include_once $config['homedir'].'/general/firts_task/custom_graphs.php'; + include_once $config['homedir'].'/general/first_task/custom_graphs.php'; } ?> diff --git a/pandora_console/godmode/reporting/map_builder.php b/pandora_console/godmode/reporting/map_builder.php index 8f5774b3a9..96f86191d7 100644 --- a/pandora_console/godmode/reporting/map_builder.php +++ b/pandora_console/godmode/reporting/map_builder.php @@ -395,7 +395,7 @@ if ($own_info['is_admin'] || $vconsoles_read) { if (!$maps && !is_metaconsole()) { $total = count(visual_map_get_user_layouts($config['id_user'], false, false, false)); if (!$total) { - include_once $config['homedir'].'/general/firts_task/map_builder.php'; + include_once $config['homedir'].'/general/first_task/map_builder.php'; } else { ui_print_info_message( [ 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/servers/servers.build_table.php b/pandora_console/godmode/servers/servers.build_table.php index f0e2a4ad08..0006fc3e9b 100644 --- a/pandora_console/godmode/servers/servers.build_table.php +++ b/pandora_console/godmode/servers/servers.build_table.php @@ -154,7 +154,7 @@ foreach ($servers as $server) { if ($server['type'] == 'recon') { $data[8] .= ''; $data[8] .= html_print_image( - 'images/firts_task/icono_grande_reconserver.png', + 'images/first_task/icono_grande_reconserver.png', true, [ 'title' => __('Manage Discovery tasks'), diff --git a/pandora_console/godmode/tag/tag.php b/pandora_console/godmode/tag/tag.php index 680d0b7a45..cb5fb27ab1 100644 --- a/pandora_console/godmode/tag/tag.php +++ b/pandora_console/godmode/tag/tag.php @@ -304,7 +304,7 @@ if (!empty($result)) { } else if ($filter_performed) { echo $filter_form; } else { - include $config['homedir'].'/general/firts_task/tags.php'; + include $config['homedir'].'/general/first_task/tags.php'; return; } } diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index ed523d0b82..da6f4e572e 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -145,7 +145,7 @@ class DiscoveryTaskList extends Wizard $ret2 = $this->showList(); if ($ret === false && $ret2 === false) { - include_once $config['homedir'].'/general/firts_task/recon_view.php'; + include_once $config['homedir'].'/general/first_task/recon_view.php'; } else { $form = [ 'form' => [ @@ -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 5ffeb716d9..3e43f0bf69 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -436,11 +436,15 @@ class Wizard * * @param array $input Definition of target block to be printed. * @param boolean $return Return as string or direct output. + * @param boolean $direct Avoid encapsulation if input print is direct. * * @return string HTML content. */ - public function printBlock(array $input, bool $return=false, bool $not_direct=false) - { + public function printBlock( + array $input, + bool $return=false, + bool $direct=false + ) { $output = ''; if ($input['hidden'] == 1) { $class = ' hidden'; @@ -453,7 +457,8 @@ class Wizard } if (is_array($input['block_content']) === true) { - $not_direct = (bool) $input['direct']; + $direct = (bool) $input['direct']; + $toggle = (bool) $input['toggle']; // Print independent block of inputs. $output .= '
  • '; @@ -462,17 +467,44 @@ class Wizard $output .= '<'.$input['wrapper'].' id="'.$input['block_id'].'" class="'.$class.'">'; } - if (!$not_direct) { + if (!$direct) { // Avoid encapsulation if input is direct => 1. $output .= '
      '; } - foreach ($input['block_content'] as $input) { - $output .= $this->printBlock($input, $return, (bool) $not_direct); + $html = ''; + + foreach ($input['block_content'] as $in) { + $html .= $this->printBlock( + $in, + $return, + (bool) $direct + ); + } + + if ($toggle === true) { + $output .= ui_print_toggle( + [ + 'name' => (isset($input['toggle_name']) ? $input['toggle_name'] : 'toggle_'.uniqid()), + 'content' => $html, + 'title' => $input['toggle_title'], + 'id' => $input['toggle_id'], + 'hidden_default' => $input['toggle_hidden_default'], + 'return' => (isset($input['toggle_return']) ? $input['toggle_return'] : true), + 'toggle_class' => $input['toggle_toggle_class'], + 'main_class' => $input['toggle_main_class'], + 'container_class' => $input['toggle_container_class'], + 'img_a' => $input['toggle_img_a'], + 'img_b' => $input['toggle_img_b'], + 'clean' => (isset($input['toggle_clean']) ? $input['toggle_clean'] : true), + ] + ); + } else { + $output .= $html; } // Close block. - if (!$not_direct) { + if (!$direct) { $output .= '
    '; } @@ -483,7 +515,7 @@ class Wizard $output .= '
  • '; } else { if ($input['arguments']['type'] != 'hidden') { - if (!$not_direct) { + if (!$direct) { $output .= '
  • '; } @@ -491,7 +523,7 @@ class Wizard $output .= $this->printInput($input['arguments']); // Allow dynamic content. $output .= $input['extra']; - if (!$not_direct) { + if (!$direct) { $output .= '
  • '; } } else { @@ -799,15 +831,18 @@ class Wizard $first_block_printed = true; } - $output .= '
    '; + $output .= '
    '; foreach ($row['columns'] as $column) { $width = isset($column['width']) ? 'width: '.$column['width'].';' : 'width: 100%;'; $padding_left = isset($column['padding-left']) ? 'padding-left: '.$column['padding-left'].';' : 'padding-left: 0;'; $padding_right = isset($column['padding-right']) ? 'padding-right: '.$column['padding-right'].';' : 'padding-right: 0;'; $extra_styles = isset($column['style']) ? $column['style'] : ''; + $class = isset($column['class']) ? $column['class'] : ''; - $output .= '
    '; + $output .= '
    '; foreach ($column['inputs'] as $input) { if (is_array($input)) { diff --git a/pandora_console/images/firts_task/icono-cluster-activo.png b/pandora_console/images/first_task/icono-cluster-activo.png similarity index 100% rename from pandora_console/images/firts_task/icono-cluster-activo.png rename to pandora_console/images/first_task/icono-cluster-activo.png diff --git a/pandora_console/images/firts_task/icono_aws.png b/pandora_console/images/first_task/icono_aws.png similarity index 100% rename from pandora_console/images/firts_task/icono_aws.png rename to pandora_console/images/first_task/icono_aws.png diff --git a/pandora_console/images/firts_task/icono_grande_custom_reporting.png b/pandora_console/images/first_task/icono_grande_custom_reporting.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_custom_reporting.png rename to pandora_console/images/first_task/icono_grande_custom_reporting.png diff --git a/pandora_console/images/firts_task/icono_grande_event_alerts.png b/pandora_console/images/first_task/icono_grande_event_alerts.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_event_alerts.png rename to pandora_console/images/first_task/icono_grande_event_alerts.png diff --git a/pandora_console/images/firts_task/icono_grande_export.png b/pandora_console/images/first_task/icono_grande_export.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_export.png rename to pandora_console/images/first_task/icono_grande_export.png diff --git a/pandora_console/images/firts_task/icono_grande_gestiondetags.png b/pandora_console/images/first_task/icono_grande_gestiondetags.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_gestiondetags.png rename to pandora_console/images/first_task/icono_grande_gestiondetags.png diff --git a/pandora_console/images/firts_task/icono_grande_import.png b/pandora_console/images/first_task/icono_grande_import.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_import.png rename to pandora_console/images/first_task/icono_grande_import.png diff --git a/pandora_console/images/firts_task/icono_grande_incidencia.png b/pandora_console/images/first_task/icono_grande_incidencia.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_incidencia.png rename to pandora_console/images/first_task/icono_grande_incidencia.png diff --git a/pandora_console/images/firts_task/icono_grande_inventario.png b/pandora_console/images/first_task/icono_grande_inventario.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_inventario.png rename to pandora_console/images/first_task/icono_grande_inventario.png diff --git a/pandora_console/images/firts_task/icono_grande_licencia.png b/pandora_console/images/first_task/icono_grande_licencia.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_licencia.png rename to pandora_console/images/first_task/icono_grande_licencia.png diff --git a/pandora_console/images/firts_task/icono_grande_reconserver.png b/pandora_console/images/first_task/icono_grande_reconserver.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_reconserver.png rename to pandora_console/images/first_task/icono_grande_reconserver.png diff --git a/pandora_console/images/firts_task/icono_grande_registro_plugin.png b/pandora_console/images/first_task/icono_grande_registro_plugin.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_registro_plugin.png rename to pandora_console/images/first_task/icono_grande_registro_plugin.png diff --git a/pandora_console/images/firts_task/icono_grande_servicios.png b/pandora_console/images/first_task/icono_grande_servicios.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_servicios.png rename to pandora_console/images/first_task/icono_grande_servicios.png diff --git a/pandora_console/images/firts_task/icono_grande_topology.png b/pandora_console/images/first_task/icono_grande_topology.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_topology.png rename to pandora_console/images/first_task/icono_grande_topology.png diff --git a/pandora_console/images/firts_task/icono_grande_visualconsole.png b/pandora_console/images/first_task/icono_grande_visualconsole.png similarity index 100% rename from pandora_console/images/firts_task/icono_grande_visualconsole.png rename to pandora_console/images/first_task/icono_grande_visualconsole.png diff --git a/pandora_console/images/firts_task/icono_manage_agents.png b/pandora_console/images/first_task/icono_manage_agents.png similarity index 100% rename from pandora_console/images/firts_task/icono_manage_agents.png rename to pandora_console/images/first_task/icono_manage_agents.png diff --git a/pandora_console/images/first_task/omnishell.png b/pandora_console/images/first_task/omnishell.png new file mode 100644 index 0000000000000000000000000000000000000000..8724d322fb21ecbccfb69ac82b9e07ceb73725ba GIT binary patch literal 3129 zcmV-9494?`P)e92`3<&060O&2||{$g6#jPFf|8={}VjF6TDx|v=T+MEE(HahVCkg z1S~Mpr|wp(-4=p{g@uKMg@uKMg@xr1X*K-^{Px@Lv3$Cbj|g8%<>UFUzy7;Cusz7L zd@SW>q#o_N*uHy6dxoJL2s-lVK|cDHL$>lUk^{2M_zY-2w7i|j$H38kCZFysZ>RYE zD~6$Z7}oMBb{qx+a!Jil2MBum9tDI01YNGOfC@?44FzH70RjkUkD0|Z3=6dHdV&D* z)Rca0H&ij)60d=eFvr=f%MeY9Px~p+K9=nx4-fSeXPb7Y&7BWjKJK_TS_{q(;182M(bv zHpYN;v3+9E0wz4qhN+1h?Ki9$s*{C9^+%q^E(qNHP=v2Rmj693B&xfLe1dls(lw$n*6}NKh z7RuRsutXEf27%H-tC~T8@p%&;`5rMo!&tr9`lappgX4_D?l3o?P8nF1c$EO*0AW<8 zwnPxtVt@ZdNypYNF3m9Uw75({XNS-0T80-KvfBX{A`FzTo>#=%9%~Tw-ft$o*f+Dxq6}Hp>D_@ zj3+;-fNX23Sycn(6LhK=1fLYVL;La)CkmYZs{zC=596SvrSXF|6{)#hryrUfRE5cC zCO%y2NSF|}&j4x~^8-2- zzrgGq==kRXC;rX&Oa(-*0v{q0`4Uc|BZ2@n{KtVG`$c?C)Kz`B#XhiRc=Cl2~IxGi)Y*{G&9)0KN1{$Qq%j1fTX+hK4}RFju~fgrJLY64x3Z zV3?90N zBKt~cwTZI;Q$T1HFe`dS*A%gAnv;;(%3#DGLOl?*IV?X)Fgf)doL8HUCwM ztLXbQGYsrZ@wiUYL1?6A$e|&AK^PzxFtTU^a0)jX1hM$Y?gCBmf&)Dv2D}Gt9onHW zAmq{vxb53FW=d@p%`^=`rRKdL2we*ZTO3SX8|Z@yfIKQt$OFUNDMjDauDx{K+z`<(7Ci#je9pC1}r;~uLr4FF&^?@(V7Wrti7eN&qmeS z;UrB0$d0zjHMI=YHG;@4A2<{r38s7Xp3tm>2ttZLEby2ap%uo29}Zv^rw!$+8x zl^tF34C!D35j8h9r5JswePpJ2jIHYpRNtFJxfY8;~*%)McDhR|51TD_e7X_{u4^7%9 z41)5e;X>OE?m%W00d@MK8VL8|Bafl+7x$bT3>ogwSW2Bs&8W61`f>3qInxklhoIor}{1eU5a1kVmH~wo#=yv(JUJj*HGxp1h!rJ;!s58ZeDWEDQwE|{0|-HF zb)#u`GX_xIn{w}Fsw(*80OD4ZoA5$yoRtnl>zqNbXa(>OMtH4+In#GJ5j8BKZ5pRk zAll~)f;Q_uou@Jd7`|Q_OWC7~R$`p!np&4Y7s4m_5yE*L1Bf<*&>X26 zh&F@3KpX@E-l8bRM~6W;Eg;&S5X4xr<~w?|yT9dYuMEQJ0CC{~0u1(przg%J92p3$ zicNNT3y67GY6oJFqsg6lN1iOrVDkqOc!>Q<>>VDG+9jeiHfjxO z8-AF}f#d;iGz^J$ce)Kx9sk-F2HVZPrU->;a}pkl;3Ua2Mp>8Sr`o05y6Ld(`>)QS zcd-tXZbG4S(Gqt#Ri@N8V^Tro*~ImJ1*Z$~p&>Z-xH9Z#O?cO8!uMj6l<*-=RrH&~ z$EYFSu%z%C{;$8kyMa7bi+Q!Y|EATAC?YG1HvcK;E$|m_7|=s?-2h8v0;l49MVZa4 zn~_gM_7?a9=2jG4QTS@;jhR8-_V@y50GFgK4JbgZLHgR|sa$xP(-vSkJu;MU2-=-|AD%Q=RH@_@;>zCl~$ov-{^zdQ~e^fAB-}} zLqc1@q#je6yv<{q--lFx;DDOfMohI#sa;_V;7!dL2!00ejZnMKz}eA%{IkTOoKelE!leONSXcs-{|hhx%Xv^( Tj(pQf00000NkvXXu0mjfv>2@* literal 0 HcmV?d00001 diff --git a/pandora_console/images/firts_task/op_workspace.menu.png b/pandora_console/images/first_task/op_workspace.menu.png similarity index 100% rename from pandora_console/images/firts_task/op_workspace.menu.png rename to pandora_console/images/first_task/op_workspace.menu.png diff --git a/pandora_console/images/firts_task/slave-mode.png b/pandora_console/images/first_task/slave-mode.png similarity index 100% rename from pandora_console/images/firts_task/slave-mode.png rename to pandora_console/images/first_task/slave-mode.png diff --git a/pandora_console/images/sap_icon.png b/pandora_console/images/sap_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..536c43b28b8bc6407d4197fc7db3abab6b170229 GIT binary patch literal 324 zcmV-K0lWT*P) __('Custom'), 'AWS' => __('Aws'), 'AZURE' => __('Azure'), + 'SAP' => __('SAP'), // 'GOOGLE' => __('Google'), ], 'selected' => (isset($values['product']) ? $values['product'] : 'CUSTOM'), @@ -900,6 +901,7 @@ class CredentialStore extends Wizard case 'GOOGLE': // Need further investigation. case 'CUSTOM': + case 'SAP': $user_label = __('Account ID'); $pass_label = __('Password'); $extra1 = false; @@ -1038,7 +1040,12 @@ class CredentialStore extends Wizard $('#div-extra_2 label').text(''); $('#div-extra_1').show(); $('#div-extra_2').show(); - } + } else if ($('#product :selected').val() == "SAP") { + $('#div-username label').text(''); + $('#div-password label').text(''); + $('#div-extra_1').hide(); + $('#div-extra_2').hide(); + } } /** diff --git a/pandora_console/include/class/Diagnostics.class.php b/pandora_console/include/class/Diagnostics.class.php index 94acbc4ba2..ee61ec743d 100644 --- a/pandora_console/include/class/Diagnostics.class.php +++ b/pandora_console/include/class/Diagnostics.class.php @@ -68,6 +68,10 @@ class Diagnostics extends Wizard // Check access. check_login(); + $this->url = ui_get_full_url( + 'index.php?sec=gextensions&sec2=tools/diagnostics' + ); + $this->ajaxController = $page; $this->pdf = $pdf; $this->product_name = io_safe_output(get_product_name()); @@ -123,15 +127,34 @@ class Diagnostics extends Wizard { global $config; + if ($this->pdf === true) { + $this->exportPDF(); + exit; + } + ui_require_css_file('diagnostics'); + $pdf_url = $this->url.'&pdf=true'; + $pdf_img = html_print_image( + 'images/pdf.png', + true, + ['title' => __('Export to PDF')] + ); + $header_buttons = [ + 'csv' => [ + 'active' => false, + 'text' => ''.$pdf_img.'', + ], + ]; + // Header. ui_print_page_header( __('%s Diagnostic tool', $this->product_name), 'images/gm_massive_operations.png', false, 'diagnostic_tool_tab', - true + true, + $header_buttons ); // Print all Methods Diagnostic Info. @@ -2080,6 +2103,11 @@ class Diagnostics extends Wizard enterprise_include_once('/include/class/Pdf.class.php'); $mpdf = new Pdf([]); + // Ignore pending HTML outputs. + while (@ob_end_clean()) { + $ignore_me; + } + // ADD style. $mpdf->addStyle($config['homedir'].'/include/styles/diagnostics.css'); @@ -2112,6 +2140,8 @@ class Diagnostics extends Wizard // Write html filename. $mpdf->writePDFfile($filename); + + exit; } 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/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_html.php b/pandora_console/include/functions_html.php index 12a8ecfa88..e329af6013 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -1618,6 +1618,89 @@ function html_print_input_email(array $settings):string } +/** + * Render an input number element. + * + * @param array $settings Array with attributes input. + * only name is necessary. + * + * @return string + */ +function html_print_input_number(array $settings):string +{ + // TODO: const. + $valid_attrs = [ + 'accept', + 'disabled', + 'maxlength', + 'name', + 'readonly', + 'placeholder', + 'size', + 'value', + 'accesskey', + 'class', + 'dir', + 'id', + 'lang', + 'style', + 'tabindex', + 'title', + 'xml:lang', + 'onfocus', + 'onblur', + 'onselect', + 'onchange', + 'onclick', + 'ondblclick', + 'onmousedown', + 'onmouseup', + 'onmouseover', + 'onmousemove', + 'onmouseout', + 'onkeypress', + 'onkeydown', + 'onkeyup', + 'required', + 'pattern', + 'autocomplete', + ]; + + $output = ''; + if (isset($settings) === true && is_array($settings) === true) { + // Check Name is necessary. + if (isset($settings['name']) === true) { + $output = ' $attr_value) { + // Check valid attribute. + if (in_array($attribute, $valid_attrs) === false) { + continue; + } + + $output .= $attribute.'="'.$attr_value.'" '; + } + + $output .= $function.'/>'; + } + } + + return $output; +} + + /** * Render an input image element. * @@ -3309,6 +3392,10 @@ function html_print_input($data, $wrapper='div', $input_only=false) $output .= html_print_input_email($data); break; + case 'number': + $output .= html_print_input_number($data); + break; + case 'hidden': $output .= html_print_input_hidden( $data['name'], @@ -3413,7 +3500,8 @@ function html_print_input($data, $wrapper='div', $input_only=false) break; case 'submit': - $output .= '<'.$wrapper.' class="action-buttons" style="width: 100%">'.html_print_submit_button( + $width = (isset($data['width']) === true) ? 'width: '.$data['width'] : 'width: 100%'; + $output .= '<'.$wrapper.' class="action-buttons" style="'.$width.'">'.html_print_submit_button( ((isset($data['label']) === true) ? $data['label'] : 'OK'), ((isset($data['name']) === true) ? $data['name'] : ''), ((isset($data['disabled']) === true) ? $data['disabled'] : false), @@ -3498,6 +3586,10 @@ function html_print_input($data, $wrapper='div', $input_only=false) $output .= html_print_input_email($data); break; + case 'multicheck': + $output .= html_print_input_multicheck($data); + break; + default: // Ignore. break; @@ -3514,6 +3606,33 @@ function html_print_input($data, $wrapper='div', $input_only=false) } +/** + * Print all checkbox in the same row. + * + * @param array $data Array with attributes input. + * only name is necessary. + * + * @return string + */ +function html_print_input_multicheck(array $data):string +{ + $html = ''; + if (isset($data['data']) === true && is_array($data['data']) === true) { + foreach ($data['data'] as $key => $value) { + $html .= $value; + $html .= html_print_checkbox( + 'days_week_'.$key, + 1, + $data['checked'][$key], + true + ); + } + } + + return $html; +} + + /** * Print an autocomplete input filled out with Integria IMS users. * diff --git a/pandora_console/include/functions_menu.php b/pandora_console/include/functions_menu.php index 36785064ef..ee242a1624 100644 --- a/pandora_console/include/functions_menu.php +++ b/pandora_console/include/functions_menu.php @@ -536,7 +536,7 @@ function menu_add_extras(&$menu) $menu_extra['galertas']['sub']['godmode/alerts/configure_alert_action']['text'] = __('Manage alert actions'); $menu_extra['galertas']['sub']['godmode/alerts/configure_alert_command']['text'] = __('Manage commands'); - $menu_extra['galertas']['sub']['enterprise/godmode/alerts/alert_events']['text'] = __('Manage event alerts'); + $menu_extra['galertas']['sub']['enterprise/godmode/alerts/alert_correlation']['text'] = __('Manage event alerts'); $menu_extra['gservers']['sub']['enterprise/godmode/servers/manage_export_form']['text'] = __('Manage export targets'); diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index a430f02fdc..dd1cc5443e 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, @@ -2911,6 +2916,84 @@ function ui_progress( } +/** + * Generates a progress bar CSS based. + * Requires css progress.css + * + * @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( + array $data +) { + if (is_array($data) === false) { + // Failed. + return false; + } + + if (is_array($data['slices']) === false) { + // Failed. + return false; + } + + if (isset($data['width']) === false) { + $data['width'] = '100'; + } + + 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; + } + + ui_require_css_file('progress'); + + // Main container. + $output .= '
    '; + + foreach ($data['slices'] as $label => $def) { + $width = ($def['value'] * 100 / $total); + $output .= '
    '; - $output .= '
    '.html_print_image( + $output .= '
    '.html_print_image( $original, true, [ @@ -3643,7 +3736,8 @@ function ui_print_toggle($data) (isset($data['container_class']) === true) ? $data['container_class'] : 'white-box-content', (isset($data['main_class']) === true) ? $data['main_class'] : 'box-shadow white_table_graph', (isset($data['img_a']) === true) ? $data['img_a'] : 'images/arrow_down_green.png', - (isset($data['img_b']) === true) ? $data['img_b'] : 'images/arrow_right_green.png' + (isset($data['img_b']) === true) ? $data['img_b'] : 'images/arrow_right_green.png', + (isset($data['clean']) === true) ? $data['clean'] : false ); } diff --git a/pandora_console/include/javascript/alert.js b/pandora_console/include/javascript/alert.js new file mode 100644 index 0000000000..435649833d --- /dev/null +++ b/pandora_console/include/javascript/alert.js @@ -0,0 +1,174 @@ +/* eslint-disable no-unused-vars */ +/* global $, load_modal, generalShowMsg, confirmDialog */ + +function allowDrop(ev) { + ev.preventDefault(); +} + +function drag(ev) { + ev.dataTransfer.setData("html", ev.target.outerHTML); +} + +function drop(ev) { + ev.preventDefault(); + var data = document.createElement("span"); + var content = ev.dataTransfer.getData("html"); + if (content.includes("nexo")) { + content = "
    " + content; + } + data.innerHTML = content; + document.getElementById(ev.target.id).appendChild(data); +} + +function add_alert_action(settings) { + load_modal({ + target: $("#modal-add-action-form"), + form: "modal_form_add_actions", + url: settings.url_ajax, + modal: { + title: settings.title, + cancel: settings.btn_cancel, + ok: settings.btn_text + }, + onshow: { + page: settings.url, + method: "addAlertActionForm", + extradata: { + id: settings.id + } + }, + onsubmit: { + page: settings.url, + method: "addAlertAction", + dataType: "json" + }, + ajax_callback: add_alert_action_acept, + idMsgCallback: "msg-add-action" + }); +} + +function add_alert_action_acept(data, idMsg) { + if (data.error === 1) { + console.log(data.text); + return; + } + + if ($("#emptyli-al-" + data.id_alert).length > 0) { + $("#emptyli-al-" + data.id_alert).remove(); + } + + $.ajax({ + method: "post", + url: data.url, + data: { + page: data.page, + method: "addRowActionAjax", + id_alert: data.id_alert, + id_action: data.id_action + }, + dataType: "html", + success: function(li) { + $(".ui-dialog-content").dialog("close"); + $("#ul-al-" + data.id_alert).append(li); + }, + error: function(error) { + console.log(error); + } + }); +} + +function delete_alert_action(settings) { + confirmDialog({ + title: settings.title, + message: settings.msg, + onAccept: function() { + $.ajax({ + method: "post", + url: settings.url, + data: { + page: settings.page, + method: "deleteActionAlert", + id_alert: settings.id_alert, + id_action: settings.id_action + }, + dataType: "json", + success: function(data) { + // Delete row table. + $( + "#li-al-" + settings.id_alert + "-act-" + settings.id_action + ).remove(); + + var num_row = $("#ul-al-" + settings.id_alert + " li").length; + if (num_row === 0) { + var emptyli = + "
  • " + + settings.emptyli + + "
  • "; + $("#ul-al-" + settings.id_alert).append(emptyli); + } + }, + error: function(error) { + console.log(error); + } + }); + } + }); +} + +function standby_alert(settings) { + confirmDialog({ + title: settings.title, + message: settings.msg, + onAccept: function() { + $.ajax({ + method: "post", + url: settings.url, + data: { + page: settings.page, + method: "standByAlert", + id_alert: settings.id_alert, + standby: settings.standby + }, + dataType: "html", + success: function(data) { + $("#standby-alert-" + settings.id_alert).empty(); + $("#standby-alert-" + settings.id_alert).append(data); + }, + error: function(error) { + console.log(error); + } + }); + } + }); +} + +function disabled_alert(settings) { + confirmDialog({ + title: settings.title, + message: settings.msg, + onAccept: function() { + $.ajax({ + method: "post", + url: settings.url, + data: { + page: settings.page, + method: "disabledAlert", + id_alert: settings.id_alert, + disabled: settings.disabled + }, + dataType: "json", + success: function(data) { + $("#disabled-alert-" + settings.id_alert).empty(); + $("#disabled-alert-" + settings.id_alert).append(data.disabled); + $("#status-alert-" + settings.id_alert).empty(); + $("#status-alert-" + settings.id_alert).append(data.status); + }, + error: function(error) { + console.log(error); + } + }); + } + }); +} diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index c3ed855213..6a29b6b552 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -1885,12 +1885,35 @@ function load_modal(settings) { } data.append("page", settings.onshow.page); data.append("method", settings.onshow.method); + if (settings.onshow.extradata != undefined) { + data.append("extradata", JSON.stringify(settings.onshow.extradata)); + } + + if (settings.target == undefined) { + var uniq = uniqId(); + var div = document.createElement("div"); + div.id = "div-modal-" + uniq; + div.style.display = "none"; + + document.getElementById("main").append(div); + + var id_modal_target = "#div-modal-" + uniq; + + settings.target = $(id_modal_target); + } var width = 630; if (settings.onshow.width) { width = settings.onshow.width; } + if (settings.modal.overlay == undefined) { + settings.modal.overlay = { + opacity: 0.5, + background: "black" + }; + } + settings.target.html("Loading modal..."); settings.target .dialog({ @@ -2081,14 +2104,16 @@ function load_modal(settings) { modal: true, title: settings.modal.title, width: width, - overlay: { - opacity: 0.5, - background: "black" - }, + overlay: settings.modal.overlay, buttons: required_buttons, closeOnEscape: false, open: function() { $(".ui-dialog-titlebar-close").hide(); + }, + close: function() { + if (id_modal_target != undefined) { + $(id_modal_target).remove(); + } } }); }, @@ -2100,13 +2125,7 @@ function load_modal(settings) { //Function that shows a dialog box to confirm closures of generic manners. The modal id is random function confirmDialog(settings) { - var randomStr = - Math.random() - .toString(36) - .substring(2, 15) + - Math.random() - .toString(36) - .substring(2, 15); + var randomStr = uniqId(); $("body").append( '
    ' + settings.message + "
    " @@ -2142,6 +2161,18 @@ function confirmDialog(settings) { .show(); } +function uniqId() { + var randomStr = + Math.random() + .toString(36) + .substring(2, 15) + + Math.random() + .toString(36) + .substring(2, 15); + + return randomStr; +} + /** * Function to show modal with message Validation. * diff --git a/pandora_console/include/lib/WebSocketServer.php b/pandora_console/include/lib/WebSocketServer.php index 2d9eb1d9fd..dfdc81d075 100644 --- a/pandora_console/include/lib/WebSocketServer.php +++ b/pandora_console/include/lib/WebSocketServer.php @@ -439,6 +439,9 @@ abstract class WebSocketServer if ((time() - $this->lastTickTimestamp) > $this->tickInterval) { $this->lastTickTimestamp = time(); $this->tick(); + + // Keep connection with DB active. + $this->dbHearthbeat(); } socket_select($read, $write, $except, 0, $this->timeout); @@ -1530,4 +1533,23 @@ abstract class WebSocketServer } + /** + * Keeps db connection opened. + * + * @return void + */ + public function dbHearthbeat() + { + global $config; + + if (isset($config['dbconnection']) === false + || mysqli_ping($config['dbconnection']) === false + ) { + // Retry connection. + db_select_engine(); + $config['dbconnection'] = db_connect(); + } + } + + } diff --git a/pandora_console/include/styles/alert.css b/pandora_console/include/styles/alert.css new file mode 100644 index 0000000000..3368bf0796 --- /dev/null +++ b/pandora_console/include/styles/alert.css @@ -0,0 +1,128 @@ +li#li-buttons-alert-list > div { + margin-left: 10px; +} + +li#li-buttons-alert-list > label, +li#li-filters-alert-list > label { + width: initial; +} + +form#advanced_filters_alert ul li label, +form#general_filters_alert ul li label { + width: 150px; +} + +form#conditions_filters_alert ul li label:first-child { + width: 300px; +} + +li#li-name-group input { + margin-right: 50px; +} + +li#li-description textarea { + flex: 1 1 auto; +} + +li#li-from-to-threshold > label:not(:first-child), +li#li-time-from-to > label:not(:first-child) { + width: initial; + margin-right: 15px; +} + +li#li-from-to-threshold > input, +li#li-time-from-to > input { + margin-right: 15px; +} + +form#advanced_filters_alert textarea { + flex: 1 1 auto; + height: 5em; + min-height: 5em; +} + +form#advanced_filters_alert ul li label img { + margin-bottom: -2px; + margin-left: 5px; +} + +/*DRAG DROP*/ +#threshold_manual, +#threshold_default { + /*TODO: UGLY*/ + width: initial !important; + margin-right: 10px; +} + +img.handle-alerts { + width: 20px; + cursor: move; +} + +.content { + width: 80%; + min-height: 4em; + border: 1px solid #ddd; + padding-top: 1em; + padding-bottom: 1em; +} +ul.sample { + max-width: 50%; + flex-grow: 1; + justify-content: space-between; +} +ul.sample li { + padding-bottom: 1em; +} +ul.sample li:last-child { + padding-bottom: 0; +} +div.target { + flex-grow: 1; + margin-left: 3em; + border: 1px solid #ddd; +} + +.field { + display: inline-block; + border-radius: 10px; + padding: 5px; + padding-left: 8px; + padding-right: 8px; + margin: 3px; + color: #fff; + font-family: "lato-lighter", "Open Sans", sans-serif; + font-weight: 600; + background-color: #333; +} + +.log { + background-color: #638460; +} +.event { + background-color: #587cff; +} + +.operator { + background-color: #908787; +} + +.variable { + background-color: #82b92e; +} + +.modifier { + background-color: #cba9d2; +} + +.nexo { + background-color: #424242; +} + +.rules div { + display: inline-block; +} + +.inEdit { + background-color: #888; +} diff --git a/pandora_console/include/styles/discovery.css b/pandora_console/include/styles/discovery.css index 2aee23f645..fc5749b4a8 100644 --- a/pandora_console/include/styles/discovery.css +++ b/pandora_console/include/styles/discovery.css @@ -31,7 +31,7 @@ li.discovery > a label { } div.data_container > label { - font-family: "lato-bolder", "Open Sans", sans-serif; + font-family: "lato", "Open Sans", sans-serif; font-weight: lighter; } @@ -204,6 +204,7 @@ label { width: 100%; } +li > input[type="number"], li > input[type="text"], li > input[type="email"], li > input[type="password"], diff --git a/pandora_console/include/styles/firts_task.css b/pandora_console/include/styles/first_task.css similarity index 88% rename from pandora_console/include/styles/firts_task.css rename to pandora_console/include/styles/first_task.css index be75dd632d..06aa36af82 100755 --- a/pandora_console/include/styles/firts_task.css +++ b/pandora_console/include/styles/first_task.css @@ -1,5 +1,11 @@ +.new_task p, +.new_task div { + font-family: "lato-lighter", "Open Sans", sans-serif; + font-weight: lighter; +} .new_task { margin-top: 30px; + min-width: 600px; left: 20px; width: 60%; height: 300px; @@ -30,6 +36,7 @@ div.new_task_cluster > div { .image_task { width: 20%; + min-width: 175px; height: 100%; float: left; } @@ -47,7 +54,7 @@ div.new_task_cluster > div { .text_task { width: 70%; - float: right; + float: left; height: 100%; padding-right: 25px; } diff --git a/pandora_console/include/styles/omnishell.css b/pandora_console/include/styles/omnishell.css new file mode 100644 index 0000000000..265ca5f445 --- /dev/null +++ b/pandora_console/include/styles/omnishell.css @@ -0,0 +1,515 @@ +.edit_yaml { + margin-left: 39px; + margin-top: 10px; + margin-bottom: 10px; +} + +.margin_button { + margin-right: 5px; +} + +.container-target { + display: flex; + flex-flow: row wrap; +} + +.element-target { + width: 20px; + margin: 2px; + height: 20px; +} + +.element-target-big { + width: 100px; + margin: 2px; + height: 100px; +} + +.element-target-big:hover { + box-shadow: 0 0 10px -5px #424242; +} + +.element-target-big:before { + content: attr(data-label); + position: relative; + text-align: center; + width: 100%; + height: 100%; + color: #373737; + font-weight: bolder; + display: flex; + flex-direction: row; + font-size: 1.8em; + align-items: center; + justify-content: center; + overflow: hidden; + font-family: "lato-bolder", "Open Sans", sans-serif; + text-decoration: none; +} + +.container-target a:hover { + text-decoration: none; +} + +.status-normal { + background-color: #add570; +} + +.status-critical { + background-color: #e3485e; +} + +.status-notinit { + background-color: #8bbbdd; +} + +.container-msg-target-modal { + max-height: 400px; + overflow: initial; + padding-right: 20px; + padding-left: 20px; +} + +.container-msg-target-modal p { + font-family: "lato-lighter", "Open Sans", sans-serif; + margin-bottom: 20px; + font-size: 10pt; +} + +span.failed { + color: #fb4444; + font-weight: bolder; +} + +span.success { + color: #82b92f; + font-weight: bolder; +} + +.container-msg-target-modal pre { + font-family: monospace; + padding: 1em; + white-space: pre-wrap; + background-color: #efefef; + color: #565656; + font-size: 1.2em; + border: 2px solid #ddd; + border-radius: 5px; +} + +.container-msg-target-modal p img { + margin-right: 0.3em; + height: 1.3em; +} + +ul.wizard li > textarea { + height: 5em; +} + +.label_select { + font-family: "lato-lighter", "Open Sans", sans-serif; + font-weight: bolder; +} + +.divided select { + width: 100%; +} + +.inline { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + align-content: center; + align-items: center; +} + +.inline label:first-child { + width: 250px; + vertical-align: top; + display: inline-block; +} + +.inline label:nth-child(3) { + margin-right: 1em; + margin-left: 1em; +} + +.inline select { + margin-right: 1em; +} + +.middle { + align-self: center; +} +.edit_discovery_info { + padding-top: 0; +} + +ul.wizard { + width: 100%; +} + +.filter_column { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-content: center; +} + +.filter_column .edit_discovery_input { + flex-grow: 1; + width: 100%; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + align-content: baseline; + margin-left: 2em; +} +.filter_column .edit_discovery_input .label_select { + display: inline; + margin: 0; +} + +.filter_column .edit_discovery_input select { + flex-grow: 1; + margin-left: 2em; +} + +.wizard li { + display: flex; +} + +.no-class.action-buttons.mw120px.textright.sorting_disabled, +.textright { + text-align: right; + padding-right: 2em; +} + +/* + * Discovery css global + */ + +ul.bigbuttonlist { + min-height: 200px; +} + +li.discovery { + display: inline-block; + float: left; + width: 250px; + margin: 15px; + padding-bottom: 50px; +} + +li.discovery > a { + text-decoration: none; + color: #333; +} +li.discovery > a:hover { + color: #000; +} + +li.discovery img { + height: 90px; +} + +li.discovery > a label { + cursor: pointer; +} + +div.data_container > label { + font-family: "lato", "Open Sans", sans-serif; + font-weight: lighter; +} + +div.data_container { + width: 100%; + height: 100%; + text-align: center; + padding-top: 30px; + padding-bottom: 30px; +} + +div.data_container:hover { + box-shadow: 2px 2px 10px #ddd; +} + +/* + * TODO: This may be at hostdevices.css + */ +.texto { + height: auto; + text-align: center; +} +h1.wizard { + padding: 0; + margin: 0; +} +h1.wizard a { + margin-left: -20px; +} +h1.wizard a:hover { + color: #fff; +} +#text_wizard { + font-weight: bolder; + text-decoration: none; + font-size: 24px; +} +div.arrow_box { + display: inline-block; + position: relative; + color: #888; + padding: 1.3em; + margin-left: 20px; + margin-bottom: 10px; + padding-left: 3em; +} + +.arrow_box.selected { + background: #424242; + color: #ccc; +} + +.arrow_box:after { + left: 0%; + border-left-color: white; + border-width: 20px; + margin-top: -20px; +} + +div.arrow_box:before { + left: 100%; + border-left-color: #ccc; + border-width: 20px; + margin-top: -20px; +} +.arrow_box.selected:before { + border-left-color: #424242; +} + +.arrow_box.selected:hover { + color: #fff; +} +.arrow_box:hover { + color: #000; +} + +/* + * Breadcrum + */ + +#menu_tab_frame_view_bc { + display: flex; + justify-content: space-between; + border-bottom: 2px solid #82b92e; + max-height: 70px; + min-height: 55px; + width: 100%; + padding-right: 0px; + margin-left: 0px; + margin-bottom: 20px; + height: 55px; + box-sizing: border-box; + background-color: #fafafa; + border-top-right-radius: 7px; + border-top-left-radius: 7px; + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1); +} + +#menu_tab_frame_view_bc .breadcrumbs_container { + align-self: flex-start; +} + +.breadcrumbs_container { + padding-top: 4px; + text-indent: 0.25em; + padding-left: 2.5em; +} + +.breadcrumb_link { + color: #848484; + font-size: 10pt; + font-family: "lato-bolder", "Open Sans", sans-serif; + text-decoration: none; +} + +span.breadcrumb_link { + color: #d0d0d0; + font-size: 12pt; +} + +.breadcrumb_link.selected { + color: #95b750; +} + +.breadcrumb_link.selected:hover { + color: #95b750; +} +.breadcrumb_link:hover { + color: #95b750; +} + +/* + * Discovery forms structure + */ + +form.discovery * { + font-size: 10pt; +} + +form.discovery .label_select b { + font-family: "lato", "Open Sans", sans-serif; + font-weight: bolder; +} + +.edit_discovery_info { + display: flex; + align-items: flex-start; + padding-top: 25px; +} + +.edit_discovery_input { + align-items: center; + margin-bottom: 25px; +} + +/* + * Discovery text inputs + */ + +.discovery_label_hint { + display: flex; +} + +label { + color: #343434; + font-weight: bold; +} + +.discovery_full_width_input { + width: 100%; +} + +li > input[type="text"], +li > input[type="email"], +li > input[type="password"], +li > input[type="email"], +.discovery_text_input > input[type="password"], +.discovery_text_input > input[type="text"], +#interval_manual > input[type="text"] { + background-color: transparent; + border: none; + border-radius: 0; + border-bottom: 1px solid #ccc; + font-family: "lato-bolder", "Open Sans", sans-serif; + font-weight: lighter; + padding: 0px 0px 2px 0px; + box-sizing: border-box; + margin-bottom: 4px; +} + +#interval_manual > input[type="text"] { + width: 50px; + margin-left: 10px; + margin-right: 10px; +} + +.discovery_list_input { + width: 100%; + border: 1px solid #cbcbcb; + overflow-y: auto; +} + +.discovery_list_input option { + text-align: left; +} + +.discovery_list_input option:checked { + background: #1aab8e -webkit-linear-gradient(bottom, #7db742 0%, #7db742 100%); + color: #fff; +} + +.discovery_textarea_input { + background-color: #fbfbfb; + padding-left: 10px; + width: 100%; + height: 100px; + max-height: 100px; + max-width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + resize: none; +} + +a.tip { + margin-left: 8px; +} + +.inline_switch > label { + float: right; +} + +.discovery_interval_select_width { + width: 90%; +} + +a.ext_link { + margin-left: 1em; + font-size: 8pt; +} + +div.ui-tooltip.ui-corner-all.ui-widget-shadow.ui-widget.ui-widget-content.uitooltip { + background: grey; + opacity: 0.9; + border-radius: 4px; + box-shadow: 6px 5px 9px -9px black; + padding: 6px; +} + +.ui-tooltip-content { + background: transparent; + color: #fff; + font-weight: bold; + font-family: "lato-lighter", "Open Sans", sans-serif; + letter-spacing: 0.03pt; + font-size: 8pt; +} + +.arrow { + width: 70px; + height: 16px; + overflow: hidden; + position: absolute; + left: 50%; + margin-left: -35px; + bottom: -16px; +} +.arrow.top { + top: -16px; + bottom: auto; +} +.arrow.left { + left: 50%; +} +.arrow:after { + background: grey; + content: ""; + position: absolute; + left: 20px; + top: -20px; + width: 25px; + height: 25px; + box-shadow: 6px 5px 9px -9px black; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} +.arrow.top:after { + bottom: -20px; + top: auto; +} diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index ef1d250759..1ecd197ece 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -551,6 +551,18 @@ select:-internal-list-box { align-items: center; } +.flex-space-around { + justify-content: space-around; +} + +.flex-end { + justify-content: flex-end; +} + +.flex-start { + justify-content: flex-start; +} + .nowrap { flex-wrap: nowrap; } @@ -5698,7 +5710,11 @@ div#status_pie { align-items: center; flex-wrap: wrap; padding: 1em; - min-width: fit-content; + min-width: 100%; +} +.white-box-content-clean { + padding-left: 2em; + padding-top: 1em; } .white_table_graph_content { diff --git a/pandora_console/include/styles/progress.css b/pandora_console/include/styles/progress.css index f263e87fcf..bfbb2409ef 100644 --- a/pandora_console/include/styles/progress.css +++ b/pandora_console/include/styles/progress.css @@ -4,7 +4,17 @@ position: relative; width: 100%; display: inline-block; + display: flex; } + +.progress_main_noborder { + height: 2.5em; + position: relative; + width: 100%; + display: inline-block; + display: flex; +} + .progress_main:before { content: attr(data-label); position: absolute; diff --git a/pandora_console/operation/agentes/ver_agente.php b/pandora_console/operation/agentes/ver_agente.php index 7444dda595..aa91a09ee6 100644 --- a/pandora_console/operation/agentes/ver_agente.php +++ b/pandora_console/operation/agentes/ver_agente.php @@ -68,14 +68,7 @@ if (is_ajax()) { if ($refresh_contact) { $id_agente = get_parameter('id_agente', 0); 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 - ) - ); + $last_contact = agents_get_next_contact_time_left($id_agente); $progress = agents_get_next_contact($id_agente); if ($progress < 0 || $progress > 100) { @@ -1336,6 +1329,19 @@ if ($config['ehorus_enabled'] && !empty($config['ehorus_custom_field']) } } +$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 = ''; +} + + $onheader = [ 'manage' => $managetab, 'main' => $maintab, @@ -1349,6 +1355,8 @@ $onheader = [ 'ux_console' => $ux_console_tab, 'wux_console' => $wux_console_tab, 'url_route_analyzer' => $url_route_analyzer_tab, + 'sap_view' => $saptab, + ]; // Added after it exists @@ -1512,6 +1520,12 @@ switch ($tab) { $tab_name = $tab_name_extensions; break; + case 'sap_view': + $tab_description = '- '.__('SAP view'); + $help_header = 'sap_view'; + $tab_name = 'SAP View'; + break; + default: $tab_name = ''; $help_header = ''; @@ -1619,6 +1633,10 @@ switch ($tab) { include 'operation/agentes/ehorus.php'; break; + case 'sap_view': + include 'general/sap_view.php'; + break; + case 'extension': $found = false; foreach ($config['extensions'] as $extension) { diff --git a/pandora_console/operation/incidents/incident.php b/pandora_console/operation/incidents/incident.php index 5057b4d281..62e2f33fee 100755 --- a/pandora_console/operation/incidents/incident.php +++ b/pandora_console/operation/incidents/incident.php @@ -372,7 +372,7 @@ if ($count_total >= 1) { } if ($count_total < 1) { - include_once $config['homedir'].'/general/firts_task/incidents.php'; + include_once $config['homedir'].'/general/first_task/incidents.php'; } else { // TOTAL incidents $url = 'index.php?sec=workspace&sec2=operation/incidents/incident'; diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 58213ed8ee..dfa52551fc 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -155,6 +155,8 @@ if (!empty($sub2)) { enterprise_hook('cluster_menu'); enterprise_hook('aws_menu'); +enterprise_hook('SAP_view'); + if (!empty($sub)) { $menu_operation['estado']['text'] = __('Monitoring'); diff --git a/pandora_console/operation/search_agents.php b/pandora_console/operation/search_agents.php index 7edd7be878..05383df31a 100755 --- a/pandora_console/operation/search_agents.php +++ b/pandora_console/operation/search_agents.php @@ -30,6 +30,7 @@ if (!$agents || !$searchAgents) { echo "
    ".__('Zero results found')."
    \n"; } } else { + $table = new StdClass(); $table->cellpadding = 4; $table->cellspacing = 4; $table->width = '98%'; diff --git a/pandora_console/operation/servers/recon_view.php b/pandora_console/operation/servers/recon_view.php index 5401f6e307..facf494179 100644 --- a/pandora_console/operation/servers/recon_view.php +++ b/pandora_console/operation/servers/recon_view.php @@ -36,7 +36,7 @@ if ($servers === false) { $recon_task = db_get_all_rows_sql('SELECT * FROM trecon_task'); if ($recon_task === false) { ui_print_page_header(__('Recon View'), 'images/op_recon.png', false, '', false); - include_once $config['homedir'].'/general/firts_task/recon_view.php'; + include_once $config['homedir'].'/general/first_task/recon_view.php'; return; } else { include_once $config['homedir'].'/include/functions_graph.php'; diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 3b11dccb4d..28bb83d287 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -699,7 +699,7 @@ CREATE TABLE IF NOT EXISTS `tgrupo` ( 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, @@ -2782,6 +2782,9 @@ CREATE TABLE IF NOT EXISTS `tevent_rule` ( `id_tag` integer(10) unsigned NOT NULL default '0', `name` text default '', `group_recursion` INT(1) unsigned default 0, + `log_content` text, + `log_source` text, + `log_agent` text, PRIMARY KEY (`id_event_rule`), KEY `idx_id_event_alert` (`id_event_alert`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -3658,3 +3661,35 @@ CREATE TABLE `tdeployment_hosts` ( FOREIGN KEY (`target_agent_version_id`) REFERENCES `tagent_repository`(`id`) ON UPDATE CASCADE ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- ---------------------------------------------------------------------- +-- Table `tremote_command` +-- ---------------------------------------------------------------------- +CREATE TABLE `tremote_command` ( + `id` SERIAL, + `name` varchar(150) NOT NULL, + `timeout` int(10) unsigned NOT NULL default 30, + `retries` int(10) unsigned NOT NULL default 3, + `preconditions` text, + `script` text, + `postconditions` text, + `utimestamp` int(20) unsigned NOT NULL default 0, + `id_group` int(10) unsigned NOT NULL default 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- ---------------------------------------------------------------------- +-- Table `tremote_command_target` +-- ---------------------------------------------------------------------- +CREATE TABLE `tremote_command_target` ( + `id` SERIAL, + `rcmd_id` bigint unsigned NOT NULL, + `id_agent` int(10) unsigned NOT NULL, + `utimestamp` int(20) unsigned NOT NULL default 0, + `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; \ No newline at end of file diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index a041f4afab..f5f48bda69 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -109,10 +109,10 @@ INSERT INTO `tconfig` (`token`, `value`) VALUES ('custom_report_front_logo', 'images/pandora_logo_white.jpg'), ('custom_report_front_header', ''), ('custom_report_front_footer', ''), -('MR', 32), +('MR', 33), ('identification_reminder', 1), ('identification_reminder_timestamp', 0), -('current_package_enterprise', '740'), +('current_package_enterprise', '741'), ('post_process_custom_values', '{"0.00000038580247":"Seconds to months","0.00000165343915":"Seconds to weeks","0.00001157407407":"Seconds to days","0.01666666666667":"Seconds to minutes","0.00000000093132":"Bytes to Gigabytes","0.00000095367432":"Bytes to Megabytes","0.0009765625":"Bytes to Kilobytes","0.00000001653439":"Timeticks to weeks","0.00000011574074":"Timeticks to days"}'), ('custom_docs_logo', 'default_docs.png'), ('custom_support_logo', 'default_support.png'), diff --git a/pandora_console/tools/diagnostics.php b/pandora_console/tools/diagnostics.php index 30be89efc4..fc2b2fecd2 100644 --- a/pandora_console/tools/diagnostics.php +++ b/pandora_console/tools/diagnostics.php @@ -32,7 +32,7 @@ global $config; require_once $config['homedir'].'/include/class/Diagnostics.class.php'; $ajaxPage = 'tools/diagnostics'; -$pdf = false; +$pdf = get_parameter('pdf', false); // Control call flow. diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 03ebf6404c..1a2daed397 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -80,7 +80,9 @@ then mkdir -p temp_package/var/spool/pandora/data_in/netflow chmod 770 temp_package/var/spool/pandora/data_in/netflow mkdir -p temp_package/var/spool/pandora/data_in/trans - chmod 770 temp_package/var/spool/pandora/data_in/trans + chmod 770 temp_package/var/spool/pandora/data_in/trans + mkdir -p temp_package/var/spool/pandora/data_in/commands + chmod 770 temp_package/var/spool/pandora/data_in/commands mkdir -p temp_package/var/log/pandora/ chmod 754 temp_package/var/log/pandora/ mkdir -p temp_package/usr/share/pandora_server/conf/ diff --git a/pandora_server/conf/pandora_server.conf.new b/pandora_server/conf/pandora_server.conf.new index 2a2930f7eb..16a4a51b62 100644 --- a/pandora_server/conf/pandora_server.conf.new +++ b/pandora_server/conf/pandora_server.conf.new @@ -130,9 +130,15 @@ networkserver 1 dataserver 1 -# Activate (1) Pandora FMS Recon server +# Activate (1) Pandora FMS Discovery server -reconserver 1 +discoveryserver 1 + +# Discovery SAP (PANDORA FMS ENTERPRISE ONLY) +# java /usr/bin/java + +# Discovery SAP utils (PANDORA FMS ENTERPRISE ONLY) +# sap_utils /usr/share/pandora_server/util/recon_scripts/SAP # pluginserver : 1 or 0. Set to 1 to activate plugin server with this setup diff --git a/pandora_server/conf/tentacle_server.conf.new b/pandora_server/conf/tentacle_server.conf.new index d4ebe4a71f..992a6b1944 100644 --- a/pandora_server/conf/tentacle_server.conf.new +++ b/pandora_server/conf/tentacle_server.conf.new @@ -21,7 +21,7 @@ daemon 1 # insecure 0 # Filters (regexp:dir;regexp:dir...) -filters .*\.conf:conf;.*\.md5:md5;.*\.zip:collections;.*\.lock:trans +filters .*\.conf:conf;.*\.md5:md5;.*\.zip:collections;.*\.lock:trans;.*\.rcmd:commands # [-m] Maximum file size allowed by the server in bytes #max_size 2000000 diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 8af432738c..3db1e4b9c3 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -349,6 +349,12 @@ sub pandora_load_config { $pa_config->{"fping"} = "/usr/sbin/fping"; # > 5.1SP2 + # Discovery SAP + $pa_config->{"java"} = "/usr/bin/java"; + + # Discovery SAP utils + $pa_config->{"sap_utils"} = "/usr/share/pandora_server/util/recon_scripts/SAP"; + # braa for enterprise snmp server $pa_config->{"braa"} = "/usr/bin/braa"; @@ -841,6 +847,12 @@ sub pandora_load_config { elsif ($parametro =~ m/^fping\s(.*)/i) { $pa_config->{'fping'}= clean_blank($1); } + elsif ($parametro =~ m/^java\s(.*)/i) { + $pa_config->{'java'}= clean_blank($1); + } + elsif ($parametro =~ m/^sap_utils\s(.*)/i) { + $pa_config->{'sap_utils'}= clean_blank($1); + } elsif ($parametro =~ m/^nmap_timing_template\s+([0-9]*)/i) { $pa_config->{'nmap_timing_template'}= clean_blank($1); } diff --git a/pandora_server/lib/PandoraFMS/DataServer.pm b/pandora_server/lib/PandoraFMS/DataServer.pm index df1cbbecfb..38a33fc263 100644 --- a/pandora_server/lib/PandoraFMS/DataServer.pm +++ b/pandora_server/lib/PandoraFMS/DataServer.pm @@ -602,8 +602,12 @@ sub process_xml_data ($$$$$) { # Process events process_events_dataserver($pa_config, $data, $agent_id, $group_id, $dbh); - # Process disovery modules + # Process discovery modules enterprise_hook('process_discovery_data', [$pa_config, $data, $server_id, $dbh]); + + # Process command responses + enterprise_hook('process_rcmd_report', [$pa_config, $data, $server_id, $dbh, $agent_id, $timestamp]); + } ########################################################################## diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 7d90ff411a..5555f61af1 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -56,7 +56,25 @@ my $TaskSem :shared; use constant { OS_OTHER => 10, OS_ROUTER => 17, - OS_SWITCH => 18 + OS_SWITCH => 18, + STEP_SCANNING => 1, + STEP_AFT => 2, + STEP_TRACEROUTE => 3, + STEP_GATEWAY => 4, + STEP_STATISTICS => 1, + STEP_APP_SCAN => 2, + STEP_CUSTOM_QUERIES => 3, + DISCOVERY_HOSTDEVICES => 0, + DISCOVERY_HOSTDEVICES_CUSTOM => 1, + DISCOVERY_CLOUD_AWS => 2, + DISCOVERY_APP_VMWARE => 3, + DISCOVERY_APP_MYSQL => 4, + DISCOVERY_APP_ORACLE => 5, + DISCOVERY_CLOUD_AWS_EC2 => 6, + DISCOVERY_CLOUD_AWS_RDS => 7, + DISCOVERY_CLOUD_AZURE_COMPUTE => 8, + DISCOVERY_DEPLOY_AGENTS => 9, + DISCOVERY_APP_SAP => 10, }; ######################################################################################## @@ -196,6 +214,31 @@ sub data_consumer ($$) { return; } + + if ($task->{'type'} == DISCOVERY_APP_SAP) { + # SAP TASK, retrieve license. + $task->{'sap_license'} = pandora_get_config_value( + $dbh, + 'sap_license' + ); + + # Retrieve credentials for task (optional). + if (defined($task->{'auth_strings'}) + && $task->{'auth_strings'} ne '' + ) { + my $key = credential_store_get_key( + $pa_config, + $dbh, + $task->{'auth_strings'} + ); + + # Inside an eval, here it shouln't fail unless bad configured. + $task->{'username'} = $key->{'username'}; + $task->{'password'} = $key->{'password'}; + + } + } + my $recon = new PandoraFMS::Recon::Base( communities => \@communities, dbh => $dbh, diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 335504821e..b444e92672 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -22,7 +22,7 @@ use constant { STEP_TRACEROUTE => 3, STEP_GATEWAY => 4, STEP_STATISTICS => 1, - STEP_DATABASE_SCAN => 2, + STEP_APP_SCAN => 2, STEP_CUSTOM_QUERIES => 3, DISCOVERY_HOSTDEVICES => 0, DISCOVERY_HOSTDEVICES_CUSTOM => 1, @@ -34,6 +34,7 @@ use constant { DISCOVERY_CLOUD_AWS_RDS => 7, DISCOVERY_CLOUD_AZURE_COMPUTE => 8, DISCOVERY_DEPLOY_AGENTS => 9, + DISCOVERY_APP_SAP => 10, }; # $DEVNULL @@ -1440,10 +1441,11 @@ sub cloud_scan($) { my $type = ''; - if ($self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2 - || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { + if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2 + || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { $type = 'Aws'; } else { + # Unrecognized task type. call('message', 'Unrecognized task type', 1); $self->call('update_progress', -1); @@ -1465,9 +1467,11 @@ sub cloud_scan($) { ); if (!$cloudObj) { + # Failed to initialize, check Cloud credentials or anything. call('message', 'Unable to initialize PandoraFMS::Recon::Cloud::'.$type, 3); } else { + # Let Cloud object manage scan. $cloudObj->scan(); } @@ -1479,6 +1483,85 @@ sub cloud_scan($) { } +########################################################################## +# Performs a database scan. +########################################################################## +sub database_scan($$$) { + my ($self, $type, $obj, $global_percent, $targets) = @_; + + my @data; + my @modules; + + my $dbObjCfg = $obj->get_config(); + + $self->{'summary'}->{'discovered'} += 1; + $self->{'summary'}->{'alive'} += 1; + + push @modules, + { + name => $type . ' connection', + type => 'generic_proc', + data => 1, + description => $type . ' availability' + }; + + # Analyze. + $self->{'step'} = STEP_STATISTICS; + $self->{'c_network_percent'} = 30; + $self->call('update_progress', $global_percent + (30 / (scalar @$targets))); + $self->{'c_network_name'} = $obj->get_host(); + + # Retrieve connection statistics. + # Retrieve uptime statistics + # Retrieve query stats + # Retrieve connections + # Retrieve innodb + # Retrieve cache + $self->{'c_network_percent'} = 50; + $self->call('update_progress', $global_percent + (50 / (scalar @$targets))); + push @modules, $obj->get_statistics(); + + # Custom queries. + $self->{'step'} = STEP_CUSTOM_QUERIES; + $self->{'c_network_percent'} = 80; + $self->call('update_progress', $global_percent + (80 / (scalar @$targets))); + push @modules, $obj->execute_custom_queries(); + + if (defined($dbObjCfg->{'scan_databases'}) + && "$dbObjCfg->{'scan_databases'}" eq "1") { + + # Skip database scan in Oracle tasks + next if $self->{'type'} == DISCOVERY_APP_ORACLE; + + my $__data = $obj->scan_databases(); + + if (ref($__data) eq "ARRAY") { + if (defined($dbObjCfg->{'agent_per_database'}) + && $dbObjCfg->{'agent_per_database'} == 1) { + + # Agent per database detected. + push @data, @{$__data}; + + } else { + + # Merge modules into engine agent. + my @_modules = map { + map { $_ } + @{$_->{'module_data'}} + } @{$__data}; + + push @modules, @_modules; + } + } + } + + return { + 'modules' => @modules, + 'data' => @data + }; +} + + ########################################################################## # Perform an Application scan. ########################################################################## @@ -1487,11 +1570,15 @@ sub app_scan($) { my ($progress, $step); my $type = ''; + my $db_scan = 0; + # APP object initialization. if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL) { $type = 'MySQL'; } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { $type = 'Oracle'; + } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { + $type = 'SAP'; } else { # Unrecognized task type. call('message', 'Unrecognized task type', 1); @@ -1505,10 +1592,17 @@ sub app_scan($) { my $global_percent = 0; my $i = 0; foreach my $target (@targets) { + if ( !defined($target) + || $target eq '' + || $target =~ /^#/) { + # Ignore empty target or commented one. + next; + } + my @data; my @modules; - $self->{'step'} = STEP_DATABASE_SCAN; + $self->{'step'} = STEP_APP_SCAN; $self->{'c_network_name'} = $target; $self->{'c_network_percent'} = 0; @@ -1524,16 +1618,25 @@ sub app_scan($) { $self->call('update_progress', $global_percent + (10 / (scalar @targets))); # Connect to target. - my $dbObj = PandoraFMS::Recon::Util::enterprise_new( + my $obj = PandoraFMS::Recon::Util::enterprise_new( 'PandoraFMS::Recon::Applications::'.$type, - $self->{'task_data'} + { + %{$self->{'task_data'}}, + 'target' => $target, + 'pa_config' => $self->{'pa_config'}, + 'parent' => $self + }, ); - if (defined($dbObj)) { - if (!$dbObj->is_connected()) { + if (defined($obj)) { + + # Verify if object is connected. If cannot connect to current target + # return with module. + if (!$obj->is_connected()) { call('message', 'Cannot connect to target ' . $target, 3); $global_percent += $global_step; $self->{'c_network_percent'} = 90; + # Update progress $self->call('update_progress', $global_percent + (90 / (scalar @targets))); $self->{'summary'}->{'not_alive'} += 1; @@ -1545,74 +1648,51 @@ sub app_scan($) { }; } else { - my $dbObjCfg = $dbObj->get_config(); + # + # $results is always a hash with: + # @modules => 'global' modules. + # @data => { + # 'agent_data' => {} + # 'module_data' => [] + # } + my $results; - $self->{'summary'}->{'discovered'} += 1; - $self->{'summary'}->{'alive'} += 1; + # Scan connected obj. + if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL + || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { - push @modules, { - name => $type . ' connection', - type => 'generic_proc', - data => 1, - description => $type . ' availability' - }; + # Database. + $results = $self->database_scan($type, $obj, $global_percent, \@targets); - # Analyze. - $self->{'step'} = STEP_STATISTICS; - $self->{'c_network_percent'} = 30; - $self->call('update_progress', $global_percent + (30 / (scalar @targets))); - $self->{'c_network_name'} = $dbObj->get_host(); + } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { - # Retrieve connection statistics. - # Retrieve uptime statistics - # Retrieve query stats - # Retrieve connections - # Retrieve innodb - # Retrieve cache - $self->{'c_network_percent'} = 50; - $self->call('update_progress', $global_percent + (50 / (scalar @targets))); - push @modules, $dbObj->get_statistics(); + # SAP scan + $results = $obj->scan(); - # Custom queries. - $self->{'step'} = STEP_CUSTOM_QUERIES; - $self->{'c_network_percent'} = 80; - $self->call('update_progress', $global_percent + (80 / (scalar @targets))); - push @modules, $dbObj->execute_custom_queries(); + } - if (defined($dbObjCfg->{'scan_databases'}) - && "$dbObjCfg->{'scan_databases'}" eq "1") { - # Skip database scan in Oracle tasks - next if $self->{'type'} == DISCOVERY_APP_ORACLE; + # Add results. + if (ref($results) eq 'HASH') { + if (defined($results->{'modules'})) { + push @modules, $results->{'modules'}; + } - my $__data = $dbObj->scan_databases(); - - if (ref($__data) eq "ARRAY") { - if (defined($dbObjCfg->{'agent_per_database'}) - && $dbObjCfg->{'agent_per_database'} == 1) { - # Agent per database detected. - push @data, @{$__data}; - } else { - # Merge modules into engine agent. - my @_modules = map { - map { $_ } @{$_->{'module_data'}} - } @{$__data}; - - push @modules, @_modules; - } + if (defined($results->{'data'})) { + push @data, $results->{'data'}; } } } # Put engine agent at the beginning of the list. - my $version = $dbObj->get_version(); - unshift @data,{ + my $version = $obj->get_version(); + unshift @data, { 'agent_data' => { - 'agent_name' => $dbObj->get_agent_name(), + 'agent_name' => $obj->get_agent_name(), 'os' => $type, 'os_version' => (defined($version) ? $version : 'Discovery'), 'interval' => $self->{'task_data'}->{'interval_sweep'}, 'id_group' => $self->{'task_data'}->{'id_group'}, - 'address' => $dbObj->get_host(), + 'address' => $obj->get_host(), 'description' => '', }, 'module_data' => \@modules, @@ -1621,7 +1701,7 @@ sub app_scan($) { $self->call('create_agents', \@data); # Destroy item. - undef($dbObj); + undef($obj); } $global_percent += $global_step; @@ -1657,9 +1737,11 @@ sub deploy_scan($) { ); if (!$deployer) { + # Failed to initialize, check Cloud credentials or anything. call('message', 'Unable to initialize PandoraFMS::Recon::Deployer', 3); } else { + # Let deployer object manage scan. $deployer->scan(); } @@ -1682,13 +1764,16 @@ sub scan($) { $self->call('update_progress', 1); if (defined($self->{'task_data'})) { - if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL - || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { - # Database scan. + if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL + || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE + || $self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { + + # Application scan. return $self->app_scan(); } if ($self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { + # Cloud scan. return $self->cloud_scan(); } diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 3a3e1904a0..05adbf79d1 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -110,6 +110,7 @@ our @EXPORT = qw( is_offline to_number clean_blank + credential_store_get_key pandora_sendmail pandora_trash_ascii enterprise_hook @@ -487,6 +488,33 @@ sub pandora_daemonize { # Pandora other General functions | # -------------------------------------------+ +######################################################################## +# SUB credential_store_get_key +# Retrieve all information related to target identifier. +# param1 - config hash +# param2 - dbh link +# param3 - string identifier +######################################################################## +sub credential_store_get_key($$$) { + my ($pa_config, $dbh, $identifier) = @_; + + my $sql = 'SELECT * FROM tcredential_store WHERE identifier = ?'; + my $key = PandoraFMS::DB::get_db_single_row($dbh, $sql, $identifier); + + return { + 'username' => PandoraFMS::Core::pandora_output_password( + $pa_config, + $key->{'username'} + ), + 'password' => PandoraFMS::Core::pandora_output_password( + $pa_config, + $key->{'password'} + ), + 'extra_1' => $key->{'extra_1'}, + 'extra_2' => $key->{'extra_2'}, + }; + +} ######################################################################## # SUB pandora_sendmail diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index 0dab5db6bd..597049b8c9 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -54,6 +54,8 @@ mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/pandora/data_in/conf mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/pandora/data_in/md5 mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/pandora/data_in/collections mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/pandora/data_in/netflow +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/pandora/data_in/trans +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/pandora/data_in/commands mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log/pandora/ mkdir -p $RPM_BUILD_ROOT%{prefix}/pandora_server/conf/ mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1/ @@ -195,3 +197,5 @@ exit 0 %{_localstatedir}/spool/pandora/data_in/collections %{_localstatedir}/spool/pandora/data_in/conf %{_localstatedir}/spool/pandora/data_in/netflow +%{_localstatedir}/spool/pandora/data_in/trans +%{_localstatedir}/spool/pandora/data_in/commands diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index bcdfb0af1f..5714dcfad8 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -61,6 +61,7 @@ mkdir -p $RPM_BUILD_ROOT/var/spool/pandora/data_in/md5 mkdir -p $RPM_BUILD_ROOT/var/spool/pandora/data_in/collections mkdir -p $RPM_BUILD_ROOT/var/spool/pandora/data_in/netflow mkdir -p $RPM_BUILD_ROOT/var/spool/pandora/data_in/trans +mkdir -p $RPM_BUILD_ROOT/var/spool/pandora/data_in/commands mkdir -p $RPM_BUILD_ROOT/var/log/pandora/ mkdir -p $RPM_BUILD_ROOT%{prefix}/pandora_server/conf/ mkdir -p $RPM_BUILD_ROOT%{prefix}/tentacle/conf/ @@ -198,6 +199,7 @@ rm -Rf /usr/share/man/man1/tentacle_server.1.gz /var/spool/pandora/data_in/netflow /var/spool/pandora/data_in/conf /var/spool/pandora/data_in/trans +/var/spool/pandora/data_in/commands %defattr(-,pandora,root,750) /etc/pandora diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index 15903c26e3..03a96b1792 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -315,6 +315,8 @@ install () { chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/netflow mkdir $DESTDIR$PANDORA_SPOOL/data_in/trans 2> /dev/null chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/trans + mkdir $DESTDIR$PANDORA_SPOOL/data_in/commands 2> /dev/null + chmod 2770 $DESTDIR$PANDORA_SPOOL/data_in/commands mkdir -p $DESTDIR$PANDORA_LOG 2> /dev/null chown -R pandora $DESTDIR$PANDORA_LOG 2> /dev/null chmod 2774 $DESTDIR$PANDORA_LOG 2> /dev/null