implement cluster in open project
This commit is contained in:
parent
61b3bc724a
commit
17d7261173
|
@ -1666,3 +1666,11 @@ godmode/um_client/vendor/sebastian/object-enumerator
|
||||||
godmode/um_client/vendor/sebastian
|
godmode/um_client/vendor/sebastian
|
||||||
godmode/um_client/vendor
|
godmode/um_client/vendor
|
||||||
update_manager_client/resources/styles/pandora.css
|
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
|
||||||
|
|
|
@ -68,7 +68,7 @@ ui_print_info_message(['no_close' => true, 'message' => __('There are no cluster
|
||||||
if (check_acl($config['id_user'], 0, 'AW')) {
|
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'); ?>" />
|
<input type="submit" class="button_task ui_toggle" value="<?php echo __('Create Cluster'); ?>" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -732,17 +732,15 @@ if ($agents !== false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||||
if (enterprise_installed()) {
|
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
$agent['id_agente']
|
||||||
$agent['id_agente']
|
);
|
||||||
);
|
$url = 'index.php?sec=reporting&sec2=';
|
||||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
$url .= '/operation/cluster/cluster';
|
||||||
$url .= '/operation/cluster/cluster';
|
$url = ui_get_full_url(
|
||||||
$url = ui_get_full_url(
|
$url.'&op=update&id='.$cluster->id()
|
||||||
$url.'&op=update&id='.$cluster->id()
|
);
|
||||||
);
|
echo '<a href="'.$url.'">'.ui_print_truncate_text($agent['alias'], 'agent_medium').'</a>';
|
||||||
echo '<a href="'.$url.'">'.ui_print_truncate_text($agent['alias'], 'agent_medium').'</a>';
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
echo '<a alt ='.$agent['nombre']." href='index.php?sec=gagente&
|
echo '<a alt ='.$agent['nombre']." href='index.php?sec=gagente&
|
||||||
sec2=godmode/agentes/configurar_agente&tab=$main_tab&
|
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">';
|
echo '</span><div class="left actions clear_left" style=" visibility: hidden">';
|
||||||
if ($check_aw) {
|
if ($check_aw) {
|
||||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||||
if (enterprise_installed()) {
|
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
$agent['id_agente']
|
||||||
$agent['id_agente']
|
);
|
||||||
);
|
$url = 'index.php?sec=reporting&sec2=';
|
||||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
$url .= '/operation/cluster/cluster';
|
||||||
$url .= '/operation/cluster/cluster';
|
$url = ui_get_full_url(
|
||||||
$url = ui_get_full_url(
|
$url.'&op=update&id='.$cluster->id()
|
||||||
$url.'&op=update&id='.$cluster->id()
|
);
|
||||||
);
|
echo '<a href="'.$url.'">'.__('Edit').'</a>';
|
||||||
echo '<a href="'.$url.'">'.__('Edit').'</a>';
|
echo ' | ';
|
||||||
echo ' | ';
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
echo '<a href="index.php?sec=gagente&
|
echo '<a href="index.php?sec=gagente&
|
||||||
sec2=godmode/agentes/configurar_agente&tab=main&
|
sec2=godmode/agentes/configurar_agente&tab=main&
|
||||||
|
@ -825,17 +821,15 @@ if ($agents !== false) {
|
||||||
echo ' | ';
|
echo ' | ';
|
||||||
|
|
||||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||||
if (enterprise_installed()) {
|
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
$agent['id_agente']
|
||||||
$agent['id_agente']
|
);
|
||||||
);
|
$url = 'index.php?sec=reporting&sec2=';
|
||||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
$url .= '/operation/cluster/cluster';
|
||||||
$url .= '/operation/cluster/cluster';
|
$url = ui_get_full_url(
|
||||||
$url = ui_get_full_url(
|
$url.'&op=view&id='.$cluster->id()
|
||||||
$url.'&op=view&id='.$cluster->id()
|
);
|
||||||
);
|
echo '<a href="'.$url.'">'.__('View').'</a>';
|
||||||
echo '<a href="'.$url.'">'.__('View').'</a>';
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
echo '<a href="index.php?sec=estado
|
echo '<a href="index.php?sec=estado
|
||||||
&sec2=operation/agentes/ver_agente
|
&sec2=operation/agentes/ver_agente
|
||||||
|
|
|
@ -62,7 +62,7 @@ enterprise_include_once('include/functions_cron.php');
|
||||||
// Clases.
|
// Clases.
|
||||||
use PandoraFMS\Agent;
|
use PandoraFMS\Agent;
|
||||||
use PandoraFMS\Module;
|
use PandoraFMS\Module;
|
||||||
use PandoraFMS\Enterprise\Cluster;
|
use PandoraFMS\Cluster;
|
||||||
use PandoraFMS\Enterprise\Metaconsole\Node;
|
use PandoraFMS\Enterprise\Metaconsole\Node;
|
||||||
use PandoraFMS\SpecialDay;
|
use PandoraFMS\SpecialDay;
|
||||||
|
|
||||||
|
|
|
@ -691,10 +691,10 @@ function treeview_printTable($id_agente, $server_data=[], $no_head=false)
|
||||||
|
|
||||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||||
if (enterprise_installed()) {
|
if (enterprise_installed()) {
|
||||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||||
$agent['id_agente']
|
$agent['id_agente']
|
||||||
);
|
);
|
||||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
$url = 'index.php?sec=reporting&sec2=';
|
||||||
$url .= '/operation/cluster/cluster';
|
$url .= '/operation/cluster/cluster';
|
||||||
$url = ui_get_full_url(
|
$url = ui_get_full_url(
|
||||||
$url.'&op=update&id='.$cluster->id()
|
$url.'&op=update&id='.$cluster->id()
|
||||||
|
|
|
@ -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) {
|
||||||
|
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
|
@ -847,10 +847,10 @@ foreach ($agents as $agent) {
|
||||||
|
|
||||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||||
if (enterprise_installed()) {
|
if (enterprise_installed()) {
|
||||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||||
$agent['id_agente']
|
$agent['id_agente']
|
||||||
);
|
);
|
||||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
$url = 'index.php?sec=reporting&sec2=';
|
||||||
$url .= '/operation/cluster/cluster';
|
$url .= '/operation/cluster/cluster';
|
||||||
$url = ui_get_full_url(
|
$url = ui_get_full_url(
|
||||||
$url.'&op=view&id='.$cluster->id()
|
$url.'&op=view&id='.$cluster->id()
|
||||||
|
@ -866,10 +866,10 @@ foreach ($agents as $agent) {
|
||||||
|
|
||||||
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
if ($agent['id_os'] == CLUSTER_OS_ID) {
|
||||||
if (enterprise_installed()) {
|
if (enterprise_installed()) {
|
||||||
$cluster = PandoraFMS\Enterprise\Cluster::loadFromAgentId(
|
$cluster = PandoraFMS\Cluster::loadFromAgentId(
|
||||||
$agent['id_agente']
|
$agent['id_agente']
|
||||||
);
|
);
|
||||||
$url = 'index.php?sec=reporting&sec2='.ENTERPRISE_DIR;
|
$url = 'index.php?sec=reporting&sec2=';
|
||||||
$url .= '/operation/cluster/cluster';
|
$url .= '/operation/cluster/cluster';
|
||||||
$url = ui_get_full_url(
|
$url = ui_get_full_url(
|
||||||
$url.'&op=update&id='.$cluster->id()
|
$url.'&op=update&id='.$cluster->id()
|
||||||
|
|
|
@ -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';
|
$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('aws_menu');
|
||||||
enterprise_hook('SAP_view');
|
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);
|
Loading…
Reference in New Issue