diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control
index 12c86842bb..5cca3bfc08 100644
--- a/pandora_agents/unix/DEBIAN/control
+++ b/pandora_agents/unix/DEBIAN/control
@@ -1,5 +1,5 @@
package: pandorafms-agent-unix
-Version: 7.0NG.760-220308
+Version: 7.0NG.760-220323
Architecture: all
Priority: optional
Section: admin
diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh
index db3dac0ba8..1cd4bb6a44 100644
--- a/pandora_agents/unix/DEBIAN/make_deb_package.sh
+++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh
@@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-pandora_version="7.0NG.760-220308"
+pandora_version="7.0NG.760-220323"
echo "Test if you has the tools for to make the packages."
whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null
diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent
index 031891f6f7..1fb038bd67 100755
--- a/pandora_agents/unix/pandora_agent
+++ b/pandora_agents/unix/pandora_agent
@@ -1015,7 +1015,7 @@ my $Sem = undef;
my $ThreadSem = undef;
use constant AGENT_VERSION => '7.0NG.760';
-use constant AGENT_BUILD => '220308';
+use constant AGENT_BUILD => '220323';
# Agent log default file size maximum and instances
use constant DEFAULT_MAX_LOG_SIZE => 600000;
diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec
index c139325a33..c4e7643283 100644
--- a/pandora_agents/unix/pandora_agent.redhat.spec
+++ b/pandora_agents/unix/pandora_agent.redhat.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_agent_unix
%define version 7.0NG.760
-%define release 220308
+%define release 220323
Summary: Pandora FMS Linux agent, PERL version
Name: %{name}
@@ -24,7 +24,7 @@ Requires(preun): chkconfig /bin/rm /usr/sbin/userdel
Requires: coreutils unzip
Requires: util-linux procps grep
Requires: /sbin/ip /bin/awk
-Requires: perl perl(Sys::Syslog) perl(IO::Compress::Zip)
+Requires: perl(Sys::Syslog) perl(IO::Compress::Zip)
# Required by plugins
#Requires: sh-utils sed passwd net-tools rpm
AutoReq: 0
diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec
index 5a86e5fde6..c82c54a8b8 100644
--- a/pandora_agents/unix/pandora_agent.spec
+++ b/pandora_agents/unix/pandora_agent.spec
@@ -3,7 +3,7 @@
#
%define name pandorafms_agent_unix
%define version 7.0NG.760
-%define release 220308
+%define release 220323
Summary: Pandora FMS Linux agent, PERL version
Name: %{name}
diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer
index b56b236a58..5ad8783635 100755
--- a/pandora_agents/unix/pandora_agent_installer
+++ b/pandora_agents/unix/pandora_agent_installer
@@ -10,7 +10,7 @@
# **********************************************************************
PI_VERSION="7.0NG.760"
-PI_BUILD="220308"
+PI_BUILD="220323"
OS_NAME=`uname -s`
FORCE=0
diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi
index d0a547543d..2562c227cd 100644
--- a/pandora_agents/win32/installer/pandora.mpi
+++ b/pandora_agents/win32/installer/pandora.mpi
@@ -186,7 +186,7 @@ UpgradeApplicationID
{}
Version
-{220308}
+{220323}
ViewReadme
{Yes}
diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc
index 9ae0dc6643..ac0d6ecf37 100644
--- a/pandora_agents/win32/pandora.cc
+++ b/pandora_agents/win32/pandora.cc
@@ -30,7 +30,7 @@ using namespace Pandora;
using namespace Pandora_Strutils;
#define PATH_SIZE _MAX_PATH+1
-#define PANDORA_VERSION ("7.0NG.760 Build 220308")
+#define PANDORA_VERSION ("7.0NG.760 Build 220323")
string pandora_path;
string pandora_dir;
diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc
index e3dc078a25..31e8d991b3 100644
--- a/pandora_agents/win32/versioninfo.rc
+++ b/pandora_agents/win32/versioninfo.rc
@@ -11,7 +11,7 @@ BEGIN
VALUE "LegalCopyright", "Artica ST"
VALUE "OriginalFilename", "PandoraAgent.exe"
VALUE "ProductName", "Pandora FMS Windows Agent"
- VALUE "ProductVersion", "(7.0NG.760(Build 220308))"
+ VALUE "ProductVersion", "(7.0NG.760(Build 220323))"
VALUE "FileVersion", "1.0.0.0"
END
END
diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control
index 3166e9ae22..f6becafe45 100644
--- a/pandora_console/DEBIAN/control
+++ b/pandora_console/DEBIAN/control
@@ -1,5 +1,5 @@
package: pandorafms-console
-Version: 7.0NG.760-220308
+Version: 7.0NG.760-220323
Architecture: all
Priority: optional
Section: admin
diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh
index cf5d20c7fb..5ad1d08da0 100644
--- a/pandora_console/DEBIAN/make_deb_package.sh
+++ b/pandora_console/DEBIAN/make_deb_package.sh
@@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-pandora_version="7.0NG.760-220308"
+pandora_version="7.0NG.760-220323"
package_pear=0
package_pandora=1
diff --git a/pandora_console/extensions/dbmanager.php b/pandora_console/extensions/dbmanager.php
index fbe3d7cb47..8c248367dc 100644
--- a/pandora_console/extensions/dbmanager.php
+++ b/pandora_console/extensions/dbmanager.php
@@ -11,6 +11,9 @@
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
+use PandoraFMS\Enterprise\Metaconsole\Node;
+
+
function dbmanager_query($sql, &$error, $dbconnection)
{
global $config;
@@ -88,6 +91,10 @@ function dbmgr_extension_main()
global $config;
+ if (is_metaconsole() === true) {
+ open_meta_frame();
+ }
+
if (!is_user_admin($config['id_user'])) {
db_pandora_audit(
AUDIT_LOG_ACL_VIOLATION,
@@ -98,11 +105,59 @@ function dbmgr_extension_main()
}
$sql = (string) get_parameter('sql');
+ $node_id = (int) get_parameter('node_id', -1);
ui_print_page_header(__('Database interface'), 'images/gm_db.png', false, false, true);
- echo '
";
diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php
index 2b771497fe..a53246c071 100644
--- a/pandora_console/include/functions_html.php
+++ b/pandora_console/include/functions_html.php
@@ -4267,6 +4267,10 @@ function html_print_input_file($name, $return=false, $options=false)
if (isset($options['onchange'])) {
$output .= ' onchange="'.$options['onchange'].'"';
}
+
+ if (isset($options['style']) === true) {
+ $output .= ' style="'.$options['style'].'"';
+ }
}
$output .= ' />';
@@ -4936,7 +4940,13 @@ function html_print_input($data, $wrapper='div', $input_only=false)
((isset($data['size']) === true) ? $data['size'] : false),
((isset($data['modal']) === true) ? $data['modal'] : false),
((isset($data['message']) === true) ? $data['message'] : ''),
- ((isset($data['select_all']) === true) ? $data['select_all'] : false)
+ ((isset($data['select_all']) === true) ? $data['select_all'] : false),
+ ((isset($data['simple_multiple_options']) === true) ? $data['simple_multiple_options'] : false),
+ ((isset($data['required']) === true) ? $data['required'] : false),
+ ((isset($data['truncate_size']) === true) ? $data['truncate_size'] : false),
+ ((isset($data['select2_enable']) === true) ? $data['select2_enable'] : true),
+ ((isset($data['select2_multiple_enable']) === true) ? $data['select2_multiple_enable'] : false),
+ ((isset($data['select2_multiple_enable_all']) === true) ? $data['select2_multiple_enable_all'] : false)
);
break;
@@ -5728,3 +5738,198 @@ function html_print_select_search(
echo $output;
}
}
+
+
+/**
+ * Print html select for agents secondary.
+ *
+ * @param integer $agent Agent.
+ * @param integer $id_agente Id Agent.
+ * @param array $options Array options.
+ *
+ * @return string Html output.
+ */
+function html_print_select_agent_secondary($agent, $id_agente, $options=[])
+{
+ ui_require_css_file('agent_manager');
+ ui_require_javascript_file('pandora_agents');
+
+ if (empty($options) === '' || isset($options['id_form']) === false) {
+ $options['id_form'] = 'form_agent';
+ }
+
+ if (empty($options) === '' || isset($options['extra_id']) === false) {
+ $options['extra_id'] = '';
+ }
+
+ if (empty($options) === '' || isset($options['only_select']) === false) {
+ $options['only_select'] = false;
+ }
+
+ $secondary_groups_selected = enterprise_hook(
+ 'agents_get_secondary_groups',
+ [$id_agente]
+ );
+
+ $name = 'secondary_groups'.$options['extra_id'];
+ if ($options['only_select'] === true) {
+ $name = 'secondary_groups'.$options['extra_id'].'[]';
+ }
+
+ $adv_secondary_groups_left = html_print_select_groups(
+ // Id_user.
+ // Use the current user to select the groups.
+ false,
+ // Privilege.
+ // ACL permission.
+ 'AR',
+ // ReturnAllGroup.
+ // Not all group.
+ false,
+ // Name.
+ // HTML id.
+ $name,
+ // Selected.
+ // No select any by default.
+ '',
+ // Script.
+ // Javascript onChange code.
+ '',
+ // Nothing.
+ // Do not user no selected value.
+ false,
+ // Nothing_value.
+ // Do not use no selected value.
+ 0,
+ // Return.
+ // Return HTML (not echo).
+ true,
+ // Multiple.
+ // Multiple selection.
+ true,
+ // Sort.
+ // Sorting by default.
+ true,
+ // Class.
+ // CSS classnames (default).
+ '',
+ // Disabled.
+ // Not disabled (default).
+ false,
+ // Style.
+ // Inline styles (default).
+ 'min-width:170px;',
+ // Option_style.
+ // Option style select (default).
+ false,
+ // Id_group.
+ // Do not truncate the users tree (default).
+ false,
+ // Keys_field.
+ // Key to get as value (default).
+ 'id_grupo',
+ // Strict_user.
+ // Not strict user (default).
+ false,
+ // Delete_groups.
+ // Do not show the primary group in this selection.
+ array_merge(
+ (empty($secondary_groups_selected['plain']) === false) ? $secondary_groups_selected['plain'] : [],
+ [$agent['id_grupo']]
+ )
+ // Include_groups.
+ // Size.
+ // Simple_multiple_options.
+ );
+
+ if ($options['only_select'] === false) {
+ $dictionary = base64_encode(
+ json_encode(
+ [
+ 'primary_group' => __('Primary group cannot be secondary too.'),
+ 'strNone' => __('None'),
+ ]
+ )
+ );
+
+ $adv_secondary_groups_arrows = html_print_input_image(
+ 'add_secondary',
+ 'images/darrowright_green.png',
+ 1,
+ '',
+ true,
+ [
+ 'id' => 'right_autorefreshlist'.$options['extra_id'],
+ 'title' => __('Add secondary groups'),
+ 'onclick' => 'agent_manager_add_secondary_groups(event, '.$id_agente.',\''.$options['extra_id'].'\', \''.$options['id_form'].'\', \''.$dictionary.'\');',
+ ]
+ );
+
+ $adv_secondary_groups_arrows .= html_print_input_image(
+ 'remove_secondary',
+ 'images/darrowleft_green.png',
+ 1,
+ '',
+ true,
+ [
+ 'id' => 'left_autorefreshlist'.$options['extra_id'],
+ 'title' => __('Remove secondary groups'),
+ 'onclick' => 'agent_manager_remove_secondary_groups(event, '.$id_agente.',\''.$options['extra_id'].'\', \''.$options['id_form'].'\', \''.$dictionary.'\');',
+ ]
+ );
+
+ $adv_secondary_groups_right .= html_print_select(
+ // Values.
+ $secondary_groups_selected['for_select'],
+ // HTML id.
+ 'secondary_groups_selected'.$options['extra_id'],
+ // Selected.
+ '',
+ // Javascript onChange code.
+ '',
+ // Nothing selected.
+ false,
+ // Nothing selected.
+ 0,
+ // Return HTML (not echo).
+ true,
+ // Multiple selection.
+ true,
+ // Sort.
+ true,
+ // Class.
+ '',
+ // Disabled.
+ false,
+ // Style.
+ 'min-width:170px;'
+ );
+
+ $output = '';
+ if (isset($options['container']) === true
+ && $options['container'] === true
+ ) {
+ $output = '
';
+ }
+
+ $output .= '
';
+ $output .= $adv_secondary_groups_left;
+ $output .= '
';
+ $output .= '
';
+ $output .= $adv_secondary_groups_arrows;
+ $output .= '
';
+ $output .= '
';
+ $output .= $adv_secondary_groups_right;
+ $output .= '
';
+
+ if (isset($options['container']) === true
+ && $options['container'] === true
+ ) {
+ $output .= '
';
+ }
+ } else {
+ $output .= $adv_secondary_groups_left;
+ }
+
+ return $output;
+}
diff --git a/pandora_console/include/functions_netflow.php b/pandora_console/include/functions_netflow.php
index 60229d79ae..f88f6b751d 100644
--- a/pandora_console/include/functions_netflow.php
+++ b/pandora_console/include/functions_netflow.php
@@ -321,6 +321,72 @@ function netflow_data_table($data, $start_date, $end_date, $aggregate)
}
+/**
+ * Show a table with netflow top N data.
+ *
+ * @param array $data Netflow data.
+ * @param integer $total_bytes Total bytes count to calculate percent data.
+ *
+ * @return string HTML data table.
+ */
+function netflow_top_n_table(array $data, int $total_bytes)
+{
+ global $nfdump_date_format;
+
+ $values = [];
+ $table = new stdClass();
+ $table->class = 'w100p';
+ $table->cellspacing = 0;
+ $table->data = [];
+
+ $table->head = [];
+ $table->head[0] = '
'.__('Source IP').'';
+ $table->head[1] = '
'.__('Destination IP').'';
+ $table->head[2] = '
'.__('Bytes').'';
+ $table->head[3] = '
'.__('% Traffic').'';
+ $table->head[4] = '
'.__('Avg. Throughput').'';
+ $table->style[0] = 'padding: 4px';
+
+ $i = 0;
+
+ foreach ($data as $value) {
+ $table->data[$i][0] = $value['ip_src'];
+ $table->data[$i][1] = $value['ip_dst'];
+ $table->data[$i][2] = network_format_bytes($value['bytes']);
+
+ $traffic = '-';
+
+ if ($total_bytes > 0) {
+ $traffic = sprintf(
+ '%.2f',
+ (($value['bytes'] / $total_bytes) * 100)
+ );
+ }
+
+ $table->data[$i][3] = $traffic.' %';
+
+ $units = [
+ 'bps',
+ 'Kbps',
+ 'Mbps',
+ 'Gbps',
+ 'Tbps',
+ ];
+
+ $pow = floor((($value['bps'] > 0) ? log($value['bps']) : 0) / log(1024));
+ $pow = min($pow, (count($units) - 1));
+
+ $value['bps'] /= pow(1024, $pow);
+
+ $table->data[$i][4] = round($value['bps'], 2).' '.$units[$pow];
+
+ $i++;
+ }
+
+ return html_print_table($table, true);
+}
+
+
/**
* Show a table with a traffic summary.
*
@@ -395,6 +461,67 @@ function netflow_is_net($address)
}
+/**
+ * Returns netflow top N connections for the given period in an array (based on total traffic).
+ *
+ * @param string $start_date Period start date.
+ * @param string $end_date Period end date.
+ * @param array $filter Netflow filter.
+ * @param integer $max Maximum number of aggregates.
+ * @param string $connection_name Node name when data is get in meta.
+ *
+ * @return array An array with netflow stats.
+ */
+function netflow_get_top_N(
+ string $start_date,
+ string $end_date,
+ array $filter,
+ int $max,
+ string $connection_name=''
+) {
+ global $nfdump_date_format;
+
+ // Requesting remote data.
+ if (is_metaconsole() === true && empty($connection_name) === false) {
+ $data = metaconsole_call_remote_api(
+ $connection_name,
+ 'netflow_get_top_N',
+ $start_date.'|'.$end_date.'|'.base64_encode(json_encode($filter)).'|'.$max
+ );
+
+ return json_decode($data, true);
+ }
+
+ $options = '-o "fmt:%sap,%dap,%ibyt,%bps" -q -n '.$max.' -s record/bytes -t '.date($nfdump_date_format, $start_date).'-'.date($nfdump_date_format, $end_date);
+
+ $command = netflow_get_command($options, $filter);
+
+ // Execute nfdump.
+ exec($command, $lines);
+
+ if (is_array($lines) === false) {
+ return [];
+ }
+
+ $values = [];
+ $i = 0;
+
+ foreach ($lines as $line) {
+ $parsed_line = explode(',', $line);
+ $parsed_line = array_map('trim', $parsed_line);
+
+ $values[$i]['ip_src'] = $parsed_line[0];
+ $values[$i]['ip_dst'] = $parsed_line[1];
+ $values[$i]['bytes'] = $parsed_line[2];
+ $values[$i]['bps'] = $parsed_line[3];
+
+ $i++;
+ }
+
+ return $values;
+}
+
+
/**
* Returns netflow data for the given period in an array.
*
@@ -707,7 +834,7 @@ function netflow_get_summary($start_date, $end_date, $filter, $connection_name='
global $config;
// Requesting remote data.
- if (defined('METACONSOLE') && $connection_name != '') {
+ if (is_metaconsole() === true && $connection_name != '') {
$data = metaconsole_call_remote_api($connection_name, 'netflow_get_summary', "$start_date|$end_date|".base64_encode(json_encode($filter)));
return json_decode($data, true);
}
@@ -1051,6 +1178,7 @@ function netflow_get_chart_types()
'netflow_area' => __('Area graph'),
'netflow_summary' => __('Summary'),
'netflow_data' => __('Data table'),
+ 'netflow_top_N' => __('Top-N connections'),
'netflow_mesh' => __('Circular mesh'),
'netflow_host_treemap' => __('Host detailed traffic'),
];
@@ -1218,6 +1346,54 @@ function netflow_draw_item(
}
break;
+ case 'netflow_top_N':
+ $data_summary = netflow_get_summary(
+ $start_date,
+ $end_date,
+ $filter,
+ $connection_name
+ );
+
+ if (empty($data_summary) === true) {
+ break;
+ }
+
+ $data_top_n = netflow_get_top_N(
+ $start_date,
+ $end_date,
+ $filter,
+ $max_aggregates,
+ $connection_name
+ );
+
+ if (empty($data_top_n) === true) {
+ break;
+ }
+
+ if ($output === 'HTML' || $output === 'PDF') {
+ $html = '
';
+ $html .= '';
+ $html .= "";
+ $html .= netflow_summary_table($data_summary);
+ $html .= ' | ';
+ $html .= '
';
+ $html .= '';
+ $html .= "";
+ $html .= netflow_top_n_table($data_top_n, $data_summary['totalbytes']);
+ $html .= ' | ';
+ $html .= '
';
+ $html .= '
';
+
+ return $html;
+ } else if ($output === 'XML') {
+ $xml = '
'.$aggregate."\n";
+ $xml .= '
'.$interval_length."\n";
+ // Same as netflow_aggregate_area_xml.
+ $xml .= netflow_aggregate_area_xml($data_top_n);
+ return $xml;
+ }
+ break;
+
case 'netflow_mesh':
$data = netflow_get_relationships_raw_data(
$start_date,
@@ -1304,6 +1480,46 @@ function netflow_draw_item(
}
+/**
+ * Get data of a netflow report item.
+ *
+ * @param string $start_date Period start date.
+ * @param string $end_date Period end date.
+ * @param array $filter Netflow filter.
+ * @param integer $max_aggregates Maximum number of aggregates.
+ * @param string $connection_name Node name when data is get in meta.
+ *
+ * @return array Netflow item data (summary and top N data).
+ */
+function netflow_get_item_data(
+ string $start_date,
+ string $end_date,
+ array $filter,
+ int $max_aggregates,
+ string $connection_name
+) {
+ $data_summary = netflow_get_summary(
+ $start_date,
+ $end_date,
+ $filter,
+ $connection_name
+ );
+
+ $data_top_n = netflow_get_top_N(
+ $start_date,
+ $end_date,
+ $filter,
+ $max_aggregates,
+ $connection_name
+ );
+
+ return [
+ 'summary' => $data_summary,
+ 'top_n' => $data_top_n,
+ ];
+}
+
+
/**
* Render an aggregated area chart as an XML.
*
diff --git a/pandora_console/include/functions_planned_downtimes.php b/pandora_console/include/functions_planned_downtimes.php
index f6fdf49c11..796f09ab72 100644
--- a/pandora_console/include/functions_planned_downtimes.php
+++ b/pandora_console/include/functions_planned_downtimes.php
@@ -989,7 +989,7 @@ function planned_downtimes_copy($id_downtime)
foreach ($planned_modules as $planned_module) {
// Unset id.
unset($planned_module['id']);
- // Set id_planned downtime
+ // Set id_planned downtime.
$planned_module['id_downtime'] = $result['id_downtime'];
$result['id_modules'][] = db_process_sql_insert(
'tplanned_downtime_moduless',
@@ -1004,3 +1004,82 @@ function planned_downtimes_copy($id_downtime)
return $result;
}
+
+
+/**
+ * Get agentts and modules for planned_downtime.
+ *
+ * @param [type] $id Id planned.
+ *
+ * @return array Result array data.
+ */
+function get_agents_modules_planned_dowtime($id, $options, $count=false)
+{
+ $result = [];
+
+ $filters_agent = '';
+ if (isset($options['filters']['filter_agents']) === true
+ && empty($options['filters']['filter_agents']) === false
+ ) {
+ $filters_agent = sprintf(
+ ' AND (tagente.alias LIKE "%%%s%%")',
+ $options['filters']['filter_agents']
+ );
+ }
+
+ $filters_module = '';
+ if (isset($options['filters']['filter_modules']) === true
+ && empty($options['filters']['filter_modules']) === false
+ ) {
+ $filters_module = sprintf(
+ ' AND (tagente_modulo.nombre LIKE "%%%s%%")',
+ $options['filters']['filter_modules']
+ );
+ }
+
+ if ($count === false) {
+ $query = sprintf(
+ 'SELECT tplanned_downtime_modules.*,
+ tagente.alias as agent_name,
+ tagente_modulo.nombre as module_name
+ FROM tplanned_downtime_modules
+ INNER JOIN tagente
+ ON tplanned_downtime_modules.id_agent = tagente.id_agente
+ INNER JOIN tagente_modulo
+ ON tplanned_downtime_modules.id_agent_module = tagente_modulo.id_agente_modulo
+ WHERE id_downtime = %d
+ %s
+ %s
+ ORDER BY %s
+ LIMIT %d, %d',
+ $id,
+ $filters_agent,
+ $filters_module,
+ $options['order'],
+ $options['limit'],
+ $options['offset']
+ );
+ } else {
+ $query = sprintf(
+ 'SELECT count(tplanned_downtime_modules.id) as total
+ FROM tplanned_downtime_modules
+ INNER JOIN tagente
+ ON tplanned_downtime_modules.id_agent = tagente.id_agente
+ INNER JOIN tagente_modulo
+ ON tplanned_downtime_modules.id_agent_module = tagente_modulo.id_agente_modulo
+ WHERE id_downtime = %d
+ %s
+ %s',
+ $id,
+ $filters_agent,
+ $filters_module
+ );
+ }
+
+ $result = db_get_all_rows_sql($query);
+ if ($result === false) {
+ $result = [];
+ }
+
+ return $result;
+}
diff --git a/pandora_console/include/functions_reporting.php b/pandora_console/include/functions_reporting.php
index 3693a72dcd..ba3dc52551 100755
--- a/pandora_console/include/functions_reporting.php
+++ b/pandora_console/include/functions_reporting.php
@@ -606,6 +606,18 @@ function reporting_make_reporting_data(
);
break;
+ case 'netflow_top_N':
+ $report['contents'][] = reporting_netflow(
+ $report,
+ $content,
+ $type,
+ $force_width_chart,
+ $force_height_chart,
+ 'netflow_top_N',
+ $pdf
+ );
+ break;
+
case 'monitor_report':
$report['contents'][] = reporting_monitor_report(
$report,
@@ -730,6 +742,13 @@ function reporting_make_reporting_data(
);
break;
+ case 'agent_module_status':
+ $report['contents'][] = reporting_agent_module_status(
+ $report,
+ $content
+ );
+ break;
+
case 'alert_report_actions':
$report['contents'][] = reporting_alert_report_actions(
$report,
@@ -2854,6 +2873,136 @@ function reporting_agent_module($report, $content)
}
+/**
+ * Agents module status
+ *
+ * @param array $report Info Report.
+ * @param array $content Info content.
+ *
+ * @return array
+ */
+function reporting_agent_module_status($report, $content)
+{
+ global $config;
+ $return['type'] = 'agent_module_status';
+
+ if (empty($content['name'])) {
+ $content['name'] = __('Agent/Modules Status');
+ }
+
+ $return['title'] = io_safe_output($content['name']);
+ $return['landscape'] = $content['landscape'];
+ $return['pagebreak'] = $content['pagebreak'];
+ $group_name = groups_get_name($content['id_group'], true);
+ if ($content['id_module_group'] == 0) {
+ $module_group_name = __('All');
+ } else {
+ $module_group_name = db_get_value(
+ 'name',
+ 'tmodule_group',
+ 'id_mg',
+ $content['id_module_group']
+ );
+ }
+
+ $return['subtitle'] = $group_name.' - '.$module_group_name;
+ $return['description'] = io_safe_output($content['description']);
+ $return['date'] = reporting_get_date_text($report, $content);
+ $return['label'] = (isset($content['style']['label'])) ? $content['style']['label'] : '';
+
+ $return['data'] = [];
+
+ $external_source = json_decode(
+ $content['external_source'],
+ true
+ );
+
+ $agents = json_decode(
+ io_safe_output(
+ base64_decode($external_source['id_agents'])
+ ),
+ true
+ );
+
+ $modules = json_decode(
+ io_safe_output(
+ base64_decode($external_source['module'])
+ ),
+ true
+ );
+
+ if (is_metaconsole() === true) {
+ $agents_per_node = [];
+ $modules_per_node = [];
+
+ if (empty($agents) === false) {
+ foreach ($agents as $value) {
+ $agent_array = explode('|', $value);
+ $agents_per_node[$agent_array[0]][] = $agent_array[1];
+ }
+ }
+
+ if (empty($modules) === false) {
+ foreach ($modules as $value) {
+ $module_array = explode('|', $value);
+ $modules_per_node[$module_array[0]][] = $module_array[1];
+ }
+ }
+
+ if (empty($agents_per_node) === false) {
+ foreach ($agents_per_node as $server => $agents) {
+ $connection = metaconsole_get_connection_by_id($server);
+ if (metaconsole_connect($connection) != NOERR) {
+ continue;
+ }
+
+ $res[$connection['server_name']] = get_status_data_agent_modules(
+ $content['id_group'],
+ $agents,
+ $modules_per_node[$server]
+ );
+
+ metaconsole_restore_db();
+ }
+ } else {
+ $metaconsole_connections = metaconsole_get_connection_names();
+ // For all nodes.
+ if (isset($metaconsole_connections) === true
+ && is_array($metaconsole_connections) === true
+ ) {
+ foreach ($metaconsole_connections as $metaconsole) {
+ // Get server connection data.
+ $server_data = metaconsole_get_connection($metaconsole);
+
+ // Establishes connection.
+ if (metaconsole_load_external_db($server_data) !== NOERR) {
+ continue;
+ }
+
+ $res[$server_data['server_name']] = get_status_data_agent_modules(
+ $content['id_group'],
+ $agents,
+ $modules
+ );
+
+ metaconsole_restore_db();
+ }
+ }
+ }
+ } else {
+ $res['node'] = get_status_data_agent_modules(
+ $content['id_group'],
+ $agents,
+ $modules
+ );
+ }
+
+ $return['data'] = $res;
+
+ return reporting_check_structure_content($return);
+}
+
+
function reporting_exception(
$report,
$content,
@@ -5432,6 +5581,10 @@ function reporting_netflow(
$return['type'] = 'netflow_summary';
break;
+ case 'netflow_top_N':
+ $return['type'] = 'netflow_top_N';
+ break;
+
default:
$return['type'] = 'unknown';
break;
@@ -5451,6 +5604,10 @@ function reporting_netflow(
$content['name'] = __('Netflow Data');
break;
+ case 'netflow_top_N':
+ $content['name'] = __('Netflow top-N connections');
+ break;
+
default:
$content['name'] = __('Unknown report');
break;
@@ -5490,26 +5647,61 @@ function reporting_netflow(
true
);
- switch ($type) {
- case 'dinamic':
- case 'static':
- case 'data':
- $return['chart'] = netflow_draw_item(
- ($report['datetime'] - $content['period']),
- $report['datetime'],
- $content['top_n'],
- $type_netflow,
- $filter,
- $content['top_n_value'],
- $content['server_name'],
- $pdf ? 'PDF' : 'HTML'
- );
- break;
+ if ($type_netflow === 'netflow_top_N') {
+ // Always aggregate by destination port.
+ $filter['aggregate'] = 'dstport';
- case 'data':
- default:
- // Nothing to do.
- break;
+ switch ($type) {
+ case 'dinamic':
+ case 'static':
+ $return['chart'] = netflow_draw_item(
+ ($report['datetime'] - $content['period']),
+ $report['datetime'],
+ $content['top_n'],
+ $type_netflow,
+ $filter,
+ $content['top_n_value'],
+ $content['server_name'],
+ (($pdf === true) ? 'PDF' : 'HTML')
+ );
+ break;
+
+ case 'data':
+ $return['data'] = netflow_get_item_data(
+ ($report['datetime'] - $content['period']),
+ $report['datetime'],
+ $filter,
+ $content['top_n_value'],
+ $content['server_name']
+ );
+ break;
+
+ default:
+ // Nothing to do.
+ break;
+ }
+ } else {
+ switch ($type) {
+ case 'dinamic':
+ case 'static':
+ case 'data':
+ $return['chart'] = netflow_draw_item(
+ ($report['datetime'] - $content['period']),
+ $report['datetime'],
+ $content['top_n'],
+ $type_netflow,
+ $filter,
+ $content['top_n_value'],
+ $content['server_name'],
+ $pdf ? 'PDF' : 'HTML'
+ );
+ break;
+
+ case 'data':
+ default:
+ // Nothing to do.
+ break;
+ }
}
$return['subtitle'] = netflow_generate_subtitle_report(
@@ -11049,11 +11241,29 @@ function reporting_get_stats_users($data)
$tdata = [];
$tdata[0] = html_print_image('images/user.png', true, ['title' => __('Defined users'), 'class' => 'invert_filter']);
- $user_groups = users_get_strict_mode_groups($config['id_user'], false);
- if (array_key_exists(0, $user_groups)) {
- $users = users_get_user_users($config['id_user'], 'AR', true);
+ $user_is_admin = users_is_admin();
+
+ $users = [];
+
+ if ($user_is_admin) {
+ $users = get_users('', ['disabled' => 0], ['id_user', 'is_admin']);
} else {
- $users = users_get_user_users($config['id_user'], 'AR', false);
+ $group_um = users_get_groups_UM($config['id_user']);
+ // 0 is the group 'all'.
+ if (isset($group_um[0])) {
+ $users = get_users('', ['disabled' => 0], ['id_user', 'is_admin']);
+ } else {
+ foreach ($group_um as $group => $value) {
+ $users = array_merge($users, users_get_users_by_group($group, $value, false));
+ }
+ }
+ }
+
+ foreach ($users as $user_id => $user_info) {
+ // If user is not admin then don't display admin users.
+ if ($user_is_admin === false && (bool) $user_info['is_admin'] === true) {
+ unset($users[$user_id]);
+ }
}
$tdata[1] = count($users);
diff --git a/pandora_console/include/functions_reporting_html.php b/pandora_console/include/functions_reporting_html.php
index f697b10a01..b18b2a4b91 100644
--- a/pandora_console/include/functions_reporting_html.php
+++ b/pandora_console/include/functions_reporting_html.php
@@ -326,6 +326,7 @@ function reporting_html_print_report($report, $mini=false, $report_info=1)
case 'netflow_area':
case 'netflow_data':
case 'netflow_summary':
+ case 'netflow_top_N':
reporting_html_graph($table, $item);
break;
@@ -377,6 +378,10 @@ function reporting_html_print_report($report, $mini=false, $report_info=1)
reporting_html_agent_module($table, $item);
break;
+ case 'agent_module_status':
+ reporting_html_agent_module_status($table, $item);
+ break;
+
case 'alert_report_actions':
reporting_html_alert_report_actions($table, $item);
break;
@@ -1999,6 +2004,125 @@ function reporting_html_agent_module($table, $item)
}
+/**
+ * Html report agent modules status.
+ *
+ * @param object $table Head table or false if it comes from pdf.
+ * @param array $item Items data.
+ * @param integer $pdf Pdf output.
+ *
+ * @return mixed
+ */
+function reporting_html_agent_module_status($table, $item, $pdf=0)
+{
+ global $config;
+
+ $return_pdf = '';
+
+ if (empty($item['data']) === true) {
+ if ($pdf !== 0) {
+ $return_pdf .= __('No items');
+ } else {
+ $table->colspan['group_report']['cell'] = 3;
+ $table->cellstyle['group_report']['cell'] = 'text-align: center;';
+ $table->data['group_report']['cell'] = __('No items');
+ }
+ } else {
+ $table_info = new stdClass();
+ $table_info->width = '99%';
+
+ $table_info->align = [];
+ if (is_metaconsole() === true) {
+ $table_info->align['server'] = 'left';
+ }
+
+ $table_info->align['name_group'] = 'left';
+ $table_info->align['name_agent'] = 'left';
+ $table_info->align['name_module'] = 'left';
+ $table_info->align['status_module'] = 'left';
+ $table_info->align['data_module'] = 'left';
+ $table_info->align['data_time_module'] = 'left';
+
+ $table_info->headstyle = [];
+ if (is_metaconsole() === true) {
+ $table_info->headstyle['server'] = 'text-align: left';
+ }
+
+ $table_info->headstyle['name_group'] = 'text-align: left';
+ $table_info->headstyle['name_agent'] = 'text-align: left';
+ $table_info->headstyle['name_module'] = 'text-align: left';
+ $table_info->headstyle['status_module'] = 'text-align: left';
+ $table_info->headstyle['data_module'] = 'text-align: left';
+ $table_info->headstyle['data_time_module'] = 'text-align: left';
+
+ $table_info->head = [];
+ if (is_metaconsole() === true) {
+ $table_info->head['server'] = __('Server');
+ }
+
+ $table_info->head['name_agent'] = __('Agent');
+ $table_info->head['name_module'] = __('Module');
+ $table_info->head['name_group'] = __('Group');
+ $table_info->head['status_module'] = __('Status');
+ $table_info->head['data_module'] = __('Data');
+ $table_info->head['data_time_module'] = __('Last time');
+
+ $table_info->data = [];
+
+ foreach ($item['data'] as $server => $info) {
+ foreach ($info as $data) {
+ $row = [];
+ if (is_metaconsole() === true) {
+ $row['server'] = $server;
+ }
+
+ $row['name_agent'] = $data['name_agent'];
+ $row['name_module'] = $data['name_module'];
+ $row['name_group'] = $data['name_group'];
+ $row['status_module'] = ui_print_module_status(
+ $data['status_module'],
+ true,
+ 'status_rounded_rectangles',
+ null,
+ ($pdf === 1) ? ' ' : ''
+ );
+
+ if (is_numeric($data['data_module']) === true) {
+ $row['data_module'] = remove_right_zeros(
+ number_format(
+ $data['data_module'],
+ $config['graph_precision']
+ )
+ );
+ } else {
+ $row['data_module'] = (empty($data['data_module']) === true) ? '--' : $data['data_module'];
+ }
+
+ $row['data_module'] .= $data['unit_module'];
+ $row['data_time_module'] = $data['data_time_module'];
+
+ $table_info->data[] = $row;
+ }
+ }
+
+ if ($pdf !== 0) {
+ $table_info->title = $item['title'];
+ $table_info->titleclass = 'title_table_pdf';
+ $table_info->titlestyle = 'text-align:left;';
+ $return_pdf .= html_print_table($table_info, true);
+ } else {
+ $table->colspan['data']['cell'] = 3;
+ $table->cellstyle['data']['cell'] = 'text-align: center;';
+ $table->data['data']['cell'] = html_print_table($table_info, true);
+ }
+ }
+
+ if ($pdf !== 0) {
+ return $return_pdf;
+ }
+}
+
+
/**
* Function to print to HTML Exception report.
*
diff --git a/pandora_console/include/functions_reports.php b/pandora_console/include/functions_reports.php
index f310856ad2..f8fa28a0e7 100755
--- a/pandora_console/include/functions_reports.php
+++ b/pandora_console/include/functions_reports.php
@@ -653,7 +653,8 @@ function reports_get_report_types($template=false, $not_editor=false)
'optgroup' => __('Graphs'),
'name' => __('Custom graph'),
];
- // Only pandora managers have access to the whole database
+
+ // Only pandora managers have access to the whole database.
if (check_acl($config['id_user'], 0, 'PM')) {
$types['sql_graph_vbar'] = [
'optgroup' => __('Graphs'),
@@ -711,7 +712,7 @@ function reports_get_report_types($template=false, $not_editor=false)
'name' => __('Hourly S.L.A.'),
];
- if (!$config['metaconsole'] && !$template) {
+ if ($template === false) {
$types['SLA_services'] = [
'optgroup' => __('SLA'),
'name' => __('Services S.L.A.'),
@@ -796,6 +797,11 @@ function reports_get_report_types($template=false, $not_editor=false)
}
}
+ $types['agent_module_status'] = [
+ 'optgroup' => __('Grouped'),
+ 'name' => __('Agents/Modules status'),
+ ];
+
// Only pandora managers have access to the whole database.
if (check_acl($config['id_user'], 0, 'PM')) {
$types['sql'] = [
@@ -901,6 +907,10 @@ function reports_get_report_types($template=false, $not_editor=false)
'optgroup' => __('Netflow'),
'name' => __('Netflow summary table'),
];
+ $types['netflow_top_N'] = [
+ 'optgroup' => __('Netflow'),
+ 'name' => __('Netflow top-N connections'),
+ ];
}
if ($config['enterprise_installed'] && $template === false && !is_metaconsole()) {
diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php
index b3b66a4a9b..e25a5d74bb 100755
--- a/pandora_console/include/functions_ui.php
+++ b/pandora_console/include/functions_ui.php
@@ -2713,16 +2713,15 @@ function ui_print_status_image(
$imagepath = $path;
}
- if ($imagepath == 'images/status_sets/default') {
+ if ($imagepath === 'images/status_sets/default') {
$image_with_css = true;
}
- $imagepath .= '/'.$type;
-
if ($image_with_css === true) {
$shape_status = get_shape_status_set($type);
return ui_print_status_sets($type, $title, $return, $shape_status, $extra_info);
} else {
+ $imagepath .= '/'.$type;
if ($options === false) {
$options = [];
}
@@ -2737,10 +2736,11 @@ function ui_print_status_image(
/**
* Returns html code to print a shape for a module.
*
- * @param integer $status Module status.
- * @param boolean $return True or false.
- * @param string $class Custom class or use defined.
- * @param string $title Custom title or inherit from module status.
+ * @param integer $status Module status.
+ * @param boolean $return True or false.
+ * @param string $class Custom class or use defined.
+ * @param string $title Custom title or inherit from module status.
+ * @param string $div_content Content.
*
* @return string HTML code for shape.
*/
@@ -2748,7 +2748,8 @@ function ui_print_module_status(
$status,
$return=false,
$class='status_rounded_rectangles',
- $title=null
+ $title=null,
+ $div_content=''
) {
$color = modules_get_color_status($status, true);
if ($title === null) {
@@ -2758,7 +2759,7 @@ function ui_print_module_status(
$output = '
';
+ $output .= $title.'" data-use_title_for_force_title="1">'.$div_content.'
';
if ($return === false) {
echo $output;
@@ -2869,7 +2870,7 @@ function ui_print_status_sets(
$options = [];
}
- if (isset($options['style'])) {
+ if (isset($options['style']) === true) {
$options['style'] .= ' display: inline-block;';
} else {
$options['style'] = 'display: inline-block;';
@@ -2879,15 +2880,15 @@ function ui_print_status_sets(
$options['style'] .= ' background: '.modules_get_color_status($status).';';
}
- if (isset($options['class'])) {
+ if (isset($options['class']) === true) {
$options['class'] = $options['class'];
}
- if ($title != '') {
- $options['title'] = empty($extra_info) ? $title : $title.'
'.$extra_info;
- $options['data-title'] = empty($extra_info) ? $title : $title.'