diff --git a/pandora_console/extras/pandora_diag.php b/pandora_console/extras/pandora_diag.php index eb9a199456..b047106679 100644 --- a/pandora_console/extras/pandora_diag.php +++ b/pandora_console/extras/pandora_diag.php @@ -1,796 +1,2 @@ - - $value) { - db_process_sql_update( - 'tupdate_settings', - [db_escape_key_identifier('value') => $value], - [db_escape_key_identifier('key') => $key] - ); - } - - ui_print_success_message(__('License updated')); -} - -ui_require_javascript_file_enterprise('load_enterprise'); -enterprise_include_once('include/functions_license.php'); -$license = enterprise_hook('license_get_info'); - -$rows = db_get_all_rows_in_table('tupdate_settings'); - -$settings = new StdClass; -foreach ($rows as $row) { - $settings->{$row['key']} = $row['value']; -} - -echo ''; - - -function render_info($table) -{ - global $console_mode; - - $info = db_get_sql("SELECT COUNT(*) FROM $table"); - render_row($info, "DB Table $table"); -} - - -function render_info_data($query, $label) -{ - global $console_mode; - - $info = db_get_sql($query); - render_row($info, $label); -} - - -function render_row($data, $label) -{ - global $console_mode; - - if ($console_mode == 1) { - echo $label; - echo '|'; - echo $data; - echo "\n"; - } else { - echo ''; - echo "
".$label; - echo '
'; - echo "
".$data; - echo '
'; - echo ''; - } -} - - -function get_value_sum($arr) -{ - foreach ($arr as $clave) { - foreach ($clave as $valor) { - if (is_numeric($valor) === true) { - $result += $valor; - } - } - } - - return $result; -} - - -function execution_time() -{ - $times = db_get_all_rows_sql('SELECT datos FROM tagente_datos WHERE id_agente_modulo = 29 ORDER BY utimestamp DESC LIMIT 2'); - if ($times[0]['datos'] > ($times[1]['datos'] * 1.2)) { - return "Warning Status   The execution time could be degrading. For a more extensive information of this data consult the Execution Time graph"; - } else { - return "Normal Status   The execution time is correct. For more information about this data, check the Execution Time graph"; - } -} - - -function get_logs_size($file) -{ - $file_name = '/var'.$file.''; - $size_server_log = filesize($file_name); - return $size_server_log; - -} - - -function get_status_logs($path) -{ - $status_server_log = ''; - $size_server_log = number_format(get_logs_size($path)); - $size_server_log = (0 + str_replace(',', '', $size_server_log)); - if ($size_server_log <= 10485760) { - $status_server_log = "Normal Status   You have less than 10 MB of logs"; - } else { - $status_server_log = "Warning Status   You have more than 10 MB of logs"; - } - - return $status_server_log; -} - - -function percentage_modules_per_agent() -{ - $status_average_modules = ''; - $total_agents = db_get_value_sql('SELECT count(*) FROM tagente'); - $total_modules = db_get_value_sql('SELECT count(*) FROM tagente_modulo'); - $average_modules_per_agent = ($total_modules / $total_agents); - if ($average_modules_per_agent <= 40) { - $status_average_modules = "Normal Status   The average of modules per agent is less than 40"; - } else { - $status_average_modules = "Warning Status  The average of modules per agent is more than 40. You can have performance problems"; - } - - return $status_average_modules; -} - - -function license_capacity() -{ - $license = enterprise_hook('license_get_info'); - $license_limit = $license['limit']; - $status_license_capacity = ''; - $current_count = db_get_value_sql('SELECT count(*) FROM tagente'); - if ($current_count > ($license_limit * 90 / 100)) { - $status_license_capacity = "Warning Status   License capacity exceeds 90 percent"; - } else { - $status_license_capacity = "Normal Status   License capacity is less than 90 percent"; - } - - return $status_license_capacity; -} - - -function status_license_params($license_param) -{ - $status_license_par = ''; - if ($license_param <= 0) { - $status_license_par = 'OFF'; - } else { - $status_license_par = 'ON'; - } - - return $status_license_par; -} - - -function interval_average_of_network_modules() -{ - $total_network_modules = db_get_value_sql('SELECT count(*) FROM tagente_modulo WHERE id_tipo_modulo BETWEEN 6 AND 18'); - $total_module_interval_time = db_get_value_sql('SELECT SUM(module_interval) FROM tagente_modulo WHERE id_tipo_modulo BETWEEN 6 AND 18'); - $average_time = ((int) $total_module_interval_time / $total_network_modules); - - if ($average_time < 180) { - $status_average_modules = "Warning Status   The system is overloaded (average time $average_time) and a very fine configuration is required"; - } else { - $status_average_modules = "Normal Status   The system is not overloaded (average time $average_time) "; - } - - if ($average_time == 0) { - $status_average_modules = "Normal Status   The system has no load"; - } - - return $status_average_modules; -} - - -$attachment_total_files = count(glob($config['homedir'].'/attachment/{*.*}', GLOB_BRACE)); - - -function files_attachment_folder($total_files) -{ - if ($total_files <= 700) { - $status_total_files = "Normal Status   The attached folder contains less than 700 files."; - } else { - $status_total_files = "Warning Status   The attached folder contains more than 700 files."; - } - - return $status_total_files; -} - - -$tagente_datos_size = db_get_value_sql('SELECT COUNT(*) FROM tagente_datos'); - - -function status_tagente_datos($tagente_datos_size) -{ - if ($tagente_datos_size <= 3000000) { - $tagente_datos_size = "Normal Status   The tagente_datos table contains an acceptable amount of data."; - } else { - $tagente_datos_size = "Warning Status   The tagente_datos table contains too much data. A historical database is recommended."; - } - - return $tagente_datos_size; -} - - -function status_values($val_rec, $val) -{ - if ($val_rec <= $val) { - return $val." (Min. Recommended Value ".$val_rec.')'; - } else { - return $val." (Min. Recommended Value ".$val_rec.") Warning Status"; - } -} - - -$tables_fragmentation = db_get_sql( - "SELECT (data_free/(index_length+data_length)) -as frag_ratio from information_schema.tables where DATA_FREE > 0 and table_name='tagente_datos' and table_schema='pandora'" -); -$db_size = db_get_all_rows_sql( - 'SELECT table_schema, -ROUND(SUM(data_length+index_length)/1024/1024,3) -FROM information_schema.TABLES -GROUP BY table_schema;' -); - -if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { - $total_server_threads = shell_exec('ps -T aux | grep pandora_server | grep -v grep | wc -l'); - $percentage_threads_ram = shell_exec("ps axo pmem,cmd | grep pandora_server | awk '{sum+=$1} END {print sum}'"); - $percentage_threads_cpu = shell_exec("ps axo pcpu,cmd | grep pandora_server | awk '{sum+=$1} END {print sum}'"); - $innodb_buffer_pool_size_min_rec_value = shell_exec("cat /proc/meminfo | grep -i total | head -1 | awk '{print $(NF-1)*0.4/1024}'"); -} - -$path_server_logs = '/log/pandora/pandora_server.log'; -$path_err_logs = '/log/pandora/pandora_server.error'; -$path_console_logs = '/www/html/pandora_console/pandora_console.log'; -$innodb_log_file_size_min_rec_value = '64M'; -$innodb_log_buffer_size_min_rec_value = '16M'; -$innodb_flush_log_at_trx_commit_min_rec_value = 0; -$query_cache_limit_min_rec_value = 2; -$max_allowed_packet_min_rec_value = 32; -$innodb_buffer_pool_size_min_rec_value = shell_exec("cat /proc/meminfo | grep -i total | head -1 | awk '{print $(NF-1)*0.4/1024}'"); -$sort_buffer_size_min_rec_value = 32; -$join_buffer_size_min_rec_value = 265; -$query_cache_type_min_rec_value = 'ON'; -$query_cache_size_min_rec_value = 24; -$innodb_lock_wait_timeout_max_rec_value = 120; -$tables_fragmentation_max_rec_value = 10; -$thread_cache_size_max_rec_value = 8; -$thread_stack_min_rec_value = 256; -$max_connections_max_rec_value = 150; -$key_buffer_size_min_rec_value = 256; -$read_buffer_size_min_rec_value = 32; -$read_rnd_buffer_size_min_rec_value = 32; -$query_cache_min_res_unit_min_rec_value = 2; -$innodb_file_per_table_min_rec_value = 1; - - -function status_fragmentation_tables($tables_fragmentation_max_rec_value, $tables_fragmentation) -{ - $status_tables_frag = ''; - if ($tables_fragmentation > $tables_fragmentation_max_rec_value) { - $status_tables_frag = "Warning Status   Table fragmentation is higher than recommended. They should be defragmented."; - } else { - $status_tables_frag = "Normal Status   Table fragmentation is correct."; - } - - return $status_tables_frag; -} - - -$console_mode = 1; -if (!isset($argc)) { - $console_mode = 0; -} - -if ($console_mode == 1) { - echo "\nPandora FMS PHP diagnostic tool v3.2 (c) Artica ST 2009-2010 \n"; - - if ($argc == 1 || in_array($argv[1], ['--help', '-help', '-h', '-?'])) { - echo "\nThis command line script contains information about Pandora FMS database. - This program can only be executed from the console, and it needs a parameter, the - full path to Pandora FMS 'config.php' file. - - Usage: - php pandora_diag.php path_to_pandora_console - - Example: - php pandora_diag.php /var/www/pandora_console - -"; - exit; - } - - if (preg_match('/[^a-zA-Z0-9_\/\.]|(\/\/)|(\.\.)/', $argv[1])) { - echo "Invalid path: $argv[1]. Always use absolute paths."; - exit; - } - - include $argv[1].'/include/config.php'; -} else { - if (file_exists('../include/config.php')) { - include '../include/config.php'; - } - - // Not from console, this is a web session. - if ((!isset($config['id_user'])) || (!check_acl($config['id_user'], 0, 'PM'))) { - echo "

You don't have privileges to use diagnostic tool

"; - echo '

Please login with an administrator account before try to use this tool

'; - exit; - } - - // Header. - ui_print_page_header( - __('Pandora FMS Diagnostic tool'), - '', - false, - 'diagnostic_tool_tab', - true - ); - - echo ""; - echo "'; -} - -render_row($build_version, 'Pandora FMS Build'); -render_row($pandora_version, 'Pandora FMS Version'); -render_info_data("SELECT value FROM tconfig where token ='MR'", 'Minor Release'); -render_row($config['homedir'], 'Homedir'); -render_row($config['homeurl'], 'HomeUrl'); -render_info_data( - "SELECT `value` - FROM tconfig - WHERE `token` = 'enterprise_installed'", - 'Enterprise installed' -); - - $full_key = db_get_sql( - "SELECT value - FROM tupdate_settings - WHERE `key` = 'customer_key'" - ); - - $compressed_key = substr($full_key, 0, 5).'...'.substr($full_key, -5); - - render_row($compressed_key, 'Update Key'); - - render_info_data( - "SELECT value - FROM tupdate_settings - WHERE `key` = 'updating_code_path'", - 'Updating code path' - ); - - render_info_data( - "SELECT value - FROM tupdate_settings - WHERE `key` = 'current_update'", - 'Current Update #' - ); - - - echo "'; - - - render_row(phpversion(), 'PHP Version'); - - render_row(ini_get('max_execution_time').' seconds', 'PHP Max execution time'); - - render_row(ini_get('max_input_time').' seconds', 'PHP Max input time'); - - render_row(ini_get('memory_limit'), 'PHP Memory limit'); - - render_row(ini_get('session.cookie_lifetime'), 'Session cookie lifetime'); - - echo "'; - - render_info_data('SELECT COUNT(*) FROM tagente', 'Total agents'); - render_info_data('SELECT COUNT(*) FROM tagente_modulo', 'Total modules'); - render_info_data('SELECT COUNT(*) FROM tgrupo', 'Total groups'); - render_info_data('SELECT COUNT(*) FROM tagente_datos', 'Total module data records'); - render_info_data('SELECT COUNT(*) FROM tagent_access', 'Total agent access record'); - render_info_data('SELECT COUNT(*) FROM tevento', 'Total events'); - - if ($config['enterprise_installed']) { - render_info_data('SELECT COUNT(*) FROM ttrap', 'Total traps'); - } - - render_info_data('SELECT COUNT(*) FROM tusuario', 'Total users'); - render_info_data('SELECT COUNT(*) FROM tsesion', 'Total sessions'); - - echo "'; - - render_info_data( - 'SELECT COUNT( DISTINCT tagente.id_agente) - FROM tagente_estado, tagente, tagente_modulo - WHERE tagente.disabled = 0 - AND tagente_modulo.id_agente_modulo = tagente_estado.id_agente_modulo - AND tagente_modulo.disabled = 0 - AND tagente_estado.id_agente = tagente.id_agente - AND tagente_estado.estado = 3', - 'Total unknown agents' - ); - - render_info_data( - 'SELECT COUNT(tagente_estado.estado) - FROM tagente_estado - WHERE tagente_estado.estado = 4', - 'Total not-init modules' - ); - - - $last_run_difference = ''; - - $diferencia = (time() - date( - db_get_sql( - "SELECT `value` - FROM tconfig - WHERE `token` = 'db_maintance'" - ) - )); - - $last_run_difference_months = 0; - $last_run_difference_weeks = 0; - $last_run_difference_days = 0; - $last_run_difference_minutos = 0; - $last_run_difference_seconds = 0; - - while ($diferencia >= 2419200) { - $diferencia -= 2419200; - $last_run_difference_months++; - } - - while ($diferencia >= 604800) { - $diferencia -= 604800; - $last_run_difference_weeks++; - } - - while ($diferencia >= 86400) { - $diferencia -= 86400; - $last_run_difference_days++; - } - - while ($diferencia >= 3600) { - $diferencia -= 3600; - $last_run_difference_hours++; - } - - while ($diferencia >= 60) { - $diferencia -= 60; - $last_run_difference_minutes++; - } - - $last_run_difference_seconds = $diferencia; - - if ($last_run_difference_months > 0) { - $last_run_difference .= $last_run_difference_months.'month/s '; - } - - if ($last_run_difference_weeks > 0) { - $last_run_difference .= $last_run_difference_weeks.' week/s '; - } - - if ($last_run_difference_days > 0) { - $last_run_difference .= $last_run_difference_days.' day/s '; - } - - if ($last_run_difference_hours > 0) { - $last_run_difference .= $last_run_difference_hours.' hour/s '; - } - - if ($last_run_difference_minutes > 0) { - $last_run_difference .= $last_run_difference_minutes.' minute/s '; - } - - $last_run_difference .= $last_run_difference_seconds.' second/s ago'; - - render_row( - date( - 'Y/m/d H:i:s', - db_get_sql( - "SELECT `value` - FROM tconfig - WHERE `token` = 'db_maintance'" - ) - ).' ('.$last_run_difference.')'.' *', - 'PandoraDB Last run' - ); - - echo "'; - - switch ($config['dbtype']) { - case 'mysql': - render_info_data( - "SELECT `value` - FROM tconfig - WHERE `token` = 'db_scheme_first_version'", - 'DB Schema Version (first installed)' - ); - render_info_data( - "SELECT `value` - FROM tconfig - WHERE `token` = 'db_scheme_version'", - 'DB Schema Version (actual)' - ); - render_info_data( - "SELECT `value` - FROM tconfig - WHERE `token` = 'db_scheme_build'", - 'DB Schema Build' - ); - - render_row(get_value_sum($db_size).'M', 'DB Size'); - - - if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { - echo "'; - - $output = 'cat /proc/cpuinfo | grep "model name" | tail -1 | cut -f 2 -d ":"'; - $output2 = 'cat /proc/cpuinfo | grep "processor" | wc -l'; - - render_row(exec($output).' x '.exec($output2), 'CPU'); - - $output = 'cat /proc/meminfo | grep "MemTotal"'; - - render_row(exec($output), 'RAM'); - } - break; - - case 'postgresql': - render_info_data( - "SELECT \"value\" - FROM tconfig - WHERE \"token\" = 'db_scheme_version'", - 'DB Schema Version' - ); - render_info_data( - "SELECT \"value\" - FROM tconfig - WHERE \"token\" = 'db_scheme_build'", - 'DB Schema Build' - ); - render_info_data( - "SELECT \"value\" - FROM tconfig - WHERE \"token\" = 'enterprise_installed'", - 'Enterprise installed' - ); - render_row( - date( - 'Y/m/d H:i:s', - db_get_sql( - "SELECT \"value\" - FROM tconfig WHERE \"token\" = 'db_maintance'" - ) - ), - 'PandoraDB Last run' - ); - - render_info_data( - "SELECT value - FROM tupdate_settings - WHERE \"key\" = 'customer_key';", - 'Update Key' - ); - render_info_data( - "SELECT value - FROM tupdate_settings - WHERE \"key\" = 'updating_code_path'", - 'Updating code path' - ); - render_info_data( - "SELECT value - FROM tupdate_settings - WHERE \"key\" = 'current_update'", - 'Current Update #' - ); - break; - - case 'oracle': - render_info_data( - "SELECT value - FROM tconfig - WHERE token = 'db_scheme_version'", - 'DB Schema Version' - ); - render_info_data( - "SELECT value - FROM tconfig - WHERE token = 'db_scheme_build'", - 'DB Schema Build' - ); - render_info_data( - "SELECT value - FROM tconfig - WHERE token = 'enterprise_installed'", - 'Enterprise installed' - ); - render_row( - db_get_sql( - "SELECT value - FROM tconfig - WHERE token = 'db_maintance'" - ), - 'PandoraDB Last run' - ); - - render_info_data( - 'SELECT '.db_escape_key_identifier('value')." FROM tupdate_settings - WHERE \"key\" = 'customer_key'", - 'Update Key' - ); - render_info_data( - 'SELECT '.db_escape_key_identifier('value')." FROM tupdate_settings - WHERE \"key\" = 'updating_code_path'", - 'Updating code path' - ); - render_info_data( - 'SELECT '.db_escape_key_identifier('value')." FROM tupdate_settings - WHERE \"key\" = 'current_update'", - 'Current Update #' - ); - break; - } - - $innodb_log_file_size = (db_get_value_sql('SELECT @@innodb_log_file_size') / 1048576); - $innodb_log_buffer_size = (db_get_value_sql('SELECT @@innodb_log_buffer_size') / 1048576); - $innodb_flush_log_at_trx_commit = db_get_value_sql('SELECT @@innodb_flush_log_at_trx_commit'); - $max_allowed_packet = (db_get_value_sql('SELECT @@max_allowed_packet') / 1048576); - $innodb_buffer_pool_size = (db_get_value_sql('SELECT @@innodb_buffer_pool_size') / 1024); - $sort_buffer_size = number_format((db_get_value_sql('SELECT @@sort_buffer_size') / 1024), 2); - $join_buffer_size = (db_get_value_sql('SELECT @@join_buffer_size') / 1024); - $query_cache_type = db_get_value_sql('SELECT @@query_cache_type'); - $query_cache_size = (db_get_value_sql('SELECT @@query_cache_size') / 1048576); - $query_cache_limit = (db_get_value_sql('SELECT @@query_cache_limit') / 1048576); - $innodb_lock_wait_timeout = db_get_value_sql('SELECT @@innodb_lock_wait_timeout'); - $thread_cache_size = db_get_value_sql('SELECT @@thread_cache_size'); - $thread_stack = (db_get_value_sql('SELECT @@thread_stack') / 1024); - $max_connections = db_get_value_sql('SELECT @@max_connections'); - $key_buffer_size = (db_get_value_sql('SELECT @@key_buffer_size') / 1024); - $read_buffer_size = (db_get_value_sql('SELECT @@read_buffer_size') / 1024); - $read_rnd_buffer_size = (db_get_value_sql('SELECT @@read_rnd_buffer_size') / 1024); - $query_cache_min_res_unit = (db_get_value_sql('SELECT @@query_cache_min_res_unit') / 1024); - $innodb_file_per_table = db_get_value_sql('SELECT @@innodb_file_per_table'); - echo "'; - - render_row(status_values($innodb_log_file_size_min_rec_value, $innodb_log_file_size), 'InnoDB log file size ', 'InnoDB log file size '); - render_row(status_values($innodb_log_buffer_size_min_rec_value, $innodb_log_buffer_size), 'InnoDB log buffer size ', 'InnoDB log buffer size '); - render_row(status_values($innodb_flush_log_at_trx_commit_min_rec_value, $innodb_flush_log_at_trx_commit), 'InnoDB flush log at trx-commit ', 'InnoDB flush log at trx-commit '); - render_row(status_values($max_allowed_packet_min_rec_value, $max_allowed_packet), 'Maximun allowed packet ', 'Maximun allowed packet '); - render_row(status_values($innodb_buffer_pool_size_min_rec_value, $innodb_buffer_pool_size), 'InnoDB buffer pool size ', 'InnoDB buffer pool size '); - render_row(status_values($sort_buffer_size_min_rec_value, $sort_buffer_size), 'Sort buffer size ', 'Sort buffer size '); - render_row(status_values($join_buffer_size_min_rec_value, $join_buffer_size), 'Join buffer size ', 'Join buffer size '); - render_row(status_values($query_cache_type_min_rec_value, $query_cache_type), 'Query cache type ', 'Query cache type '); - render_row(status_values($query_cache_size_min_rec_value, $query_cache_size), 'Query cache size ', 'Query cache size '); - render_row(status_values($query_cache_limit_min_rec_value, $query_cache_limit), 'Query cache limit ', 'Query cache limit '); - render_row(status_values($innodb_lock_wait_timeout_max_rec_value, $innodb_lock_wait_timeout), 'InnoDB lock wait timeout ', 'InnoDB lock wait timeout '); - render_row(status_values($thread_cache_size_max_rec_value, $thread_cache_size), 'Thread cache size ', 'Thread cache size '); - render_row(status_values($thread_stack_min_rec_value, $thread_stack), 'Thread stack ', 'Thread stack '); - render_row(status_values($max_connections_max_rec_value, $max_connections), 'Maximum connections ', 'Maximun connections '); - render_row(status_values($key_buffer_size_min_rec_value, $key_buffer_size), 'Key buffer size ', 'Key buffer size '); - render_row(status_values($read_buffer_size_min_rec_value, $read_buffer_size), 'Read buffer size ', 'Read buffer size '); - render_row(status_values($read_rnd_buffer_size_min_rec_value, $read_rnd_buffer_size), 'Read rnd-buffer size ', 'Read rnd-buffer size '); - render_row(status_values($query_cache_min_res_unit_min_rec_value, $query_cache_min_res_unit), 'Query cache min-res-unit ', 'Query cache min-res-unit '); - render_row(status_values($innodb_file_per_table_min_rec_value, $innodb_file_per_table), 'InnoDB file per table ', 'InnoDB file per table '); - echo "'; - - - - render_row($tables_fragmentation_max_rec_value.'%', 'Tables fragmentation (maximum recommended value)'); - render_row(number_format($tables_fragmentation, 2).'%', 'Tables fragmentation (current value)'); - render_row(status_fragmentation_tables($tables_fragmentation_max_rec_value, $tables_fragmentation), 'Table fragmentation status'); - - echo "'; - - render_row(number_format((get_logs_size($path_server_logs) / 1048576), 3).'M', 'Size server logs (current value)'); - render_row(get_status_logs($path_server_logs), 'Status server logs'); - render_row(number_format((get_logs_size($path_err_logs) / 1048576), 3).'M', 'Size error logs (current value)'); - render_row(get_status_logs($path_err_logs), 'Status error logs'); - render_row(number_format((get_logs_size($path_console_logs) / 1048576), 3).'M', 'Size console logs (current value)'); - render_row(get_status_logs($path_console_logs), 'Status console logs'); - - echo "'; - - render_row(html_print_textarea('keys[customer_key]', 10, 255, $settings->customer_key, 'style="height:40px; width:450px;"', true), 'Customer key'); - render_row($license['expiry_date'], $license['expiry_caption']); - render_row($license['limit'].' agents', 'Platform Limit'); - render_row($license['count'].' agents', 'Current Platform Count'); - render_row($license['count_enabled'].' agents', 'Current Platform Count (enabled: items)'); - render_row($license['count_disabled'].' agents', 'Current Platform Count (disabled: items)'); - render_row($license['license_mode'], 'License Mode'); - render_row(status_license_params($license['nms']), 'Network Management System'); - render_row(status_license_params($license['dhpm']), 'Satellite'); - render_row($license['licensed_to'], 'Licensed to'); - render_row(license_capacity(), 'Status of agents capacity'); - render_row(percentage_modules_per_agent(), 'Status of average modules per agent'); - render_row(interval_average_of_network_modules(), 'Interval average of the network modules'); - - echo "'; - - render_row($attachment_total_files, 'Total files in the attached folder'); - render_row(files_attachment_folder($attachment_total_files), 'Status of the attachment folder'); - - echo "'; - - render_row($tagente_datos_size, 'Total data in tagente_datos table'); - render_row(status_tagente_datos($tagente_datos_size), 'Tangente_datos table status'); - render_row(execution_time(), 'Execution time degradation when executing a count'); - - echo "'; - - render_row($total_server_threads, 'Total server threads'); - render_row($percentage_threads_ram.'%', 'Percentage of threads used by the RAM'); - render_row($percentage_threads_cpu.'%', 'Percentage of threads used by the CPU'); - - echo "'; - - $server_name = db_get_value_sql('SELECT name FROM tserver WHERE master = 1'); - $agent_id = db_get_value_sql("SELECT id_agente FROM tagente WHERE nombre = '$server_name'"); - - $id_modules = agents_get_modules($agent_id); - - $id_modules = [ - modules_get_agentmodule_id('Agents_Unknown', $agent_id), - modules_get_agentmodule_id('Database Maintenance', $agent_id), - modules_get_agentmodule_id('FreeDisk_SpoolDir', $agent_id), - modules_get_agentmodule_id('Free_RAM', $agent_id), - modules_get_agentmodule_id('Queued_Modules', $agent_id), - modules_get_agentmodule_id('Status', $agent_id), - modules_get_agentmodule_id('System_Load_AVG', $agent_id), - modules_get_agentmodule_id('Execution_time', $agent_id), - ]; - - foreach ($id_modules as $id_module) { - $params = [ - 'agent_module_id' => $id_module['id_agente_modulo'], - 'period' => SECONDS_1MONTH, - 'date' => time(), - 'height' => '150', - ]; - render_row(grafico_modulo_sparse($params), 'Graph of the '.$id_module['nombre'].' module.'); - } - - if ($console_mode == 0) { - echo '
".__('Pandora status info').'
".__('PHP setup').'
".__('Database size stats').'
".__('Database sanity').'
".__('Database status info').'
".__('System info').'
".__('MySQL Performance metrics').' '.ui_print_help_icon('performance_metrics_tab', true).'
".__('Tables fragmentation in the Pandora FMS database').'
".__(' Pandora FMS logs dates').'
".__(' Pandora FMS Licence Information').'
".__(' Status of the attachment folder').'
".__(' Information from the tagente_datos table').'
".__(' Pandora FMS server threads').'
".__(' Graphs modules that represent the self-monitoring system').'
'; - } - - echo "
"; - - echo ''.__( - '(*) Please check your Pandora Server setup and make sure that the database maintenance daemon is running. It\' is very important to - keep the database up-to-date to get the best performance and results in Pandora' - ).'


'; +// remove file. diff --git a/pandora_console/general/header.php b/pandora_console/general/header.php index 99bb38cc21..e060cf96f6 100644 --- a/pandora_console/general/header.php +++ b/pandora_console/general/header.php @@ -328,9 +328,27 @@ if ($config['menu_type'] == 'classic') { $header_autorefresh_counter .= $autorefresh_additional; $header_autorefresh_counter .= ''; + // Button for feedback pandora. + if (enterprise_installed()) { + $header_feedback = '
'; + $header_feedback .= ''; + $header_feedback .= ''; + $header_feedback .= html_print_image( + '/images/feedback-header.png', + true, + [ + 'title' => __('Feedback'), + 'id' => 'feedback-header', + 'alt' => __('Feedback'), + 'style' => 'cursor: pointer; width: 27px;', + ] + ); + $header_feedback .= '
'; + } + // Support. - if (defined('PANDORA_ENTERPRISE')) { + if (enterprise_installed()) { $header_support_link = 'https://support.artica.es/'; } else { $header_support_link = 'https://pandorafms.com/forums/'; @@ -388,9 +406,9 @@ if ($config['menu_type'] == 'classic') { echo '
'.$config['custom_title_header'].''.$config['custom_subtitle_header'].'
'.$header_searchbar.'
-
'.$header_chat, $header_autorefresh, $header_autorefresh_counter, $header_discovery, $servers_list, $header_support, $header_docu, $header_user, $header_logout.'
'; +
'.$header_chat, $header_autorefresh, $header_autorefresh_counter, $header_discovery, $servers_list, $header_feedback, $header_support, $header_docu, $header_user, $header_logout.'
'; ?> - + @@ -610,8 +628,46 @@ if ($config['menu_type'] == 'classic') { }); var fixed_header = ; - + var new_chat = ; + + /** + * Loads modal from AJAX to add feedback. + */ + function show_feedback() { + + var btn_ok_text = ''; + var btn_cancel_text = ''; + var title = ''; + var url = ''; + + load_modal({ + target: $('#modal-feedback-form'), + form: 'modal_form_feedback', + url: '', + modal: { + title: title, + ok: btn_ok_text, + cancel: btn_cancel_text, + }, + onshow: { + page: url, + method: 'formFeedback', + }, + onsubmit: { + page: url, + method: 'createdScheduleFeedbackTask', + dataType: 'json', + }, + ajax_callback: generalShowMsg, + idMsgCallback: 'msg-header', + }); + } + $(document).ready (function () { // Check new notifications on a periodic way @@ -661,7 +717,15 @@ if ($config['menu_type'] == 'classic') { $("#ui_close_dialog_titlebar").click(function () { $("#agent_access").css("display",""); }); - + + // Feedback. + $("#feedback-header").click(function () { + // Clean DOM. + $("#feedback-header").empty(); + // Function charge Modal. + show_feedback(); + }); + function blinkpubli(){ $(".publienterprise").delay(100).fadeTo(300,0.2).delay(100).fadeTo(300,1, blinkpubli); } diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 7175081912..edf7be1873 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -339,13 +339,13 @@ if (check_acl($config['id_user'], 0, 'PM') || check_acl($config['id_user'], 0, ' $sub = []; if (check_acl($config['id_user'], 0, 'PM')) { - // Audit //meter en extensiones + // Audit //meter en extensiones. $sub['godmode/admin_access_logs']['text'] = __('System audit log'); $sub['godmode/admin_access_logs']['id'] = 'System audit log'; $sub['godmode/setup/links']['text'] = __('Links'); $sub['godmode/setup/links']['id'] = 'Links'; - $sub['extras/pandora_diag']['text'] = __('Diagnostic info'); - $sub['extras/pandora_diag']['id'] = 'Diagnostic info'; + $sub['tools/diagnostics']['text'] = __('Diagnostic info'); + $sub['tools/diagnostics']['id'] = 'Diagnostic info'; $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/images/feedback-header.png b/pandora_console/images/feedback-header.png new file mode 100644 index 0000000000..c77ff461e4 Binary files /dev/null and b/pandora_console/images/feedback-header.png differ diff --git a/pandora_console/include/class/Diagnostics.class.php b/pandora_console/include/class/Diagnostics.class.php new file mode 100644 index 0000000000..43f3d948b4 --- /dev/null +++ b/pandora_console/include/class/Diagnostics.class.php @@ -0,0 +1,2175 @@ +ajaxController = $page; + $this->pdf = $pdf; + } + + + /** + * Allowed methods to be called using AJAX request. + * + * @var array + */ + public $AJAXMethods = [ + 'getStatusInfo', + 'getPHPSetup', + 'getDatabaseSizeStats', + 'getDatabaseHealthStatus', + 'getDatabaseStatusInfo', + 'getSystemInfo', + 'getMySQLPerformanceMetrics', + 'getTablesFragmentation', + 'getPandoraFMSLogsDates', + 'getLicenceInformation', + 'getAttachmentFolder', + 'getInfoTagenteDatos', + 'getServerThreads', + 'getShowEngine', + 'datatablesDraw', + 'getChartAjax', + 'formFeedback', + 'createdScheduleFeedbackTask', + ]; + + + /** + * Checks if target method is available to be called using AJAX. + * + * @param string $method Target method. + * + * @return boolean True allowed, false not. + */ + public function ajaxMethod(string $method):bool + { + return in_array($method, $this->AJAXMethods); + } + + + /** + * Show view diagnostics. + * + * @return void + */ + public function run() + { + global $config; + + ui_require_css_file('diagnostics'); + + // Header. + ui_print_page_header( + __('Pandora FMS Diagnostic tool'), + 'images/gm_massive_operations.png', + false, + 'diagnostic_tool_tab', + true + ); + + // Print all Methods Diagnostic Info. + echo $this->printMethodsDiagnostigsInfo(); + + // Print all charts Monitoring. + echo $this->printCharts(); + + echo ''; + } + + + /** + * Print Methods: + * Info status pandoraFms. + * PHP setup. + * Database size stats. + * Database health status. + * Database status info. + * System Info. + * MySQL Performance metrics. + * Tables fragmentation in the Pandora FMS database. + * Pandora FMS logs dates. + * Pandora FMS Licence Information. + * Status of the attachment folder. + * Information from the tagente_datos table. + * Pandora FMS server threads. + * + * @return string Html. + */ + public function printMethodsDiagnostigsInfo():string + { + $infoMethods = [ + 'getStatusInfo', + 'getPHPSetup', + 'getDatabaseSizeStats', + 'getDatabaseHealthStatus', + 'getDatabaseStatusInfo', + 'getSystemInfo', + 'getMySQLPerformanceMetrics', + 'getTablesFragmentation', + 'getPandoraFMSLogsDates', + 'getLicenceInformation', + 'getAttachmentFolder', + 'getInfoTagenteDatos', + 'getServerThreads', + ]; + + if ($this->pdf === true) { + $infoMethods[] = 'getShowEngine'; + } + + $return = ''; + + foreach ($infoMethods as $key => $method) { + switch ($method) { + case 'getStatusInfo': + $title = __('Info status pandoraFms'); + break; + + case 'getPHPSetup': + $title = __('PHP setup'); + break; + + case 'getDatabaseSizeStats': + $title = __('Database size stats'); + break; + + case 'getDatabaseHealthStatus': + $title = __('Database health status'); + break; + + case 'getDatabaseStatusInfo': + $title = __('Database status info'); + break; + + case 'getSystemInfo': + $title = __('System Info'); + break; + + case 'getMySQLPerformanceMetrics': + $title = __('MySQL Performance metrics'); + break; + + case 'getTablesFragmentation': + $title = __( + 'Tables fragmentation in the Pandora FMS database' + ); + break; + + case 'getPandoraFMSLogsDates': + $title = __('Pandora FMS logs dates'); + break; + + case 'getLicenceInformation': + $title = __('Pandora FMS Licence Information'); + break; + + case 'getAttachmentFolder': + $title = __('Status of the attachment folder'); + break; + + case 'getInfoTagenteDatos': + $title = __('Information from the tagente_datos table'); + break; + + case 'getServerThreads': + $title = __('Pandora FMS server threads'); + break; + + case 'getShowEngine': + $title = __('SQL show engine innodb status'); + break; + + default: + // Not possible. + $title = ''; + break; + } + + $return .= '
'; + $return .= $this->printData($method, $title); + $return .= '
'; + } + + return $return; + } + + + /** + * Print table graps: + * Graph of the Agents Unknown module. + * Graph of the Database Maintenance module. + * Graph of the Free Disk Spool Dir module. + * Graph of the Free RAM module. + * Graph of the Queued Modules module. + * Graph of the Status module. + * Graph of the System Load AVG module. + * Graph of the Execution Time module. + * + * @return string + */ + public function printCharts() + { + /* + * Agent id with name Master Server. + */ + + $agentIdMasterServer = $this->getAgentIdMasterServer(); + + $result = ''; + if ($agentIdMasterServer !== 0) { + $agentMonitoring = [ + 'chartAgentsUnknown' => [ + 'title' => __( + 'Graph of the Agents Unknown module.' + ), + 'nameModule' => 'Agents_Unknown', + 'idAgent' => $agentIdMasterServer, + ], + 'chartDatabaseMain' => [ + 'title' => __( + 'Graph of the Database Maintenance module.' + ), + 'nameModule' => 'Database Maintenance', + 'idAgent' => $agentIdMasterServer, + ], + 'chartFreeDiskSpoolDir' => [ + 'title' => __( + 'Graph of the Free Disk Spool Dir module.' + ), + 'nameModule' => 'FreeDisk_SpoolDir', + 'idAgent' => $agentIdMasterServer, + ], + 'chartFreeRAM' => [ + 'title' => __('Graph of the Free RAM module.'), + 'nameModule' => 'Free_RAM', + 'idAgent' => $agentIdMasterServer, + ], + 'chartQueuedModules' => [ + 'title' => __( + 'Graph of the Queued Modules module.' + ), + 'nameModule' => 'Queued_Modules', + 'idAgent' => $agentIdMasterServer, + ], + 'chartStatus' => [ + 'title' => __('Graph of the Status module.'), + 'nameModule' => 'Status', + 'idAgent' => $agentIdMasterServer, + ], + 'chartSystemLoadAVG' => [ + 'title' => __( + 'Graph of the System Load AVG module.' + ), + 'nameModule' => 'System_Load_AVG', + 'idAgent' => $agentIdMasterServer, + ], + 'chartExecutionTime' => [ + 'title' => __( + 'Graph of the Execution Time module.' + ), + 'nameModule' => 'Execution_time', + 'idAgent' => $agentIdMasterServer, + ], + ]; + + $return .= '
'; + $return .= __( + 'Graphs modules that represent the self-monitoring system' + ); + $return .= '
'; + $return .= '
'; + foreach ($agentMonitoring as $key => $value) { + $return .= $this->printDataCharts($value); + } + + $return .= '
'; + } + + return $return; + } + + + /** + * Info status pandoraFms. + * + * @return string + */ + public function getStatusInfo(): string + { + global $config; + global $build_version; + global $pandora_version; + + $sql = sprintf( + "SELECT `key`, `value` + FROM `tupdate_settings` + WHERE `key` = '%s' + OR `key` = '%s' + OR `key` = '%s'", + 'current_update', + 'customer_key', + 'updating_code_path' + ); + + $values_key = db_get_all_rows_sql($sql); + $values_key = array_reduce( + $values_key, + function ($carry, $item) { + if ($item['key'] === 'customer_key') { + $customer = substr($item['value'], 0, 5); + $customer .= '...'; + $customer .= substr($item['value'], -5); + $item['value'] = $customer; + } + + $carry[$item['key']] = $item['value']; + return $carry; + } + ); + + $result = [ + 'error' => false, + 'data' => [ + 'buildVersion' => [ + 'name' => __('Pandora FMS Build'), + 'value' => $build_version, + ], + 'version' => [ + 'name' => __('Pandora FMS Version'), + 'value' => $pandora_version, + ], + 'mr' => [ + 'name' => __('Minor Release'), + 'value' => $config['MR'], + ], + 'homeDir' => [ + 'name' => __('Homedir'), + 'value' => $config['homedir'], + ], + 'homeUrl' => [ + 'name' => __('HomeUrl'), + 'value' => $config['homeurl'], + ], + 'isEnterprise' => [ + 'name' => __('Enterprise installed'), + 'value' => (enterprise_installed()) ? __('true') : __('false'), + ], + 'customerKey' => [ + 'name' => __('Update Key'), + 'value' => $values_key['customer_key'], + ], + 'updatingCode' => [ + 'name' => __('Updating code path'), + 'value' => $values_key['updating_code_path'], + ], + 'currentUpdate' => [ + 'name' => __('Current Update #'), + 'value' => $values_key['current_update'], + ], + + ], + ]; + + return json_encode($result); + } + + + /** + * PHP Status. + * + * @return string + */ + public function getPHPSetup(): string + { + global $config; + + $result = [ + 'error' => false, + 'data' => [ + 'phpVersion' => [ + 'name' => __('PHP Version'), + 'value' => phpversion(), + ], + 'maxExecutionTime' => [ + 'name' => __('PHP Max execution time'), + 'value' => ini_get('max_execution_time'), + ], + 'maxInputTime' => [ + 'name' => __('PHP Max input time'), + 'value' => ini_get('max_input_time'), + ], + 'memoryLimit' => [ + 'name' => __('PHP Memory limit'), + 'value' => ini_get('memory_limit'), + ], + 'sessionLifetime' => [ + 'name' => __('Session cookie lifetime'), + 'value' => ini_get('session.cookie_lifetime'), + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Database size stats. + * + * @return string + */ + public function getDatabaseSizeStats(): string + { + global $config; + + $countAgents = db_get_value_sql('SELECT COUNT(*) FROM tagente'); + $countModules = db_get_value_sql('SELECT COUNT(*) FROM tagente_modulo'); + $countGroups = db_get_value_sql('SELECT COUNT(*) FROM tgrupo'); + $countModuleData = db_get_value_sql( + 'SELECT COUNT(*) FROM tagente_datos' + ); + $countAgentAccess = db_get_value_sql( + 'SELECT COUNT(*) FROM tagent_access' + ); + $countEvents = db_get_value_sql('SELECT COUNT(*) FROM tevento'); + + if (enterprise_installed() === true) { + $countTraps = db_get_value_sql('SELECT COUNT(*) FROM ttrap'); + } + + $countUsers = db_get_value_sql('SELECT COUNT(*) FROM tusuario'); + $countSessions = db_get_value_sql('SELECT COUNT(*) FROM tsesion'); + + $result = [ + 'error' => false, + 'data' => [ + 'countAgents' => [ + 'name' => __('Total agentsy'), + 'value' => $countAgents, + ], + 'countModules' => [ + 'name' => __('Total modules'), + 'value' => $countModules, + ], + 'countGroups' => [ + 'name' => __('Total groups'), + 'value' => $countGroups, + ], + 'countModuleData' => [ + 'name' => __('Total module data records'), + 'value' => $countModuleData, + ], + 'countAgentAccess' => [ + 'name' => __('Total agent access record'), + 'value' => $countAgentAccess, + ], + 'countEvents' => [ + 'name' => __('Total events'), + 'value' => $countEvents, + ], + 'countTraps' => [ + 'name' => __('Total traps'), + 'value' => $countTraps, + ], + 'countUsers' => [ + 'name' => __('Total users'), + 'value' => $countUsers, + ], + 'countSessions' => [ + 'name' => __('Total sessions'), + 'value' => $countSessions, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Database health status. + * + * @return string + */ + public function getDatabaseHealthStatus(): string + { + global $config; + + // Count agents unknowns. + $sqlUnknownAgents = 'SELECT COUNT( DISTINCT tagente.id_agente) + FROM tagente_estado, tagente, tagente_modulo + WHERE tagente.disabled = 0 + AND tagente_modulo.id_agente_modulo = tagente_estado.id_agente_modulo + AND tagente_modulo.disabled = 0 + AND tagente_estado.id_agente = tagente.id_agente + AND tagente_estado.estado = 3'; + $unknownAgents = db_get_sql($sqlUnknownAgents); + + // Count modules not initialize. + $sqlNotInitAgents = 'SELECT COUNT(tagente_estado.estado) + FROM tagente_estado + WHERE tagente_estado.estado = 4'; + $notInitAgents = db_get_sql($sqlNotInitAgents); + + $dateDbMantenaince = $config['db_maintance']; + + $currentTime = time(); + + $pandoraDbLastRun = __('Pandora DB has never been executed'); + if ($dateDbMantenaince !== false) { + $difference = ($currentTime - $dateDbMantenaince); + $pandoraDbLastRun = human_time_comparation($difference); + $pandoraDbLastRun .= ' '.__('Ago'); + } + + $result = [ + 'error' => false, + 'data' => [ + 'unknownAgents' => [ + 'name' => __('Total unknown agents'), + 'value' => $unknownAgents, + ], + 'notInitAgents' => [ + 'name' => __('Total not-init modules'), + 'value' => $notInitAgents, + ], + 'pandoraDbLastRun' => [ + 'name' => __('PandoraDB Last run'), + 'value' => $pandoraDbLastRun, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Database status info. + * + * @return string + */ + public function getDatabaseStatusInfo(): string + { + global $config; + + // Size BBDD. + $dbSizeSql = db_get_value_sql( + 'SELECT ROUND(SUM(data_length+index_length)/1024/1024,3) + FROM information_schema.TABLES' + ); + + // Add unit size. + $dbSize = $dbSizeSql.' M'; + + $result = [ + 'error' => false, + 'data' => [ + 'dbSchemeFirstVersion' => [ + 'name' => __('DB Schema Version (first installed)'), + 'value' => $config['db_scheme_first_version'], + ], + 'dbSchemeVersion' => [ + 'name' => __('DB Schema Version (actual)'), + 'value' => $config['db_scheme_version'], + ], + 'dbSchemeBuild' => [ + 'name' => __('DB Schema Build'), + 'value' => $config['db_scheme_build'], + ], + 'dbSize' => [ + 'name' => __('DB Size'), + 'value' => $dbSize, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Database status info. + * + * @return string + */ + public function getSystemInfo(): string + { + global $config; + + $result = []; + if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { + $cpuModelName = 'cat /proc/cpuinfo | grep "model name" | tail -1 | cut -f 2 -d ":"'; + $cpuProcessor = 'cat /proc/cpuinfo | grep "processor" | wc -l'; + $ramMemTotal = 'cat /proc/meminfo | grep "MemTotal"'; + + $result = [ + 'error' => false, + 'data' => [ + 'cpuInfo' => [ + 'name' => __('CPU'), + 'value' => exec($cpuModelName).' x '.exec($cpuProcessor), + ], + 'ramInfo' => [ + 'name' => __('RAM'), + 'value' => exec($ramMemTotal), + ], + ], + ]; + } + + return json_encode($result); + } + + + /** + * MySQL Performance metrics. + * + * @return string + */ + public function getMySQLPerformanceMetrics(): string + { + global $config; + + $variablesMsql = db_get_all_rows_sql('SHOW VARIABLES'); + $variablesMsql = array_reduce( + $variablesMsql, + function ($carry, $item) { + $bytes = 1048576; + $mega = 1024; + switch ($item['Variable_name']) { + case 'sql_mode': + $name = __('Sql mode'); + $value = ($item['Value']); + $status = (empty($item['Value']) === true) ? 1 : 0; + $message = __('Must be empty'); + break; + + case 'innodb_log_file_size': + $name = __('InnoDB log file size'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 64) ? 1 : 0; + $message = __('Min. Recommended Value').' 64M'; + break; + + case 'innodb_log_buffer_size': + $name = __('InnoDB log buffer size'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 16) ? 1 : 0; + $message = __('Min. Recommended Value').' 16M'; + break; + + case 'innodb_flush_log_at_trx_commit': + $name = __('InnoDB flush log at trx-commit'); + $value = $item['Value']; + $status = (($item['Value'] / $bytes) >= 0) ? 1 : 0; + $message = __('Min. Recommended Value').' 0'; + break; + + case 'max_allowed_packet': + $name = __('Maximun allowed packet'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 32) ? 1 : 0; + $message = __('Min. Recommended Value').' 32M'; + break; + + case 'innodb_buffer_pool_size': + $name = __('InnoDB buffer pool size'); + $value = ($item['Value'] / $mega); + $status = (($item['Value'] / $mega) >= 250) ? 1 : 0; + $message = __( + 'It has to be 40% of the server memory not recommended to be greater or less' + ); + break; + + case 'sort_buffer_size': + $name = __('Sort buffer size'); + $value = number_format(($item['Value'] / $mega), 2); + $status = (($item['Value'] / $bytes) >= 32) ? 1 : 0; + $message = __('Min. Recommended Value').' 32'; + break; + + case 'join_buffer_size': + $name = __('Join buffer size'); + $value = ($item['Value'] / $mega); + $status = (($item['Value'] / $bytes) >= 265) ? 1 : 0; + $message = __('Min. Recommended Value 265'); + break; + + case 'query_cache_type': + $name = __('Query cache type'); + $value = $item['Value']; + $status = ($item['Value'] === 'ON') ? 1 : 0; + $message = __('Recommended ON'); + break; + + case 'query_cache_size': + $name = __('Query cache size'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 32) ? 1 : 0; + $message = __('Min. Recommended Value').' 32MB'; + break; + + case 'query_cache_limit': + $name = __('Query cache limit'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 256) ? 1 : 0; + $message = __('Min. Recommended Value').' 256K'; + break; + + case 'innodb_lock_wait_timeout': + $name = __('InnoDB lock wait timeout'); + $value = $item['Value']; + $status = (($item['Value'] / $bytes) >= 90) ? 1 : 0; + $message = __('Min. Recommended Value').' 90s'; + break; + + case 'thread_cache_size': + $name = __('Thread cache size'); + $value = $item['Value']; + $status = (($item['Value'] / $bytes) >= 8) ? 1 : 0; + $message = __('Min. Recommended Value').' 8'; + break; + + case 'thread_stack': + $name = __('Thread stack'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 256) ? 1 : 0; + $message = __('Min. Recommended Value').' 256K'; + break; + + case 'max_connections': + $name = __('Maximun connections'); + $value = $item['Value']; + $status = (($item['Value'] / $bytes) >= 90) ? 1 : 0; + $message = __('Min. Recommended Value').' 90'; + break; + + case 'key_buffer_size': + $name = __('Key buffer size'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 256) ? 1 : 0; + $message = __('Min. Recommended Value').' 256'; + break; + + case 'read_buffer_size': + $name = __('Read buffer size'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 32) ? 1 : 0; + $message = __('Min. Recommended Value').' 32'; + break; + + case 'read_rnd_buffer_size': + $name = __('Read rnd-buffer size'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 32) ? 1 : 0; + $message = __('Min. Recommended Value').' 32'; + break; + + case 'query_cache_min_res_unit': + $name = __('Query cache min-res-unit'); + $value = ($item['Value'] / $bytes); + $status = (($item['Value'] / $bytes) >= 2) ? 1 : 0; + $message = __('Min. Recommended Value').' 2k'; + break; + + case 'innodb_file_per_table': + $name = __('InnoDB file per table'); + $value = $item['Value']; + $status = ($item['Value'] === 'ON') ? 1 : 0; + $message = __('Recommended ON'); + break; + + default: + $name = ''; + $value = 0; + break; + } + + if (empty($name) !== true) { + $carry[$item['Variable_name']] = [ + 'name' => $name, + 'value' => $value, + 'status' => $status, + 'message' => $message, + ]; + } + + return $carry; + }, + [] + ); + + $result = [ + 'error' => false, + 'data' => $variablesMsql, + ]; + + return json_encode($result); + } + + + /** + * Tables fragmentation in the Pandora FMS database. + * + * @return string + */ + public function getTablesFragmentation(): string + { + global $config; + + // Estimated fragmentation percentage as maximum. + $tFragmentationMax = 10; + + // Extract the fragmentation value. + $tFragmentationValue = db_get_sql( + sprintf( + "SELECT (data_free/(index_length+data_length)) as frag_ratio + FROM information_schema.tables + WHERE DATA_FREE > 0 + AND table_name='tagente_datos' + AND table_schema='%s'", + $config['dbname'] + ) + ); + + // Check if it meets the fragmentation value. + $status_tables_frag = ''; + if ($tFragmentationValue > $tFragmentationMax) { + $tFragmentationMsg = __( + 'Table fragmentation is higher than recommended. They should be defragmented.' + ); + $tFragmentationStatus = 0; + } else { + $tFragmentationMsg = __('Table fragmentation is correct.'); + $tFragmentationStatus = 1; + } + + $result = [ + 'error' => false, + 'data' => [ + 'tablesFragmentationMax' => [ + 'name' => __( + 'Tables fragmentation (maximum recommended value)' + ), + 'value' => $tFragmentationMax.'%', + ], + 'tablesFragmentationValue' => [ + 'name' => __('Tables fragmentation (current value)'), + 'value' => number_format($tFragmentationValue, 2).'%', + ], + 'tablesFragmentationStatus' => [ + 'name' => __('Table fragmentation status'), + 'value' => $status_tables_frag, + 'status' => $tFragmentationStatus, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Pandora FMS logs dates. + * + * @return string + */ + public function getPandoraFMSLogsDates(): string + { + global $config; + + $unit = 'M'; + + $pathServerLogs = 'var/log/pandora/pandora_server.log'; + $servers = $this->getLogInfo($pathServerLogs); + + $pathErrLogs = 'var/log/pandora/pandora_server.error'; + $errors = $this->getLogInfo($pathErrLogs); + + $pathConsoleLogs = $config['homedir'].'/pandora_console.log'; + $console = $this->getLogInfo($pathConsoleLogs); + + $result = [ + 'error' => false, + 'data' => [ + 'sizeServerLog' => [ + 'name' => __('Size server logs (current value)'), + 'value' => $servers['value'].' '.$unit, + ], + 'statusServerLog' => [ + 'name' => __('Status server logs'), + 'value' => $servers['message'], + 'status' => $servers['status'], + ], + 'sizeErrorLog' => [ + 'name' => __('Size error logs (current value)'), + 'value' => $errors['value'].' '.$unit, + ], + 'statusErrorLog' => [ + 'name' => __('Status error logs'), + 'value' => $errors['message'], + 'status' => $errors['status'], + ], + 'sizeConsoleLog' => [ + 'name' => __('Size console logs (current value)'), + 'value' => $console['value'].' '.$unit, + ], + 'statusConsoleLog' => [ + 'name' => __('Status console logs'), + 'value' => $console['message'], + 'status' => $console['status'], + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Pandora FMS Licence Information. + * + * @return string + */ + public function getLicenceInformation(): string + { + global $config; + + // Extract customer key. + $sql = sprintf( + "SELECT `value` + FROM `tupdate_settings` + WHERE `key` = '%s'", + 'customer_key' + ); + $customerKey = db_get_value_sql($sql); + + // Extract Info license. + $license = enterprise_hook('license_get_info'); + + // Agent Capacity. + $agentCount = db_get_value_sql('SELECT count(*) FROM tagente'); + $agentsCapacity = __('License capacity is less than 90 percent'); + $agentsCapacitySt = 1; + if ($agentCount > ($license['limit'] * 90 / 100)) { + $agentsCapacity = __('License capacity exceeds 90 percent'); + $agentsCapacitySt = 0; + } + + // Modules average. + $modulesCount = db_get_value_sql('SELECT count(*) FROM tagente_modulo'); + $average = ($modulesCount / $agentCount); + $averageMsg = __( + 'The average of modules per agent is more than 40. You can have performance problems' + ); + $averageSt = 0; + if ($average <= 40) { + $averageMsg = __( + 'The average of modules per agent is less than 40' + ); + $averageSt = 1; + } + + // Modules Networks average. + $totalNetworkModules = db_get_value_sql( + 'SELECT count(*) + FROM tagente_modulo + WHERE id_tipo_modulo + BETWEEN 6 AND 18' + ); + $totalModuleIntervalTime = db_get_value_sql( + 'SELECT SUM(module_interval) + FROM tagente_modulo + WHERE id_tipo_modulo + BETWEEN 6 AND 18' + ); + + $averageTime = 0; + if ($totalModuleIntervalTime !== false) { + $averageTime = number_format( + ((int) $totalModuleIntervalTime / (int) $totalNetworkModules), + 3 + ); + } + + $moduleNetworkmsg = __( + sprintf( + 'The system is not overloaded (average time %d)', + $average_time + ) + ); + $moduleNetworkst = 1; + if ($average_time === 0) { + $moduleNetworkmsg = __('The system has no load'); + $moduleNetworkst = 0; + } else if ($averageTime < 180) { + $moduleNetworkmsg = __( + sprintf( + 'The system is overloaded (average time %d) and a very fine configuration is required', + $average_time + ) + ); + $moduleNetworkst = 0; + } + + $result = [ + 'error' => false, + 'data' => [ + 'customerKey' => [ + 'name' => __('Customer key'), + 'value' => $customerKey, + ], + 'customerExpires' => [ + 'name' => __('Support expires'), + 'value' => $license['expiry_date'], + ], + 'customerLimit' => [ + 'name' => __('Platform Limit'), + 'value' => $license['limit'].' '.__('Agents'), + ], + 'customerPfCount' => [ + 'name' => __('Current Platform Count'), + 'value' => $license['count'].' '.__('Agents'), + ], + 'customerPfCountEnabled' => [ + 'name' => __('Current Platform Count (enabled: items)'), + 'value' => $license['count_enabled'].' '.__('Agents'), + ], + 'customerPfCountDisabled' => [ + 'name' => __('Current Platform Count (disabled: items)'), + 'value' => $license['count_disabled'].' '.__('Agents'), + ], + 'customerMode' => [ + 'name' => __('License Mode'), + 'value' => $license['license_mode'], + ], + 'customerNMS' => [ + 'name' => __('Network Management System'), + 'value' => ($license['nms'] > 0) ? __('On') : __('Off'), + ], + 'customerSatellite' => [ + 'name' => __('Satellite'), + 'value' => ($license['dhpm'] > 0) ? __('On') : __('Off'), + ], + 'customerLicenseTo' => [ + 'name' => __('Licensed to'), + 'value' => $license['licensed_to'], + ], + 'customerCapacity' => [ + 'name' => __('Status of agents capacity'), + 'value' => $agentsCapacity, + 'status' => $agentsCapacitySt, + ], + 'customerAverage' => [ + 'name' => __('Status of average modules per agent'), + 'value' => $averageMsg, + 'status' => $averageSt, + ], + + 'customerAverageNetwork' => [ + 'name' => __('Interval average of the network modules'), + 'value' => $moduleNetworkmsg, + 'status' => $moduleNetworkst, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Status of the attachment folder. + * + * @return string + */ + public function getAttachmentFolder(): string + { + global $config; + + // Count files in attachment. + $attachmentFiles = count( + glob( + $config['homedir'].'/attachment/{*.*}', + GLOB_BRACE + ) + ); + + // Check status attachment. + $attachmentMsg = __( + 'The attached folder contains more than 700 files.' + ); + $attachmentSt = 0; + if ($attachmentFiles <= 700) { + $attachmentMsg = __( + 'The attached folder contains less than 700 files.' + ); + $attachmentSt = 1; + } + + $result = [ + 'error' => false, + 'data' => [ + 'attachFiles' => [ + 'name' => __('Total files in the attached folder'), + 'value' => $attachmentFiles, + ], + 'attachStatus' => [ + 'name' => __('Status of the attachment folder'), + 'value' => $attachmentMsg, + 'status' => $attachmentSt, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Information from the tagente_datos table. + * + * @return string + */ + public function getInfoTagenteDatos(): string + { + global $config; + + $agentDataCount = db_get_value_sql( + 'SELECT COUNT(*) + FROM tagente_datos' + ); + + $taMsg = __( + 'The tagente_datos table contains too much data. A historical database is recommended.' + ); + $taStatus = 0; + if ($agentDataCount <= 3000000) { + $taMsg = __( + 'The tagente_datos table contains an acceptable amount of data.' + ); + $taStatus = 1; + } + + $result = [ + 'error' => false, + 'data' => [ + 'agentDataCount' => [ + 'name' => __('Total data in tagente_datos table'), + 'value' => $agentDataCount, + ], + 'agentDataStatus' => [ + 'name' => __('Tagente_datos table status'), + 'value' => $taMsg, + 'status' => $taStatus, + ], + ], + ]; + + return json_encode($result); + } + + + /** + * Pandora FMS server threads. + * + * @return string + */ + public function getServerThreads(): string + { + global $config; + + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + return []; + } + + $totalServerThreads = shell_exec( + 'ps -T aux | grep pandora_server | grep -v grep | wc -l' + ); + $percentageThreadsRam = shell_exec( + "ps axo pmem,cmd | grep pandora_server | awk '{sum+=$1} END {print sum}'" + ); + $percentageThreadsCpu = shell_exec( + "ps axo pcpu,cmd | grep pandora_server | awk '{sum+=$1} END {print sum}'" + ); + + $result = [ + 'error' => false, + 'data' => [ + 'totalServerThreads' => [ + 'name' => __('Total server threads'), + 'value' => $totalServerThreads, + ], + 'percentageThreadsRam' => [ + 'name' => __('Percentage of threads used by the RAM'), + 'value' => $percentageThreadsRam.' %', + ], + 'percentageThreadsCpu' => [ + 'name' => __('Percentage of threads used by the CPU'), + 'value' => $percentageThreadsCpu.' %', + ], + ], + ]; + + return json_encode($result); + } + + + /** + * SQL show engine innodb status. + * + * @return string + */ + public function getShowEngine(): string + { + global $config; + + try { + // Trick to avoid showing error in case + // you don't have enough permissions. + $backup = error_reporting(); + error_reporting(0); + $innodb = db_get_all_rows_sql('show engine innodb status'); + error_reporting($backup); + } catch (Exception $e) { + $innodb['Status'] = $e->getMessage(); + } + + $result = []; + if (isset($innodb[0]['Status']) === true + && $innodb[0]['Status'] !== false + ) { + $lenght = strlen($innodb[0]['Status']); + + $data = []; + for ($i = 0; $i < $lenght; $i = ($i + 500)) { + $str = substr($innodb[0]['Status'], $i, ($i + 500)); + $data['showEngine-'.$i] = [ + 'name' => '', + 'value' => '
'.$str.'
', + ]; + } + + $result = [ + 'error' => false, + 'data' => $data, + 'id' => 'showEngine', + ]; + } + + return json_encode($result); + } + + + /** + * Agent Id whit name is equal to Server Name. + * + * @return integer Id agent module. + */ + public function getAgentIdMasterServer(): int + { + global $config; + + $serverName = db_get_value_sql( + 'SELECT `name` + FROM tserver + WHERE `name` IS NOT NULL + AND `master` > 0 + ORDER BY `master` DESC' + ); + $agentId = (int) db_get_value_sql( + sprintf( + 'SELECT id_agente + FROM tagente + WHERE nombre = "%s"', + $serverName + ) + ); + + if (isset($agentId) === false || is_numeric($agentId) === false) { + $agentId = 0; + } + + return $agentId; + } + + + /** + * Graph. + * + * @param integer $id Id agent. + * @param string $name Name module. + * @param boolean $image Chart interactive or only image. + * @param boolean $base64 Image or base64. + * + * @return string + */ + public function getChart( + int $id, + string $name, + bool $image=false, + bool $base64=false + ): string { + global $config; + + include_once $config['homedir'].'/include/functions_graph.php'; + $data = modules_get_agentmodule_id($name, $id); + $params = [ + 'agent_module_id' => $data['id_agente_modulo'], + 'period' => SECONDS_1MONTH, + 'date' => time(), + 'height' => '200', + 'only_image' => $image, + 'return_img_base_64' => $base64, + ]; + + return grafico_modulo_sparse($params); + } + + + /** + * Check pandoradb installed. + * + * @return string + */ + public function checkPandoraDB(): string + { + global $config; + $result = ''; + + if (isset($config['db_maintenance']) === false) { + $result .= '(*) '; + $result .= __( + 'Please check your Pandora Server setup and make sure that the database maintenance daemon is running.' + ); + $result .= ' '; + $result .= __( + 'It\' is very important to keep the database up-to-date to get the best performance and results in Pandora' + ); + } + + return $result; + } + + + /** + * Draw table. + * + * @param string $method Method. + * @param string $title Title. + * + * @return string Return html. + */ + public function printData(string $method, string $title): string + { + global $config; + + if (is_ajax()) { + // TODO: Call method. + $result = $method; + } else { + // Datatables list. + try { + $columns = [ + [ + 'class' => 'datatables-td-title', + 'text' => 'name', + ], + [ + 'class' => 'datatables-td-max', + 'text' => 'value', + ], + 'message', + ]; + + $columnNames = [ + [ + 'style' => 'display:none;', + 'text' => '', + ], + [ + 'style' => 'display:none', + 'text' => '', + ], + [ + 'style' => 'display:none', + 'text' => '', + ], + ]; + + $tableId = $method.'_'.uniqid(); + // Load datatables user interface. + if ($this->pdf === false) { + $result = ui_print_datatable( + [ + 'id' => $tableId, + 'class' => 'info_table caption_table', + 'style' => 'width: 100%', + 'columns' => $columns, + 'column_names' => $columnNames, + 'ajax_data' => [ + 'method' => 'datatablesDraw', + 'name' => $method, + ], + 'ajax_url' => $this->ajaxController, + 'paging' => 0, + 'no_sortable_columns' => [-1], + 'caption' => $title, + 'print' => true, + ] + ); + } else { + $data = json_decode( + $this->datatablesDraw($method, true), + true + ); + + $table = new stdClass(); + $table->width = '100%'; + $table->class = 'pdf-report'; + $table->style = []; + $table->style[0] = 'font-weight: bolder;'; + + // FIX tables break content. + if ($data['idTable'] === 'showEngine') { + $table->styleTable = 'page-break-inside: auto;'; + } else { + $table->autosize = 1; + } + + $table->head = []; + $table->head_colspan[0] = 3; + $table->head[0] = $title; + $table->data = []; + + if (isset($data) === true + && is_array($data) === true + && count($data) > 0 + ) { + $i = 0; + foreach ($data['data'] as $key => $value) { + $table->data[$i][0] = $value['name']; + $table->data[$i][1] = $value['value']; + $table->data[$i][2] = $value['message']; + $i++; + } + } + + $result = html_print_table($table, true); + } + } catch (Exception $e) { + $result = $e->getMessage(); + } + } + + return $result; + } + + + /** + * Prepare params for getCarts. + * + * @return void + */ + public function getChartAjax():void + { + global $config; + + $params = json_decode( + io_safe_output(get_parameter('params', '')), + true + ); + + $return = ''; + if (isset($params['idAgent']) === true + && empty($params['idAgent']) === false + && isset($params['nameModule']) + && empty($params['nameModule']) === false + ) { + $return = $this->getChart( + $params['idAgent'], + $params['nameModule'] + ); + } + + exit($return); + } + + + /** + * Paint table with charts. + * + * @param array $params Info charts. + * + * @return string Html. + */ + public function printDataCharts(array $params): string + { + global $config; + + if (!$params) { + $params = get_parameter('params'); + } + + if (is_ajax()) { + // TODO: Call method. + $return = $method; + } else { + // Datatables list. + try { + $id = str_replace( + ' ', + '', + io_safe_output($params['nameModule']) + ); + + if ($this->pdf === false) { + $return = '
'; + $settings = [ + 'type' => 'POST', + 'dataType' => 'html', + 'url' => ui_get_full_url( + 'ajax.php', + false, + false, + false + ), + 'data' => [ + 'page' => $this->ajaxController, + 'method' => 'getChartAjax', + 'params' => json_encode($params), + ], + ]; + + ?> + + width = '100%'; + $table->class = 'pdf-report'; + $table->style = []; + $table->style[0] = 'font-weight: bolder;'; + $table->autosize = 1; + + $table->head = []; + $table->head[0] = $params['nameModule']; + + $table->data = []; + $table->data[0] = $this->getChart( + $params['idAgent'], + $params['nameModule'], + true, + false + ); + + $return = html_print_table($table, true); + } + } catch (Exception $e) { + $return = $e->getMessage(); + } + } + + return $return; + } + + + /** + * Private function for Info size path. + * + * @param string $path Route file. + * + * @return array With values size file and message and status. + */ + private function getLogInfo(string $path): array + { + global $config; + + // Vars. + $mega = 1048576; + $tenMega = 10485760; + + $result = [ + 'value' => 0, + 'message' => '', + 'status' => 0, + ]; + + if (is_file($path) === true) { + $fileSize = filesize($path); + $sizeServerLog = number_format($fileSize); + $sizeServerLog = (0 + str_replace(',', '', $sizeServerLog)); + + $value = number_format(($fileSize / $mega), 3); + $message = __('You have more than 10 MB of logs'); + $status = 0; + if ($sizeServerLog <= $tenMega) { + $message = __('You have less than 10 MB of logs'); + $status = 1; + } + + $result = [ + 'value' => $value, + 'message' => $message, + 'status' => $status, + ]; + } + + return $result; + } + + + /** + * Undocumented function + * + * @param string|null $method Method data requested. + * @param boolean $return Type return. + * + * @return string|null + */ + public function datatablesDraw( + ?string $method=null, + bool $return=false + ):?string { + if (isset($method) === false) { + $method = get_parameter('name', ''); + } + + if (method_exists($this, $method) === true) { + $data = json_decode($this->{$method}(), true); + } + + $result = []; + if (isset($data) === true + && is_array($data) === true + && count($data) > 0 + ) { + $items = $data['data']; + $dataReduce = array_reduce( + array_keys($data['data']), + function ($carry, $key) use ($items) { + // Transforms array of arrays $data into an array + // of objects, making a post-process of certain fields. + if (isset($items[$key]['status']) === true) { + $acumValue = $items[$key]['value']; + if ($items[$key]['status'] === 1) { + $items[$key]['value'] = html_print_image( + 'images/exito.png', + true, + [ + 'title' => __('Succesfuly'), + 'style' => 'width:15px;', + ] + ); + } else { + $items[$key]['value'] = html_print_image( + 'images/error_1.png', + true, + [ + 'title' => __('Error'), + 'style' => 'width:15px;', + ] + ); + } + + $items[$key]['value'] .= ' '.$acumValue; + } + + // FIX for customer key. + if ($key === 'customerKey') { + $customerKey = ui_print_truncate_text( + $items[$key]['value'], + 30, + false, + true, + false + ); + $spanValue = ''.$customerKey.''; + $items[$key]['value'] = $spanValue; + } + + if (isset($items[$key]['message']) === false) { + $items[$key]['message'] = ''; + } + + $carry[] = (object) $items[$key]; + return $carry; + } + ); + + $result = [ + 'data' => $dataReduce, + 'recordsTotal' => count($dataReduce), + 'recordsFiltered' => count($dataReduce), + 'idTable' => (isset($data['id']) === true) ? $data['id'] : '', + ]; + } + + // Datatables format: RecordsTotal && recordsfiltered. + if ($return === false) { + echo json_encode($result); + return null; + } else { + return json_encode($result); + } + } + + + /** + * Print Diagnostics Form feedback. + * + * @return void + */ + public function formFeedback(): void + { + $form = [ + 'action' => '#', + 'id' => 'modal_form_feedback', + 'onsubmit' => 'return false;', + 'class' => 'modal', + ]; + + $inputs = []; + + $inputs[] = [ + 'label' => __('What happened').'?', + 'id' => 'div-what-happened', + 'class' => 'flex-row', + 'arguments' => [ + 'name' => 'what-happened', + 'type' => 'textarea', + 'value' => '', + 'return' => true, + 'rows' => 1, + 'columns' => 1, + 'size' => 25, + 'attributes' => 'required="required"', + ], + ]; + + $inputs[] = [ + 'label' => __('Your email'), + 'class' => 'flex-row-baseline', + 'arguments' => [ + 'name' => 'email', + 'id' => 'email', + 'type' => 'email', + 'size' => 42, + 'required' => 'required', + ], + ]; + + $inputs[] = [ + 'label' => __('Include installation data'), + 'class' => 'flex-row-vcenter', + 'arguments' => [ + 'name' => 'include_installation_data', + 'id' => 'include_installation_data', + 'type' => 'switch', + 'value' => 1, + ], + ]; + + exit( + $this->printForm( + [ + 'form' => $form, + 'inputs' => $inputs, + ], + true + ) + ); + } + + + /** + * Create cron task form feedback. + * + * @return void Json result AJAX request. + */ + public function createdScheduleFeedbackTask():void + { + global $config; + + $mail_feedback = 'feedback@artica.es'; + $email = $mail_feedback; + $subject = 'PandoraFMS Report '.$config['pandora_uid']; + $text = get_parameter('what-happened', ''); + $attachment = get_parameter_switch('include_installation_data', 0); + $email_from = get_parameter_switch('email', ''); + $title = __('Hello Feedback-Men'); + + $product_name = io_safe_output(get_product_name()); + + if (check_acl($config['id_user'], 0, 'PM') !== 1) { + $email = get_mail_admin(); + $name_admin = get_name_admin(); + + $subject = __('Feedback').' '.$product_name.' '.$config['pandora_uid']; + + $title = __('Hello').' '.$name_admin; + } + + $p1 = __( + 'User %s is reporting an issue in its %s experience', + $email_from, + $product_name + ); + $p1 .= ':'; + + $p2 = $text; + + if ($attachment === 1) { + $msg_attch = __('Find some files attached to this mail'); + $msg_attch .= '. '; + $msg_attch .= __( + 'PDF is the diagnostic information retrieved at report time' + ); + $msg_attch .= '. '; + $msg_attch .= __('CSV contains the statuses of every product file'); + $msg_attch .= '. '; + } + + $p3 = __( + 'If you think this report must be escalated, feel free to forward this mail to "%s"', + $mail_feedback + ); + + $legal = __('LEGAL WARNING'); + $legal1 = __( + 'The information contained in this transmission is privileged and confidential information intended only for the use of the individual or entity named above' + ); + $legal1 .= '. '; + $legal2 = __( + 'If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited' + ); + $legal2 .= '. '; + $legal3 = __( + 'If you have received this transmission in error, do not read it' + ); + $legal3 .= '. '; + $legal4 = __( + 'Please immediately reply to the sender that you have received this communication in error and then delete it' + ); + $legal4 .= '.'; + + $patterns = [ + '/__title__/', + '/__p1__/', + '/__p2__/', + '/__attachment__/', + '/__p3__/', + '/__legal__/', + '/__legal1__/', + '/__legal2__/', + '/__legal3__/', + '/__legal4__/', + ]; + + $substitutions = [ + $title, + $p1, + $p2, + $msg_attch, + $p3, + $legal, + $legal1, + $legal2, + $legal3, + $legal4, + ]; + + $html_template = file_get_contents( + $config['homedir'].'/include/templates/feedback_send_mail.html' + ); + + $text = preg_replace($patterns, $substitutions, $html_template); + + $idUserTask = db_get_value( + 'id', + 'tuser_task', + 'function_name', + 'cron_task_feedback_send_mail' + ); + + // Params for send mail with cron. + $parameters = [ + 0 => '0', + 1 => $email, + 2 => $subject, + 3 => $text, + 4 => $attachment, + 'first_execution' => strtotime('now'), + ]; + + // Values insert task cron. + $values = [ + 'id_usuario' => $config['id_user'], + 'id_user_task' => $idUserTask, + 'args' => serialize($parameters), + 'scheduled' => 'no', + 'id_grupo' => 0, + ]; + + $result = db_process_sql_insert( + 'tuser_task_scheduled', + $values + ); + + $error = 1; + if ($result === false) { + $error = 0; + } + + $return = [ + 'error' => $error, + 'title' => [ + __('Failed'), + __('Success'), + ], + 'text' => [ + ui_print_error_message(__('Invalid cron task'), '', true), + ui_print_success_message(__('Cron task generated'), '', true), + ], + ]; + + exit(json_encode($return)); + } + + + /** + * Print Diagnostics PDF report. + * + * @param string|null $filename Filename. + * + * @return void + */ + public function exportPDF(?string $filename=null):void + { + global $config; + + $this->pdf = true; + + enterprise_include_once('/include/class/Pdf.class.php'); + $mpdf = new Pdf([]); + + // ADD style. + $mpdf->addStyle($config['homedir'].'/include/styles/diagnostics.css'); + + // ADD Metadata. + $product_name = io_safe_output(get_product_name()); + $mpdf->setMetadata( + __('Diagnostics Info'), + $product_name.' Enteprise', + $product_name, + __( + 'Automated %s report for user defined report', + $product_name + ) + ); + + // ADD Header. + $mpdf->setHeaderHTML(__('Diagnostics Info')); + + // ADD content to report. + $mpdf->addHTML( + $this->printMethodsDiagnostigsInfo() + ); + + $mpdf->addHTML( + $this->printCharts() + ); + + // ADD Footer. + $mpdf->setFooterHTML(); + + // Write html filename. + $mpdf->writePDFfile($filename); + } + + + /** + * Send Csv md5 files. + * + * @return string + */ + public function csvMd5Files():string + { + global $config; + + // Extract files. + $files = $this->recursiveDirValidation($config['homedir']); + + // Type divider. + $divider = html_entity_decode($config['csv_divider']); + + // BOM. + $result = pack('C*', 0xEF, 0xBB, 0xBF); + + $result .= __('Path').$divider.__('MD5')."\n"; + foreach ($files as $key => $value) { + $result .= $key.$divider.$value."\n"; + } + + return $result; + } + + + /** + * Function to return array with name file -> MD%. + * + * @param string $dir Directory. + * + * @return array Result all files in directory recursively. + */ + private function recursiveDirValidation(string $dir):array + { + $result = []; + + $dir_content = scandir($dir); + + // Dont check attachment. + if (strpos($dir, $config['homedir'].'/attachment') === false) { + if (is_array($dir_content) === true) { + foreach (scandir($dir) as $file) { + if ('.' === $file || '..' === $file) { + continue; + } + + if (is_dir($dir.'/'.$file) === true) { + $result += $this->recursiveDirValidation( + $dir.'/'.$file + ); + } else { + $result[$dir.'/'.$file] = md5_file($dir.'/'.$file); + } + } + } + } + + return $result; + } + + + /** + * Send PHP info in report. + * + * @param string $filename Download dir report. + * + * @return void + */ + public function phpInfoReports(string $filename) + { + global $config; + + $this->pdf = true; + + // Extract info PHP. + ob_start(); + phpinfo(); + $php_info = ob_get_clean(); + + enterprise_include_once('/include/class/Pdf.class.php'); + $mpdf = new Pdf([]); + + // ADD Metadata. + $product_name = io_safe_output(get_product_name()); + $mpdf->setMetadata( + __('PHP Info'), + $product_name.' Enteprise', + $product_name, + __( + 'Automated %s report for user defined report', + $product_name + ) + ); + + // ADD Header. + $mpdf->setHeaderHTML(__('PHP Info')); + + // ADD content to report. + $mpdf->addHTML($php_info); + + // ADD Footer. + $mpdf->setFooterHTML(); + + // Write html filename. + $mpdf->writePDFfile($filename); + } + + +} diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index 70eb7b8728..4ce47bac09 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -3881,11 +3881,11 @@ function generator_chart_to_pdf($type_graph_pdf, $params, $params_combined=false $img_content = join("\n", $result); if ($params['return_img_base_64']) { - // To be used in alerts + // To be used in alerts. $width_img = 500; return $img_content; } else { - // to be used in PDF files + // to be used in PDF files. $config['temp_images'][] = $img_path; return ''; } diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index ab3aad9c7a..ca809a727f 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -1535,6 +1535,89 @@ function html_print_input_text($name, $value, $alt='', $size=50, $maxlength=255, } +/** + * Render an input email element. + * + * @param array $settings Array with attributes input. + * only name is necessary. + * + * @return string Html input. + */ +function html_print_input_email(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. * @@ -1898,6 +1981,7 @@ function html_get_predefined_table($model='transparent', $columns=4) * $table->titlestyle - Title style * $table->titleclass - Title class * $table->styleTable - Table style + * $table->autosize - Autosize * $table->caption - Table title * @param bool Whether to return an output string or echo now * @@ -2008,6 +2092,12 @@ function html_print_table(&$table, $return=false) // $table->width = '80%'; } + if (isset($table->autosize) === true) { + $table->autosize = 'autosize = "1"'; + } else { + $table->autosize = ''; + } + if (empty($table->border)) { if (empty($table)) { $table = new stdClass(); @@ -2042,9 +2132,9 @@ function html_print_table(&$table, $return=false) $tableid = empty($table->id) ? 'table'.$table_count : $table->id; if (!empty($table->width)) { - $output .= 'width.'; '.$styleTable.' '.$table->tablealign; } else { - $output .= '
tablealign; } $output .= ' cellpadding="'.$table->cellpadding.'" cellspacing="'.$table->cellspacing.'"'; @@ -3003,23 +3093,24 @@ function html_print_csrf_error() /** - * Print an swith button + * Print an swith button. * - * @param array $atributes. Valid params: - * name: Usefull to handle in forms - * value: If is checked or not - * disabled: Disabled. Cannot be pressed. - * id: Optional id for the switch. - * class: Additional classes (string). - * @return string with HTML of button + * @param array $attributes Valid params. + * name: Usefull to handle in forms. + * value: If is checked or not. + * disabled: Disabled. Cannot be pressed. + * id: Optional id for the switch. + * class: Additional classes (string). + * + * @return string with HTML of button. */ function html_print_switch($attributes=[]) { $html_expand = ''; // Check the load values on status. - $html_expand .= (bool) $attributes['value'] ? ' checked' : ''; - $html_expand .= (bool) $attributes['disabled'] ? ' disabled' : ''; + $html_expand .= (bool) ($attributes['value']) ? ' checked' : ''; + $html_expand .= (bool) ($attributes['disabled']) ? ' disabled' : ''; // Only load the valid attributes. $valid_attrs = [ @@ -3042,7 +3133,7 @@ function html_print_switch($attributes=[]) } return ""; } @@ -3200,6 +3291,10 @@ function html_print_input($data, $wrapper='div', $input_only=false) ); break; + case 'email': + $output .= html_print_input_email($data); + break; + case 'hidden': $output .= html_print_input_hidden( $data['name'], diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 493cbd1156..b3429dbc5c 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -3015,6 +3015,10 @@ function ui_print_datatable(array $parameters) $parameters['default_pagination'] = $config['block_size']; } + if (!isset($parameters['paging'])) { + $parameters['paging'] = true; + } + $no_sortable_columns = []; if (isset($parameters['no_sortable_columns'])) { $no_sortable_columns = json_encode($parameters['no_sortable_columns']); @@ -3175,7 +3179,7 @@ function ui_print_datatable(array $parameters) $table = '
'; - $table .= ''; + $table .= ''; if (isset($parameters['column_names']) && is_array($parameters['column_names']) @@ -3224,7 +3228,7 @@ function ui_print_datatable(array $parameters) }, processing: true, serverSide: true, - paging: true, + paging: '.$parameters['paging'].', pageLength: '.$parameters['default_pagination'].', searching: false, responsive: true, @@ -3324,10 +3328,18 @@ function ui_print_datatable(array $parameters) $("#'.$form_id.'_search_bt").click(function (){ dt_'.$table_id.'.draw().page(0) - }); - }); + });'; -'; + if (isset($parameters['caption']) === true + && empty($parameters['caption']) === false + ) { + $js .= '$("#'.$table_id.'").append("");'; + $js .= '$(".datatables_thead_tr").css("height", 0);'; + } + + $js .= '});'; + + $js .= ''; // Order. $err_msg = '
'; @@ -3343,7 +3355,7 @@ function ui_print_datatable(array $parameters) $output = $include.$output; // Print datatable if needed. - if (!(isset($parameters['print']) && $parameters['print'] === false)) { + if (isset($parameters['print']) === false || $parameters['print'] === false) { echo $output; } diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index 97d97c7273..86e4475eea 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -1236,3 +1236,29 @@ function users_get_explode_tags(&$group) } } + + +/** + * Get mail admin. + * + * @return string Return mail admin. + */ +function get_mail_admin():string +{ + $mail = db_get_value('email', 'tusuario', 'is_admin', 1); + + return $mail; +} + + +/** + * Get name admin. + * + * @return string Return name admin. + */ +function get_name_admin():string +{ + $mail = db_get_value('fullname', 'tusuario', 'is_admin', 1); + + return $mail; +} diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index 33ab956a1f..f3737eabdf 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -1,3 +1,6 @@ +/* global $ */ +/* exported load_modal */ + var ENTERPRISE_DIR = "enterprise"; /* Function to hide/unhide a specific Div id */ @@ -1872,8 +1875,6 @@ function logo_preview(icon_name, icon_path, incoming_options) { } // Advanced Form control. -/* global $ */ -/* exported load_modal */ function load_modal(settings) { var AJAX_RUNNING = 0; var data = new FormData(); @@ -1943,6 +1944,10 @@ function load_modal(settings) { if (settings.onsubmit.preaction != undefined) { settings.onsubmit.preaction(); } + if (settings.onsubmit.dataType == undefined) { + settings.onsubmit.dataType = "html"; + } + var formdata = new FormData(); if (settings.extradata) { settings.extradata.forEach(function(item) { @@ -1953,29 +1958,57 @@ function load_modal(settings) { formdata.append("page", settings.onsubmit.page); formdata.append("method", settings.onsubmit.method); + var flagError = false; + $("#" + settings.form + " :input").each(function() { + if (this.checkValidity() === false) { + $(this).prop("title", this.validationMessage); + $(this).tooltip({ + tooltipClass: "uitooltip", + position: { my: "right bottom", at: "right bottom" }, + show: { duration: 200 } + }); + $(this).tooltip("open"); + flagError = true; + } + if (this.type == "file") { if ($(this).prop("files")[0]) { formdata.append(this.name, $(this).prop("files")[0]); } } else { - formdata.append(this.name, $(this).val()); + if ($(this).attr("type") == "checkbox") { + if (this.checked) { + formdata.append(this.name, "on"); + } + } else { + formdata.append(this.name, $(this).val()); + } } }); - $.ajax({ - method: "post", - url: settings.url, - processData: false, - contentType: false, - data: formdata, - success: function(data) { - if (settings.ajax_callback != undefined) { - settings.ajax_callback(data); + if (flagError === false) { + $.ajax({ + method: "post", + url: settings.url, + processData: false, + contentType: false, + data: formdata, + dataType: settings.onsubmit.dataType, + success: function(data) { + if (settings.ajax_callback != undefined) { + if (settings.idMsgCallback != undefined) { + settings.ajax_callback(data, settings.idMsgCallback); + } else { + settings.ajax_callback(data); + } + } + AJAX_RUNNING = 0; } - AJAX_RUNNING = 0; - } - }); + }); + } else { + AJAX_RUNNING = 0; + } } } ], @@ -1987,3 +2020,75 @@ function load_modal(settings) { } }); } + +/** + * Function to show modal with message Validation. + * + * @param {json} data Json example: + * $return = [ + * 'error' => 0 or 1, + * 'title' => [ + * Failed, + * Success, + * ], + * 'text' => [ + * Failed, + * Success, + * ], + *]; + * @param {string} idMsg ID div charge modal. + * + * @return {void} + */ +function generalShowMsg(data, idMsg) { + var title = data.title[data.error]; + var text = data.text[data.error]; + var failed = !data.error; + + $("#" + idMsg).empty(); + $("#" + idMsg).html(text); + $("#" + idMsg).dialog({ + width: 450, + position: { + my: "center", + at: "center", + of: window, + collision: "fit" + }, + title: title, + buttons: [ + { + class: + "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next", + text: "OK", + click: function(e) { + if (!failed) { + $(".ui-dialog-content").dialog("close"); + } else { + $(this).dialog("close"); + } + } + } + ] + }); +} + +/** + * Function for AJAX request. + * + * @param {string} id Id container append data. + * @param {json} settings Json with settings. + * + * @return {void} + */ +function ajaxRequest(id, settings) { + $.ajax({ + type: settings.type, + dataType: settings.html, + url: settings.url, + data: settings.data, + success: function(data) { + $("#" + id).append(data); + } + }); +} diff --git a/pandora_console/include/styles/diagnostics.css b/pandora_console/include/styles/diagnostics.css new file mode 100644 index 0000000000..3b541ac523 --- /dev/null +++ b/pandora_console/include/styles/diagnostics.css @@ -0,0 +1,58 @@ +.pdf-report { + page-break-inside: avoid; +} + +.pdf-report th, +.title-self-monitoring, +.caption_table caption { + text-align: center; + font-size: 1.5em; + font-weight: bolder; + color: #fff; + background: #282828; + padding: 8px; +} + +.pdf-report tr { + text-align: justify; +} + +.datatables-td-title { + width: 25% !important; + font-weight: bolder; +} + +.datatables-td-max { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.datatables-td-max img { + margin-right: 10px; +} + +.datatables-td-max span { + width: 400px; + display: inline-block; + word-wrap: break-word; +} + +.pdf-report td { + font-size: 1.2em; +} + +.container-self-monitoring { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.element-self-monitoring { + flex: 2 1 600px; +} + +.footer-self-monitoring { + margin: 30px; + font-style: italic; +} diff --git a/pandora_console/include/styles/discovery.css b/pandora_console/include/styles/discovery.css index 82b022050f..2095e98b8e 100644 --- a/pandora_console/include/styles/discovery.css +++ b/pandora_console/include/styles/discovery.css @@ -205,6 +205,7 @@ label { } li > input[type="text"], +li > input[type="email"], li > input[type="password"], .discovery_text_input > input[type="password"], .discovery_text_input > input[type="text"], @@ -270,3 +271,29 @@ a.ext_link { margin-left: 1em; font-size: 8pt; } + +input:invalid, +input[type="email"]:invalid { + border-bottom-color: #fb4444; +} + +textarea:invalid { + border-color: #fb4444; +} + +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: 0 0 0px #fff; + 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; +} diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 459cc5c54d..758114e12d 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -544,6 +544,13 @@ select:-internal-list-box { align-items: baseline; } +.flex-row-vcenter { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; +} + .nowrap { flex-wrap: nowrap; } diff --git a/pandora_console/include/templates/feedback_send_mail.html b/pandora_console/include/templates/feedback_send_mail.html new file mode 100644 index 0000000000..e06b68f246 --- /dev/null +++ b/pandora_console/include/templates/feedback_send_mail.html @@ -0,0 +1,58 @@ + + + + + + + Feedback + + + +

__title__

+
+

__p1__

+

__p2__

+

__attachment__

+

__p3__

+
+
__legal__
+ + + + + + diff --git a/pandora_console/tools/diagnostics.php b/pandora_console/tools/diagnostics.php new file mode 100644 index 0000000000..30be89efc4 --- /dev/null +++ b/pandora_console/tools/diagnostics.php @@ -0,0 +1,73 @@ + '[Diagnostics]'.$e->getMessage() ]); + exit; + } else { + echo '[Diagnostics]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; +} + +// AJAX controller. +if (is_ajax()) { + $method = get_parameter('method'); + + if (method_exists($cs, $method) === true) { + if ($cs->ajaxMethod($method) === true) { + $cs->{$method}(); + } else { + $cs->error('Unavailable method.'); + } + } else { + $cs->error('Method not found. ['.$method.']'); + } + + // Stop any execution. + exit; +} else { + // Run. + $cs->run(); +}
'.$parameters['caption'].'