Merge branch 'ent-6387-limitar-agentes-por-grupo' into 'develop'

Added control for max agents in groups

Closes pandora_enterprise#6387

See merge request artica/pandorafms!3800
This commit is contained in:
Daniel Rodriguez 2021-04-19 07:17:56 +00:00
commit 59ec6c850d
9 changed files with 189 additions and 56 deletions

View File

@ -1,5 +1,6 @@
START TRANSACTION; START TRANSACTION;
ALTER TABLE `tgrupo` ADD COLUMN `max_agents` int(10) NOT NULL DEFAULT 0;
ALTER TABLE `tagent_custom_fields` MODIFY COLUMN `combo_values` TEXT NOT NULL DEFAULT ''; ALTER TABLE `tagent_custom_fields` MODIFY COLUMN `combo_values` TEXT NOT NULL DEFAULT '';
ALTER TABLE `treport_content` MODIFY `external_source` MEDIUMTEXT; ALTER TABLE `treport_content` MODIFY `external_source` MEDIUMTEXT;
ALTER TABLE `treport_content_template` MODIFY `external_source` MEDIUMTEXT; ALTER TABLE `treport_content_template` MODIFY `external_source` MEDIUMTEXT;

View File

@ -2853,6 +2853,12 @@ UPDATE twidget SET description='Show a visual console' WHERE class_name='MapsMad
UPDATE twidget SET description='Clock' WHERE class_name='ClockWidget'; UPDATE twidget SET description='Clock' WHERE class_name='ClockWidget';
UPDATE twidget SET description='Group status' WHERE class_name='SystemGroupStatusWidget'; UPDATE twidget SET description='Group status' WHERE class_name='SystemGroupStatusWidget';
--
-- Modifies tgrupo table.
--
ALTER TABLE tgrupo ADD COLUMN max_agents int(10) NOT NULL DEFAULT 0;
-- ---------------------------------------------------------------------- -- ----------------------------------------------------------------------
-- Table `tnode_relations` -- Table `tnode_relations`
-- ---------------------------------------------------------------------- -- ----------------------------------------------------------------------

View File

@ -37,6 +37,8 @@ require_once $config['homedir'].'/include/functions_cron.php';
ui_require_javascript_file('encode_decode_base64'); ui_require_javascript_file('encode_decode_base64');
ui_require_css_file('agent_manager'); ui_require_css_file('agent_manager');
use PandoraFMS\Event;
check_login(); check_login();
// Get tab parameter to check ACL in each tabs. // Get tab parameter to check ACL in each tabs.
@ -229,6 +231,9 @@ if ($create_agent) {
if ($alias == '') { if ($alias == '') {
$agent_creation_error = __('No agent alias specified'); $agent_creation_error = __('No agent alias specified');
$agent_created_ok = 0; $agent_created_ok = 0;
} else if (group_allow_more_agents($grupo, true, 'create') === false) {
$agent_creation_error = __('Agent cannot be created due to the maximum agent limit for this group');
$agent_created_ok = 0;
} else { } else {
if ($alias_as_name) { if ($alias_as_name) {
$sql = 'SELECT nombre FROM tagente WHERE nombre = "'.$alias.'"'; $sql = 'SELECT nombre FROM tagente WHERE nombre = "'.$alias.'"';
@ -1034,6 +1039,8 @@ if ($update_agent) {
if ($grupo <= 0) { if ($grupo <= 0) {
ui_print_error_message(__('The group id %d is incorrect.', $grupo)); ui_print_error_message(__('The group id %d is incorrect.', $grupo));
} else if (group_allow_more_agents($grupo, true, 'update') === false) {
ui_print_error_message(__('Agent cannot be updated due to the maximum agent limit for this group'));
} else if ($exists_ip) { } else if ($exists_ip) {
ui_print_error_message(__('Duplicate main IP address')); ui_print_error_message(__('Duplicate main IP address'));
} else { } else {

View File

@ -1,16 +1,32 @@
<?php <?php
/**
* Configure agent groups.
*
* @category Agents group management.
* @package Pandora FMS
* @subpackage User interface.
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation for version 2.
* This program is distributed in the hope that it will be useful,
* 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.
* ============================================================================
*/
// Pandora FMS - http://pandorafms.com // Begin.
// ==================================================
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
// Please see http://pandorafms.org for full contribution list
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation for version 2.
// This program is distributed in the hope that it will be useful,
// 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.
global $config; global $config;
check_login(); check_login();
@ -27,7 +43,7 @@ require_once $config['homedir'].'/include/functions_groups.php';
require_once $config['homedir'].'/include/functions_users.php'; require_once $config['homedir'].'/include/functions_users.php';
enterprise_include_once('meta/include/functions_agents_meta.php'); enterprise_include_once('meta/include/functions_agents_meta.php');
// Init vars // Default values.
$icon = ''; $icon = '';
$name = ''; $name = '';
$id_parent = 0; $id_parent = 0;
@ -39,6 +55,7 @@ $skin = 0;
$contact = ''; $contact = '';
$other = ''; $other = '';
$description = ''; $description = '';
$max_agents = 0;
$create_group = (bool) get_parameter('create_group'); $create_group = (bool) get_parameter('create_group');
$id_group = (int) get_parameter('id_group'); $id_group = (int) get_parameter('id_group');
@ -62,6 +79,7 @@ if ($id_group) {
$description = $group['description']; $description = $group['description'];
$contact = $group['contact']; $contact = $group['contact'];
$other = $group['other']; $other = $group['other'];
$max_agents = $group['max_agents'];
} else { } else {
ui_print_error_message(__('There was a problem loading group')); ui_print_error_message(__('There was a problem loading group'));
echo '</table>'; echo '</table>';
@ -224,6 +242,10 @@ $i++;
// $table->data[10][0] = __('Skin'); // $table->data[10][0] = __('Skin');
// $table->data[10][1] = skins_print_select($config['id_user'], 'skin', $skin, '', __('None'), 0, true); // $table->data[10][1] = skins_print_select($config['id_user'], 'skin', $skin, '', __('None'), 0, true);
// } // }
$table->data[$i][0] = __('Max agents allowed').'&nbsp;'.ui_print_help_tip(__('Set the maximum of agents allowed for this group. 0 is unlimited.'), true);
$table->data[$i][1] = html_print_input_text('max_agents', $max_agents, '', 10, 255, true);
$i++;
if (defined('METACONSOLE')) { if (defined('METACONSOLE')) {
$sec = 'advanced'; $sec = 'advanced';
} else { } else {
@ -241,6 +263,7 @@ if (isset($config['metaconsole_node_id']) && $config['metaconsole_node_id'] > 0)
echo '<form name="grupo" method="post" action="index.php?sec='.$sec.'&sec2=godmode/groups/group_list&pure='.$config['pure'].'"'.$confirm_bottom.' >'; echo '<form name="grupo" method="post" action="index.php?sec='.$sec.'&sec2=godmode/groups/group_list&pure='.$config['pure'].'"'.$confirm_bottom.' >';
html_print_table($table); html_print_table($table);
echo '<div class="action-buttons" style="width: '.$table->width.'">'; echo '<div class="action-buttons" style="width: '.$table->width.'">';
html_print_button(__('Back'), 'button_back', false, '', 'class="sub cancel"');
if ($id_group) { if ($id_group) {
html_print_input_hidden('update_group', 1); html_print_input_hidden('update_group', 1);
html_print_input_hidden('id_group', $id_group); html_print_input_hidden('id_group', $id_group);
@ -331,5 +354,8 @@ function parent_changed () {
$(document).ready (function () { $(document).ready (function () {
$('#icon').change (icon_changed); $('#icon').change (icon_changed);
$('#id_parent').change (parent_changed); $('#id_parent').change (parent_changed);
$('#button-button_back').on('click', function(){
window.location = '<?php echo ui_get_full_url('index.php?sec='.$sec.'&sec2=godmode/groups/group_list'); ?>';
});
}); });
</script> </script>

View File

@ -387,6 +387,7 @@ if (($create_group) && ((bool) check_acl($config['id_user'], 0, 'PM') === true))
$description = (string) get_parameter('description'); $description = (string) get_parameter('description');
$contact = (string) get_parameter('contact'); $contact = (string) get_parameter('contact');
$other = (string) get_parameter('other'); $other = (string) get_parameter('other');
$max_agents = (int) get_parameter('max_agents', 0);
$check = db_get_value('nombre', 'tgrupo', 'nombre', $name); $check = db_get_value('nombre', 'tgrupo', 'nombre', $name);
$propagate = (bool) get_parameter('propagate'); $propagate = (bool) get_parameter('propagate');
@ -411,6 +412,7 @@ if (($create_group) && ((bool) check_acl($config['id_user'], 0, 'PM') === true))
'propagate' => $propagate, 'propagate' => $propagate,
'other' => $other, 'other' => $other,
'password' => io_safe_input($group_pass), 'password' => io_safe_input($group_pass),
'max_agents' => $max_agents,
]; ];
$result = db_process_sql_insert('tgrupo', $values); $result = db_process_sql_insert('tgrupo', $values);
@ -444,6 +446,7 @@ if ($update_group) {
$description = (string) get_parameter('description'); $description = (string) get_parameter('description');
$contact = (string) get_parameter('contact'); $contact = (string) get_parameter('contact');
$other = (string) get_parameter('other'); $other = (string) get_parameter('other');
$max_agents = (int) get_parameter('max_agents', 0);
$aviable_name = true; $aviable_name = true;
if (preg_match('/script/i', $name)) { if (preg_match('/script/i', $name)) {
@ -477,6 +480,7 @@ if ($update_group) {
'propagate' => $propagate, 'propagate' => $propagate,
'other' => $other, 'other' => $other,
'password' => io_safe_input($group_pass), 'password' => io_safe_input($group_pass),
'max_agents' => $max_agents,
]; ];
$result = db_process_sql_update( $result = db_process_sql_update(

View File

@ -1,27 +1,38 @@
<?php <?php
// Pandora FMS - http://pandorafms.com
// ==================================================
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
// Please see http://pandorafms.org for full contribution list
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; version 2
// This program is distributed in the hope that it will be useful,
// 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.
/** /**
* @package Include * Agents Functions.
* @subpackage Agents *
* @category Agents functions.
* @package Pandora FMS
* @subpackage User interface.
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
* Please see http://pandorafms.org for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation for version 2.
* This program is distributed in the hope that it will be useful,
* 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.
* ============================================================================
*/ */
// Begin.
require_once $config['homedir'].'/include/functions.php'; require_once $config['homedir'].'/include/functions.php';
require_once $config['homedir'].'/include/functions_modules.php'; require_once $config['homedir'].'/include/functions_modules.php';
require_once $config['homedir'].'/include/functions_users.php'; require_once $config['homedir'].'/include/functions_users.php';
use PandoraFMS\Enterprise\RCMDFile as RCMDFile; use PandoraFMS\Enterprise\RCMDFile as RCMDFile;
use PandoraFMS\Event;
/** /**
@ -203,11 +214,13 @@ function agents_create_agent(
$values=false, $values=false,
$alias_as_name=false $alias_as_name=false
) { ) {
if (empty($name)) { global $config;
if (empty($name) === true) {
return false; return false;
} }
if (empty($id_group) && (int) $id_group != 0) { if (empty($id_group) === true && (int) $id_group !== 0) {
return false; return false;
} }
@ -216,11 +229,11 @@ function agents_create_agent(
$interval = false; $interval = false;
} }
if (empty($interval)) { if (empty($interval) === true) {
return false; return false;
} }
if (! is_array($values)) { if (is_array($values) === false) {
$values = []; $values = [];
} }
@ -229,17 +242,22 @@ function agents_create_agent(
$values['id_grupo'] = $id_group; $values['id_grupo'] = $id_group;
$values['intervalo'] = $interval; $values['intervalo'] = $interval;
if (!empty($ip_address)) { if (empty($ip_address) === false) {
$values['direccion'] = $ip_address; $values['direccion'] = $ip_address;
} }
// Check if group has limit or overrides the agent limit.
if (group_allow_more_agents($id_group, true, 'create') === false) {
return false;
}
$id_agent = db_process_sql_insert('tagente', $values); $id_agent = db_process_sql_insert('tagente', $values);
if ($id_agent === false) { if ($id_agent === false) {
return false; return false;
} }
// Create address for this agent in taddress. // Create address for this agent in taddress.
if (!empty($ip_address)) { if (empty($ip_address) === false) {
agents_add_address($id_agent, $ip_address); agents_add_address($id_agent, $ip_address);
} }
@ -3857,6 +3875,70 @@ function agents_get_last_status_change($id_agent)
} }
/**
* Checks if group allow more agents due itself limitation.
*
* @param integer $id_group Id of the group.
* @param boolean $generateEvent If true and the check fails, will generate an event.
* @param string $action Action for perform (only if generateEvent is true).
*
* @return boolean True if allow more agents.
*/
function group_allow_more_agents(
int $id_group,
bool $generateEvent=false,
string $action='create'
):bool {
global $config;
$groupMaxAgents = (int) db_get_value('max_agents', 'tgrupo', sprintf('id_grupo = %d', $id_group));
$groupCountAgents = (int) db_get_num_rows(sprintf('SELECT nombre FROM tagente WHERE id_grupo = "%s"', $id_group));
// If `max_agents` is not defined or the count of agents in the group is below of max agents allowed.
$output = ($groupMaxAgents === 0 || $groupCountAgents < $groupMaxAgents);
if ($output === false && $generateEvent === true) {
// Get the group name.
$groupName = db_get_value(
'nombre',
'tgrupo',
'id_grupo',
$id_group
);
// New event.
$evt = new Event;
// Set parameters.
$evt->evento(
sprintf(
'Agent cannot be %sd due to the maximum agent limit for group %s',
$action,
$groupName
)
);
$evt->id_grupo($id_group);
$evt->id_agente(0);
$evt->id_agentmodule(0);
$evt->id_usuario($config['id_user']);
$evt->estado(EVENT_STATUS_NEW);
$evt->event_type(EVENTS_SYSTEM);
$evt->criticity(EVENT_CRIT_WARNING);
$evt->timestamp(date('Y-m-d H:i:s'));
$evt->utimestamp(time());
$evt->data(0);
$evt->source('agent_creation');
// Any fields are only available in meta.
if (is_metaconsole() === true) {
$evt->id_source_event(0);
}
// Save the event.
$evt->save();
}
return $output;
}
/** /**
* Return the list of agents for a planned downtime * Return the list of agents for a planned downtime
* *
@ -3866,7 +3948,7 @@ function agents_get_last_status_change($id_agent)
* *
* @return array * @return array
*/ */
function get_planned_downtime_agents_list($id_downtime, $filter_cond, $id_groups_str) function get_planned_downtime_agents_list($id_downtime, $filter_cond, $id_groups_str):array
{ {
$agents = []; $agents = [];

View File

@ -1479,6 +1479,12 @@ function api_set_update_agent($id_agent, $thrash2, $other, $thrash3)
return; return;
} }
// Check if group allow more agents or have limit stablished.
if (group_allow_more_agents($idGroup, true, 'update') === false) {
returnError('Agent cannot be updated due to the maximum agent limit for this group');
return;
}
// Check selected parent // Check selected parent
if ($idParent != 0) { if ($idParent != 0) {
$parentCheck = agents_check_access_agent($idParent); $parentCheck = agents_check_access_agent($idParent);
@ -1680,6 +1686,8 @@ function api_set_new_agent($thrash1, $thrash2, $other, $thrash3)
returnError('The agent name already exists in DB.'); returnError('The agent name already exists in DB.');
} else if (db_get_value_sql('SELECT id_grupo FROM tgrupo WHERE id_grupo = '.$grupo) === false) { } else if (db_get_value_sql('SELECT id_grupo FROM tgrupo WHERE id_grupo = '.$grupo) === false) {
returnError('The group does not exist.'); returnError('The group does not exist.');
} else if (group_allow_more_agents($grupo, true, 'create') === false) {
returnError('Agent cannot be created due to the maximum agent limit for this group');
} else if (db_get_value_sql('SELECT id_os FROM tconfig_os WHERE id_os = '.$id_os) === false) { } else if (db_get_value_sql('SELECT id_os FROM tconfig_os WHERE id_os = '.$id_os) === false) {
returnError('The OS does not exist.'); returnError('The OS does not exist.');
} else if ($server_name === false) { } else if ($server_name === false) {
@ -8403,6 +8411,7 @@ function api_set_create_group($id, $thrash1, $other, $thrash3)
$values['custom_id'] = $safe_other_data[5]; $values['custom_id'] = $safe_other_data[5];
$values['contact'] = $safe_other_data[6]; $values['contact'] = $safe_other_data[6];
$values['other'] = $safe_other_data[7]; $values['other'] = $safe_other_data[7];
$values['max_agents'] = $safe_other_data[8];
$id_group = groups_create_group($group_name, $values); $id_group = groups_create_group($group_name, $values);
@ -8482,7 +8491,8 @@ function api_set_update_group($id_group, $thrash2, $other, $thrash3)
$disabled = $other['data'][5]; $disabled = $other['data'][5];
$custom_id = $other['data'][6]; $custom_id = $other['data'][6];
$contact = $other['data'][7]; $contact = $other['data'][7];
$other = $other['data'][8]; $otherData = $other['data'][8];
$maxAgents = $other['data'][9];
$return = db_process_sql_update( $return = db_process_sql_update(
'tgrupo', 'tgrupo',
@ -8495,7 +8505,8 @@ function api_set_update_group($id_group, $thrash2, $other, $thrash3)
'disabled' => $disabled, 'disabled' => $disabled,
'custom_id' => $custom_id, 'custom_id' => $custom_id,
'contact' => $contact, 'contact' => $contact,
'other' => $other, 'other' => $otherData,
'max_agents' => $maxAgents,
], ],
['id_grupo' => $id_group] ['id_grupo' => $id_group]
); );

View File

@ -60,18 +60,15 @@ class Event extends Entity
*/ */
public function __construct(?int $event_id=null) public function __construct(?int $event_id=null)
{ {
$table = 'tevento'; $this->table = ((bool) \is_metaconsole() === true) ? 'tmetaconsole_event' : 'tevento';
if ((bool) \is_metaconsole() === true) {
$table = 'tmetaconsole_event';
}
if ($event_id === 0) { if ($event_id === 0) {
parent::__construct($table); parent::__construct($this->table);
} else if (is_numeric($event_id) === true) { } else if (is_numeric($event_id) === true) {
parent::__construct($table, ['id_evento' => $event_id]); parent::__construct($this->table, ['id_evento' => $event_id]);
} else { } else {
// Empty skel. // Empty skel.
parent::__construct($table); parent::__construct($this->table);
} }
try { try {
@ -185,28 +182,26 @@ class Event extends Entity
*/ */
public function save() public function save()
{ {
global $config; $values = $this->fields;
// Clean null fields.
if (isset($config['centralized_management']) === true foreach ($values as $k => $v) {
&& (bool) $config['centralized_management'] === true if ($v === null) {
) { unset($values[$k]);
throw new \Exception( }
'error, cannot save in centralized management environment.'
);
} }
if ($this->id_evento === null) { if ($this->id_evento === null) {
// New. // New.
return db_process_sql_insert( return db_process_sql_insert(
'tgrupo', $this->table,
$this->fields $values
); );
} else if ($this->fields['id_evento'] > 0) { } else if ($this->fields['id_evento'] > 0) {
// Update. // Update.
return db_process_sql_update( return db_process_sql_update(
'tgrupo', $this->table,
$this->fields, $values,
['id_evento' => $this->fields['id_evento']] ['id_evento' => $values['id_evento']]
); );
} }

View File

@ -723,6 +723,7 @@ CREATE TABLE IF NOT EXISTS `tgrupo` (
`contact` text, `contact` text,
`other` text, `other` text,
`password` varchar(45) default '', `password` varchar(45) default '',
`max_agents` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`id_grupo`), PRIMARY KEY (`id_grupo`),
KEY `parent_index` (`parent`) KEY `parent_index` (`parent`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;