Merge branch 'ent-8535-Monitorizacion-de-clusters-Pasar-de-Enterprise-a-Open' into 'develop'
implement cluster in open project See merge request artica/pandorafms!5204
This commit is contained in:
commit
cc2da2d4a4
|
@ -1666,6 +1666,14 @@ godmode/um_client/vendor/sebastian/object-enumerator
|
|||
godmode/um_client/vendor/sebastian
|
||||
godmode/um_client/vendor
|
||||
update_manager_client/resources/styles/pandora.css
|
||||
enterprise/views/cluster/edit.php
|
||||
enterprise/views/cluster/list.php
|
||||
enterprise/views/cluster/view.php
|
||||
enterprise/include/lib/Cluster.php
|
||||
enterprise/include/lib/ClusterModule.php
|
||||
enterprise/include/lib/ClusterViewer/ClusterManager.php
|
||||
enterprise/include/lib/ClusterViewer/ClusterWizard.php
|
||||
enterprise/operation/cluster/cluster.php
|
||||
enterprise/meta/general/upload_head_image.php
|
||||
general/first_task/transactional_list.php
|
||||
enterprise/include/ajax/transactional.ajax.php
|
||||
|
|
|
@ -68,7 +68,7 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no cluster
|
|||
if (check_acl($config['id_user'], 0, 'AW')) {
|
||||
?>
|
||||
|
||||
<form action='index.php?sec=estado&sec2=enterprise/operation/cluster/cluster&op=new' method="post">
|
||||
<form action='index.php?sec=estado&sec2=operation/cluster/cluster&op=new' method="post">
|
||||
<input type="submit" class="button_task ui_toggle" value="<?php echo __('Create Cluster'); ?>" />
|
||||
</form>
|
||||
|
||||
|
@ -76,4 +76,4 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no cluster
|
|||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -732,17 +732,15 @@ if ($agents !== false) {
|
|||
}
|
||||
|
||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||
if (enterprise_installed()) {
|
||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
||||
$url .= '/operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
echo '<a href="'.$url.'">'.ui_print_truncate_text($agent['alias'], 'agent_medium').'</a>';
|
||||
}
|
||||
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2=';
|
||||
$url .= 'operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
echo '<a href="'.$url.'">'.ui_print_truncate_text($agent['alias'], 'agent_medium').'</a>';
|
||||
} else {
|
||||
echo '<a alt ='.$agent['nombre']." href='index.php?sec=gagente&
|
||||
sec2=godmode/agentes/configurar_agente&tab=$main_tab&
|
||||
|
@ -792,18 +790,16 @@ if ($agents !== false) {
|
|||
echo '</span><div class="left actions clear_left" style=" visibility: hidden">';
|
||||
if ($check_aw) {
|
||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||
if (enterprise_installed()) {
|
||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
||||
$url .= '/operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
echo '<a href="'.$url.'">'.__('Edit').'</a>';
|
||||
echo ' | ';
|
||||
}
|
||||
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2=';
|
||||
$url .= 'operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
echo '<a href="'.$url.'">'.__('Edit').'</a>';
|
||||
echo ' | ';
|
||||
} else {
|
||||
echo '<a href="index.php?sec=gagente&
|
||||
sec2=godmode/agentes/configurar_agente&tab=main&
|
||||
|
@ -825,17 +821,15 @@ if ($agents !== false) {
|
|||
echo ' | ';
|
||||
|
||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||
if (enterprise_installed()) {
|
||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
||||
$url .= '/operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=view&id='.$cluster->id()
|
||||
);
|
||||
echo '<a href="'.$url.'">'.__('View').'</a>';
|
||||
}
|
||||
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2=';
|
||||
$url .= 'operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=view&id='.$cluster->id()
|
||||
);
|
||||
echo '<a href="'.$url.'">'.__('View').'</a>';
|
||||
} else {
|
||||
echo '<a href="index.php?sec=estado
|
||||
&sec2=operation/agentes/ver_agente
|
||||
|
|
|
@ -62,7 +62,7 @@ enterprise_include_once('include/functions_cron.php');
|
|||
// Clases.
|
||||
use PandoraFMS\Agent;
|
||||
use PandoraFMS\Module;
|
||||
use PandoraFMS\Enterprise\Cluster;
|
||||
use PandoraFMS\Cluster;
|
||||
use PandoraFMS\Enterprise\Metaconsole\Node;
|
||||
use PandoraFMS\Event;
|
||||
use PandoraFMS\SpecialDay;
|
||||
|
|
|
@ -690,18 +690,16 @@ function treeview_printTable($id_agente, $server_data=[], $no_head=false)
|
|||
$go_to_agent = '<div style="text-align: right">';
|
||||
|
||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||
if (enterprise_installed()) {
|
||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
||||
$url .= '/operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
$go_to_agent .= '<a target="_blank" href="'.$url.'">';
|
||||
$go_to_agent .= html_print_submit_button(__('Edit cluster'), 'upd_button', false, 'class="sub config"', true);
|
||||
}
|
||||
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2=';
|
||||
$url .= 'operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
$go_to_agent .= '<a target="_blank" href="'.$url.'">';
|
||||
$go_to_agent .= html_print_submit_button(__('Edit cluster'), 'upd_button', false, 'class="sub config"', true);
|
||||
} else {
|
||||
$go_to_agent .= '<a target=_blank href="'.$console_url.'index.php?sec=gagente&sec2=godmode/agentes/configurar_agente&id_agente='.$id_agente.$ent.'">';
|
||||
$go_to_agent .= html_print_submit_button(__('Go to agent edition'), 'upd_button', false, 'class="sub config"', true);
|
||||
|
|
|
@ -0,0 +1,906 @@
|
|||
<?php
|
||||
/**
|
||||
* Cluster entity class.
|
||||
*
|
||||
* @category Class
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @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.
|
||||
namespace PandoraFMS;
|
||||
|
||||
use PandoraFMS\Entity;
|
||||
use PandoraFMS\Agent;
|
||||
use PandoraFMS\Module;
|
||||
use PandoraFMS\Group;
|
||||
|
||||
/**
|
||||
* PandoraFMS Cluster entity.
|
||||
*/
|
||||
class Cluster extends Entity
|
||||
{
|
||||
|
||||
/**
|
||||
* References cluster status Module.
|
||||
*
|
||||
* @var PandoraFMS\Module
|
||||
*/
|
||||
private $clusterStatus;
|
||||
|
||||
/**
|
||||
* Array of PandoraFMS\Agents members of this cluster.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $members = [];
|
||||
|
||||
/**
|
||||
* AA modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $aaModules = [];
|
||||
|
||||
/**
|
||||
* AP modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $apModules = [];
|
||||
|
||||
/**
|
||||
* Removed items.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $removedItems = [];
|
||||
|
||||
|
||||
/**
|
||||
* Loads a cluster definition from target agent (rel 1-1).
|
||||
*
|
||||
* @param integer $id_agent Agent id.
|
||||
* @param boolean $load_members Load members or not.
|
||||
*
|
||||
* @return PandoraFMS\Cluster Object.
|
||||
*/
|
||||
public static function loadFromAgentId(
|
||||
int $id_agent,
|
||||
?bool $load_members=true
|
||||
) {
|
||||
if (is_numeric($id_agent) === true
|
||||
&& $id_agent > 0
|
||||
) {
|
||||
$cluster_id = db_get_value(
|
||||
'id',
|
||||
'tcluster',
|
||||
'id_agent',
|
||||
$id_agent
|
||||
);
|
||||
|
||||
return new self($cluster_id, $load_members);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds a PandoraFMS\ClusterViewer\Cluster object from a cluster id.
|
||||
*
|
||||
* @param integer $id_cluster Cluster Id.
|
||||
* @param boolean $load_members Load members or not.
|
||||
*
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function __construct(?int $id_cluster=null, ?bool $load_members=true)
|
||||
{
|
||||
if (is_numeric($id_cluster) === true
|
||||
&& $id_cluster > 0
|
||||
) {
|
||||
try {
|
||||
parent::__construct('tcluster', ['id' => $id_cluster]);
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Cluster id not found.');
|
||||
}
|
||||
|
||||
if ($load_members === true) {
|
||||
// Retrieve members.
|
||||
$data = \db_get_all_rows_filter(
|
||||
'tcluster_agent',
|
||||
['id_cluster' => $id_cluster]
|
||||
);
|
||||
|
||||
if (is_array($data) === true) {
|
||||
foreach ($data as $row) {
|
||||
$this->addMember($row['id_agent']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve items.
|
||||
$data = \db_get_all_rows_filter(
|
||||
'tcluster_item',
|
||||
['id_cluster' => $id_cluster]
|
||||
);
|
||||
|
||||
if (is_array($data) === true) {
|
||||
foreach ($data as $row) {
|
||||
if ($row['item_type'] === 'AA') {
|
||||
$this->aaModules[$row['name']] = new ClusterModule(
|
||||
$row['id']
|
||||
);
|
||||
} else if ($row['item_type'] === 'AP') {
|
||||
$this->apModules[$row['name']] = new ClusterModule(
|
||||
$row['id']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parent::__construct('tcluster');
|
||||
}
|
||||
|
||||
// Customize certain fields.
|
||||
try {
|
||||
$this->fields['group'] = new Group($this->group());
|
||||
} catch (\Exception $e) {
|
||||
$this->fields['group'] = new Group();
|
||||
}
|
||||
|
||||
if ($this->id_agent() !== null) {
|
||||
try {
|
||||
$this->fields['agent'] = new Agent($this->id_agent(), true);
|
||||
} catch (\Exception $e) {
|
||||
$this->fields['agent'] = new Agent();
|
||||
}
|
||||
} else {
|
||||
$this->fields['agent'] = new Agent();
|
||||
}
|
||||
|
||||
if ($this->id_agent() !== null) {
|
||||
$this->clusterStatus = Module::search(
|
||||
[
|
||||
'nombre' => io_safe_input('Cluster status'),
|
||||
'id_agente' => $this->id_agent(),
|
||||
],
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an array of PandoraFMS\Agents as members of current cluster.
|
||||
*
|
||||
* @return array Of agents.
|
||||
*/
|
||||
public function getMembers()
|
||||
{
|
||||
if (is_array($this->members) === true) {
|
||||
return $this->members;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleans members from cluster object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanMembers()
|
||||
{
|
||||
unset($this->members);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a new agent in the cluster.
|
||||
*
|
||||
* @param integer $id_agent New id_agent to be added.
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function addMember(int $id_agent)
|
||||
{
|
||||
if (isset($this->members[$id_agent]) === true) {
|
||||
// Already joining.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$agent = new Agent($id_agent);
|
||||
} catch (\Exception $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($agent->id_agente() === null) {
|
||||
throw new \Exception('Invalid agent id.');
|
||||
}
|
||||
|
||||
$this->members[$agent->id_agente()] = $agent;
|
||||
|
||||
return $agent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove an agent from the cluster.
|
||||
*
|
||||
* @param integer $id_agent New id_agent to be removed.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function removeMember(int $id_agent)
|
||||
{
|
||||
if (isset($this->members[$id_agent]) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->members[$id_agent]);
|
||||
|
||||
$rs = \db_process_sql_delete(
|
||||
'tcluster_agent',
|
||||
[
|
||||
'id_cluster' => $this->fields['id'],
|
||||
'id_agent' => $id_agent,
|
||||
]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return AA modules associated to current cluster.
|
||||
*
|
||||
* @param integer $type AA or AP (use constants)
|
||||
* MODULE_PREDICTION_CLUSTER_AA
|
||||
* MODULE_PREDICTION_CLUSTER_AP.
|
||||
*
|
||||
* @return array Of items.
|
||||
*/
|
||||
public function getItems(?int $type=null)
|
||||
{
|
||||
$items = [];
|
||||
|
||||
if ($type === MODULE_PREDICTION_CLUSTER_AA) {
|
||||
if (is_array($this->aaModules) === true) {
|
||||
return $this->aaModules;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === MODULE_PREDICTION_CLUSTER_AP) {
|
||||
if (is_array($this->apModules) === true) {
|
||||
return $this->apModules;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($this->apModules) === true
|
||||
) {
|
||||
$items = array_merge($items, $this->apModules);
|
||||
}
|
||||
|
||||
if (is_array($this->aaModules) === true
|
||||
) {
|
||||
$items = array_merge($items, $this->aaModules);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve AA modules.
|
||||
*
|
||||
* @return array Of ClusterItem definition.
|
||||
*/
|
||||
public function getAAModules()
|
||||
{
|
||||
return $this->getItems(MODULE_PREDICTION_CLUSTER_AA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve AP modules.
|
||||
*
|
||||
* @return array Of ClusterItem definition.
|
||||
*/
|
||||
public function getAPModules()
|
||||
{
|
||||
return $this->getItems(MODULE_PREDICTION_CLUSTER_AP);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves module definition from current members matching name.
|
||||
*
|
||||
* @param string $name Target name to retrieve.
|
||||
*
|
||||
* @return array Module fields.
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function getModuleSkel(string $name)
|
||||
{
|
||||
foreach ($this->members as $member) {
|
||||
$module = $member->searchModules(
|
||||
['nombre' => $name]
|
||||
);
|
||||
|
||||
if ($module !== null && empty($module) === false) {
|
||||
if (count($module) > 1) {
|
||||
$msg = __METHOD__.' error: Multiple occurrences of "';
|
||||
$msg .= $name.'", please remove duplicates from agent "';
|
||||
$msg .= $member->alias().'".';
|
||||
throw new \Exception(
|
||||
$msg
|
||||
);
|
||||
}
|
||||
|
||||
// Method searchModules returns multiple occurrences.
|
||||
$module = $module[0];
|
||||
$module = $module->toArray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove specific fields.
|
||||
unset($module['id_agente_modulo']);
|
||||
unset($module['id_agente']);
|
||||
|
||||
return $module;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an item to the cluster.
|
||||
*
|
||||
* @param string $name Target name.
|
||||
* @param integer $type Item type.
|
||||
* @param array $definition Module definition.
|
||||
*
|
||||
* @return ClusterModule Created module.
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function addItem(string $name, int $type, array $definition)
|
||||
{
|
||||
$item = new ClusterModule();
|
||||
$item->name($name);
|
||||
$item->id_cluster($this->id());
|
||||
|
||||
// Skel values.
|
||||
$module_skel = $this->getModuleSkel($name);
|
||||
|
||||
// Customize definition.
|
||||
$definition = array_merge($module_skel, $definition);
|
||||
|
||||
// Store in cluster agent.
|
||||
$definition['id_agente'] = $this->id_agent();
|
||||
|
||||
if ($type === MODULE_PREDICTION_CLUSTER_AA) {
|
||||
$item->item_type('AA');
|
||||
} else if ($type === MODULE_PREDICTION_CLUSTER_AP) {
|
||||
$item->item_type('AP');
|
||||
} else {
|
||||
throw new \Exception(__METHOD__.' error: Invalid item type');
|
||||
}
|
||||
|
||||
// Set module definition.
|
||||
$item->setModule($definition);
|
||||
|
||||
// Default values.
|
||||
$item->critical_limit(0);
|
||||
$item->warning_limit(0);
|
||||
$item->is_critical(0);
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add AA module to the cluster.
|
||||
*
|
||||
* @param string $name Target name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addAAModule(string $name)
|
||||
{
|
||||
if (empty($this->aaModules[$name]) === true) {
|
||||
$main_id = $this->clusterStatus->id_agente_modulo();
|
||||
|
||||
// Register module in agent.
|
||||
// id_modulo = 0,
|
||||
// tcp_port = 1,
|
||||
// prediction_moddule = 6.
|
||||
// Set thresholds while updating.
|
||||
$this->aaModules[$name] = $this->addItem(
|
||||
$name,
|
||||
MODULE_PREDICTION_CLUSTER_AA,
|
||||
[
|
||||
'nombre' => $name,
|
||||
'id_modulo' => 0,
|
||||
'prediction_module' => 6,
|
||||
'tcp_port' => 1,
|
||||
'id_tipo_modulo' => 1,
|
||||
'custom_integer_1' => $this->id(),
|
||||
'parent_module_id' => $main_id,
|
||||
]
|
||||
);
|
||||
|
||||
\db_pandora_audit(
|
||||
AUDIT_LOG_AGENT_MANAGEMENT,
|
||||
'Module '.io_safe_output(
|
||||
$name
|
||||
).' added to cluster'.io_safe_output(
|
||||
$this->fields['name']
|
||||
).' as Active-Active module'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add AP module to the cluster.
|
||||
*
|
||||
* @param string $name Target name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addAPModule(string $name)
|
||||
{
|
||||
if (empty($this->apModules[$name]) === true) {
|
||||
$main_id = $this->clusterStatus->id_agente_modulo();
|
||||
|
||||
$type = db_get_value(
|
||||
'id_tipo_modulo',
|
||||
'tagente_modulo',
|
||||
'nombre',
|
||||
$name
|
||||
);
|
||||
|
||||
if (empty($type) === true) {
|
||||
$type = 1;
|
||||
}
|
||||
|
||||
// Register module in agent.
|
||||
// id_modulo = 5,
|
||||
// tcp_port = 1,
|
||||
// prediction_moddule = 7.
|
||||
// Set thresholds while updating.
|
||||
$this->apModules[$name] = $this->addItem(
|
||||
$name,
|
||||
MODULE_PREDICTION_CLUSTER_AP,
|
||||
[
|
||||
'nombre' => $name,
|
||||
'id_modulo' => 5,
|
||||
'prediction_module' => 7,
|
||||
'tcp_port' => 1,
|
||||
'id_tipo_modulo' => $type,
|
||||
'custom_integer_1' => $this->id(),
|
||||
'parent_module_id' => $main_id,
|
||||
]
|
||||
);
|
||||
|
||||
\db_pandora_audit(
|
||||
AUDIT_LOG_AGENT_MANAGEMENT,
|
||||
'Module '.io_safe_output(
|
||||
$name
|
||||
).' added to cluster'.io_safe_output(
|
||||
$this->fields['name']
|
||||
).' as Active-Passive module'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes AA module from the cluster.
|
||||
*
|
||||
* @param string $name Target name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAAModule(string $name)
|
||||
{
|
||||
if (empty($this->aaModules[$name]) === false) {
|
||||
// Mark item for db elimination.
|
||||
$this->removedItems[] = [
|
||||
'id' => $this->aaModules[$name]->id(),
|
||||
'item_type' => $this->aaModules[$name]->item_type(),
|
||||
];
|
||||
$this->aaModules[$name]->delete();
|
||||
unset($this->aaModules[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes AP module from the cluster.
|
||||
*
|
||||
* @param string $name Target name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeAPModule(string $name)
|
||||
{
|
||||
if (empty($this->apModules[$name]) === false) {
|
||||
// Mark item for db elimination.
|
||||
$this->removedItems[] = [
|
||||
'id' => $this->apModules[$name]->id(),
|
||||
'item_type' => $this->apModules[$name]->item_type(),
|
||||
];
|
||||
$this->apModules[$name]->delete();
|
||||
unset($this->apModules[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return found cluster definitions.
|
||||
*
|
||||
* @param array $filter Conditions.
|
||||
*
|
||||
* @return mixed Array or false.
|
||||
*/
|
||||
public static function search(array $filter)
|
||||
{
|
||||
return \db_get_all_rows_filter(
|
||||
'tcluster',
|
||||
$filter
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Operates with group.
|
||||
*
|
||||
* @param integer|null $id_group Target group to update. Retrieve group obj
|
||||
* if null.
|
||||
*
|
||||
* @return mixed Void if set, PandoraFMS\Group if argument is null.
|
||||
*/
|
||||
public function group(?int $id_group=null)
|
||||
{
|
||||
if (is_numeric($id_group) === true && $id_group > 0) {
|
||||
$this->fields['group'] = new Group($id_group);
|
||||
} else {
|
||||
return $this->fields['group'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns AA modules as nodes for a map if any, if not, retrieves members.
|
||||
*
|
||||
* @return array Of PandoraFMS\Networkmap nodes.
|
||||
*/
|
||||
public function getNodes()
|
||||
{
|
||||
// Parse agents.
|
||||
$nodes = [];
|
||||
$node_count = 0;
|
||||
$parent = $node_count;
|
||||
$id_node = $node_count++;
|
||||
$status = \agents_get_status_from_counts($this->agent()->toArray());
|
||||
$image = 'images/networkmap/'.os_get_icon($this->agent()->id_os());
|
||||
|
||||
if (empty($this->aaModules) === true) {
|
||||
// No AA modules, use members.
|
||||
$parent = $this->agent()->id_agente();
|
||||
|
||||
// Add node.
|
||||
foreach ($this->members as $agent) {
|
||||
$node = [];
|
||||
|
||||
foreach ($agent->toArray() as $k => $v) {
|
||||
$node[$k] = $v;
|
||||
}
|
||||
|
||||
$node['id_agente'] = $agent->id_agente();
|
||||
$node['id_parent'] = $parent;
|
||||
$node['id_node'] = $node_count;
|
||||
$node['image'] = 'images/networkmap/'.os_get_icon(
|
||||
$agent->id_os()
|
||||
);
|
||||
$node['status'] = \agents_get_status_from_counts(
|
||||
$agent->toArray()
|
||||
);
|
||||
|
||||
$nodes[$node_count++] = $node;
|
||||
}
|
||||
} else {
|
||||
foreach ($this->aaModules as $cl_item) {
|
||||
$cl_module = $cl_item->getModule();
|
||||
|
||||
if ($cl_module === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->members as $agent) {
|
||||
$module = $agent->searchModules(
|
||||
['nombre' => $cl_module->nombre()]
|
||||
);
|
||||
|
||||
if (empty($module) === true) {
|
||||
// AA Module not found in member.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Transform multi array to get first occurrence.
|
||||
// Warning. Here must only be 1 result.
|
||||
$module = array_shift($module);
|
||||
|
||||
$node = [];
|
||||
|
||||
$node['type'] = NODE_GENERIC;
|
||||
$node['label'] = $agent->alias().' » ';
|
||||
$node['label'] .= $module->nombre();
|
||||
$node['id_agente'] = $module->id_agente();
|
||||
$node['id_agente_modulo'] = $module->id_agente_modulo();
|
||||
$node['id_parent'] = $parent;
|
||||
$node['id_node'] = $node_count;
|
||||
$node['image'] = 'images/networkmap/'.os_get_icon(
|
||||
$agent->id_os()
|
||||
);
|
||||
$node['status'] = $module->getStatus()->last_known_status();
|
||||
|
||||
$nodes[$node_count++] = $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$nodes[$parent] = $this->agent()->toArray();
|
||||
$nodes[$parent] = ($nodes[$parent] + [
|
||||
'id_parent' => $parent,
|
||||
'id_node' => $id_node,
|
||||
'status' => $status,
|
||||
'id_agente' => $this->agent()->id_agente(),
|
||||
'image' => $image,
|
||||
]);
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves current group definition to database.
|
||||
*
|
||||
* @return mixed Affected rows of false in case of error.
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$values = $this->fields;
|
||||
|
||||
unset($values['agent']);
|
||||
$values['group'] = $this->group()->id_grupo();
|
||||
if (isset($values['id']) === true && $values['id'] > 0) {
|
||||
// Update.
|
||||
$rs = \db_process_sql_update(
|
||||
'tcluster',
|
||||
$values,
|
||||
['id' => $this->fields['id']]
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
global $config;
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
\db_pandora_audit(
|
||||
AUDIT_LOG_AGENT_MANAGEMENT,
|
||||
'Cluster '.io_safe_output($this->fields['name']).' modified'
|
||||
);
|
||||
} else {
|
||||
// New.
|
||||
$rs = \db_process_sql_insert(
|
||||
'tcluster',
|
||||
$values
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
global $config;
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
$this->fields['id'] = $rs;
|
||||
\db_pandora_audit(
|
||||
AUDIT_LOG_AGENT_MANAGEMENT,
|
||||
'Cluster '.io_safe_output($this->fields['name']).' created'
|
||||
);
|
||||
}
|
||||
|
||||
$this->saveMembers();
|
||||
$this->saveItems();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates entries in tcluster_agent.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function saveMembers()
|
||||
{
|
||||
$err = __METHOD__.' error: ';
|
||||
|
||||
$values = [];
|
||||
foreach ($this->members as $agent) {
|
||||
$values[$agent->id_agente()] = [
|
||||
'id_cluster' => $this->fields['id'],
|
||||
'id_agent' => $agent->id_agente(),
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($values) === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean previous relationships.
|
||||
$rs = \db_process_sql_delete(
|
||||
'tcluster_agent',
|
||||
[ 'id_cluster' => $this->fields['id'] ]
|
||||
);
|
||||
|
||||
foreach ($values as $set) {
|
||||
// Add current relationships.
|
||||
$rs = \db_process_sql_insert(
|
||||
'tcluster_agent',
|
||||
$set
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
global $config;
|
||||
throw new \Exception(
|
||||
$err.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function saveItems()
|
||||
{
|
||||
$items = $this->getItems();
|
||||
|
||||
foreach ($this->removedItems as $item) {
|
||||
\db_process_sql_delete(
|
||||
'tcluster_item',
|
||||
$item
|
||||
);
|
||||
}
|
||||
|
||||
// Save cluster modules.
|
||||
foreach ($items as $item) {
|
||||
$item->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Force cluster status module to be executed.
|
||||
*
|
||||
* @param boolean $get_informed Throw exception if clusterStatus is null.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function force(?bool $get_informed=true)
|
||||
{
|
||||
if ($this->clusterStatus === null) {
|
||||
if ($get_informed === true) {
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: Cluster status module does not exist'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->clusterStatus->flag(1);
|
||||
$this->clusterStatus->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete cluster from db.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
global $config;
|
||||
|
||||
if ($this->agent() !== null) {
|
||||
// Delete agent and modules.
|
||||
$this->agent()->delete();
|
||||
}
|
||||
|
||||
// Remove entries from db.
|
||||
// Table tcluster_agent.
|
||||
$rs = \db_process_sql_delete(
|
||||
'tcluster_agent',
|
||||
['id_cluster' => $this->fields['id']]
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
// Table tcluster_item.
|
||||
$rs = \db_process_sql_delete(
|
||||
'tcluster_item',
|
||||
['id_cluster' => $this->fields['id']]
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
// Table tcluster.
|
||||
$rs = \db_process_sql_delete(
|
||||
'tcluster',
|
||||
['id' => $this->fields['id']]
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
\db_pandora_audit(
|
||||
AUDIT_LOG_AGENT_MANAGEMENT,
|
||||
'Cluster '.io_safe_output($this->fields['name']).' deleted'
|
||||
);
|
||||
|
||||
unset($this->aaModules);
|
||||
unset($this->apModules);
|
||||
unset($this->fields);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
<?php
|
||||
// phpcs:disable Squiz.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* Cluster module entity class.
|
||||
*
|
||||
* @category Class
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @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.
|
||||
namespace PandoraFMS;
|
||||
|
||||
use PandoraFMS\Entity;
|
||||
use PandoraFMS\Module;
|
||||
|
||||
/**
|
||||
* Represents AA and AP modules entity from a cluster.
|
||||
*/
|
||||
class ClusterModule extends Entity
|
||||
{
|
||||
|
||||
/**
|
||||
* Associated module.
|
||||
*
|
||||
* @var PandoraFMS\Module
|
||||
*/
|
||||
private $module;
|
||||
|
||||
|
||||
/**
|
||||
* Builds a PandoraFMS\ClusterViewer\ClusterModule object from a id.
|
||||
*
|
||||
* @param integer $id ClusterModule Id.
|
||||
*
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function __construct(?int $id=null)
|
||||
{
|
||||
if (is_numeric($id) === true && $id > 0) {
|
||||
try {
|
||||
parent::__construct('tcluster_item', ['id' => $id]);
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('ClusterModule id not found.');
|
||||
}
|
||||
|
||||
// Get module.
|
||||
$this->module = Module::search(
|
||||
[
|
||||
'nombre' => $this->name(),
|
||||
'custom_integer_1' => $this->id_cluster(),
|
||||
],
|
||||
1
|
||||
);
|
||||
} else {
|
||||
parent::__construct('tcluster_item');
|
||||
|
||||
$this->module = new Module();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns current object as array.
|
||||
*
|
||||
* @return array Of fields.
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associates a module to this clusterModule.
|
||||
*
|
||||
* @param array $params Module parameters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setModule(array $params)
|
||||
{
|
||||
$this->module = new Module();
|
||||
foreach ($params as $k => $v) {
|
||||
$this->module->{$k}($v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associates a module to this clusterModule.
|
||||
*
|
||||
* @param PandoraFMS\Module $module Module definition.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setModuleObject(Module $module)
|
||||
{
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns current module.
|
||||
*
|
||||
* @return PandoraFMS\Module Object.
|
||||
*/
|
||||
public function getModule()
|
||||
{
|
||||
return $this->module;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves or retrieves value of warning_limit.
|
||||
*
|
||||
* @param float|null $value Warning value.
|
||||
*
|
||||
* @return mixed Value or empty.
|
||||
*/
|
||||
public function warning_limit(?float $value=null)
|
||||
{
|
||||
if ($value !== null) {
|
||||
$this->fields['warning_limit'] = $value;
|
||||
if ($this->module !== null) {
|
||||
$this->module->min_warning($value);
|
||||
}
|
||||
} else {
|
||||
return $this->fields['warning_limit'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves or retrieves value of critical_limit.
|
||||
*
|
||||
* @param float|null $value Critical value.
|
||||
*
|
||||
* @return mixed Value or empty.
|
||||
*/
|
||||
public function critical_limit(?float $value=null)
|
||||
{
|
||||
if ($value !== null) {
|
||||
$this->fields['critical_limit'] = $value;
|
||||
if ($this->module !== null) {
|
||||
$this->module->min_critical($value);
|
||||
}
|
||||
} else {
|
||||
return $this->fields['critical_limit'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save ClusterModule.
|
||||
*
|
||||
* @return boolean True if success, false if error.
|
||||
* @throws \Exception On db error.
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$values = $this->fields;
|
||||
|
||||
if ($this->module === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (method_exists($this->module, 'save') === false) {
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: Cluster module "'.$this->name().'" invalid.'
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($values['id']) === true && $values['id'] > 0) {
|
||||
// Update.
|
||||
$rs = \db_process_sql_update(
|
||||
'tcluster_item',
|
||||
$values,
|
||||
['id' => $this->fields['id']]
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
global $config;
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->module === null) {
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: Cluster module "'.$this->name().'" is not defined'
|
||||
);
|
||||
}
|
||||
|
||||
// Update reference.
|
||||
$this->module->custom_integer_2($this->fields['id']);
|
||||
|
||||
// Update module.
|
||||
$this->module->save();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// New.
|
||||
$rs = \db_process_sql_insert(
|
||||
'tcluster_item',
|
||||
$values
|
||||
);
|
||||
|
||||
if ($rs === false) {
|
||||
global $config;
|
||||
throw new \Exception(
|
||||
__METHOD__.' error: '.$config['dbconnection']->error
|
||||
);
|
||||
}
|
||||
|
||||
$this->fields['id'] = $rs;
|
||||
|
||||
// Update reference.
|
||||
$this->module->custom_integer_2($this->fields['id']);
|
||||
|
||||
// Update module.
|
||||
$this->module->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Erases this object and its module.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if (method_exists($this->module, 'delete') === true) {
|
||||
$this->module->delete();
|
||||
}
|
||||
|
||||
unset($this->fields);
|
||||
unset($this->module);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,767 @@
|
|||
<?php
|
||||
/**
|
||||
* Cluster view main class.
|
||||
*
|
||||
* @category Class
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @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.
|
||||
namespace PandoraFMS\ClusterViewer;
|
||||
|
||||
use PandoraFMS\View;
|
||||
use PandoraFMS\Group;
|
||||
use PandoraFMS\Cluster;
|
||||
|
||||
/**
|
||||
* Class to handle Cluster view operations.
|
||||
*/
|
||||
class ClusterManager
|
||||
{
|
||||
|
||||
/**
|
||||
* Url of controller.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $ajaxController;
|
||||
|
||||
/**
|
||||
* Url (main).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* Number of clusters defined.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private static $count;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $ajax_page Path to ajax controller.
|
||||
* @param string $url Url.
|
||||
*/
|
||||
public function __construct(
|
||||
string $ajax_page='operation/cluster/cluster',
|
||||
string $url='index.php?sec=estado&sec2=operation/cluster/cluster'
|
||||
) {
|
||||
global $config;
|
||||
|
||||
check_login();
|
||||
|
||||
if (! check_acl($config['id_user'], 0, 'AR')
|
||||
&& ! check_acl($config['id_user'], 0, 'AW')
|
||||
) {
|
||||
db_pandora_audit(
|
||||
AUDIT_LOG_ACL_VIOLATION,
|
||||
'Trying to access cluster viewer'
|
||||
);
|
||||
|
||||
if (is_ajax()) {
|
||||
echo json_encode(['error' => 'noaccess']);
|
||||
} else {
|
||||
include 'general/noaccess.php';
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->ajaxController = $ajax_page;
|
||||
$this->url = $url;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main program starts here.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
|
||||
$operation = get_parameter('op', '');
|
||||
|
||||
switch ($operation) {
|
||||
case 'new':
|
||||
case 'update':
|
||||
$this->showClusterEditor($operation);
|
||||
break;
|
||||
|
||||
case 'view':
|
||||
$this->showCluster();
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
$this->deleteCluster();
|
||||
break;
|
||||
|
||||
case 'force':
|
||||
$this->forceCluster();
|
||||
break;
|
||||
|
||||
default:
|
||||
$n_clusters = $this->getCount();
|
||||
|
||||
if ($n_clusters > 0) {
|
||||
$this->showList();
|
||||
} else {
|
||||
$this->showWelcome();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints error message
|
||||
*
|
||||
* @param string $msg Message.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function error(string $msg)
|
||||
{
|
||||
if (is_ajax()) {
|
||||
echo json_encode(
|
||||
['error' => $msg]
|
||||
);
|
||||
} else {
|
||||
ui_print_error_message($msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads view 'first tasks' for cluster view.
|
||||
* Old style.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function showWelcome()
|
||||
{
|
||||
global $config;
|
||||
include_once $config['homedir'].'/general/first_task/cluster_builder.php';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepares available clusters definition for current users and loads view.
|
||||
*
|
||||
* @param string|null $msg Message (if any).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function showList(?string $msg='')
|
||||
{
|
||||
global $config;
|
||||
|
||||
// Extract data.
|
||||
$n_clusters = $this->getCount();
|
||||
|
||||
if ($n_clusters > 0) {
|
||||
$clusters = $this->getAll();
|
||||
} else {
|
||||
$clusters = [];
|
||||
}
|
||||
|
||||
View::render(
|
||||
'cluster/list',
|
||||
[
|
||||
'message' => $msg,
|
||||
'config' => $config,
|
||||
'model' => $this,
|
||||
'n_clusters' => $n_clusters,
|
||||
'clusters' => $clusters,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show cluster information.
|
||||
*
|
||||
* @param string|null $msg Message (if any).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function showCluster(?string $msg=null)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$err = '';
|
||||
$id = get_parameter('id', null);
|
||||
|
||||
try {
|
||||
$cluster = new Cluster($id);
|
||||
} catch (\Exception $e) {
|
||||
$err = ui_print_error_message(
|
||||
__('Cluster not found: '.$e->getMessage()),
|
||||
'',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
if ($cluster->agent()->id_agente() === null) {
|
||||
// Failed.
|
||||
$err = ui_print_error_message(
|
||||
__('Cluster agent not found: '),
|
||||
'',
|
||||
true
|
||||
);
|
||||
$critical = true;
|
||||
}
|
||||
|
||||
View::render(
|
||||
'cluster/view',
|
||||
[
|
||||
'message' => $msg,
|
||||
'error' => $err,
|
||||
'config' => $config,
|
||||
'model' => $this,
|
||||
'cluster' => $cluster,
|
||||
'critical' => $critical,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a cluster from db.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCluster()
|
||||
{
|
||||
$msg = '';
|
||||
$id = get_parameter('id', null);
|
||||
|
||||
try {
|
||||
$cluster = new Cluster($id);
|
||||
$cluster->delete();
|
||||
unset($cluster);
|
||||
} catch (\Exception $e) {
|
||||
$msg = ui_print_error_message(
|
||||
__('Error while deleting, reason: %s', $e->getMessage()),
|
||||
'',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($msg) === true) {
|
||||
$msg = ui_print_success_message(
|
||||
__('Cluster successfully deleted.'),
|
||||
'',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$this->showList($msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Force cluster execution.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forceCluster()
|
||||
{
|
||||
$msg = '';
|
||||
$id = get_parameter('id', null);
|
||||
|
||||
try {
|
||||
$cluster = new Cluster($id);
|
||||
$cluster->force();
|
||||
unset($cluster);
|
||||
} catch (\Exception $e) {
|
||||
$msg = ui_print_error_message(
|
||||
__('Error while forcing, reason: %s', $e->getMessage()),
|
||||
'',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($msg) === true) {
|
||||
$msg = ui_print_success_message(
|
||||
__('Cluster successfully forced.'),
|
||||
'',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$this->showCluster($msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows editor for target cluster (or new one).
|
||||
*
|
||||
* @param string $operation Current operation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function showClusterEditor(string $operation)
|
||||
{
|
||||
|
||||
global $config;
|
||||
if (!check_acl($config['id_user'], 0, 'AW')) {
|
||||
|
||||
db_pandora_audit(
|
||||
AUDIT_LOG_ACL_VIOLATION,
|
||||
'Trying to create clusters'
|
||||
);
|
||||
include 'general/noaccess.php';
|
||||
} else {
|
||||
$wizard = new ClusterWizard(
|
||||
$this->url,
|
||||
$operation
|
||||
);
|
||||
|
||||
$wizard->run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns number of clusters registered.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getCount()
|
||||
{
|
||||
if (isset($this->count) !== true) {
|
||||
$this->count = $this->getAll('count');
|
||||
}
|
||||
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all cluster definitons matching given filters.
|
||||
*
|
||||
* @param mixed $fields Fields array or 'count' keyword to retrieve
|
||||
* count, null or default to use default ones.
|
||||
* @param array $filter Filters to be applied.
|
||||
* @param integer $offset Offset (pagination).
|
||||
* @param integer $limit Limit (pagination).
|
||||
* @param string $order Sort order.
|
||||
* @param string $sort_field Sort field.
|
||||
*
|
||||
* @return array With all results or false if error.
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public static function getAll(
|
||||
$fields=null,
|
||||
array $filter=[],
|
||||
?int $offset=null,
|
||||
?int $limit=null,
|
||||
?string $order=null,
|
||||
?string $sort_field=null
|
||||
) {
|
||||
$sql_filters = [];
|
||||
$order_by = '';
|
||||
$pagination = '';
|
||||
|
||||
global $config;
|
||||
|
||||
if (is_array($filter) === false) {
|
||||
throw new \Exception('[ClusterManager::getAll] Filter must be an array.');
|
||||
}
|
||||
|
||||
if (empty($filter['id_group']) === false
|
||||
&& (int) $filter['id_group'] !== 0
|
||||
) {
|
||||
$sql_filters[] = sprintf(
|
||||
' AND tc.`group` = %d',
|
||||
$filter['id_group']
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($filter['free_search']) === false) {
|
||||
$topic = io_safe_input($filter['free_search']);
|
||||
$sql_filters[] = sprintf(
|
||||
' AND (lower(tc.name) like lower("%%%s%%")
|
||||
OR lower(tc.description) like lower("%%%s%%") ) ',
|
||||
$topic,
|
||||
$topic
|
||||
);
|
||||
}
|
||||
|
||||
$count = false;
|
||||
if (is_array($fields) === false && $fields === 'count') {
|
||||
$fields = ['tc.*'];
|
||||
$count = true;
|
||||
} else if (is_array($fields) === false) {
|
||||
// Default values.
|
||||
$fields = [
|
||||
'tc.*',
|
||||
'(SELECT COUNT(*) FROM `tcluster_agent` WHERE `id_cluster` = tc.`id`) as `nodes`',
|
||||
'tas.known_status',
|
||||
];
|
||||
}
|
||||
|
||||
if (isset($order) === true) {
|
||||
$dir = 'asc';
|
||||
if ($order === 'desc') {
|
||||
$dir = 'desc';
|
||||
};
|
||||
|
||||
if ($sort_field === 'type') {
|
||||
$sort_field = 'cluster_type';
|
||||
}
|
||||
|
||||
if (in_array(
|
||||
$sort_field,
|
||||
[
|
||||
'name',
|
||||
'description',
|
||||
'group',
|
||||
'cluster_type',
|
||||
'nodes',
|
||||
'known_status',
|
||||
]
|
||||
) === true
|
||||
) {
|
||||
$order_by = sprintf(
|
||||
'ORDER BY `%s` %s',
|
||||
$sort_field,
|
||||
$dir
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($limit) === true && $limit > 0
|
||||
&& isset($offset) === true && $offset >= 0
|
||||
) {
|
||||
$pagination = sprintf(
|
||||
' LIMIT %d OFFSET %d ',
|
||||
$limit,
|
||||
$offset
|
||||
);
|
||||
}
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT %s
|
||||
FROM tcluster tc
|
||||
LEFT JOIN tagente ta
|
||||
ON tc.id_agent = ta.id_agente
|
||||
LEFT JOIN tagente_modulo tam
|
||||
ON tam.id_agente = tc.id_agent
|
||||
AND tam.nombre = "%s"
|
||||
LEFT JOIN tagente_estado tas
|
||||
ON tam.id_agente_modulo=tas.id_agente_modulo
|
||||
WHERE 1=1
|
||||
%s
|
||||
%s
|
||||
%s',
|
||||
join(',', $fields),
|
||||
io_safe_input('Cluster status'),
|
||||
join(' ', $sql_filters),
|
||||
$order_by,
|
||||
$pagination
|
||||
);
|
||||
|
||||
if ($count === true) {
|
||||
$sql = sprintf('SELECT count(*) as n FROM ( %s ) tt', $sql);
|
||||
|
||||
// Counter.. All data.
|
||||
return db_get_value_sql($sql);
|
||||
}
|
||||
|
||||
return db_get_all_rows_sql($sql);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return data for datatables painting.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception On Error.
|
||||
*/
|
||||
public function draw()
|
||||
{
|
||||
global $config;
|
||||
|
||||
// Datatables offset, limit and order.
|
||||
$filter = get_parameter('filter', []);
|
||||
$start = get_parameter('start', 0);
|
||||
$length = get_parameter('length', $config['block_size']);
|
||||
$order = get_datatable_order(true);
|
||||
try {
|
||||
ob_start();
|
||||
|
||||
$fields = [
|
||||
'tc.*',
|
||||
'(SELECT COUNT(*) FROM `tcluster_agent` WHERE `id_cluster` = tc.`id`) as `nodes`',
|
||||
'tas.known_status',
|
||||
];
|
||||
|
||||
// Retrieve data.
|
||||
$data = self::getAll(
|
||||
// Fields.
|
||||
$fields,
|
||||
// Filter.
|
||||
$filter,
|
||||
// Offset.
|
||||
$start,
|
||||
// Limit.
|
||||
$length,
|
||||
// Order.
|
||||
$order['direction'],
|
||||
// Sort field.
|
||||
$order['field']
|
||||
);
|
||||
|
||||
// Retrieve counter.
|
||||
$count = self::getAll(
|
||||
'count',
|
||||
$filter
|
||||
);
|
||||
|
||||
if ($data) {
|
||||
$data = array_reduce(
|
||||
$data,
|
||||
function ($carry, $item) {
|
||||
global $config;
|
||||
// Transforms array of arrays $data into an array
|
||||
// of objects, making a post-process of certain fields.
|
||||
$tmp = (object) $item;
|
||||
|
||||
$manage = check_acl(
|
||||
$config['id_user'],
|
||||
$tmp->group,
|
||||
'AW',
|
||||
true
|
||||
);
|
||||
|
||||
$tmp->name = '<b><a href="'.ui_get_full_url(
|
||||
$this->url.'&op=view&id='.$tmp->id
|
||||
).'">'.$tmp->name.'</a></b>';
|
||||
|
||||
if (empty($tmp->group) === true) {
|
||||
$tmp->group = __('Not set');
|
||||
} else {
|
||||
$tmp->group = ui_print_group_icon(
|
||||
$tmp->group,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// Type.
|
||||
if ($tmp->cluster_type === 'AA') {
|
||||
$tmp->type = __('Active-Active');
|
||||
} else if ($tmp->cluster_type === 'AP') {
|
||||
$tmp->type = __('Active-Passive');
|
||||
} else {
|
||||
$tmp->type = __('Unknown');
|
||||
}
|
||||
|
||||
// Status.
|
||||
$tmp->known_status = ui_print_module_status(
|
||||
$tmp->known_status,
|
||||
true
|
||||
);
|
||||
|
||||
// Options. View.
|
||||
$tmp->options = '<a href="';
|
||||
$tmp->options .= ui_get_full_url(
|
||||
$this->url.'&op=view&id='.$tmp->id
|
||||
);
|
||||
$tmp->options .= '">';
|
||||
$tmp->options .= html_print_image(
|
||||
'images/operation.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('View'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$tmp->options .= '</a>';
|
||||
|
||||
if ($manage) {
|
||||
// Options. Edit.
|
||||
$tmp->options .= '<a href="';
|
||||
$tmp->options .= ui_get_full_url(
|
||||
$this->url.'&op=update&id='.$tmp->id
|
||||
);
|
||||
$tmp->options .= '">';
|
||||
$tmp->options .= html_print_image(
|
||||
'images/config.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Edit'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$tmp->options .= '</a>';
|
||||
|
||||
// Options. Delete.
|
||||
$tmp->options .= '<a href="';
|
||||
$tmp->options .= ui_get_full_url(
|
||||
$this->url.'&op=delete&id='.$tmp->id
|
||||
);
|
||||
$tmp->options .= '">';
|
||||
$tmp->options .= html_print_image(
|
||||
'images/cross.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Delete'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$tmp->options .= '</a>';
|
||||
}
|
||||
|
||||
$carry[] = $tmp;
|
||||
return $carry;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Datatables format: RecordsTotal && recordsfiltered.
|
||||
echo json_encode(
|
||||
[
|
||||
'data' => $data,
|
||||
'recordsTotal' => $count,
|
||||
'recordsFiltered' => $count,
|
||||
]
|
||||
);
|
||||
// Capture output.
|
||||
$response = ob_get_clean();
|
||||
} catch (\Exception $e) {
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// If not valid, show error with issue.
|
||||
json_decode($response);
|
||||
if (json_last_error() == JSON_ERROR_NONE) {
|
||||
// If valid dump.
|
||||
echo $response;
|
||||
} else {
|
||||
echo json_encode(
|
||||
['error' => $response]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides data for wizard. Ajax method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAgentsFromGroup()
|
||||
{
|
||||
$side = get_parameter('side', null);
|
||||
$id = get_parameter('id', null);
|
||||
$group_id = get_parameter('group_id', 0);
|
||||
$group_recursion = (bool) get_parameter('group_recursion', 0);
|
||||
|
||||
$groups = [];
|
||||
if ($group_recursion === true) {
|
||||
$groups = groups_get_children_ids($group_id, true);
|
||||
} else {
|
||||
$groups = $group_id;
|
||||
}
|
||||
|
||||
if ($side === 'left') {
|
||||
// Available agents.
|
||||
$agents = agents_get_agents(
|
||||
[ 'id_grupo' => $groups ],
|
||||
[
|
||||
'id_agente',
|
||||
'alias',
|
||||
]
|
||||
);
|
||||
|
||||
$agents = array_reduce(
|
||||
$agents,
|
||||
function ($carry, $item) {
|
||||
$carry[$item['id_agente']] = io_safe_output($item['alias']);
|
||||
return $carry;
|
||||
}
|
||||
);
|
||||
} else if ($side === 'right') {
|
||||
// Selected agents.
|
||||
$cluster = new Cluster($id);
|
||||
$agents = $cluster->getMembers();
|
||||
$agents = array_reduce(
|
||||
$agents,
|
||||
function ($carry, $item) use ($groups) {
|
||||
if (in_array($item->id_grupo(), $groups) === true) {
|
||||
$carry[$item->id_agente()] = io_safe_output(
|
||||
$item->alias()
|
||||
);
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($agents) === true) {
|
||||
echo '[]';
|
||||
} else {
|
||||
// Dump response.
|
||||
echo json_encode($agents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a goBack form structure.
|
||||
*
|
||||
* @return array Form structure.
|
||||
*/
|
||||
public function getGoBackForm()
|
||||
{
|
||||
$form['form']['action'] = $this->url;
|
||||
$form['form']['method'] = 'POST';
|
||||
$form['form']['id'] = 'go-back-form';
|
||||
$form['inputs'] = [
|
||||
[
|
||||
'arguments' => [
|
||||
'name' => 'submit',
|
||||
'label' => __('Go back'),
|
||||
'type' => 'submit',
|
||||
'attributes' => 'class="sub cancel"',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -846,17 +846,15 @@ foreach ($agents as $agent) {
|
|||
$data[0] .= '<div class="agentleft_'.$agent['id_agente'].'" style="visibility: hidden; clear: left;">';
|
||||
|
||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||
if (enterprise_installed()) {
|
||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
||||
$url .= '/operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=view&id='.$cluster->id()
|
||||
);
|
||||
$data[0] .= '<a href="'.$url.'">'.__('View').'</a>';
|
||||
}
|
||||
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2=';
|
||||
$url .= 'operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=view&id='.$cluster->id()
|
||||
);
|
||||
$data[0] .= '<a href="'.$url.'">'.__('View').'</a>';
|
||||
} else {
|
||||
$data[0] .= '<a href="index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente='.$agent['id_agente'].'">'.__('View').'</a>';
|
||||
}
|
||||
|
@ -865,17 +863,15 @@ foreach ($agents as $agent) {
|
|||
$data[0] .= ' | ';
|
||||
|
||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||
if (enterprise_installed()) {
|
||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
||||
$url .= '/operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
$data[0] .= '<a href="'.$url.'">'.__('Edit').'</a>';
|
||||
}
|
||||
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||
$agent['id_agente']
|
||||
);
|
||||
$url = 'index.php?sec=reporting&sec2=';
|
||||
$url .= 'operation/cluster/cluster';
|
||||
$url = ui_get_full_url(
|
||||
$url.'&op=update&id='.$cluster->id()
|
||||
);
|
||||
$data[0] .= '<a href="'.$url.'">'.__('Edit').'</a>';
|
||||
} else {
|
||||
$data[0] .= '<a href="index.php?sec=gagente&sec2=godmode/agentes/configurar_agente&id_agente='.$agent['id_agente'].'">'.__('Edit').'</a>';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* Cluster view entrypoint.
|
||||
*
|
||||
* @category View
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @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.
|
||||
global $config;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use PandoraFMS\ClusterViewer\ClusterManager;
|
||||
|
||||
$ajaxPage = 'operation/cluster/cluster';
|
||||
|
||||
// Control call flow.
|
||||
try {
|
||||
|
||||
// User access and validation is being processed on class constructor.
|
||||
$obj = new ClusterManager($ajaxPage);
|
||||
} catch (Exception $e) {
|
||||
if (is_ajax()) {
|
||||
echo json_encode(['error' => '[ClusterManager]'.$e->getMessage() ]);
|
||||
exit;
|
||||
} else {
|
||||
echo '[ClusterManager]'.$e->getMessage();
|
||||
}
|
||||
|
||||
// Stop this execution, but continue 'globally'.
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX controller.
|
||||
if (is_ajax()) {
|
||||
$method = get_parameter('method');
|
||||
|
||||
if (method_exists($obj, $method) === true) {
|
||||
$obj->{$method}();
|
||||
} else {
|
||||
$obj->error('Method not found. [ClusterManager::'.$method.']');
|
||||
}
|
||||
|
||||
// Stop any execution.
|
||||
exit;
|
||||
} else {
|
||||
// Run.
|
||||
$obj->run();
|
||||
}
|
|
@ -147,7 +147,12 @@ if ($access_console_node === true) {
|
|||
$sub['snmpconsole']['subtype'] = 'nolink';
|
||||
}
|
||||
|
||||
enterprise_hook('cluster_menu');
|
||||
if (check_acl($config['id_user'], 0, 'AR')) {
|
||||
$sub['operation/cluster/cluster']['text'] = __('Cluster View');
|
||||
$sub['operation/cluster/cluster']['id'] = 'cluster';
|
||||
$sub['operation/cluster/cluster']['refr'] = 0;
|
||||
}
|
||||
|
||||
enterprise_hook('aws_menu');
|
||||
enterprise_hook('SAP_view');
|
||||
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
/**
|
||||
* Cluster View: Edit
|
||||
*
|
||||
* @category View
|
||||
* @package Pandora FMS
|
||||
* @subpackage Cluster View
|
||||
* @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.
|
||||
// Prepare header and breadcrums.
|
||||
$i = 0;
|
||||
$bc = [];
|
||||
$extra = '&op='.$wizard->operation;
|
||||
|
||||
if ($wizard->id !== null) {
|
||||
$extra .= '&id='.$wizard->id;
|
||||
}
|
||||
|
||||
$bc[] = [
|
||||
'link' => $wizard->parentUrl,
|
||||
'label' => __('Cluster list'),
|
||||
'selected' => false,
|
||||
];
|
||||
|
||||
$labels = $wizard->getLabels();
|
||||
foreach ($labels as $key => $label) {
|
||||
$bc[] = [
|
||||
'link' => $wizard->url.(($key >= 0) ? $extra.'&page='.$key : ''),
|
||||
'label' => __($label),
|
||||
'selected' => ($wizard->page == $key),
|
||||
];
|
||||
}
|
||||
|
||||
$wizard->prepareBreadcrum($bc);
|
||||
|
||||
$header_str = __(ucfirst($wizard->getOperation())).' ';
|
||||
$header_str .= (($cluster->name() !== null) ? $cluster->name() : __('cluster '));
|
||||
$header_str .= ' » '.__($labels[$wizard->page]);
|
||||
|
||||
// Header.
|
||||
$buttons = [];
|
||||
|
||||
$main_page = '<a href="'.$wizard->parentUrl.'">';
|
||||
$main_page .= html_print_image(
|
||||
'images/list.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Cluster list'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$main_page .= '</a>';
|
||||
|
||||
$buttons = [
|
||||
[
|
||||
'active' => false,
|
||||
'text' => $main_page,
|
||||
],
|
||||
];
|
||||
|
||||
if ($cluster !== null) {
|
||||
if ($cluster->id() !== null) {
|
||||
$view = '<a href="'.$wizard->parentUrl.'&op=view&id='.$cluster->id().'">';
|
||||
$view .= html_print_image(
|
||||
'images/operation.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('View this cluster'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$view .= '</a>';
|
||||
|
||||
$buttons[] = [
|
||||
'active' => false,
|
||||
'text' => $view,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
ui_print_page_header(
|
||||
$header_str,
|
||||
'',
|
||||
false,
|
||||
'cluster_view',
|
||||
true,
|
||||
// Buttons.
|
||||
$buttons,
|
||||
false,
|
||||
'',
|
||||
GENERIC_SIZE_TEXT,
|
||||
'',
|
||||
$wizard->printHeader(true)
|
||||
);
|
||||
|
||||
// Check if any error ocurred.
|
||||
if (empty($wizard->errMessages) === false) {
|
||||
foreach ($wizard->errMessages as $msg) {
|
||||
ui_print_error_message(__($msg));
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($form) === false) {
|
||||
// Print form (prepared in ClusterWizard).
|
||||
HTML::printForm($form, false, ($wizard->page < 6));
|
||||
}
|
||||
|
||||
// Print always go back button.
|
||||
HTML::printForm($wizard->getGoBackForm(), false);
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
/**
|
||||
* Cluster View: List
|
||||
*
|
||||
* @category View
|
||||
* @package Pandora FMS
|
||||
* @subpackage Cluster View
|
||||
* @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.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
// Header.
|
||||
\ui_print_page_header(
|
||||
__('Monitoring').' » '.__('Clusters'),
|
||||
'images/chart.png',
|
||||
false,
|
||||
'',
|
||||
false
|
||||
);
|
||||
|
||||
if (empty($message) === false) {
|
||||
echo $message;
|
||||
}
|
||||
|
||||
// Datatables list.
|
||||
try {
|
||||
$columns = [
|
||||
'name',
|
||||
'description',
|
||||
'group',
|
||||
'type',
|
||||
'nodes',
|
||||
'known_status',
|
||||
[
|
||||
'text' => 'options',
|
||||
'class' => 'action_buttons',
|
||||
],
|
||||
];
|
||||
|
||||
$column_names = [
|
||||
__('Name'),
|
||||
__('Description'),
|
||||
__('Group'),
|
||||
__('Type'),
|
||||
__('Nodes'),
|
||||
__('Status'),
|
||||
__('Options'),
|
||||
];
|
||||
|
||||
$tableId = 'clusters';
|
||||
|
||||
// Load datatables user interface.
|
||||
ui_print_datatable(
|
||||
[
|
||||
'id' => $tableId,
|
||||
'class' => 'info_table',
|
||||
'style' => 'width: 100%',
|
||||
'columns' => $columns,
|
||||
'column_names' => $column_names,
|
||||
'ajax_url' => $model->ajaxController,
|
||||
'ajax_data' => ['method' => 'draw'],
|
||||
'no_sortable_columns' => [-1],
|
||||
'order' => [
|
||||
'field' => 'known_status',
|
||||
'direction' => 'asc',
|
||||
],
|
||||
'search_button_class' => 'sub filter float-right',
|
||||
'form' => [
|
||||
'inputs' => [
|
||||
[
|
||||
'label' => __('Filter group'),
|
||||
'name' => 'id_group',
|
||||
'returnAllGroup' => true,
|
||||
'privilege' => 'AR',
|
||||
'type' => 'select_groups',
|
||||
'return' => true,
|
||||
'size' => '250px',
|
||||
],
|
||||
[
|
||||
'label' => __('Free search'),
|
||||
'type' => 'text',
|
||||
'class' => 'mw250px',
|
||||
'id' => 'free_search',
|
||||
'name' => 'free_search',
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
if (check_acl($config['id_user'], 0, 'AW')) {
|
||||
HTML::printForm(
|
||||
[
|
||||
'form' => [
|
||||
'method' => 'POST',
|
||||
'action' => ui_get_full_url($model->url.'&op=new'),
|
||||
],
|
||||
'inputs' => [
|
||||
[
|
||||
'class' => 'w100p',
|
||||
'arguments' => [
|
||||
'name' => 'submit',
|
||||
'label' => __('New cluster'),
|
||||
'type' => 'submit',
|
||||
'attributes' => 'class="sub next"',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
|
@ -0,0 +1,453 @@
|
|||
<?php
|
||||
/**
|
||||
* Cluster View: View
|
||||
*
|
||||
* @category View
|
||||
* @package Pandora FMS
|
||||
* @subpackage Cluster View
|
||||
* @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.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
ui_require_css_file('discovery');
|
||||
ui_require_css_file('agent_view');
|
||||
ui_require_css_file('cluster_view');
|
||||
|
||||
$html = new HTML();
|
||||
|
||||
// Begin.
|
||||
// Prepare header and breadcrums.
|
||||
$i = 0;
|
||||
$bc = [];
|
||||
|
||||
$bc[] = [
|
||||
'link' => $model->url,
|
||||
'label' => __('Cluster list'),
|
||||
'selected' => false,
|
||||
];
|
||||
|
||||
$bc[] = [
|
||||
'link' => $model->url.'&op=view&id='.$cluster->id(),
|
||||
'label' => __('Cluster details'),
|
||||
'selected' => true,
|
||||
];
|
||||
|
||||
|
||||
$html->prepareBreadcrum($bc);
|
||||
|
||||
// Header.
|
||||
$main_page = '<a href="'.$model->url.'">';
|
||||
$main_page .= html_print_image(
|
||||
'images/list.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Cluster list'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$main_page .= '</a>';
|
||||
|
||||
$edit = '<a href="'.$model->url.'&op=update&id='.$cluster->id().'">';
|
||||
$edit .= html_print_image(
|
||||
'images/setup.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Edit this cluster'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$edit .= '</a>';
|
||||
|
||||
ui_print_page_header(
|
||||
__('Cluster details').' » '.$cluster->name(),
|
||||
'',
|
||||
false,
|
||||
// Help link.
|
||||
'cluster_view',
|
||||
true,
|
||||
// Buttons.
|
||||
[
|
||||
[
|
||||
'active' => false,
|
||||
'text' => $main_page,
|
||||
],[
|
||||
'active' => false,
|
||||
'text' => $edit,
|
||||
],
|
||||
],
|
||||
false,
|
||||
'',
|
||||
GENERIC_SIZE_TEXT,
|
||||
'',
|
||||
$html->printHeader(true)
|
||||
);
|
||||
|
||||
|
||||
if (empty($error) === false) {
|
||||
echo $error;
|
||||
}
|
||||
|
||||
if (empty($message) === false) {
|
||||
echo $message;
|
||||
}
|
||||
|
||||
if ($critical === true) {
|
||||
// Print always go back button.
|
||||
HTML::printForm($model->getGoBackForm(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* All this block has been retrieved from 'estado_generalagente.php' as
|
||||
* described in issue #5755.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* CLUSTER AGENT DETAILS.
|
||||
*
|
||||
*/
|
||||
|
||||
// Prepare information for view.
|
||||
$alive_animation = agents_get_status_animation(
|
||||
agents_get_interval_status($cluster->agent()->toArray(), false)
|
||||
);
|
||||
|
||||
|
||||
$agent_name = ui_print_agent_name(
|
||||
$cluster->agent()->id_agente(),
|
||||
true,
|
||||
500,
|
||||
'font-size: medium;font-weight:bold',
|
||||
true,
|
||||
'',
|
||||
'',
|
||||
false,
|
||||
false
|
||||
);
|
||||
$in_planned_downtime = db_get_sql(
|
||||
'SELECT executed FROM tplanned_downtime
|
||||
INNER JOIN tplanned_downtime_agents
|
||||
ON tplanned_downtime.id = tplanned_downtime_agents.id_downtime
|
||||
WHERE tplanned_downtime_agents.id_agent = '.$cluster->agent()->id_agente().' AND tplanned_downtime.executed = 1'
|
||||
);
|
||||
|
||||
if ($cluster->agent()->disabled()) {
|
||||
if ($in_planned_downtime) {
|
||||
$agent_name = '<em>'.$agent_name.ui_print_help_tip(__('Disabled'), true);
|
||||
} else {
|
||||
$agent_name = '<em>'.$agent_name.'</em>'.ui_print_help_tip(__('Disabled'), true);
|
||||
}
|
||||
} else if ($cluster->agent()->quiet()) {
|
||||
if ($in_planned_downtime) {
|
||||
$agent_name = "<em'>".$agent_name.' '.html_print_image('images/dot_blue.png', true, ['border' => '0', 'title' => __('Quiet'), 'alt' => '']);
|
||||
} else {
|
||||
$agent_name = "<em'>".$agent_name.' '.html_print_image('images/dot_blue.png', true, ['border' => '0', 'title' => __('Quiet'), 'alt' => '']).'</em>';
|
||||
}
|
||||
} else {
|
||||
$agent_name = $agent_name;
|
||||
}
|
||||
|
||||
if ($in_planned_downtime && !$cluster->agent()->disabled() && !$cluster->agent()->quiet()) {
|
||||
$agent_name .= '<em> '.ui_print_help_tip(
|
||||
__('Agent in scheduled downtime'),
|
||||
true,
|
||||
'images/minireloj-16.png'
|
||||
).'</em>';
|
||||
} else if (($in_planned_downtime && !$cluster->agent()->disabled())
|
||||
|| ($in_planned_downtime && !$cluster->agent()->quiet())
|
||||
) {
|
||||
$agent_name .= ' '.ui_print_help_tip(
|
||||
__('Agent in scheduled downtime'),
|
||||
true,
|
||||
'images/minireloj-16.png'
|
||||
).'</em>';
|
||||
}
|
||||
|
||||
|
||||
$table_agent_header = '<div class="agent_details_agent_alias">';
|
||||
$table_agent_header .= $agent_name;
|
||||
$table_agent_header .= '</div>';
|
||||
$table_agent_header .= '<div class="agent_details_agent_name">';
|
||||
if (!$config['show_group_name']) {
|
||||
$table_agent_header .= ui_print_group_icon(
|
||||
$cluster->agent()->id_grupo(),
|
||||
true,
|
||||
'groups_small',
|
||||
'padding-right: 6px;'
|
||||
);
|
||||
}
|
||||
|
||||
$table_agent_header .= '</div>';
|
||||
|
||||
$status_img = agents_detail_view_status_img(
|
||||
$cluster->agent()->critical_count(),
|
||||
$cluster->agent()->warning_count(),
|
||||
$cluster->agent()->unknown_count(),
|
||||
$cluster->agent()->total_count(),
|
||||
$cluster->agent()->notinit_count()
|
||||
);
|
||||
|
||||
$table_agent_header .= '<div class="icono_right">'.$status_img.'</div>';
|
||||
$table_agent_header .= ' ';
|
||||
$table_agent_header .= '<a href="'.$model->url.'&op=force&id='.$cluster->id();
|
||||
$table_agent_header .= '">'.html_print_image(
|
||||
'images/target.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Force cluster status calculation'),
|
||||
'alt' => '',
|
||||
'class' => 'invert_filter',
|
||||
|
||||
]
|
||||
).'</a>';
|
||||
// Fixed width non interactive charts.
|
||||
$status_chart_width = 180;
|
||||
$graph_width = 180;
|
||||
|
||||
$table_agent_graph = '<div id="status_pie" style="width: '.$status_chart_width.'px;">';
|
||||
$table_agent_graph .= graph_agent_status(
|
||||
$cluster->agent()->id_agente(),
|
||||
$graph_width,
|
||||
$graph_width,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
);
|
||||
$table_agent_graph .= '</div>';
|
||||
|
||||
$table_agent_os = '<p>'.ui_print_os_icon(
|
||||
$cluster->agent()->id_os(),
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
['title' => __('OS').': '.get_os_name($cluster->agent()->id_os())]
|
||||
);
|
||||
$table_agent_os .= (empty($cluster->agent()->os_version()) === true) ? get_os_name((int) $cluster->agent()->id_os()) : $cluster->agent()->os_version().'</p>';
|
||||
|
||||
|
||||
|
||||
$addresses = agents_get_addresses($cluster->agent()->id_agente());
|
||||
$address = agents_get_address($cluster->agent()->id_agente());
|
||||
|
||||
foreach ($addresses as $k => $add) {
|
||||
if ($add == $address) {
|
||||
unset($addresses[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($address) === false) {
|
||||
$table_agent_ip = '<p>'.html_print_image(
|
||||
'images/world.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('IP address'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$table_agent_ip .= '<span class="align-top inline">';
|
||||
$table_agent_ip .= empty($address) ? '<em>'.__('N/A').'</em>' : $address;
|
||||
$table_agent_ip .= '</span></p>';
|
||||
}
|
||||
|
||||
$table_agent_description = '<p>'.html_print_image(
|
||||
'images/list.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Description'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$table_agent_description .= '<span class="align-top inline">';
|
||||
$table_agent_description .= empty(
|
||||
$cluster->description()
|
||||
) ? '<em>'.__('N/A').'</em>' : $cluster->description();
|
||||
$table_agent_description .= '</span></p>';
|
||||
|
||||
$table_agent_count_modules = reporting_tiny_stats(
|
||||
$cluster->agent()->toArray(),
|
||||
true,
|
||||
'agent',
|
||||
// Useless.
|
||||
':',
|
||||
true
|
||||
);
|
||||
|
||||
$table_agent_version = '<p>'.html_print_image(
|
||||
'images/version.png',
|
||||
true,
|
||||
[
|
||||
'title' => __('Agent Version'),
|
||||
'class' => 'invert_filter',
|
||||
]
|
||||
);
|
||||
$table_agent_version .= '<span class="align-top inline">';
|
||||
$table_agent_version .= empty($cluster->agent()->agent_version()) ? '<i>'.__('Cluster agent').'</i>' : $cluster->agent()->agent_version();
|
||||
$table_agent_version .= '</span></p>';
|
||||
|
||||
/*
|
||||
*
|
||||
* MAP
|
||||
*
|
||||
*/
|
||||
|
||||
$nodes = $cluster->getNodes();
|
||||
|
||||
$font_size = 20;
|
||||
$width = '45%';
|
||||
$height = '500';
|
||||
$node_radius = 40;
|
||||
|
||||
// Generate map.
|
||||
$map_manager = new NetworkMap(
|
||||
[
|
||||
'nodes' => $nodes,
|
||||
'no_pandora_node' => 1,
|
||||
'pure' => 1,
|
||||
'map_options' => [
|
||||
'generation_method' => LAYOUT_SPRING1,
|
||||
'font_size' => $font_size,
|
||||
'node_radius' => $node_radius,
|
||||
'height' => $height,
|
||||
'width' => '100%',
|
||||
'tooltip' => true,
|
||||
'size_image' => 50,
|
||||
'z_dash' => 0.5,
|
||||
'map_filter' => [
|
||||
'node_sep' => 7,
|
||||
'node_radius' => 50,
|
||||
'x_offs' => 130,
|
||||
'y_offs' => -70,
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* EVENTS 24h
|
||||
*
|
||||
*/
|
||||
|
||||
$table_events = '<div class="white_table_graph" id="table_events">';
|
||||
$table_events .= '<div class="white_table_graph_header">';
|
||||
$table_events .= html_print_image(
|
||||
'images/arrow_down_green.png',
|
||||
true
|
||||
);
|
||||
$table_events .= '<span>';
|
||||
$table_events .= __('Events (Last 24h)');
|
||||
$table_events .= '</span>';
|
||||
$table_events .= '</div>';
|
||||
$table_events .= '<div class="white_table_graph_content white-table-graph-content">';
|
||||
$table_events .= graph_graphic_agentevents(
|
||||
$cluster->agent()->id_agente(),
|
||||
95,
|
||||
70,
|
||||
SECONDS_1DAY,
|
||||
'',
|
||||
true,
|
||||
true,
|
||||
500
|
||||
);
|
||||
$table_events .= '</div>';
|
||||
$table_events .= '</div>';
|
||||
|
||||
?>
|
||||
<div id="agent_details_first_row" class="w100p cluster-agent-data">
|
||||
<div class="box-shadow agent_details_col agent_details_col_left">
|
||||
<div class="agent_details_header">
|
||||
<?php echo $table_agent_header; ?>
|
||||
</div>
|
||||
<div class="agent_details_content">
|
||||
<div class="agent_details_graph">
|
||||
<?php echo $table_agent_graph; ?>
|
||||
<div class="agent_details_bullets">
|
||||
<?php echo $table_agent_count_modules; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="agent_details_info">
|
||||
<?php
|
||||
echo $alive_animation;
|
||||
echo $table_agent_os;
|
||||
echo $table_agent_ip;
|
||||
echo $table_agent_version;
|
||||
echo $table_agent_description;
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-shadow agent_details_col agent_details_col_right">
|
||||
<div class="cluster-map">
|
||||
<?php $map_manager->printMap(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w100p cluster-events-graph">
|
||||
<?php echo $table_events; ?>
|
||||
</div>
|
||||
|
||||
<div id='cluster-modules' class="w100p modules">
|
||||
<?php
|
||||
$id_agente = $cluster->agent()->id_agente();
|
||||
require_once $config['homedir'].'/operation/agentes/estado_monitores.php';
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
<?php
|
||||
HTML::printForm(
|
||||
[
|
||||
'form' => [
|
||||
'action' => $model->url.'&op=view&id='.$cluster->id(),
|
||||
'method' => 'POST',
|
||||
],
|
||||
'inputs' => [
|
||||
[
|
||||
'arguments' => [
|
||||
'name' => 'submit',
|
||||
'label' => __('Reload'),
|
||||
'type' => 'submit',
|
||||
'attributes' => 'class="sub cancel"',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
echo '<br/>';
|
||||
|
||||
// Print always go back button.
|
||||
HTML::printForm($model->getGoBackForm(), false);
|
|
@ -280,6 +280,9 @@ our @EXPORT = qw(
|
|||
notification_set_targets
|
||||
notification_get_users
|
||||
notification_get_groups
|
||||
exec_cluster_aa_module
|
||||
exec_cluster_ap_module
|
||||
exec_cluster_status_module
|
||||
);
|
||||
|
||||
# Some global variables
|
||||
|
@ -7275,6 +7278,175 @@ sub pandora_snmptrapd_still_working ($$) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
################################################################################
|
||||
# Execute a cluster status module.
|
||||
################################################################################
|
||||
sub exec_cluster_status_module ($$$$) {
|
||||
my ($pa_config, $module, $server_id, $dbh) = @_;
|
||||
|
||||
# Execute cluster modules.
|
||||
my @modules = get_db_rows($dbh,
|
||||
'SELECT *
|
||||
FROM tagente_modulo
|
||||
WHERE tagente_modulo.id_agente = ?
|
||||
AND tagente_modulo.disabled != 1
|
||||
AND tagente_modulo.tcp_port = 1',
|
||||
$module->{'id_agente'});
|
||||
foreach my $agent_module (@modules) {
|
||||
# Cluster active-active module.
|
||||
if ($agent_module->{'prediction_module'} == 6) {
|
||||
logger ($pa_config, "Executing cluster active-active critical module " . $agent_module->{'nombre'}, 10);
|
||||
exec_cluster_aa_module($pa_config, $agent_module, $server_id, $dbh);
|
||||
}
|
||||
# Cluster active-passive module.
|
||||
elsif ($agent_module->{'prediction_module'} == 7) {
|
||||
logger ($pa_config, "Executing cluster active-passive critical module " . $agent_module->{'nombre'}, 10);
|
||||
exec_cluster_ap_module($pa_config, $agent_module, $server_id, $dbh);
|
||||
}
|
||||
}
|
||||
|
||||
# Get the status of cluster modules.
|
||||
my $data = -1;
|
||||
@modules = get_db_rows($dbh,
|
||||
'SELECT tagente_modulo.id_agente_modulo, tagente_estado.estado
|
||||
FROM tagente_estado, tagente_modulo
|
||||
WHERE tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND tagente_modulo.disabled != 1
|
||||
AND tagente_modulo.tcp_port = 1
|
||||
AND tagente_modulo.id_agente = ?',
|
||||
$module->{'id_agente'});
|
||||
foreach my $cluster_module (@modules) {
|
||||
next if ($cluster_module->{'id_agente_modulo'} == $module->{'id_agente_modulo'}); # Skip the current module.
|
||||
|
||||
# Critical.
|
||||
if ($cluster_module->{'estado'} == MODULE_NORMAL && $data < 0) {
|
||||
$data = 0;
|
||||
} elsif ($cluster_module->{'estado'} == MODULE_WARNING && $data < 1) {
|
||||
$data = 1;
|
||||
} elsif (($cluster_module->{'estado'} == MODULE_CRITICAL || $cluster_module->{'estado'} == MODULE_UNKNOWN) && $data < 2) {
|
||||
$data = 2;
|
||||
}
|
||||
}
|
||||
|
||||
# No data.
|
||||
if ($data < 0) {
|
||||
pandora_update_module_on_error ($pa_config, $module, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Get the current timestamp.
|
||||
my $utimestamp = time ();
|
||||
my $timestamp = strftime("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
# Update the module.
|
||||
pandora_process_module($pa_config, {'data' => $data}, '', $module, '', $timestamp, $utimestamp, $server_id, $dbh);
|
||||
|
||||
pandora_update_agent($pa_config, $timestamp, $module->{'id_agente'}, undef, undef, -1, $dbh);
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Execute a cluster active-active module.
|
||||
################################################################################
|
||||
sub exec_cluster_aa_module ($$$$) {
|
||||
my ($pa_config, $module, $server_id, $dbh) = @_;
|
||||
|
||||
# Get the cluster item.
|
||||
my $item = get_db_single_row($dbh, 'SELECT * FROM tcluster_item WHERE id=?', $module->{'custom_integer_2'});
|
||||
if (!defined($item)) {
|
||||
pandora_update_module_on_error ($pa_config, $module, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Get cluster agents and compute the item status.
|
||||
my ($not_normal, $total) = (0, 0);
|
||||
my @agents = get_db_rows($dbh, 'SELECT id_agent FROM tcluster_agent WHERE id_cluster = ?', $module->{'custom_integer_1'});
|
||||
foreach my $agent_id (@agents) {
|
||||
my $item_status = get_db_value($dbh,
|
||||
'SELECT estado
|
||||
FROM tagente_estado, tagente_modulo
|
||||
WHERE tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND tagente_modulo.id_agente = ?
|
||||
AND tagente_modulo.nombre = ?',
|
||||
$agent_id->{'id_agent'}, $item->{'name'});
|
||||
|
||||
# Count modules in a status other than normal.
|
||||
if (!defined($item_status) || $item_status != MODULE_NORMAL) {
|
||||
$not_normal += 1;
|
||||
}
|
||||
|
||||
$total += 1;
|
||||
}
|
||||
|
||||
# No data.
|
||||
if ($total < 1) {
|
||||
pandora_update_module_on_error ($pa_config, $module, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Convert $not_normal to a percentage.
|
||||
$not_normal = 100 * $not_normal / $total;
|
||||
|
||||
# Get the current timestamp.
|
||||
my $utimestamp = time ();
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
# Update module
|
||||
pandora_process_module ($pa_config, {'data' => $not_normal}, '', $module, '', $timestamp, $utimestamp, $server_id, $dbh);
|
||||
|
||||
pandora_update_agent ($pa_config, $timestamp, $module->{'id_agente'}, undef, undef, -1, $dbh);
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Execute a cluster active-pasive module.
|
||||
################################################################################
|
||||
sub exec_cluster_ap_module ($$$$) {
|
||||
my ($pa_config, $module, $server_id, $dbh) = @_;
|
||||
|
||||
# Get the cluster item.
|
||||
my $item = get_db_single_row($dbh, 'SELECT * FROM tcluster_item WHERE id=?', $module->{'custom_integer_2'});
|
||||
if (!defined($item)) {
|
||||
pandora_update_module_on_error ($pa_config, $module, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Get cluster agents and compute the item status.
|
||||
my $data = undef;
|
||||
my $utimestamp = 0;
|
||||
my @agents = get_db_rows($dbh, 'SELECT id_agent FROM tcluster_agent WHERE id_cluster = ?', $module->{'custom_integer_1'});
|
||||
foreach my $agent_id (@agents) {
|
||||
my $status = get_db_single_row($dbh,
|
||||
'SELECT datos, estado, utimestamp
|
||||
FROM tagente_estado, tagente_modulo
|
||||
WHERE tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo
|
||||
AND tagente_modulo.id_agente = ?
|
||||
AND tagente_modulo.nombre = ?',
|
||||
$agent_id->{'id_agent'}, $item->{'name'});
|
||||
|
||||
# Get the most recent data.
|
||||
if (defined($status) && $status->{'estado'} != MODULE_UNKNOWN && $status->{'utimestamp'} > $utimestamp) {
|
||||
$utimestamp = $status->{'utimestamp'};
|
||||
$data = $status->{'datos'};
|
||||
}
|
||||
}
|
||||
|
||||
# No data.
|
||||
if ($utimestamp == 0) {
|
||||
pandora_update_module_on_error ($pa_config, $module, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Get the current timestamp.
|
||||
$utimestamp = time ();
|
||||
my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp));
|
||||
|
||||
# Update the module.
|
||||
pandora_process_module ($pa_config, {'data' => $data }, '', $module, '', $timestamp, $utimestamp, $server_id, $dbh);
|
||||
|
||||
# Update the agent.
|
||||
pandora_update_agent ($pa_config, $timestamp, $module->{'id_agente'}, undef, undef, -1, $dbh);
|
||||
}
|
||||
|
||||
# End of function declaration
|
||||
# End of defined Code
|
||||
|
||||
|
|
|
@ -207,21 +207,21 @@ sub exec_prediction_module ($$$$) {
|
|||
# Cluster status module.
|
||||
if ($agent_module->{'prediction_module'} == 5) {
|
||||
logger ($pa_config, "Executing cluster status module " . $agent_module->{'nombre'}, 10);
|
||||
enterprise_hook ('exec_cluster_status_module', [$pa_config, $agent_module, $server_id, $dbh]);
|
||||
exec_cluster_status_module($pa_config, $agent_module, $server_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Cluster active-active module.
|
||||
if ($agent_module->{'prediction_module'} == 6) {
|
||||
logger ($pa_config, "Executing cluster active-active module " . $agent_module->{'nombre'}, 10);
|
||||
enterprise_hook ('exec_cluster_aa_module', [$pa_config, $agent_module, $server_id, $dbh]);
|
||||
exec_cluster_aa_module($pa_config, $agent_module, $server_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
# Cluster active-passive module.
|
||||
if ($agent_module->{'prediction_module'} == 7) {
|
||||
logger ($pa_config, "Executing cluster active-passive module " . $agent_module->{'nombre'}, 10);
|
||||
enterprise_hook ('exec_cluster_ap_module', [$pa_config, $agent_module, $server_id, $dbh]);
|
||||
exec_cluster_ap_module($pa_config, $agent_module, $server_id, $dbh);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue