mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
New Poller validations (#14148)
* New Poller validations Seperated poller and distributed poller validations to make poller validations generally available One auto fixer added Translatable strings * lint and style fixes * and style * and style * Update LibreNMS/Validations/Poller/CheckLocking.php Co-authored-by: Jellyfrog <Jellyfrog@users.noreply.github.com> * Update CheckPythonWrapper.php * Try to check if cron is even installed before warning about not being able to read the cron files. Likely most systems they won't be readable, but also, it is very unlikely we hit the cron check and it is meaningfully different than the first Poller::exists() check. * Work on poller validation Remove errors/warnings when at least one poller of the other type is active. * style fixes Co-authored-by: Jellyfrog <Jellyfrog@users.noreply.github.com>
This commit is contained in:
@@ -23,107 +23,18 @@
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: murrant
|
||||
* Date: 10/8/17
|
||||
* Time: 2:16 AM
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations;
|
||||
|
||||
use App\Models\PollerCluster;
|
||||
use Carbon\Carbon;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Validations\Rrd\CheckRrdcachedConnectivity;
|
||||
use LibreNMS\Validator;
|
||||
|
||||
class DistributedPoller extends BaseValidation
|
||||
{
|
||||
protected $directory = 'DistributedPoller';
|
||||
protected $name = 'distributedpoller';
|
||||
|
||||
public function isDefault(): bool
|
||||
{
|
||||
// run by default if distributed polling is enabled
|
||||
return Config::get('distributed_poller');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate this module.
|
||||
* To return ValidationResults, call ok, warn, fail, or result methods on the $validator
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
public function validate(Validator $validator): void
|
||||
{
|
||||
if (! Config::get('distributed_poller')) {
|
||||
$validator->fail('You have not enabled distributed_poller', 'lnms config:set distributed_poller true');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! Config::get('rrdcached')) {
|
||||
$validator->fail('You have not configured $config[\'rrdcached\']');
|
||||
} elseif (! is_dir(Config::get('rrd_dir'))) {
|
||||
$validator->fail('You have not configured $config[\'rrd_dir\']');
|
||||
} else {
|
||||
$validator->result((new CheckRrdcachedConnectivity)->validate(), $this->name);
|
||||
}
|
||||
|
||||
if (PollerCluster::exists()) {
|
||||
if (PollerCluster::isActive()->exists()) {
|
||||
$validator->info('Detected Dispatcher Service');
|
||||
$this->checkDispatcherService($validator);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$validator->warn('Dispatcher Service has been used in your cluster, but not recently. It may take up to 5 minutes to register.');
|
||||
}
|
||||
|
||||
$validator->info('Detected Python Wrapper');
|
||||
$this->checkPythonWrapper($validator);
|
||||
}
|
||||
|
||||
private function checkDispatcherService(Validator $validator): void
|
||||
{
|
||||
$driver = config('cache.default');
|
||||
if ($driver != 'redis') {
|
||||
$validator->warn("Using $driver for distributed locking, you should set CACHE_DRIVER=redis");
|
||||
}
|
||||
|
||||
try {
|
||||
$lock = \Cache::lock('dist_test_validation');
|
||||
$lock->get();
|
||||
$lock->release();
|
||||
} catch (\Exception $e) {
|
||||
$validator->fail('Locking server issue: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$node = PollerCluster::firstWhere('node_id', config('librenms.node_id'));
|
||||
if (is_null($node)) {
|
||||
$validator->fail('Dispatcher service is enabled on your cluster, but not in use on this node');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($node->last_report->lessThan(Carbon::now()->subSeconds($node->getSettingValue('poller_frequency')))) {
|
||||
$validator->fail('Dispatcher service has not reported stats within the last poller window');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkPythonWrapper(Validator $validator): void
|
||||
{
|
||||
if (! Config::get('distributed_poller_memcached_host')) {
|
||||
$validator->fail('You have not configured $config[\'distributed_poller_memcached_host\']');
|
||||
} elseif (! Config::get('distributed_poller_memcached_port')) {
|
||||
$validator->fail('You have not configured $config[\'distributed_poller_memcached_port\']');
|
||||
} else {
|
||||
$connection = @fsockopen(Config::get('distributed_poller_memcached_host'), Config::get('distributed_poller_memcached_port'));
|
||||
if (! is_resource($connection)) {
|
||||
$validator->fail('We could not get memcached stats, it is possible that we cannot connect to your memcached server, please check');
|
||||
} else {
|
||||
fclose($connection);
|
||||
$validator->ok('Connection to memcached is ok');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckDistributedPollerEnabled.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\DistributedPoller;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Validation;
|
||||
use LibreNMS\Interfaces\ValidationFixer;
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckDistributedPollerEnabled implements Validation, ValidationFixer
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
if (! Config::get('distributed_poller')) {
|
||||
return ValidationResult::fail(trans('validation.validations.distributedpoller.CheckDistributedPollerEnabled.not_enabled'))
|
||||
->setFix('lnms config:set distributed_poller true')
|
||||
->setFixer(__CLASS__);
|
||||
}
|
||||
|
||||
$db_config = \App\Models\Config::firstWhere('config_name', 'distributed_poller');
|
||||
if ($db_config === null || ! $db_config->config_value) {
|
||||
return ValidationResult::fail(trans('validation.validations.distributedpoller.CheckDistributedPollerEnabled.not_enabled_globally'))
|
||||
->setFix('lnms config:set distributed_poller true')
|
||||
->setFixer(__CLASS__);
|
||||
}
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.distributedpoller.CheckDistributedPollerEnabled.ok'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function fix(): bool
|
||||
{
|
||||
Config::persist('distributed_poller', true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
65
LibreNMS/Validations/DistributedPoller/CheckMemcached.php
Normal file
65
LibreNMS/Validations/DistributedPoller/CheckMemcached.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckMemcached.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\DistributedPoller;
|
||||
|
||||
use App\Models\Poller;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Validation;
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckMemcached implements Validation
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
if (! Config::get('distributed_poller_memcached_host')) {
|
||||
return ValidationResult::fail(trans('validation.validations.distributedpoller.CheckMemcached.not_configured_host'), 'lnms config:set distributed_poller_memcached_host <hostname>');
|
||||
}
|
||||
|
||||
if (! Config::get('distributed_poller_memcached_port')) {
|
||||
return ValidationResult::fail(trans('validation.validations.distributedpoller.CheckMemcached.not_configured_port'), 'lnms config:set distributed_poller_memcached_port <port>');
|
||||
}
|
||||
|
||||
$connection = @fsockopen(Config::get('distributed_poller_memcached_host'), Config::get('distributed_poller_memcached_port'));
|
||||
if (! is_resource($connection)) {
|
||||
return ValidationResult::fail(trans('validation.validations.distributedpoller.CheckMemcached.could_not_connect'));
|
||||
}
|
||||
|
||||
fclose($connection);
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.distributedpoller.CheckMemcached.ok'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return Config::get('distributed_poller') && Poller::isActive()->count() > 1;
|
||||
}
|
||||
}
|
53
LibreNMS/Validations/DistributedPoller/CheckRrdcached.php
Normal file
53
LibreNMS/Validations/DistributedPoller/CheckRrdcached.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckRrdcached.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\DistributedPoller;
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\ValidationResult;
|
||||
use LibreNMS\Validations\Rrd\CheckRrdcachedConnectivity;
|
||||
|
||||
class CheckRrdcached implements \LibreNMS\Interfaces\Validation
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
if (! Config::get('rrdcached')) {
|
||||
return ValidationResult::fail(trans('validation.validations.distributedpoller.CheckRrdcached.fail'), 'lnms config:set rrdcached <rrdcached server ip:port>');
|
||||
}
|
||||
|
||||
return (new CheckRrdcachedConnectivity)->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return (bool) Config::get('distributed_poller');
|
||||
}
|
||||
}
|
32
LibreNMS/Validations/Poller.php
Normal file
32
LibreNMS/Validations/Poller.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Poller.php
|
||||
*
|
||||
* Validate poller is active and various poller support
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations;
|
||||
|
||||
class Poller extends BaseValidation
|
||||
{
|
||||
protected $directory = 'Poller';
|
||||
protected $name = 'poller';
|
||||
}
|
59
LibreNMS/Validations/Poller/CheckActivePoller.php
Normal file
59
LibreNMS/Validations/Poller/CheckActivePoller.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckActivePoller.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\Poller;
|
||||
|
||||
use App\Models\Poller;
|
||||
use App\Models\PollerCluster;
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckActivePoller implements \LibreNMS\Interfaces\Validation
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
$dispatcher_exists = PollerCluster::isActive()->exists();
|
||||
$wrapper_exists = Poller::isActive()->exists();
|
||||
if (! $dispatcher_exists && ! $wrapper_exists) {
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckActivePoller.fail'));
|
||||
}
|
||||
|
||||
if ($dispatcher_exists && $wrapper_exists) {
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckActivePoller.both_fail'));
|
||||
}
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckActivePoller.ok'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
90
LibreNMS/Validations/Poller/CheckDispatcherService.php
Normal file
90
LibreNMS/Validations/Poller/CheckDispatcherService.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckDispatcherService.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\Poller;
|
||||
|
||||
use App\Models\Poller;
|
||||
use App\Models\PollerCluster;
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckDispatcherService implements \LibreNMS\Interfaces\Validation
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
if (PollerCluster::exists()) {
|
||||
return $this->checkDispatchService();
|
||||
}
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckDispatcherService.not_detected'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkDispatchService(): ValidationResult
|
||||
{
|
||||
if (PollerCluster::isActive()->exists()) {
|
||||
// check for inactive nodes
|
||||
$this_node_id = config('librenms.node_id');
|
||||
$inactive = PollerCluster::isInactive()->get()
|
||||
->map(function (PollerCluster $node) use ($this_node_id) {
|
||||
$name = $node->poller_name ?: $node->node_id;
|
||||
|
||||
// mark this node
|
||||
if ($node->node_id == $this_node_id) {
|
||||
$name .= ' (this node)';
|
||||
}
|
||||
|
||||
return $name;
|
||||
});
|
||||
|
||||
if ($inactive->isNotEmpty()) {
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckDispatcherService.nodes_down'))
|
||||
->setList('Inactive Nodes', $inactive->toArray());
|
||||
}
|
||||
|
||||
// all ok
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckDispatcherService.ok'));
|
||||
}
|
||||
|
||||
// python wrapper found, just warn
|
||||
if (Poller::exists()) {
|
||||
$status = Poller::isActive()->exists() ? ValidationResult::SUCCESS : ValidationResult::WARNING;
|
||||
|
||||
return new ValidationResult(trans('validation.validations.poller.CheckDispatcherService.warn'), $status);
|
||||
}
|
||||
|
||||
// no python wrapper registered, fail
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckDispatcherService.fail'));
|
||||
}
|
||||
}
|
55
LibreNMS/Validations/Poller/CheckLocking.php
Normal file
55
LibreNMS/Validations/Poller/CheckLocking.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckDistributedLocking.php
|
||||
*
|
||||
* Check that distributed locking is set correctly and enabled.
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\Poller;
|
||||
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckLocking implements \LibreNMS\Interfaces\Validation
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
try {
|
||||
$lock = \Cache::lock('dist_test_validation', 5);
|
||||
$lock->get();
|
||||
$lock->release();
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckLocking.ok'));
|
||||
} catch (\Exception $e) {
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckLocking.fail', ['message' => $e->getMessage()]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
111
LibreNMS/Validations/Poller/CheckPythonWrapper.php
Normal file
111
LibreNMS/Validations/Poller/CheckPythonWrapper.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckPythonWrapper.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\Poller;
|
||||
|
||||
use App\Models\Poller;
|
||||
use App\Models\PollerCluster;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckPythonWrapper implements \LibreNMS\Interfaces\Validation
|
||||
{
|
||||
/** @var bool */
|
||||
private $could_not_check_cron = false;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
if (Poller::exists()) {
|
||||
return $this->checkPythonWrapper();
|
||||
}
|
||||
|
||||
// check if cron is installed, then try to check if the cron entries are enabled.
|
||||
$cron = Config::locateBinary('cron');
|
||||
if ($cron !== 'cron') { // cron is installed
|
||||
if ($this->wrapperCronEnabled()) {
|
||||
return $this->checkPythonWrapper();
|
||||
}
|
||||
|
||||
if ($this->could_not_check_cron) {
|
||||
return ValidationResult::info(trans('validation.validations.poller.CheckPythonWrapper.cron_unread'));
|
||||
}
|
||||
|
||||
$status = PollerCluster::isActive()->exists() ? ValidationResult::SUCCESS : ValidationResult::FAILURE;
|
||||
|
||||
return new ValidationResult(trans('validation.validations.poller.CheckPythonWrapper.not_detected'), $status);
|
||||
}
|
||||
|
||||
$status = PollerCluster::isActive()->exists() ? ValidationResult::SUCCESS : ValidationResult::FAILURE;
|
||||
|
||||
return new ValidationResult(trans('validation.validations.poller.CheckPythonWrapper.no_pollers'), $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkPythonWrapper(): ValidationResult
|
||||
{
|
||||
if (! Poller::isActive()->exists()) {
|
||||
$status = PollerCluster::isActive()->exists() ? ValidationResult::SUCCESS : ValidationResult::FAILURE;
|
||||
|
||||
return new ValidationResult(trans('validation.validations.poller.CheckPythonWrapper.fail'), $status);
|
||||
}
|
||||
|
||||
$inactive_pollers = Poller::isInactive()->get();
|
||||
if ($inactive_pollers->isNotEmpty()) {
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckPythonWrapper.nodes_down'))
|
||||
->setList('Inactive Nodes', $inactive_pollers->pluck('poller_name')->toArray());
|
||||
}
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckPythonWrapper.ok'));
|
||||
}
|
||||
|
||||
private function wrapperCronEnabled(): bool
|
||||
{
|
||||
$files = glob('/etc/cron.d/*');
|
||||
$files[] = '/etc/crontab';
|
||||
$files[] = '/var/spool/cron/crontabs/librenms';
|
||||
$this->could_not_check_cron = true; // set this in case we can't read any cron files
|
||||
|
||||
$cron_entries = array_reduce($files, function ($entries, $file) {
|
||||
if (is_readable($file)) {
|
||||
$entries .= file_get_contents($file) . PHP_EOL;
|
||||
$this->could_not_check_cron = false;
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}, '');
|
||||
|
||||
return (bool) preg_match('/^\s*[^#].*poller-wrapper\.py/', $cron_entries);
|
||||
}
|
||||
}
|
72
LibreNMS/Validations/Poller/CheckRedis.php
Normal file
72
LibreNMS/Validations/Poller/CheckRedis.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* CheckRedis.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Validations\Poller;
|
||||
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use LibreNMS\ValidationResult;
|
||||
|
||||
class CheckRedis implements \LibreNMS\Interfaces\Validation
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
if ($this->redisIsAvailable()) {
|
||||
$driver = config('cache.default');
|
||||
if ($driver != 'redis') {
|
||||
return ValidationResult::warn(trans('validation.validations.poller.CheckRedis.bad_driver', ['driver' => $driver]));
|
||||
}
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckRedis.ok'));
|
||||
}
|
||||
|
||||
if (\LibreNMS\Config::get('distributed_poller') && \App\Models\PollerCluster::isActive()->count() > 2) {
|
||||
return ValidationResult::fail(trans('validation.validations.poller.CheckRedis.unavailable'));
|
||||
}
|
||||
|
||||
return ValidationResult::ok(trans('validation.validations.poller.CheckRedis.unavailable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function enabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function redisIsAvailable(): bool
|
||||
{
|
||||
try {
|
||||
Redis::ping();
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,6 +25,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Poller extends Model
|
||||
@@ -32,4 +33,20 @@ class Poller extends Model
|
||||
public $timestamps = false;
|
||||
protected $primaryKey = 'id';
|
||||
protected $fillable = ['poller_name'];
|
||||
|
||||
// ---- Scopes ----
|
||||
|
||||
public function scopeIsInactive(Builder $query): Builder
|
||||
{
|
||||
$default = (int) \LibreNMS\Config::get('rrd.step');
|
||||
|
||||
return $query->where('last_polled', '<', \DB::raw("DATE_SUB(NOW(),INTERVAL $default SECOND)"));
|
||||
}
|
||||
|
||||
public function scopeIsActive(Builder $query): Builder
|
||||
{
|
||||
$default = (int) \LibreNMS\Config::get('rrd.step');
|
||||
|
||||
return $query->where('last_polled', '>=', \DB::raw("DATE_SUB(NOW(),INTERVAL $default SECOND)"));
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use LibreNMS\Exceptions\InvalidNameException;
|
||||
@@ -41,17 +42,29 @@ class PollerCluster extends Model
|
||||
|
||||
// ---- Accessors/Mutators ----
|
||||
|
||||
public function setPollerGroupsAttribute($groups)
|
||||
/**
|
||||
* @param array|string $groups
|
||||
* @return void
|
||||
*/
|
||||
public function setPollerGroupsAttribute($groups): void
|
||||
{
|
||||
$this->attributes['poller_groups'] = is_array($groups) ? implode(',', $groups) : $groups;
|
||||
}
|
||||
|
||||
// ---- Scopes ----
|
||||
|
||||
public function scopeIsActive($query)
|
||||
public function scopeIsActive(Builder $query): Builder
|
||||
{
|
||||
$default = (int) \LibreNMS\Config::get('service_poller_frequency');
|
||||
$query->where('last_report', '>=', \DB::raw("DATE_SUB(NOW(),INTERVAL COALESCE(`poller_frequency`, $default) SECOND)"));
|
||||
|
||||
return $query->where('last_report', '>=', \DB::raw("DATE_SUB(NOW(),INTERVAL COALESCE(`poller_frequency`, $default) SECOND)"));
|
||||
}
|
||||
|
||||
public function scopeIsInactive(Builder $query): Builder
|
||||
{
|
||||
$default = (int) \LibreNMS\Config::get('service_poller_frequency');
|
||||
|
||||
return $query->where('last_report', '<', \DB::raw("DATE_SUB(NOW(),INTERVAL COALESCE(`poller_frequency`, $default) SECOND)"));
|
||||
}
|
||||
|
||||
// ---- Helpers ----
|
||||
|
@@ -8905,26 +8905,6 @@ parameters:
|
||||
count: 1
|
||||
path: app/Models/Plugin.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\PollerCluster\\:\\:scopeIsActive\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/PollerCluster.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\PollerCluster\\:\\:scopeIsActive\\(\\) has parameter \\$query with no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/PollerCluster.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\PollerCluster\\:\\:setPollerGroupsAttribute\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/PollerCluster.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\PollerCluster\\:\\:setPollerGroupsAttribute\\(\\) has parameter \\$groups with no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/PollerCluster.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\PollerGroup\\:\\:list\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
|
@@ -221,5 +221,52 @@ return [
|
||||
|
||||
],
|
||||
],
|
||||
'distributedpoller' => [
|
||||
'CheckDistributedPollerEnabled' => [
|
||||
'ok' => 'Distributed Polling setting is enabled globally',
|
||||
'not_enabled' => 'You have not enabled distributed_poller',
|
||||
'not_enabled_globally' => 'You have not enabled distributed_poller globally',
|
||||
],
|
||||
'CheckMemcached' => [
|
||||
'not_configured_host' => 'You have not configured distributed_poller_memcached_host',
|
||||
'not_configured_port' => 'You have not configured distributed_poller_memcached_port',
|
||||
'could_not_connect' => 'Could not connect to memcached server',
|
||||
'ok' => 'Connection to memcached is ok',
|
||||
],
|
||||
'CheckRrdcached' => [
|
||||
'fail' => 'You have not enabled rrdcached',
|
||||
],
|
||||
],
|
||||
'poller' => [
|
||||
'CheckActivePoller' => [
|
||||
'fail' => 'No active polling method detected',
|
||||
'both_fail' => 'Both Dispatcher Service and Python Wrapper were active recently, this could cause double polling',
|
||||
'ok' => 'Active pollers found',
|
||||
],
|
||||
'CheckDispatcherService' => [
|
||||
'fail' => 'No active dispatcher nodes found',
|
||||
'ok' => 'Dispatcher Service is enabled',
|
||||
'nodes_down' => 'Some dispatcher nodes have not checked in recently',
|
||||
'not_detected' => 'Dispatcher Service not detected',
|
||||
'warn' => 'Dispatcher Service has been used, but not recently',
|
||||
],
|
||||
'CheckLocking' => [
|
||||
'fail' => 'Locking server issue: :message',
|
||||
'ok' => 'Locks are functional',
|
||||
],
|
||||
'CheckPythonWrapper' => [
|
||||
'fail' => 'No active python wrapper pollers found',
|
||||
'no_pollers' => 'No python wrapper pollers found',
|
||||
'cron_unread' => 'Could not read cron files',
|
||||
'ok' => 'Python poller wrapper is polling',
|
||||
'nodes_down' => 'Some poller nodes have not checked in recently',
|
||||
'not_detected' => 'Python wrapper cron entry is not present',
|
||||
],
|
||||
'CheckRedis' => [
|
||||
'bad_driver' => 'Using :driver for locking, you should set CACHE_DRIVER=redis',
|
||||
'ok' => 'Redis is functional',
|
||||
'unavailable' => 'Redis is unavailable',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
Reference in New Issue
Block a user