Merge branch 'ent-6012-servicios-dinamicos' into 'develop'

MR change smart services

See merge request artica/pandorafms!3316
This commit is contained in:
Alejandro Fraguas 2020-07-08 18:01:16 +02:00
commit df9ab22fc1
23 changed files with 1595 additions and 299 deletions

View File

@ -27,6 +27,8 @@
*/
// Begin.
require 'vendor/autoload.php';
define('AJAX', true);
if (!defined('__PAN_XHPROF__')) {
@ -50,6 +52,15 @@ require_once 'include/functions.php';
require_once 'include/functions_db.php';
require_once 'include/auth/mysql.php';
if (isset($config['console_log_enabled']) && $config['console_log_enabled'] == 1) {
ini_set('log_errors', 1);
ini_set('error_log', $config['homedir'].'/log/console.log');
} else {
ini_set('log_errors', 0);
ini_set('error_log', 0);
}
// Hash login process
if (isset($_GET['loginhash'])) {
$loginhash_data = get_parameter('loginhash_data', '');

View File

@ -1,5 +1,15 @@
START TRANSACTION;
ALTER TABLE `tservice_element` ADD COLUMN `rules` text;
ALTER TABLE `tservice` ADD COLUMN `unknown_as_critical` tinyint(1) NOT NULL default 0 AFTER `warning`;
UPDATE `tservice` SET `auto_calculate`=0;
UPDATE `tservice` SET `cps`= `cps` - 1 WHERE `cps` > 0;
UPDATE `tagente` SET `cps`= `cps` - 1 WHERE `cps` > 0;
UPDATE `tagente_modulo` SET `cps`= `cps` - 1 WHERE `cps` > 0;
ALTER TABLE `tnetwork_component` ADD COLUMN `manufacturer_id` varchar(200) NOT NULL;
ALTER TABLE `tnetwork_component` ADD COLUMN `protocol` tinytext NOT NULL;
ALTER TABLE `tnetwork_component` ADD COLUMN `module_type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1;

View File

@ -1540,7 +1540,16 @@ ALTER TABLE `tservice` ADD COLUMN `cps` int NOT NULL default 0;
ALTER TABLE `tservice` ADD COLUMN `cascade_protection` tinyint(1) NOT NULL default 0;
ALTER TABLE `tservice` ADD COLUMN `evaluate_sla` int(1) NOT NULL default 0;
ALTER TABLE `tservice` ADD COLUMN `is_favourite` tinyint(1) NOT NULL default 0;
ALTER TABLE `tservice` ADD COLUMN `unknown_as_critical` tinyint(1) NOT NULL default 0 AFTER `warning`;
UPDATE tservice SET `is_favourite` = 1 WHERE `name` REGEXP '^[_|.|\[|\(]';
-- ALl previous services are manual now.
UPDATE `tservice` SET `auto_calculate` = 0;
-- ---------------------------------------------------------------------
-- Table `tservice_element`
-- ---------------------------------------------------------------------
ALTER TABLE `tservice_element` ADD COLUMN `rules` text;
-- ---------------------------------------------------------------------
-- Table `tlayout`

View File

@ -88,7 +88,6 @@ switch ($action) {
} else {
header('Location:'.$config['homeurl'].'index.php?sec=gsetup&sec2=godmode/setup/os&tab='.$tab.'&message='.$message);
}
break;
case 'update':

View File

@ -40,6 +40,7 @@ if (is_ajax()) {
$id = get_parameter('id', -1);
$rootID = get_parameter('rootID', -1);
$serverID = get_parameter('serverID', false);
$metaID = (int) get_parameter('metaID', 0);
$childrenMethod = get_parameter('childrenMethod', 'on_demand');
$default_filters = [
@ -98,7 +99,16 @@ if (is_ajax()) {
break;
case 'services':
$tree = new TreeService($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
$tree = new TreeService(
$type,
$rootType,
$id,
$rootID,
$serverID,
$childrenMethod,
$access,
$metaID
);
break;
default:

View File

@ -29,7 +29,7 @@
// Begin.
require_once 'config.php';
require_once 'functions_api.php';
require '../vendor/autoload.php';
global $config;
define('DEBUG', 0);

View File

@ -764,8 +764,10 @@ class HTML
$output_head .= $data['pre-content'];
}
$output_head .= '<form id="'.$form['id'].'" class="discovery '.$form['class'].'" onsubmit="'.$form['onsubmit'].'" enctype="'.$form['enctype'].'" action="'.$form['action'].'" method="'.$form['method'];
if (isset($data['form']) === true) {
$output_head .= '<form name="'.$form['name'].'" id="'.$form['id'].'" class="discovery '.$form['class'].'" onsubmit="'.$form['onsubmit'].'" enctype="'.$form['enctype'].'" action="'.$form['action'].'" method="'.$form['method'];
$output_head .= '" '.$form['extra'].'>';
}
if ($return === false) {
echo $output_head;

View File

@ -64,14 +64,22 @@ class Tree
const TV_DEFAULT_AGENT_STATUS = -1;
public function __construct($type, $rootType='', $id=-1, $rootID=-1, $serverID=false, $childrenMethod='on_demand', $access='AR')
{
public function __construct(
$type,
$rootType='',
$id=-1,
$rootID=-1,
$serverID=false,
$childrenMethod='on_demand',
$access='AR',
$id_meta_server=0
) {
$this->type = $type;
$this->rootType = !empty($rootType) ? $rootType : $type;
$this->id = $id;
$this->rootID = !empty($rootID) ? $rootID : $id;
$this->serverID = $serverID;
if (is_metaconsole()) {
if (is_metaconsole() && $id_meta_server == 0) {
$this->serverName = metaconsole_get_server_by_id($serverID);
}
@ -90,7 +98,7 @@ class Tree
include_once $config['homedir'].'/include/functions_tags.php';
enterprise_include_once('include/functions_agents.php');
if (is_metaconsole()) {
if (is_metaconsole() && $id_meta_server == 0) {
enterprise_include_once('meta/include/functions_ui_meta.php');
}
}

View File

@ -1,32 +1,112 @@
<?php
// Pandora FMS- http://pandorafms.com
// ==================================================
// Copyright (c) 2005-2018 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.
/**
* Service tree view.
*
* @category Class
* @package Pandora FMS
* @subpackage Enterprise
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2005-2019 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.
global $config;
require_once $config['homedir'].'/include/class/Tree.class.php';
use PandoraFMS\Enterprise\Service;
/**
* Class to handle service tree view.
*/
class TreeService extends Tree
{
/**
* Some definitions.
*
* @var boolean
*/
protected $propagateCounters = true;
/**
* Some definitions.
*
* @var boolean
*/
protected $displayAllGroups = false;
/**
* If element is stored on remote node, this value will be greater than 0.
*
* @var integer
*/
public $metaID = 0;
public function __construct($type, $rootType='', $id=-1, $rootID=-1, $serverID=false, $childrenMethod='on_demand', $access='AR')
{
/**
* Flag to avoid double connection to node.
*
* @var boolean
*/
private $connectedToNode = false;
/**
* Builder.
*
* @param mixed $type Type.
* @param string $rootType RootType.
* @param integer $id Id.
* @param integer $rootID RootID.
* @param boolean $serverID ServerID.
* @param string $childrenMethod ChildrenMethod.
* @param string $access Access.
* @param integer $id_server_meta Id_server_meta.
*/
public function __construct(
$type,
$rootType='',
$id=-1,
$rootID=-1,
$serverID=false,
$childrenMethod='on_demand',
$access='AR',
$id_server_meta=0
) {
global $config;
parent::__construct($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
if ($id_server_meta > 0) {
$this->metaID = $id_server_meta;
$this->serverID = $id_server_meta;
}
parent::__construct(
$type,
$rootType,
$id,
$rootID,
$serverID,
$childrenMethod,
$access,
$id_server_meta
);
$this->L1fieldName = 'id_group';
$this->L1extraFields = [
@ -41,25 +121,60 @@ class TreeService extends Tree
$this->L2inner = 'LEFT JOIN tservice_element tse
ON tse.id_agent = ta.id_agente';
$this->L2condition = 'AND tse.id_service='.$this->id;
$this->L2condition = sprintf(
' AND tse.id_service=%d AND tse.id_server_meta=0 ',
$this->id
);
}
/**
* Setter (propagate counters).
*
* @param boolean $value Set.
*
* @return void
*/
public function setPropagateCounters($value)
{
$this->propagateCounters = (bool) $value;
}
/**
* Set display all groups.
*
* @param boolean $value Set.
*
* @return void
*/
public function setDisplayAllGroups($value)
{
$this->displayAllGroups = (bool) $value;
}
/**
* Generates tree data.
*
* @return void
*/
protected function getData()
{
if (is_metaconsole() === true && $this->metaID > 0) {
// Impersonate node.
\enterprise_include_once('include/functions_metaconsole.php');
\enterprise_hook(
'metaconsole_connect',
[
null,
$this->metaID,
]
);
$this->connectedToNode = true;
}
if ($this->id == -1) {
$this->getFirstLevel();
} else if ($this->type == 'services') {
@ -67,9 +182,19 @@ class TreeService extends Tree
} else if ($this->type == 'agent') {
$this->getThirdLevel();
}
if (is_metaconsole() === true && $this->metaID > 0) {
// Restore connection.
\enterprise_hook('metaconsole_restore_db');
}
}
/**
* Generates first level data.
*
* @return void
*/
protected function getFirstLevel()
{
global $config;
@ -118,10 +243,13 @@ class TreeService extends Tree
}
/**
* Retrieve root services.
*
* @return array Of root services.
*/
protected function getProcessedServices()
{
$fields = $this->getFirstLevelFields();
$is_favourite = $this->getServiceFavouriteFilter();
if (users_can_manage_group_all('AR')) {
@ -131,29 +259,32 @@ class TreeService extends Tree
}
$sql = sprintf(
"SELECT t1.*
FROM tservice_element tss
RIGHT JOIN
(SELECT ts.id, ts.id_agent_module, ts.name, ts.name AS `alias`, ts.id AS `rootID`,
'services' AS rootType, 'services' AS type,
0 AS quiet,
'SELECT
ts.id,
ts.id_agent_module,
ts.name,
ts.name as `alias`,
ts.id as `rootID`,
"services" as `rootType`,
"services" as `type`,
ts.quiet,
SUM(if((tse.id_agent<>0), 1, 0)) AS `total_agents`,
SUM(if((tse.id_agente_modulo<>0), 1, 0)) AS `total_modules`,
SUM(if((tse.id_service_child<>0), 1, 0)) AS `total_services`
SUM(if((tse.id_service_child<>0), 1, 0)) AS `total_services`,
SUM(if((tse.rules != ""), 1, 0)) AS `total_dynamic`
FROM tservice ts
LEFT JOIN tservice_element tse
ON ts.id=tse.id_service
WHERE
1=1
ON tse.id_service = ts.id
WHERE ts.id NOT IN (
SELECT DISTINCT id_service_child
FROM tservice_element
WHERE id_server_meta = 0
)
%s
%s
GROUP BY id
) as t1
ON tss.id_service_child = t1.id
WHERE tss.id_service_child IS NULL
",
$groups_acl,
$is_favourite
GROUP BY ts.id',
$is_favourite,
$groups_acl
);
$stats = db_get_all_rows_sql($sql);
@ -161,8 +292,13 @@ class TreeService extends Tree
$services = [];
foreach ($stats as $service) {
$services[$service['id']] = $this->getProcessedItem($services[$service['id']]);
if (($service['total_services'] + $service['total_agents'] + $service['total_modules']) > 0) {
$services[$service['id']] = $this->getProcessedItem(
$services[$service['id']]
);
$n_items = ($service['total_services'] + $service['total_agents']);
$n_items += ($service['total_modules'] + $service['total_dynamic']);
if ($n_items > 0) {
$services[$service['id']]['searchChildren'] = 1;
} else {
$services[$service['id']]['searchChildren'] = 0;
@ -182,6 +318,13 @@ class TreeService extends Tree
}
/**
* Retrieve first level fields.
*
* @deprecated 746.
*
* @return string With a first level fields.
*/
protected function getFirstLevelFields()
{
$fields = [];
@ -190,187 +333,349 @@ class TreeService extends Tree
}
/**
* Retrieves elements (second level) from selected rootID.
*
* @return void
*/
protected function getSecondLevel()
{
$data = [];
$data_agents = [];
$data_modules = [];
$data_services = [];
$service = new Service($this->id, true);
$sql = $this->getSecondLevelSql();
$data_agents = db_process_sql($sql);
$output = [];
foreach ($service->children() as $item) {
$tmp = [];
if (empty($data_agents)) {
$data_agents = [];
if ($this->metaID > 0) {
$tmp['metaID'] = $this->metaID;
} else if ($item->id_server_meta() !== 0) {
$tmp['metaID'] = $item->id_server_meta();
}
$this->processAgents($data_agents);
$tmp['serverID'] = $tmp['metaID'];
foreach ($data_agents as $key => $agent) {
$data_agents[$key]['showEventsBtn'] = 1;
$data_agents[$key]['eventAgent'] = $agent['id'];
switch ($item->type()) {
case SERVICE_ELEMENT_AGENT:
if ($item->agent() === null) {
// Skip item.
continue 2;
}
$sql = $this->getSecondLevelModulesSql();
$data_modules = db_process_sql($sql);
$tmp['id'] = $item->agent()->id_agente();
$tmp['name'] = $item->agent()->nombre();
$tmp['alias'] = $item->agent()->alias();
$tmp['fired_count'] = $item->agent()->fired_count();
$tmp['normal_count'] = $item->agent()->normal_count();
$tmp['warning_count'] = $item->agent()->warning_count();
$tmp['critical_count'] = $item->agent()->critical_count();
$tmp['unknown_count'] = $item->agent()->unknown_count();
$tmp['notinit_count'] = $item->agent()->notinit_count();
$tmp['total_count'] = $item->agent()->total_count();
if (empty($data_modules)) {
$data_modules = [];
if ($item->agent()->quiet() > 0
|| $item->agent()->cps() > 0
) {
$tmp['quiet'] = 1;
} else {
foreach ($data_modules as $key => $module) {
switch ($module['estado']) {
case '0':
$module_status = 'ok';
$module_title = 'NORMAL';
break;
case '1':
$module_status = 'critical';
$module_title = 'CRITICAL';
break;
case '2':
$module_status = 'warning';
$module_title = 'WARNING';
break;
case '3':
$module_status = 'down';
$module_title = 'UNKNOWN';
break;
case '4':
$module_status = 'no_data';
$module_title = 'NOT INITIALIZED';
break;
default:
$module_status = 'down';
$module_title = 'UNKNOWN';
break;
$tmp['quiet'] = 0;
}
$data_modules[$key]['statusImageHTML'] = '<img src="images/status_sets/default/agent_'.$module_status.'_ball.png" data-title="'.$module_title.' status." data-use_title_for_force_title="1" class="forced_title" alt="'.$module_title.' status." />';
$data_modules[$key]['showEventsBtn'] = 1;
$data_modules[$key]['eventModule'] = $module['id_agente_modulo'];
}
}
$sql = $this->getSecondLevelServicesSql();
$data_services = db_process_sql($sql);
$service_stats = [];
foreach ($data_services as $service) {
$service_stats[$service['id']]['id'] = (int) $service['id'];
$service_stats[$service['id']]['name'] = $service['name'];
$service_stats[$service['id']]['alias'] = $service['name'];
if (($service['total_services'] + $service['total_agents'] + $service['total_modules']) > 0) {
$service_stats[$service['id']]['searchChildren'] = 1;
} else {
$services[$service['id']]['searchChildren'] = 0;
}
$service_stats[$service['id']]['rootID'] = $service['rootID'];
$service_stats[$service['id']]['rootType'] = $service['rootType'];
$service_stats[$service['id']]['type'] = 'services';
$service_stats[$service['id']]['children'] = [];
$service_stats[$service['id']]['serviceDetail'] = 'index.php?sec=network&sec2=enterprise/operation/services/services&tab=service_map&id_service='.(int) $service['id'];
$service_stats[$service['id']]['counters'] = [
'total_services' => $service['total_services'],
'total_agents' => $service['total_agents'],
'total_modules' => $service['total_modules'],
$tmp['state_critical'] = $tmp['critical_count'];
$tmp['state_warning'] = $tmp['warning_count'];
$tmp['state_unknown'] = $tmp['unknown_count'];
$tmp['state_notinit'] = $tmp['notinit_count'];
$tmp['state_normal'] = $tmp['normal_count'];
$tmp['state_total'] = $tmp['total_count'];
$tmp['type'] = SERVICE_ELEMENT_AGENT;
$tmp['rootID'] = $this->rootID;
$tmp['rootType'] = $this->rootType;
$tmp['counters'] = [
'alerts' => $item->agent()->fired_count(),
'ok' => $item->agent()->normal_count(),
'warning' => $item->agent()->warning_count(),
'critical' => $item->agent()->critical_count(),
'unknown' => $item->agent()->unknown_count(),
'not_init' => $item->agent()->notinit_count(),
'total' => $item->agent()->total_count(),
];
switch ($item->agent()->lastStatus()) {
case AGENT_STATUS_NORMAL:
$tmp['statusImageHTML'] = '<img src="images/status_sets/default/agent_ok_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="NORMAL status." />';
break;
case AGENT_STATUS_CRITICAL:
case AGENT_STATUS_ALERT_FIRED:
$tmp['statusImageHTML'] = '<img src="images/status_sets/default/agent_critical_ball.png" data-title="CRITICAL status." data-use_title_for_force_title="1" class="forced_title" alt="CRITICAL status." />';
break;
case AGENT_STATUS_WARNING:
$tmp['statusImageHTML'] = '<img src="images/status_sets/default/agent_warning_ball.png" data-title="WARNING status." data-use_title_for_force_title="1" class="forced_title" alt="WARNING status." />';
break;
case AGENT_STATUS_UNKNOWN:
default:
$tmp['statusImageHTML'] = '<img src="images/status_sets/default/agent_no_data_ball.png" data-title="UNKNOWN status." data-use_title_for_force_title="1" class="forced_title" alt="UNKNOWN status." />';
break;
}
$own_info = get_user_info($config['id_user']);
$tmp['children'] = [];
$tmp['searchChildren'] = 1;
$tmp['showEventsBtn'] = 1;
$tmp['eventAgent'] = $item->agent()->id_agente();
break;
if ($own_info['is_admin'] || check_acl($config['id_user'], 0, 'PM')) {
$display_all_services = true;
case SERVICE_ELEMENT_MODULE:
if ($item->module() === null) {
// Skip item.
continue 2;
}
$tmp['id'] = $item->module()->id_agente_modulo();
$tmp['name'] = $item->module()->nombre();
$tmp['id_tipo_modulo'] = $item->module()->id_tipo_modulo();
$tmp['id_modulo'] = $item->module()->id_modulo();
$tmp['estado'] = $item->module()->lastStatus();
$tmp['datos'] = $item->module()->lastValue();
$tmp['parent'] = $item->module()->parent_module_id();
$alerts = alerts_get_alerts_module_name(
$item->module()->id_agente_modulo()
);
if ($alerts !== false) {
// Seems to be used as 'flag'.
$tmp['alerts'] = $alerts[0]['id'];
}
$tmp['unit'] = $item->module()->unit();
$tmp['type'] = SERVICE_ELEMENT_MODULE;
$tmp['id_module_type'] = $item->module()->id_tipo_modulo();
$tmp['server_type'] = $tmp['id_module_type'];
$tmp['status'] = $item->module()->lastStatus();
$tmp['value'] = modules_get_agentmodule_data_for_humans(
array_merge(
$item->module()->toArray(),
[ 'datos' => $item->module()->lastValue() ]
)
);
$title = $item->module()->lastStatusTitle();
if (is_numeric($item->module()->lastValue())) {
$divisor = get_data_multiplier($item->module()->unit());
$title .= ' : '.format_for_graph(
$item->module()->lastValue(),
1,
'.',
',',
$divisor
);
} else {
$display_all_services = false;
$title .= ' : '.substr(
io_safe_output(
$item->module()->lastValue()
),
0,
42
);
}
$services = services_get_services($filter, false, $display_all_services);
$tmp['serverName'] = $item->module()->agent()->server_name();
$tmp['serverID'] = $tmp['metaID'];
$tmp['statusText'] = $item->module()->lastStatusText();
$tmp['showGraphs'] = 1;
$tmp['showEventsBtn'] = 1;
$tmp['eventAgent'] = $item->module()->id_agente();
foreach ($services as $row) {
if (!array_key_exists($row['id'], $service_stats)) {
continue;
$html = '<img src="';
$html .= ui_get_full_url(
'/images/status_sets/default/'.$item->module()->lastStatusImage()
);
$html .= '" data-title="'.$title;
$html .= '" data-use_title_for_force_title="1" ';
$html .= 'class="forced_title" alt="';
$html .= $item->module()->lastStatusTitle().'" />';
$tmp['statusImageHTML'] = $html;
$tmp = array_merge(
$tmp,
$this->getModuleGraphLinks(
$tmp
)
);
break;
case SERVICE_ELEMENT_SERVICE:
if ($item->service() === null) {
// Skip item.
continue 2;
}
$status = services_get_status($row, true);
$tmp['id'] = (int) $item->service()->id();
$tmp['name'] = $item->service()->name();
$tmp['alias'] = $item->service()->name();
switch ($status) {
if ($this->connectedToNode === false
&& is_metaconsole() === true
&& $tmp['metaID'] > 0
) {
// Impersonate node.
\enterprise_include_once('include/functions_metaconsole.php');
\enterprise_hook(
'metaconsole_connect',
[
null,
$tmp['metaID'],
]
);
}
$grandchildren = $item->service()->children();
if ($this->connectedToNode === false
&& is_metaconsole() === true
&& $tmp['metaID'] > 0
) {
// Restore connection.
\enterprise_hook('metaconsole_restore_db');
}
$counters = [
'total_modules' => 0,
'total_agents' => 0,
'total_services' => 0,
'total_dynamic' => 0,
'total' => 0,
];
if (is_array($grandchildren) === true) {
$counters = array_reduce(
$grandchildren,
function ($carry, $item) {
if ($item->type() === SERVICE_ELEMENT_MODULE) {
$carry['total_modules']++;
} else if ($item->type() === SERVICE_ELEMENT_AGENT) {
$carry['total_agents']++;
} else if ($item->type() === SERVICE_ELEMENT_SERVICE) {
$carry['total_services']++;
} else if ($item->type() === SERVICE_ELEMENT_DYNAMIC) {
$carry['total_dynamic']++;
}
$carry['total']++;
return $carry;
},
$counters
);
}
if ($counters['total'] > 0) {
$tmp['searchChildren'] = 1;
}
$tmp['type'] = 'services';
$tmp['rootType'] = 'services';
$tmp['children'] = [];
$tmp['serviceDetail'] = ui_get_full_url(
'index.php?sec=network&sec2=enterprise/operation/services/services&tab=service_map&id_service='.$item->service()->id()
);
$tmp['counters'] = $counters;
$tmp['rootID'] = $this->rootID;
switch ($item->service()->lastStatus()) {
case SERVICE_STATUS_NORMAL:
$service_stats[$row['id']]['statusImageHTML'] = '<img src="images/status_sets/default/agent_ok_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="NORMAL status." />';
$tmp['statusImageHTML'] = '<img src="';
$tmp['statusImageHTML'] .= ui_get_full_url(
'images/status_sets/default/agent_ok_ball.png'
);
$tmp['statusImageHTML'] .= '" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="NORMAL status." />';
break;
case SERVICE_STATUS_CRITICAL:
$service_stats[$row['id']]['statusImageHTML'] = '<img src="images/status_sets/default/agent_critical_ball.png" data-title="CRITICAL status." data-use_title_for_force_title="1" class="forced_title" alt="CRITICAL status." />';
$tmp['statusImageHTML'] = '<img src="';
$tmp['statusImageHTML'] .= ui_get_full_url(
'images/status_sets/default/agent_critical_ball.png'
);
$tmp['statusImageHTML'] .= '" data-title="CRITICAL status." data-use_title_for_force_title="1" class="forced_title" alt="CRITICAL status." />';
break;
case SERVICE_STATUS_WARNING:
$service_stats[$row['id']][$key]['statusImageHTML'] = '<img src="images/status_sets/default/agent_warning_ball.png" data-title="WARNING status." data-use_title_for_force_title="1" class="forced_title" alt="WARNING status." />';
$tmp['statusImageHTML'] = '<img src="';
$tmp['statusImageHTML'] .= ui_get_full_url(
'images/status_sets/default/agent_warning_ball.png'
);
$tmp['statusImageHTML'] .= '" data-title="WARNING status." data-use_title_for_force_title="1" class="forced_title" alt="WARNING status." />';
break;
case SERVICE_STATUS_UNKNOWN:
default:
$service_stats[$row['id']]['statusImageHTML'] = '<img src="images/status_sets/default/agent_no_data_ball.png" data-title="UNKNOWN status." data-use_title_for_force_title="1" class="forced_title" alt="UNKNOWN status." />';
$tmp['statusImageHTML'] = '<img src="';
$tmp['statusImageHTML'] .= ui_get_full_url(
'images/status_sets/default/agent_no_data_ball.png'
);
$tmp['statusImageHTML'] .= '" data-title="UNKNOWN status." data-use_title_for_force_title="1" class="forced_title" alt="UNKNOWN status." />';
break;
}
break;
default:
// Unknown type.
continue 2;
}
$data_services = array_values($service_stats);
$data = array_merge($data_services, $data_agents, $data_modules);
if (empty($data)) {
$this->tree = [];
return;
$output[] = $tmp;
}
$this->tree = $data;
$this->tree = $output;
}
/**
* SQL query to retrieve second level items.
*
* @return string SQL.
*/
protected function getSecondLevelServicesSql()
{
$group_acl = $this->getGroupAclCondition();
$sql = "SELECT ts.id, ts.name, tse1.id_service AS `rootID`, 'services' AS rootType, 'services' AS type, 0 AS quiet, SUM(if((tse2.id_agent<>0), 1, 0)) AS `total_agents`, SUM(if((tse2.id_agente_modulo<>0), 1, 0)) AS `total_modules`, SUM(if((tse2.id_service_child<>0), 1, 0)) AS `total_services`, 0 AS fired_count, 0 AS normal_count, 0 AS warning_count, 0 AS critical_count, 0 AS unknown_count, 0 AS notinit_count, 0 AS state_critical, 0 AS state_warning, 0 AS state_unknown, 0 AS state_notinit, 0 AS state_normal, 0 AS state_total, '' AS statusImageHTML, '' AS alertImageHTML
FROM tservice_element tse1
LEFT JOIN tservice_element tse2 ON tse1.id_service_child=tse2.id_service
LEFT JOIN tservice ts ON tse1.id_service_child=ts.id
WHERE tse1.id_service=$this->id AND tse1.id_service_child<>0
GROUP BY tse1.id_service_child
";
$sql = sprintf(
'SELECT
ts.id,
ts.id_agent_module,
ts.name,
ts.name as `alias`,
tse.id_service as `rootID`,
"services" as `rootType`,
"services" as `type`,
ts.quiet,
tse.id_server_meta,
SUM(if((tse.id_agent<>0), 1, 0)) AS `total_agents`,
SUM(if((tse.id_agente_modulo<>0), 1, 0)) AS `total_modules`,
SUM(if((tse.id_service_child<>0), 1, 0)) AS `total_services`
FROM tservice ts
INNER JOIN tservice_element tse
ON tse.id_service_child = ts.id
WHERE
tse.id_service = %d
%s
GROUP BY ts.id',
$this->id,
$group_acl
);
return $sql;
}
protected function getSecondLevelModulesSql()
{
$sql = "SELECT tse.id_agente_modulo, nombre AS `name`, nombre AS `alias`, tse.id_service AS `rootID`, 'services' AS `rootType`, 'modules' AS `type`, estado
FROM tservice_element tse
INNER JOIN tagente_modulo tam ON tse.id_agente_modulo=tam.id_agente_modulo
INNER JOIN tagente_estado tae ON tam.id_agente_modulo=tae.id_agente_estado
WHERE tse.id_service=$this->id AND tse.id_agente_modulo<>0
";
return $sql;
}
protected function getAgentStatusFilter($status=self::TV_DEFAULT_AGENT_STATUS)
{
return '';
}
/**
* Retrieve SQL filter for current filte.r
*
* @return string SQL filter.
*/
protected function getServiceFavouriteFilter()
{
if (isset($this->filter['is_favourite']) && !empty($this->filter['is_favourite'])) {
if (isset($this->filter['is_favourite']) === true
&& empty($this->filter['is_favourite']) === false
) {
return ' AND is_favourite = 1';
}
@ -378,4 +683,70 @@ class TreeService extends Tree
}
/**
* Overwrites partial functionality of general Tree.class.
*
* @param array $module Data of given module.
*
* @return array Complementary information.
*/
protected function getModuleGraphLinks(array $module)
{
$graphType = return_graphtype($module['id_module_type']);
$url = ui_get_full_url(
'operation/agentes/stat_win.php',
false,
false,
false
);
$winHandle = dechex(crc32($module['id'].$module['name']));
$graph_params = [
'type' => $graphType,
'period' => SECONDS_1DAY,
'id' => $module['id'],
'refresh' => SECONDS_10MINUTES,
];
if (is_metaconsole() === true) {
// Set the server id.
$graph_params['server'] = $module['serverID'];
}
$graph_params_str = http_build_query($graph_params);
$moduleGraphURL = $url.'?'.$graph_params_str;
return [
'moduleGraph' => [
'url' => $moduleGraphURL,
'handle' => $winHandle,
],
'snapshot' => ui_get_snapshot_link(
[
'id_module' => $module['id'],
'interval' => $module['current_interval'],
'module_name' => $module['name'],
'id_node' => (($module['serverID'] > 0) ? $module['serverID'] : 0),
],
true
),
];
}
/**
* Needs to be defined to maintain Tree view functionality.
*
* @param integer $status Status.
*
* @return string Fixed string.
*/
protected function getAgentStatusFilter(
$status=self::TV_DEFAULT_AGENT_STATUS
) {
return '';
}
}

View File

@ -261,17 +261,27 @@ define('SERVICE_STATUS_NORMAL', 0);
define('SERVICE_STATUS_CRITICAL', 1);
define('SERVICE_STATUS_WARNING', 2);
define('SERVICE_STATUS_ALERT', 4);
// Default weights.
// Default service weights.
define('SERVICE_WEIGHT_CRITICAL', 1);
define('SERVICE_WEIGHT_WARNING', 0.5);
define('SERVICE_SMART_WEIGHT_CRITICAL', 50);
define('SERVICE_SMART_WEIGHT_WARNING', 30);
// Default service element weights.
define('SERVICE_ELEMENT_WEIGHT_CRITICAL', 1);
define('SERVICE_ELEMENT_WEIGHT_WARNING', 0.5);
define('SERVICE_ELEMENT_WEIGHT_OK', 0);
define('SERVICE_ELEMENT_WEIGHT_UNKNOWN', 0);
define('SERVICE_ELEMENT_SMART_CRITICAL', 100);
define('SERVICE_ELEMENT_SMART_WARNING', 50);
// Service element types.
define('SERVICE_ELEMENT_AGENT', 'agent');
define('SERVICE_ELEMENT_MODULE', 'module');
define('SERVICE_ELEMENT_SERVICE', 'service');
define('SERVICE_ELEMENT_DYNAMIC', 'dynamic');
// Modes.
define('SERVICE_MODE_MANUAL', 0);
define('SERVICE_MODE_AUTO', 1);
define('SERVICE_MODE_SIMPLE', 2);
define('SERVICE_MODE_SMART', 1);

View File

@ -2067,36 +2067,33 @@ function agents_get_addresses($id_agent)
function agents_get_status_from_counts($agent)
{
// Check if in the data there are all the necessary values
if (!isset($agent['normal_count'])
&& !isset($agent['warning_count'])
&& !isset($agent['critical_count'])
&& !isset($agent['unknown_count'])
&& !isset($agent['notinit_count'])
&& !isset($agent['total_count'])
if (isset($agent['normal_count']) === false
&& isset($agent['warning_count']) === false
&& isset($agent['critical_count']) === false
&& isset($agent['unknown_count']) === false
&& isset($agent['notinit_count']) === false
&& isset($agent['total_count']) === false
) {
return -1;
}
// Juanma (05/05/2014) Fix: This status is not init! 0 modules or all not init
// Juanma (05/05/2014) Fix: This status is not init! 0 modules or all not init.
if ($agent['notinit_count'] == $agent['total_count']) {
return AGENT_MODULE_STATUS_NOT_INIT;
return AGENT_STATUS_NOT_INIT;
}
if ($agent['critical_count'] > 0) {
return AGENT_MODULE_STATUS_CRITICAL_BAD;
return AGENT_STATUS_CRITICAL;
} else if ($agent['warning_count'] > 0) {
return AGENT_MODULE_STATUS_WARNING;
return AGENT_STATUS_WARNING;
} else if ($agent['unknown_count'] > 0) {
return AGENT_MODULE_STATUS_UNKNOWN;
return AGENT_STATUS_UNKNOWN;
} else if ($agent['normal_count'] == $agent['total_count']) {
return AGENT_MODULE_STATUS_NORMAL;
return AGENT_STATUS_NORMAL;
} else if (($agent['normal_count'] + $agent['notinit_count']) == $agent['total_count']) {
return AGENT_MODULE_STATUS_NORMAL;
return AGENT_STATUS_NORMAL;
}
// ~ else if($agent['notinit_count'] == $agent['total_count']) {
// ~ return AGENT_MODULE_STATUS_NORMAL;
// ~ }
return -1;
}

View File

@ -13123,6 +13123,9 @@ function api_set_create_service($thrash1, $thrash2, $other, $thrash3)
$quiet = $other['data'][11];
$cascade_protection = $other['data'][12];
$evaluate_sla = $other['data'][13];
$is_favourite = $other['data'][14];
$unknown_as_critical = $other['data'][15];
$server_name = $other['data'][16];
if (empty($name)) {
returnError('error_create_service', __('Error in creation service. No name'));
@ -13189,7 +13192,21 @@ function api_set_create_service($thrash1, $thrash2, $other, $thrash3)
$evaluate_sla = 0;
}
$result = services_create_service(
if (empty($is_favourite)) {
$is_favourite = false;
}
if (empty($unknown_as_critical)) {
$unknown_as_critical = false;
}
if (empty($server_name)) {
$server_name = null;
}
$result = enterprise_hook(
'services_create_service',
[
$name,
$description,
$id_group,
@ -13206,7 +13223,8 @@ function api_set_create_service($thrash1, $thrash2, $other, $thrash3)
$id_critical_module_sla,
$quiet,
$cascade_protection,
$evaluate_sla
$evaluate_sla,
]
);
if ($result) {
@ -13225,7 +13243,7 @@ function api_set_create_service($thrash1, $thrash2, $other, $thrash3)
* @param array $other it's array, $other as param is <name>;<description>;<id_group>;<critical>;
* <warning>;<id_agent>;<sla_interval>;<sla_limit>;<id_warning_module_template_alert>;
* <id_critical_module_template_alert>;<id_critical_module_sla_template_alert>;<quiet>;
* <cascade_protection>;<evaluate_sla>;
* <cascade_protection>;<evaluate_sla>;<is_favourite>;<unknown_as_critical>;<server_name>;
* in this order and separator char (after text ; ) and separator
* (pass in param othermode as othermode=url_encode_separator_<separator>)
* @param $thrash3 Don't use
@ -13342,7 +13360,24 @@ function api_set_update_service($thrash1, $thrash2, $other, $thrash3)
$evaluate_sla = $service['evaluate_sla'];
}
$result = services_update_service(
$is_favourite = $other['data'][14];
if (empty($is_favourite)) {
$is_favourite = $service['is_favourite'];
}
$unknown_as_critical = $other['data'][15];
if (empty($unknown_as_critical)) {
$unknown_as_critical = $service['unknown_as_critical'];
}
$server_name = $other['data'][16];
if (empty($server_name)) {
$server_name = $service['server_name'];
}
$result = enterprise_hook(
'services_update_service',
[
$id_service,
$name,
$description,
@ -13360,7 +13395,11 @@ function api_set_update_service($thrash1, $thrash2, $other, $thrash3)
$id_critical_module_sla,
$quiet,
$cascade_protection,
$evaluate_sla
$evaluate_sla,
$is_favourite,
$unknown_as_critical,
$server_name,
]
);
if ($result) {

View File

@ -1615,6 +1615,55 @@ function html_print_extended_select_for_cron($hour='*', $minute='*', $mday='*',
}
/**
* Prints an input slide.
*
* @param string $name Name.
* @param integer $value Value.
* @param string $id Id.
* @param boolean $return Return.
* @param integer $min Min.
* @param integer $max Max.
* @param integer $step Step.
* @param string $class Class.
* @param string $oninput Oninput.
*
* @return string HTML code for input.
*/
function html_print_input_range(
$name,
$value,
$id='',
$return=true,
$min=0,
$max=100,
$step=1,
$class='',
$oninput=''
) {
$output = '<input type="range" ';
if (isset($value) === true) {
$output .= ' value="'.$value.'" ';
}
$output .= ' name="'.$name.'" ';
$output .= ' id="'.$id.'" ';
$output .= ' min="'.$min.'" ';
$output .= ' max="'.$max.'" ';
$output .= ' step="'.$step.'" ';
$output .= ' class="'.$class.'" ';
$output .= ' oninput="'.$oninput.'" ';
$output .= ' />';
if ($return === false) {
echo $return;
}
return $output;
}
/**
* Render an input text element. Extended version, use html_print_input_text() to simplify.
*
@ -3746,6 +3795,8 @@ function html_print_csrf_error()
* disabled: Disabled. Cannot be pressed.
* id: Optional id for the switch.
* class: Additional classes (string).
* value: Check or not (boolean).
* disabled: Enabled or disabled (boolean).
*
* @return string with HTML of button.
*/
@ -3887,6 +3938,20 @@ function html_print_input($data, $wrapper='div', $input_only=false)
);
break;
case 'range':
$output .= html_print_input_range(
$data['name'],
$data['value'],
(isset($data['id']) ? $data['id'] : ''),
(isset($data['return']) ? $data['return'] : true),
(isset($data['min']) ? $data['min'] : 0),
(isset($data['max']) ? $data['max'] : 100),
(isset($data['step']) ? $data['step'] : 1),
(isset($data['class']) ? $data['class'] : ''),
(isset($data['oninput']) ? $data['oninput'] : '')
);
break;
case 'image':
$output .= html_print_input_image(
$data['name'],
@ -4046,6 +4111,25 @@ function html_print_input($data, $wrapper='div', $input_only=false)
);
break;
case 'select_metaconsole_nodes':
$output .= html_print_select_from_sql(
'SELECT `id`, `server_name` FROM `tmetaconsole_setup`',
$data['name'],
((isset($data['selected']) === true) ? $data['selected'] : ''),
((isset($data['script']) === true) ? $data['script'] : ''),
((isset($data['nothing']) === true) ? $data['nothing'] : ''),
((isset($data['nothing_value']) === true) ? $data['nothing_value'] : '0'),
((isset($data['return']) === true) ? $data['return'] : false),
((isset($data['multiple']) === true) ? $data['multiple'] : false),
((isset($data['sort']) === true) ? $data['sort'] : true),
((isset($data['disabled']) === true) ? $data['disabled'] : false),
((isset($data['style']) === true) ? $data['style'] : false),
((isset($data['size']) === true) ? $data['size'] : false),
((isset($data['trucate_size']) === true) ? $data['trucate_size'] : GENERIC_SIZE_TEXT),
((isset($data['class']) === true) ? $data['class'] : '')
);
break;
case 'select_for_unit':
$output .= html_print_extended_select_for_unit(
$data['name'],
@ -4058,7 +4142,7 @@ function html_print_input($data, $wrapper='div', $input_only=false)
((isset($data['select_style']) === true) ? $data['select_style'] : false),
((isset($data['unique_name']) === true) ? $data['unique_name'] : true),
((isset($data['disabled']) === true) ? $data['disabled'] : false),
((isset($data['disabled']) === true) ? $data['disabled'] : 0)
((isset($data['no_change']) === true) ? $data['no_change'] : 0)
);
case 'submit':
@ -4093,7 +4177,7 @@ function html_print_input($data, $wrapper='div', $input_only=false)
case 'interval':
$output .= html_print_extended_select_for_time(
$data['name'],
$data['value'],
((isset($data['value']) === true) ? $data['value'] : $data['selected']),
((isset($data['script']) === true) ? $data['script'] : ''),
((isset($data['nothing']) === true) ? $data['nothing'] : ''),
((isset($data['nothing_value']) === true) ? $data['nothing_value'] : 0),
@ -4154,6 +4238,11 @@ function html_print_input($data, $wrapper='div', $input_only=false)
$output .= html_print_input_multicheck($data);
break;
case 'agent_autocomplete':
// Direct assignment of parameters.
$output .= ui_print_agent_autocomplete_input($data);
break;
case 'autocomplete_agent':
$agent_name = '';
if (isset($data['id_agent_hidden']) === true
@ -4186,6 +4275,7 @@ function html_print_input($data, $wrapper='div', $input_only=false)
}
$params = [];
$params['disabled'] = $data['disabled'];
$params['return'] = $data['return'];
$params['show_helptip'] = false;
$params['input_name'] = $data['name'];

View File

@ -43,7 +43,7 @@ var TreeController = {
var $group = $("<ul></ul>");
// First group
if (typeof rootGroup != "undefinded" && rootGroup == true) {
if (typeof rootGroup != "undefined" && rootGroup == true) {
$group
.addClass("tree-root")
.hide()
@ -769,6 +769,7 @@ var TreeController = {
// Data pop-up
if (typeof element.id != "undefined" && !isNaN(element.id)) {
if (isNaN(element.metaID)) {
var $dataImage = $(
'<img src="' +
(controller.baseURL.length > 0
@ -781,7 +782,9 @@ var TreeController = {
try {
var serverName =
element.serverName.length > 0 ? element.serverName : "";
element.serverName.length > 0
? element.serverName
: "";
if ($("#module_details_window").length > 0)
show_module_detail_dialog(
element.id,
@ -799,6 +802,7 @@ var TreeController = {
$content.append($dataImage);
}
}
}
// Alerts
if (
@ -1008,6 +1012,7 @@ var TreeController = {
rootID: element.rootID,
serverID: element.serverID,
rootType: element.rootType,
metaID: element.metaID,
filter: controller.filter,
hash: public_hash,
id_user: public_user

View File

@ -55,16 +55,23 @@ class Agent extends Entity
* Builds a PandoraFMS\Agent object from a agent id.
*
* @param integer $id_agent Agent Id.
* @param boolean $load_modules Load all modules of this agent. Be careful.
* @param boolean $load_modules Load all modules of this agent.
*/
public function __construct(?int $id_agent=null, ?bool $load_modules=false)
{
if (is_numeric($id_agent) === true) {
parent::__construct('tagente', ['id_agente' => $id_agent]);
public function __construct(
?int $id_agent=null,
?bool $load_modules=false
) {
$table = 'tagente';
$filter = ['id_agente' => $id_agent];
if (is_numeric($id_agent) === true
&& $id_agent > 0
) {
parent::__construct($table, $filter);
if ($load_modules === true) {
$rows = \db_get_all_rows_filter(
'tagente_modulo',
['id_agente' => $id_agent]
$filter
);
if (is_array($rows) === true) {
@ -77,7 +84,7 @@ class Agent extends Entity
}
} else {
// Create empty skel.
parent::__construct('tagente');
parent::__construct($table);
// New agent has no modules.
$this->modulesLoaded = true;
@ -85,6 +92,31 @@ class Agent extends Entity
// Customize certain fields.
$this->fields['group'] = new Group($this->fields['id_grupo']);
}
/**
* Return last value (status) of the agent.
*
* @return integer Status of the agent.
*/
public function lastStatus()
{
return \agents_get_status_from_counts(
$this->toArray()
);
}
/**
* Return last value (status) of the agent.
*
* @return integer Status of the agent.
*/
public function lastValue()
{
return $this->lastStatus();
}
@ -190,6 +222,134 @@ class Agent extends Entity
}
/**
* Calculates cascade protection service value for this service.
*
* @param integer|null $id_node Meta searching node will use this field.
*
* @return integer CPS value.
* @throws \Exception On error.
*/
public function calculateCPS(?int $id_node=null)
{
if ($this->cps() < 0) {
return $this->cps();
}
// 1. check parents.
$direct_parents = db_get_all_rows_sql(
sprintf(
'SELECT id_service, cps, cascade_protection, name
FROM `tservice_element` te
INNER JOIN `tservice` t ON te.id_service = t.id
WHERE te.id_agent = %d',
$this->id_agente()
),
false,
false
);
// Here could happen 2 things.
// 1. Metaconsole service is using this method impersonating node DB.
// 2. Node service is trying to find parents into metaconsole.
if (is_metaconsole() === false
&& has_metaconsole() === true
) {
// Node searching metaconsole.
$mc_parents = [];
global $config;
$mc_db_conn = \enterprise_hook(
'metaconsole_load_external_db',
[
[
'dbhost' => $config['replication_dbhost'],
'dbuser' => $config['replication_dbuser'],
'dbpass' => io_output_password(
$config['replication_dbpass']
),
'dbname' => $config['replication_dbname'],
],
]
);
if ($mc_db_conn === NOERR) {
$mc_parents = db_get_all_rows_sql(
sprintf(
'SELECT id_service,
cps,
cascade_protection,
name
FROM `tservice_element` te
INNER JOIN `tservice` t ON te.id_service = t.id
WHERE te.id_agent = %d',
$this->id_agente()
),
false,
false
);
}
// Restore the default connection.
\enterprise_hook('metaconsole_restore_db');
} else if ($id_node > 0) {
// Impersonated node.
\enterprise_hook('metaconsole_restore_db');
$mc_parents = db_get_all_rows_sql(
sprintf(
'SELECT id_service,
cps,
cascade_protection,
name
FROM `tservice_element` te
INNER JOIN `tservice` t ON te.id_service = t.id
WHERE te.id_agent = %d',
$this->id_agente()
),
false,
false
);
// Restore impersonation.
\enterprise_include_once('include/functions_metaconsole.php');
$r = \enterprise_hook(
'metaconsole_connect',
[
null,
$id_node,
]
);
if ($r !== NOERR) {
throw new \Exception(__('Cannot connect to node %d', $r));
}
}
$cps = 0;
if (is_array($direct_parents) === false) {
$direct_parents = [];
}
if (is_array($mc_parents) === false) {
$mc_parents = [];
}
// Merge all parents (node and meta).
$parents = array_merge($direct_parents, $mc_parents);
foreach ($parents as $parent) {
$cps += $parent['cps'];
if (((bool) $parent['cascade_protection']) === true) {
$cps++;
}
}
return $cps;
}
/**
* Creates a module in current agent.
*
@ -228,6 +388,23 @@ class Agent extends Entity
}
/**
* Alias for field 'nombre'.
*
* @param string|null $name Name or empty if get operation.
*
* @return string|null Name or empty if set operation.
*/
public function name(?string $name=null)
{
if ($name === null) {
return $this->nombre();
}
$this->nombre($name);
}
/**
* Search for modules into this agent.
*

View File

@ -29,6 +29,9 @@
// Begin.
namespace PandoraFMS;
global $config;
require_once $config['homedir'].'/include/functions_groups.php';
/**
* PandoraFMS Group entity.
*/
@ -63,6 +66,38 @@ class Group extends Entity
}
/**
* Return an array of ids with all children
*
* @param boolean $ids_only Return an array of id_groups or
* entire rows.
* @param boolean $ignorePropagationState Search all children ignoring or
* depending on propagate_acl flag.
*
* @return array With all children.
*/
public function getChildren(
bool $ids_only=false,
bool $ignorePropagationState=false
) {
$available_groups = \groups_get_children(
$this->id_grupo(),
$ignorePropagationState
);
if (is_array($available_groups) === false) {
return [];
}
if ($ids_only === true) {
return array_keys($available_groups);
}
return $available_groups;
}
/**
* Saves current group definition to database.
*

View File

@ -30,7 +30,7 @@
// Begin.
namespace PandoraFMS;
use PandoraFMS\Agent;
use PandoraFMS\ModuleType;
/**
@ -46,6 +46,13 @@ class Module extends Entity
*/
private $status;
/**
* Agent where module is stored.
*
* @var PandoraFMS\Agent
*/
private $linkedAgent;
/**
* Module type matching id_tipo_modulo.
*
@ -174,10 +181,15 @@ class Module extends Entity
/**
* Builds a PandoraFMS\Module object from given id.
*
* @param integer $id_agent_module Module id.
* @param integer|null $id_agent_module Module id.
* @param boolean $link_agent Link agent object.
*
* @throws \Exception On error.
*/
public function __construct(?int $id_agent_module=null)
{
public function __construct(
?int $id_agent_module=null,
bool $link_agent=false
) {
if (is_numeric($id_agent_module) === true
&& $id_agent_module > 0
) {
@ -185,13 +197,33 @@ class Module extends Entity
'tagente_modulo',
['id_agente_modulo' => $id_agent_module]
);
if ($this->nombre() === 'delete_pending') {
return null;
}
if ($link_agent === true) {
try {
$this->linkedAgent = new Agent($this->id_agente());
} catch (\Exception $e) {
// Unexistent agent.
throw new \Exception(
__METHOD__.__(
' error: Module has no agent assigned.'
)
);
}
}
} else {
// Create empty skel.
parent::__construct('tagente_modulo');
}
if ($this->nombre() === 'delete_pending') {
return null;
try {
// Customize certain fields.
$this->status = new ModuleStatus($this->fields['id_agente_modulo']);
} catch (\Exception $e) {
$this->status = new Modulestatus();
}
// Customize certain fields.
@ -217,6 +249,26 @@ class Module extends Entity
}
/**
* Return agent object where module is defined.
*
* @return PandoraFMS\Agent Where module is defined.
*/
public function agent()
{
if ($this->linkedAgent === null) {
try {
$this->linkedAgent = new Agent($this->id_agente());
} catch (\Exception $e) {
// Unexistent agent.
return null;
}
}
return $this->linkedAgent;
}
/**
* Dynamically call methods in this object.
*
@ -296,6 +348,17 @@ class Module extends Entity
}
/**
* Return last value reported by the module.
*
* @return mixed Data depending on module type.
*/
public function lastValue()
{
return $this->status->datos();
}
/**
* Sets or retrieves value of id_tipo_modulo (complex).
*
@ -319,6 +382,110 @@ class Module extends Entity
}
/**
* Return last status reported by the module.
*
* @return mixed Data depending on module type.
*/
public function lastStatus()
{
return $this->status->estado();
}
/**
* Retrieves last status in text format.
*
* @return string Status in text format.
*/
public function lastStatusText()
{
switch ($this->lastStatus()) {
case AGENT_MODULE_STATUS_CRITICAL_ALERT:
case AGENT_MODULE_STATUS_CRITICAL_BAD:
return 'critical';
case AGENT_MODULE_STATUS_WARNING_ALERT:
case AGENT_MODULE_STATUS_WARNING:
return 'warning';
case AGENT_MODULE_STATUS_UNKNOWN:
return 'unknown';
case AGENT_MODULE_STATUS_NO_DATA:
case AGENT_MODULE_STATUS_NOT_INIT:
return 'not_init';
case AGENT_MODULE_STATUS_NORMAL_ALERT:
case AGENT_MODULE_STATUS_NORMAL:
default:
return 'ok';
}
}
/**
* Return path to image representing last status.
*
* @return string Relative URL to image.
*/
public function lastStatusImage()
{
switch ($this->lastStatus()) {
case AGENT_MODULE_STATUS_CRITICAL_ALERT:
case AGENT_MODULE_STATUS_CRITICAL_BAD:
return STATUS_MODULE_CRITICAL_BALL;
case AGENT_MODULE_STATUS_WARNING_ALERT:
case AGENT_MODULE_STATUS_WARNING:
return STATUS_MODULE_WARNING_BALL;
case AGENT_MODULE_STATUS_UNKNOWN:
return STATUS_MODULE_UNKNOWN_BALL;
case AGENT_MODULE_STATUS_NO_DATA:
case AGENT_MODULE_STATUS_NOT_INIT:
return STATUS_MODULE_NO_DATA_BALL;
case AGENT_MODULE_STATUS_NORMAL_ALERT:
case AGENT_MODULE_STATUS_NORMAL:
default:
return STATUS_MODULE_OK_BALL;
}
}
/**
* Return translated string representing last status of the module.
*
* @return string Title.
*/
public function lastStatusTitle()
{
switch ($this->lastStatus()) {
case AGENT_MODULE_STATUS_CRITICAL_ALERT:
case AGENT_MODULE_STATUS_CRITICAL_BAD:
return __('CRITICAL');
case AGENT_MODULE_STATUS_WARNING_ALERT:
case AGENT_MODULE_STATUS_WARNING:
return __('WARNING');
case AGENT_MODULE_STATUS_UNKNOWN:
return __('UNKNOWN');
case AGENT_MODULE_STATUS_NO_DATA:
case AGENT_MODULE_STATUS_NOT_INIT:
return __('NO DATA');
case AGENT_MODULE_STATUS_NORMAL_ALERT:
case AGENT_MODULE_STATUS_NORMAL:
default:
return __('NORMAL');
}
}
/**
* Sets or retrieves value of id_tipo_modulo (complex).
*
@ -348,6 +515,121 @@ class Module extends Entity
}
/**
* Alias for field 'nombre'.
*
* @param string|null $name Name or empty if get operation.
*
* @return string|null Name or empty if set operation.
*/
public function name(?string $name=null)
{
if ($name === null) {
return $this->nombre();
}
$this->nombre($name);
}
/**
* Retrieve all alert templates (ids) assigned to current module.
*
* @return array Of ids.
*/
public function alertTemplatesAssigned()
{
if ($this->id_agente_modulo() === null) {
// Need to be stored first.
return [];
}
$result = db_get_all_rows_filter(
'talert_template_modules',
['id_agent_module' => $this->id_agente_modulo()],
'id_alert_template'
);
if ($result === false) {
return [];
}
return array_reduce(
$result,
function ($carry, $item) {
$carry[] = $item['id_alert_template'];
return $carry;
},
[]
);
}
/**
* Remove a alert template assignment.
*
* @param integer $id_alert_template Target id.
*
* @return boolean Success or not.
*/
public function unassignAlertTemplate(int $id_alert_template)
{
if ($this->id_agente_modulo() === null) {
// Need to be stored first.
return false;
}
if (is_numeric($id_alert_template) === false
|| $id_alert_template <= 0
) {
// Invalid alert template.
return false;
}
return (bool) \db_process_sql_delete(
'talert_template_modules',
[
'id_agent_module' => $this->id_agente_modulo(),
'id_alert_template' => $id_alert_template,
]
);
}
/**
* Add an alert template to this module.
*
* @param integer|null $id_alert_template Target alert template.
*
* @return boolean Status of adding process.
*/
public function addAlertTemplate(?int $id_alert_template=null)
{
if ($this->id_agente_modulo() === null) {
// Need to be stored first.
return false;
}
if (is_numeric($id_alert_template) === false
|| $id_alert_template <= 0
) {
// Invalid alert template.
return false;
}
return (bool) \db_process_sql_insert(
'talert_template_modules',
[
'id_agent_module' => $this->id_agente_modulo(),
'id_alert_template' => $id_alert_template,
'last_reference' => time(),
]
);
}
/**
* Saves current definition to database.
*
@ -564,4 +846,176 @@ class Module extends Entity
}
/**
* Transforms results from classic mode into modern exceptions.
*
* @param integer|boolean $result Result received from module management.
*
* @return integer Module id created or result.
* @throws \Exception On error.
*/
public static function errorToException($result)
{
if ($result === ERR_INCOMPLETE) {
throw new \Exception(
__('Module name empty.')
);
}
if ($result === ERR_GENERIC) {
throw new \Exception(
__('Invalid characters in module name')
);
}
if ($result === ERR_EXIST) {
throw new \Exception(
__('Module already exists please select another name or agent.')
);
}
if ($result === false) {
throw new \Exception(
__('Insufficent permissions to perform this action')
);
}
if ($result === ERR_DB) {
global $config;
throw new \Exception(
__('Error while processing: %s', $config['dbconnection']->error)
);
}
return $result;
}
/**
* Calculates cascade protection service value for this service.
*
* @param integer|null $id_node Meta searching node will use this field.
*
* @return integer CPS value.
* @throws \Exception On error.
*/
public function calculateCPS(?int $id_node=null)
{
if ($this->cps() < 0) {
return $this->cps();
}
// 1. check parents.
$direct_parents = db_get_all_rows_sql(
sprintf(
'SELECT id_service, cps, cascade_protection, name
FROM `tservice_element` te
INNER JOIN `tservice` t ON te.id_service = t.id
WHERE te.id_agente_modulo = %d',
$this->id_agente_modulo()
)
);
// Here could happen 2 things.
// 1. Metaconsole service is using this method impersonating node DB.
// 2. Node service is trying to find parents into metaconsole.
if (empty($id_node) === true
&& is_metaconsole() === false
&& has_metaconsole() === true
) {
// Node searching metaconsole.
$mc_parents = [];
global $config;
$mc_db_conn = \enterprise_hook(
'metaconsole_load_external_db',
[
[
'dbhost' => $config['replication_dbhost'],
'dbuser' => $config['replication_dbuser'],
'dbpass' => io_output_password(
$config['replication_dbpass']
),
'dbname' => $config['replication_dbname'],
],
]
);
if ($mc_db_conn === NOERR) {
$mc_parents = db_get_all_rows_sql(
sprintf(
'SELECT id_service,
cps,
cascade_protection,
name
FROM `tservice_element` te
INNER JOIN `tservice` t ON te.id_service = t.id
WHERE te.id_agente_modulo = %d',
$this->id_agente_modulo()
),
false,
false
);
}
// Restore the default connection.
\enterprise_hook('metaconsole_restore_db');
} else if ($id_node > 0) {
// Impersonated node.
\enterprise_hook('metaconsole_restore_db');
$mc_parents = db_get_all_rows_sql(
sprintf(
'SELECT id_service,
cps,
cascade_protection,
name
FROM `tservice_element` te
INNER JOIN `tservice` t ON te.id_service = t.id
WHERE te.id_agente_modulo = %d',
$this->id_agente_modulo()
),
false,
false
);
// Restore impersonation.
\enterprise_include_once('include/functions_metaconsole.php');
$r = \enterprise_hook(
'metaconsole_connect',
[
null,
$id_node,
]
);
if ($r !== NOERR) {
throw new \Exception(__('Cannot connect to node %d', $r));
}
}
$cps = 0;
if (is_array($direct_parents) === false) {
$direct_parents = [];
}
if (is_array($mc_parents) === false) {
$mc_parents = [];
}
// Merge all parents (node and meta).
$parents = array_merge($direct_parents, $mc_parents);
foreach ($parents as $parent) {
$cps += $parent['cps'];
if (((bool) $parent['cascade_protection']) === true) {
$cps++;
}
}
return $cps;
}
}

View File

@ -31,6 +31,8 @@ if (!defined('__PAN_XHPROF__')) {
define('__PAN_XHPROF__', 0);
}
require 'vendor/autoload.php';
if (__PAN_XHPROF__ === 1) {
if (function_exists('tideways_xhprof_enable')) {
tideways_xhprof_enable();

View File

@ -15,8 +15,6 @@ if (! isset($config['id_user'])) {
return;
}
require 'vendor/autoload.php';
use PandoraFMS\Dashboard\Manager;
require_once 'include/functions_menu.php';

View File

@ -2699,6 +2699,7 @@ CREATE TABLE IF NOT EXISTS `tservice` (
`id_group` int(10) unsigned NOT NULL default 0,
`critical` float(20,3) NOT NULL default 0,
`warning` float(20,3) NOT NULL default 0,
`unknown_as_critical` tinyint(1) NOT NULL default 0,
`service_interval` float(20,3) NOT NULL default 0,
`service_value` float(20,3) NOT NULL default 0,
`status` tinyint(3) NOT NULL default -1,
@ -2739,6 +2740,7 @@ CREATE TABLE IF NOT EXISTS `tservice_element` (
`id_agent` int(10) unsigned NOT NULL default 0,
`id_service_child` int(10) unsigned NOT NULL default 0,
`id_server_meta` int(10) unsigned NOT NULL default 0,
`rules` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
COMMENT = 'Table to define the modules and the weights of the modules that define a service'

View File

@ -96,6 +96,7 @@ our @EXPORT = qw(
get_user_disabled
get_user_exists
get_user_profile_id
get_group_children
is_agent_address
is_group_disabled
get_agent_status
@ -292,6 +293,47 @@ sub get_group_id ($$) {
return defined ($rc) ? $rc : -1;
}
########################################################################
# Return a array of groups, children of given parent.
########################################################################
sub get_group_children ($$$;$);
sub get_group_children ($$$;$) {
my ($dbh, $parent, $ignorePropagate, $href_groups) = @_;
if (is_empty($href_groups)) {
my @groups = get_db_rows($dbh, 'SELECT * FROM tgrupo');
my %groups = map {
$_->{'id_grupo'} => $_
} @groups;
$href_groups = \%groups;
}
my $return = {};
foreach my $id_grupo (keys %{$href_groups}) {
if ($id_grupo eq 0) {
next;
}
my $g = $href_groups->{$id_grupo};
if ($ignorePropagate || $parent eq 0 || $href_groups->{$parent}{'propagate'}) {
if ($g->{'parent'} eq $parent) {
$return->{$g->{'id_grupo'}} = $g;
if ($g->{'propagate'} || $ignorePropagate) {
$return = add_hashes(
$return,
get_group_children($dbh, $g->{'id_grupo'}, $ignorePropagate, $href_groups)
);
}
}
}
}
return $return;
}
########################################################################
## Return OS ID given the OS name.
########################################################################

View File

@ -105,7 +105,7 @@ sub data_producer ($) {
AND tagente_modulo.id_modulo = 5
AND (tagente_modulo.flag = 1
OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
ORDER BY last_execution_try ASC ', (is_metaconsole($pa_config) ? '' : safe_input($pa_config->{'servername'})));
ORDER BY last_execution_try ASC ', safe_input($pa_config->{'servername'}));
}
else {
@rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo),
@ -123,7 +123,7 @@ sub data_producer ($) {
AND tagente_modulo.id_modulo = 5
AND (tagente_modulo.flag = 1
OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())
ORDER BY last_execution_try ASC', (is_metaconsole($pa_config) ? '' : safe_input($pa_config->{'servername'})), PREDICTIONSERVER);
ORDER BY last_execution_try ASC', safe_input($pa_config->{'servername'}), PREDICTIONSERVER);
}
foreach my $row (@rows) {

View File

@ -117,6 +117,7 @@ our @EXPORT = qw(
is_offline
is_empty
is_in_array
add_hashes
to_number
clean_blank
credential_store_get_key
@ -695,6 +696,30 @@ sub is_in_array {
return 0;
}
################################################################################
# Mix hashses
################################################################################
sub add_hashes {
my $_h1 = shift;
my $_h2 = shift;
if (ref($_h1) ne "HASH") {
return \%{$_h2} if (ref($_h2) eq "HASH");
}
if (ref($_h2) ne "HASH") {
return \%{$_h1} if (ref($_h1) eq "HASH");
}
if ((ref($_h1) ne "HASH") && (ref($_h2) ne "HASH")) {
return {};
}
my %ret = (%{$_h1}, %{$_h2});
return \%ret;
}
################################################################################
# SUB md5check (param_1, param_2)
# Verify MD5 file .checksum