diff --git a/pandora_console/godmode/servers/discovery.php b/pandora_console/godmode/servers/discovery.php
index 39f07aa025..3dd8e258ee 100755
--- a/pandora_console/godmode/servers/discovery.php
+++ b/pandora_console/godmode/servers/discovery.php
@@ -1,5 +1,7 @@
';
echo __('deselect all');
echo '';
+ echo '';
+ echo '';
echo '';
echo '';
@@ -1279,12 +1285,18 @@ class DiscoveryTaskList extends HTML
}
$ids = [];
+ $n_agents = 0;
$selection = io_safe_output(get_parameter('tree-data-tree', ''));
if (empty($selection) === false) {
$selection = json_decode($selection, true);
$ids = array_reduce(
$selection,
- function ($carry, $item) {
+ function ($carry, $item) use (&$n_agents) {
+ if (explode('-', $item['id'])[1] === null) {
+ // String is agent-module.
+ $n_agents++;
+ }
+
$carry[] = $item['id'];
return $carry;
}
@@ -1296,6 +1308,24 @@ class DiscoveryTaskList extends HTML
['id_rt' => $id_task]
);
+ // License precheck.
+ $license = enterprise_hook('license_get_info');
+
+ if (is_array($license) === true
+ && $n_agents > ($license['limit'] - $license['count'])
+ ) {
+ $limit = ($license['limit'] - $license['count']);
+ echo json_encode(
+ [
+ 'error' => __(
+ 'Your selection exceeds the agents available on your license. Limit %d',
+ $limit
+ ),
+ ]
+ );
+ return;
+ }
+
$summary = [];
if (is_array($ids)) {
foreach ($task_data as $row) {
diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php
index 727010cb8d..43825c31e5 100755
--- a/pandora_console/godmode/wizards/HostDevices.class.php
+++ b/pandora_console/godmode/wizards/HostDevices.class.php
@@ -946,6 +946,36 @@ class HostDevices extends Wizard
],
];
+ // License precheck.
+ $license = enterprise_hook('license_get_info');
+ $n_agents = 0;
+ foreach (explode(',', $this->task['subnet']) as $net) {
+ $mask = explode('/', $net, 2)[1];
+ if (empty($mask)) {
+ $n_agents++;
+ } else {
+ $n_agents += pow(2, (32 - $mask));
+ }
+ }
+
+ $limited = false;
+ if (is_array($license) === true
+ && $n_agents > ($license['limit'] - $license['count'])
+ ) {
+ $limit = ($license['limit'] - $license['count']);
+ $limited = true;
+ }
+
+ if ($limited === true) {
+ ui_print_warning_message(
+ __(
+ 'Configured networks could generate %d agents, your license only allows %d, \'review results\' is mandatory.',
+ $n_agents,
+ $limit
+ )
+ );
+ }
+
$form['inputs'][] = [
'label' => __('Review results').ui_print_help_tip(
__(
@@ -954,10 +984,11 @@ class HostDevices extends Wizard
true
),
'arguments' => [
- 'name' => 'review_results',
- 'type' => 'switch',
- 'return' => true,
- 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? 0 : 1,
+ 'name' => 'review_results',
+ 'type' => 'switch',
+ 'return' => true,
+ 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? (($limited) ? 1 : 0) : 1,
+ 'disabled' => $limited,
],
];
diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm
index 9d2f4c18ac..b387de5283 100644
--- a/pandora_server/lib/PandoraFMS/Core.pm
+++ b/pandora_server/lib/PandoraFMS/Core.pm
@@ -270,7 +270,9 @@ our @EXPORT = qw(
pandora_delete_custom_graph
pandora_edit_custom_graph
notification_set_targets
- );
+ notification_get_users
+ notification_get_groups
+);
# Some global variables
our @DayNames = qw(sunday monday tuesday wednesday thursday friday saturday);
@@ -6254,6 +6256,55 @@ sub notification_set_targets {
return 1;
}
+##########################################################################
+
+=head2 C<< notification_get_users (I<$dbh>, I<$source>) >>
+Get targets for given sources
+=cut
+
+##########################################################################
+sub notification_get_users {
+ my ($dbh, $source) = @_;
+
+ my @results = get_db_rows(
+ $dbh,
+ 'SELECT id_user
+ FROM tnotification_source_user nsu
+ INNER JOIN tnotification_source ns ON nsu.id_source=ns.id
+ WHERE ns.description = ?
+ ',
+ safe_input($source)
+ );
+
+ @results = map { $_->{'id_user'} } @results;
+ return @results;
+}
+
+##########################################################################
+
+=head2 C<< notification_get_groups (I<$dbh>, I<$source>) >>
+Get targets for given sources
+=cut
+
+##########################################################################
+sub notification_get_groups {
+ my ($dbh, $source) = @_;
+
+ my @results = get_db_rows(
+ $dbh,
+ 'SELECT id_group
+ FROM tnotification_source_group nsg
+ INNER JOIN tnotification_source ns ON nsg.id_source=ns.id
+ WHERE ns.description = ?
+ ',
+ safe_input($source)
+ );
+
+ @results = map { $_->{'id_group'} } @results;
+ return @results;
+}
+
+
# End of function declaration
# End of defined Code
diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm
index bdfe445f15..2c3d9f1c9f 100644
--- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm
+++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm
@@ -58,8 +58,8 @@ use constant {
STEP_AFT => 2,
STEP_TRACEROUTE => 3,
STEP_GATEWAY => 4,
- STEP_MONITORING => 5,
- STEP_PROCESSING => 6,
+ STEP_MONITORING => 5,
+ STEP_PROCESSING => 6,
STEP_STATISTICS => 1,
STEP_APP_SCAN => 2,
STEP_CUSTOM_QUERIES => 3,
@@ -206,17 +206,26 @@ sub data_consumer ($$) {
@auth_strings = split(/,/, safe_output($task->{'auth_strings'}));
}
- my $main_event = pandora_event($pa_config, "[Discovery] Execution summary",$task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh);
+ my $main_event = pandora_event($pa_config,
+ "[Discovery] Execution summary",
+ $task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh
+ );
my %cnf_extra;
- my $r = enterprise_hook('discovery_generate_extra_cnf',[$pa_config, $dbh, $task, \%cnf_extra]);
+ my $r = enterprise_hook(
+ 'discovery_generate_extra_cnf',
+ [
+ $pa_config,
+ $dbh, $task,
+ \%cnf_extra
+ ]
+ );
if (defined($r) && $r eq 'ERR') {
# Could not generate extra cnf, skip this task.
return;
}
-
if ($task->{'type'} == DISCOVERY_APP_SAP) {
# SAP TASK, retrieve license.
$task->{'sap_license'} = pandora_get_config_value(
@@ -752,74 +761,74 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) {
# Add wmi modules to the given host.
################################################################################
sub PandoraFMS::Recon::Base::create_wmi_modules {
- my ($self, $target) = @_;
+ my ($self, $target) = @_;
# Add modules to the agent if it responds to WMI.
return unless ($self->wmi_responds($target));
- my $key = $self->wmi_credentials_key($target);
+ my $key = $self->wmi_credentials_key($target);
my $creds = $self->call('get_credentials', $key);
- # Add modules.
- # CPU.
- my @cpus = $self->wmi_get_value_array($target, 'SELECT DeviceId FROM Win32_Processor', 0);
- foreach my $cpu (@cpus) {
- $self->add_module(
- $target,
- {
- 'ip_target' => $target,
- 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'",
- 'plugin_user' => $creds->{'username'},
+ # Add modules.
+ # CPU.
+ my @cpus = $self->wmi_get_value_array($target, 'SELECT DeviceId FROM Win32_Processor', 0);
+ foreach my $cpu (@cpus) {
+ $self->add_module(
+ $target,
+ {
+ 'ip_target' => $target,
+ 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'",
+ 'plugin_user' => $creds->{'username'},
'plugin_pass' => $creds->{'password'},
- 'tcp_port' => 1,
- 'name' => "CPU Load $cpu",
- 'descripcion' => safe_input("Load for $cpu (%)"),
- 'id_tipo_modulo' => 1,
+ 'tcp_port' => 1,
+ 'name' => "CPU Load $cpu",
+ 'descripcion' => safe_input("Load for $cpu (%)"),
+ 'id_tipo_modulo' => 1,
'id_modulo' => 6,
- 'unit' => '%',
- }
- );
- }
+ 'unit' => '%',
+ }
+ );
+ }
- # Memory.
- my $mem = $self->wmi_get_value($target, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0);
- if (defined($mem)) {
- $self->add_module(
- $target,
- {
- 'ip_target' => $target,
- 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem",
- 'plugin_user' => $creds->{'username'},
- 'plugin_pass' => $creds->{'password'},
- 'tcp_port' => 0,
- 'name' => 'FreeMemory',
- 'descripcion' => safe_input('Free memory'),
- 'id_tipo_modulo' => 1,
+ # Memory.
+ my $mem = $self->wmi_get_value($target, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0);
+ if (defined($mem)) {
+ $self->add_module(
+ $target,
+ {
+ 'ip_target' => $target,
+ 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem",
+ 'plugin_user' => $creds->{'username'},
+ 'plugin_pass' => $creds->{'password'},
+ 'tcp_port' => 0,
+ 'name' => 'FreeMemory',
+ 'descripcion' => safe_input('Free memory'),
+ 'id_tipo_modulo' => 1,
'id_modulo' => 6,
- 'unit' => 'KB',
- }
- );
- }
+ 'unit' => 'KB',
+ }
+ );
+ }
- # Disk.
- my @units = $self->wmi_get_value_array($target, 'SELECT DeviceID FROM Win32_LogicalDisk', 0);
- foreach my $unit (@units) {
- $self->add_module(
- $target,
- {
- 'ip_target' => $target,
- 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'",
- 'plugin_user' => $creds->{'username'},
- 'plugin_pass' => $creds->{'password'},
- 'tcp_port' => 1,
- 'name' => "FreeDisk $unit",
- 'descripcion' => safe_input('Available disk space in kilobytes'),
- 'id_tipo_modulo' => 1,
+ # Disk.
+ my @units = $self->wmi_get_value_array($target, 'SELECT DeviceID FROM Win32_LogicalDisk', 0);
+ foreach my $unit (@units) {
+ $self->add_module(
+ $target,
+ {
+ 'ip_target' => $target,
+ 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'",
+ 'plugin_user' => $creds->{'username'},
+ 'plugin_pass' => $creds->{'password'},
+ 'tcp_port' => 1,
+ 'name' => "FreeDisk $unit",
+ 'descripcion' => safe_input('Available disk space in kilobytes'),
+ 'id_tipo_modulo' => 1,
'id_modulo' => 6,
- 'unit' => 'KB',
- }
- );
- }
+ 'unit' => 'KB',
+ }
+ );
+ }
}
@@ -907,23 +916,21 @@ sub PandoraFMS::Recon::Base::get_credentials {
################################################################################
# Create agents and modules reported by Recon::Base.
################################################################################
-sub PandoraFMS::Recon::Base::report_scanned_agents($) {
- my ($self) = @_;
+sub PandoraFMS::Recon::Base::report_scanned_agents($;$) {
+ my ($self,$force) = @_;
- my $force_creation = 0;
-
- if (defined($self->{'task_data'}{'review_mode'})
- && $self->{'task_data'}{'review_mode'} == DISCOVERY_STANDARD
- ) {
- $force_creation = 1;
- }
+ my $force_creation = $force;
+ $force_creation = 0 unless (is_enabled($force));
#
# Creation
#
- if(defined($self->{'task_data'}{'review_mode'})
- && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS
+
+ if($force_creation == 1
+ || (defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS)
) {
+
# Load cache.
my @rows = get_db_rows(
$self->{'dbh'},
@@ -978,7 +985,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
my $parent_id;
my $os_id = $self->guess_os($data->{'agent'}{'direccion'});
- $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5);
+ $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5);
# Agent creation.
my $agent_id = $data->{'agent'}{'agent_id'};
@@ -999,10 +1006,11 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
$agent_id = get_db_value(
$self->{'dbh'},
'SELECT id_agente FROM tagente WHERE nombre = ?',
- safe_input($data->{'agent'}->{'name'})
+ safe_input($data->{'agent'}{'nombre'})
);
if (!defined($agent_id) || $agent_id <= 0) {
+ # Agent creation.
$agent_id = pandora_create_agent(
$self->{'pa_config'}, $self->{'servername'}, $data->{'agent'}{'nombre'},
$data->{'agent'}{'direccion'}, $self->{'task_data'}{'group_id'}, $parent_id,
@@ -1011,6 +1019,43 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
$data->{'agent'}{'timezone_offset'}
);
+ # Agent autoconfiguration.
+ if (is_enabled($self->{'autoconfiguration_enabled'})) {
+ my $agent_data = PandoraFMS::DB::get_db_single_row(
+ $self->{'dbh'},
+ 'SELECT * FROM tagente WHERE id_agente = ?',
+ $agent_id
+ );
+
+ # Update agent configuration once, after create agent.
+ enterprise_hook(
+ 'autoconfigure_agent',
+ [
+ $self->{'pa_config'},
+ $data->{'agent'}{'direccion'},
+ $agent_id,
+ $agent_data,
+ $self->{'dbh'},
+ 1
+ ]
+ );
+ }
+
+ if (defined($self->{'main_event_id'})) {
+ my $addresses_str = join(
+ ',',
+ $self->get_addresses(safe_output($data->{'agent'}{'nombre'}))
+ );
+
+ pandora_extended_event(
+ $self->{'pa_config'}, $self->{'dbh'},
+ $self->{'main_event_id'},"[Discovery] New "
+ . $self->get_device_type(safe_output($data->{'agent'}{'nombre'}))
+ . " found " . $data->{'agent'}{'nombre'} . " (" . $addresses_str
+ . ") Agent $agent_id."
+ );
+ }
+
$agent_learning = 1;
} else {
# Read from effective agent_id.
@@ -1044,24 +1089,20 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
$self->call('message', "[$agent_id] Module: ".$module->{'name'}, 5);
- my $agentmodule_id = $module->{'agentmodule_id'};
-
- if (defined($agentmodule_id) && $agentmodule_id > 0) {
- $agentmodule_id = get_db_value(
- $self->{'dbh'},
- 'SELECT id_agente_modulo FROM tagente_modulo
- WHERE id_agente_modulo = ? AND nombre = ?',
- $agentmodule_id,
- safe_input($module->{'name'})
- );
- }
+ my $agentmodule_id = get_db_value(
+ $self->{'dbh'},
+ 'SELECT id_agente_modulo FROM tagente_modulo
+ WHERE id_agente = ? AND nombre = ?',
+ $agent_id,
+ safe_input($module->{'name'})
+ );
if (!is_enabled($agentmodule_id)) {
# Create.
# Delete unwanted fields.
delete $module->{'agentmodule_id'};
- delete $module->{'checked'};
+ delete $module->{'checked'};
my $id_tipo_modulo = $module->{'id_tipo_modulo'};
$id_tipo_modulo = get_module_id($self->{'dbh'}, $module->{'type'})
@@ -1105,7 +1146,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
$self->{'dbh'}
);
- $module->{'name'} = $name;
+ $module->{'name'} = $name;
$module->{'description'} = safe_output($description);
}
@@ -1213,8 +1254,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
$self->call('message', "Storing results", 6);
my @hosts = keys %{$self->{'agents_found'}};
- $self->{'step'} = STEP_PROCESSING;
- my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%.
+ $self->{'step'} = STEP_PROCESSING;
+ my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%.
foreach my $label (keys %{$self->{'agents_found'}}) {
$self->call('update_progress', $progress);
$progress += $step;
@@ -1261,6 +1302,46 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) {
);
}
+
+ if(defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_REVIEW
+ ) {
+ # Notify.
+ my $notification = {};
+ $notification->{'subject'} = safe_input('Discovery task ');
+ $notification->{'subject'} .= $self->{'task_data'}{'name'};
+ $notification->{'subject'} .= safe_input(' review pending');
+
+ $notification->{'mensaje'} = safe_input(
+ 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'})
+ .'\' has been completed. Please review the results.'
+ );
+
+ $notification->{'id_source'} = get_db_value(
+ $self->{'dbh'},
+ 'SELECT id FROM tnotification_source WHERE description = ?',
+ safe_input('System status')
+ );
+
+ # Create message
+ my $notification_id = db_process_insert(
+ $self->{'dbh'},
+ 'id_mensaje',
+ 'tmensajes',
+ $notification
+ );
+
+ if (is_enabled($notification_id)) {
+ my @users = notification_get_users($self->{'dbh'}, 'System status');
+ my @groups = notification_get_groups($self->{'dbh'}, 'System status');
+
+ notification_set_targets(
+ $self->{'pa_config'}, $self->{'dbh'},
+ $notification_id, \@users, \@groups
+ );
+ }
+ }
+
$self->call('message', "Completed", 5);
}
@@ -1272,9 +1353,9 @@ sub PandoraFMS::Recon::Base::apply_monitoring($) {
my @hosts = keys %{$self->{'agents_found'}};
- $self->{'step'} = STEP_MONITORING;
+ $self->{'step'} = STEP_MONITORING;
# From 80% to 90%.
- my ($progress, $step) = (80, 10.0 / scalar(@hosts));
+ my ($progress, $step) = (80, 10.0 / scalar(@hosts));
my ($partial, $sub_step) = (0, 100 / scalar(@hosts));
foreach my $label (keys %{$self->{'agents_found'}}) {
diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm
index 9bf4e8e536..81e7d5993f 100644
--- a/pandora_server/lib/PandoraFMS/Recon/Base.pm
+++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm
@@ -683,7 +683,11 @@ sub get_device_type($$) {
my ($self, $device) = @_;
if (defined($self->{'visited_devices'}->{$device})) {
- return $self->{'visited_devices'}->{$device}->{'type'};
+ if (defined($self->{'visited_devices'}->{$device}->{'type'})) {
+ return $self->{'visited_devices'}->{$device}->{'type'};
+ } else {
+ $self->{'visited_devices'}->{$device}->{'type'} = 'host';
+ }
}
# Assume 'host' by default.
@@ -1931,7 +1935,14 @@ sub scan($) {
$self->call('message', "[6/6] Processing results.", 3);
$self->{'step'} = STEP_PROCESSING;
# Send agent information to Database (Discovery) or XML (satellite.).
- $self->call('report_scanned_agents', $self->{'agents_found'});
+ $self->call('report_scanned_agents');
+
+ if(defined($self->{'task_data'}{'review_mode'})
+ && $self->{'task_data'}{'review_mode'} == DISCOVERY_STANDARD
+ ) {
+ # Send agent information to Database (Discovery) or XML (satellite.).
+ $self->call('report_scanned_agents', 1);
+ }
# Done!
$self->{'step'} = '';