mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Allow ping checks to be ran separately from polling (#8821)
Allows ping checks at intervals not tied to the poller. Pointless if you are not alerting on device status. I updated the rrdstep.php script to treat ping-perf files separately and made it so it only converts if needed. Docs here: https://docs.librenms.org/Extensions/Fast-Ping-Check/ DO NOT DELETE THIS TEXT #### Please note > Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting. - [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/) #### Testers If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
This commit is contained in:
committed by
Neil Lathwood
parent
344dfb9797
commit
9bc0c542a5
46
app/Console/Commands/Ping.php
Normal file
46
app/Console/Commands/Ping.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Jobs\PingCheck;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class Ping extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'ping {--d|debug} {groups?* | Optional List of distributed poller groups to poll}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Check if devices are up or down via icmp';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->alert("Do not use this command yet, use ./ping.php");
|
||||||
|
exit();
|
||||||
|
|
||||||
|
PingCheck::dispatch(new PingCheck($this->argument('groups')));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ class Kernel extends ConsoleKernel
|
|||||||
*/
|
*/
|
||||||
protected $commands = [
|
protected $commands = [
|
||||||
Commands\Release::class,
|
Commands\Release::class,
|
||||||
|
Commands\Ping::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
305
app/Jobs/PingCheck.php
Normal file
305
app/Jobs/PingCheck.php
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PingCheck.php
|
||||||
|
*
|
||||||
|
* Device up/down icmp check job
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @package LibreNMS
|
||||||
|
* @link http://librenms.org
|
||||||
|
* @copyright 2018 Tony Murray
|
||||||
|
* @author Tony Murray <murraytony@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Device;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use LibreNMS\Config;
|
||||||
|
use LibreNMS\RRD\RrdDefinition;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class PingCheck implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private $process;
|
||||||
|
private $rrd_tags;
|
||||||
|
|
||||||
|
/** @var \Illuminate\Database\Eloquent\Collection $devices List of devices keyed by hostname */
|
||||||
|
private $devices;
|
||||||
|
/** @var array $groups List of device group ids to check */
|
||||||
|
private $groups = [];
|
||||||
|
|
||||||
|
// working data for loop
|
||||||
|
/** @var Collection $tiered */
|
||||||
|
private $tiered;
|
||||||
|
/** @var Collection $current */
|
||||||
|
private $current;
|
||||||
|
private $current_tier;
|
||||||
|
/** @var Collection $deferred */
|
||||||
|
private $deferred;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @param array $groups List of distributed poller groups to check
|
||||||
|
*/
|
||||||
|
public function __construct($groups = [])
|
||||||
|
{
|
||||||
|
if (is_array($groups)) {
|
||||||
|
$this->groups = $groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
// define rrd tags
|
||||||
|
$rrd_step = Config::get('ping_rrd_step', Config::get('rrd.step', 300));
|
||||||
|
$rrd_def = RrdDefinition::make()->addDataset('ping', 'GAUGE', 0, 65535, $rrd_step * 2);
|
||||||
|
$this->rrd_tags = ['rrd_def' => $rrd_def, 'rrd_step' => $rrd_step];
|
||||||
|
|
||||||
|
// set up fping process
|
||||||
|
$timeout = Config::get('fping_options.timeout', 500); // must be smaller than period
|
||||||
|
$retries = Config::get('fping_options.retries', 2); // how many retries on failure
|
||||||
|
|
||||||
|
$cmd = ['fping', '-f', '-', '-e', '-t', $timeout, '-r', $retries];
|
||||||
|
|
||||||
|
$wait = Config::get('rrd_step', 300) * 2;
|
||||||
|
|
||||||
|
$this->process = new Process($cmd, null, null, null, $wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$ping_start = microtime(true);
|
||||||
|
|
||||||
|
$this->fetchDevices();
|
||||||
|
|
||||||
|
d_echo($this->process->getCommandLine() . PHP_EOL);
|
||||||
|
|
||||||
|
// send hostnames to stdin to avoid overflowing cli length limits
|
||||||
|
$ordered_device_list = $this->tiered->get(1, collect())->keys()// root nodes before standalone nodes
|
||||||
|
->merge($this->devices->keys())
|
||||||
|
->unique()
|
||||||
|
->implode(PHP_EOL);
|
||||||
|
|
||||||
|
$this->process->setInput($ordered_device_list);
|
||||||
|
$this->process->start(); // start as early as possible
|
||||||
|
|
||||||
|
foreach ($this->process as $type => $line) {
|
||||||
|
d_echo($line);
|
||||||
|
|
||||||
|
if (Process::ERR === $type) {
|
||||||
|
// Check for devices we couldn't resolve dns for
|
||||||
|
if (preg_match('/^(?<hostname>[^\s]+): (?:Name or service not known|Temporary failure in name resolution)/', $line, $errored)) {
|
||||||
|
$this->recordData([
|
||||||
|
'hostname' => $errored['hostname'],
|
||||||
|
'status' => 'unreachable'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match(
|
||||||
|
'/^(?<hostname>[^\s]+) is (?<status>alive|unreachable)(?: \((?<rtt>[\d.]+) ms\))?/',
|
||||||
|
$line,
|
||||||
|
$captured
|
||||||
|
)) {
|
||||||
|
$this->recordData($captured);
|
||||||
|
|
||||||
|
$this->processTier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for any left over devices
|
||||||
|
if ($this->deferred->isNotEmpty()) {
|
||||||
|
d_echo("Leftover devices, this shouldn't happen: " . $this->deferred->flatten(1)->implode('hostname', ', ') . PHP_EOL);
|
||||||
|
d_echo("Devices left in tier: " . collect($this->current)->implode('hostname', ', ') . PHP_EOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\App::runningInConsole()) {
|
||||||
|
printf("Pinged %s devices in %.2fs\n", $this->devices->count(), microtime(true) - $ping_start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchDevices()
|
||||||
|
{
|
||||||
|
if (isset($this->devices)) {
|
||||||
|
return $this->devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
global $vdebug;
|
||||||
|
|
||||||
|
/** @var Builder $query */
|
||||||
|
$query = Device::canPing()
|
||||||
|
->select(['devices.device_id', 'hostname', 'status', 'status_reason', 'last_ping', 'last_ping_timetaken', 'max_depth'])
|
||||||
|
->orderBy('max_depth');
|
||||||
|
|
||||||
|
if ($this->groups) {
|
||||||
|
$query->whereIn('poller_group', $this->groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->devices = $query->get()->keyBy('hostname');
|
||||||
|
|
||||||
|
// working collections
|
||||||
|
$this->tiered = $this->devices->groupBy('max_depth', true);
|
||||||
|
$this->deferred = collect();
|
||||||
|
|
||||||
|
// start with tier 1 (the root nodes, 0 is standalone)
|
||||||
|
$this->current_tier = 1;
|
||||||
|
$this->current = $this->tiered->get($this->current_tier, collect());
|
||||||
|
|
||||||
|
if ($vdebug) {
|
||||||
|
$this->tiered->each(function (Collection $tier, $index) {
|
||||||
|
echo "Tier $index (" . $tier->count() . "): ";
|
||||||
|
echo $tier->implode('hostname', ', ');
|
||||||
|
echo PHP_EOL;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this tier is complete and move to the next tier
|
||||||
|
* If we moved to the next tier, check if we can report any of our deferred results
|
||||||
|
*/
|
||||||
|
private function processTier()
|
||||||
|
{
|
||||||
|
global $vdebug;
|
||||||
|
|
||||||
|
if ($this->current->isNotEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->current_tier++; // next tier
|
||||||
|
|
||||||
|
if (!$this->tiered->has($this->current_tier)) {
|
||||||
|
// out of devices
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vdebug) {
|
||||||
|
echo "Out of devices at this tier, moving to tier $this->current_tier\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->current = $this->tiered->get($this->current_tier);
|
||||||
|
|
||||||
|
// update and remove devices in the current tier
|
||||||
|
foreach ($this->deferred->pull($this->current_tier, []) as $data) {
|
||||||
|
$this->recordData($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to process the new tier in case we took care of all the devices
|
||||||
|
$this->processTier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the device is on the current tier, record the data and remove it
|
||||||
|
* $data should have keys: hostname, status, and conditionally rtt
|
||||||
|
*
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
private function recordData($data)
|
||||||
|
{
|
||||||
|
global $vdebug;
|
||||||
|
|
||||||
|
if ($vdebug) {
|
||||||
|
echo "Attempting to record data for {$data['hostname']}... ";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Device $device */
|
||||||
|
$device = $this->devices->get($data['hostname']);
|
||||||
|
|
||||||
|
// process the data if this is a standalone device or in the current tier
|
||||||
|
if ($device->max_depth === 0 || $this->current->has($device->hostname)) {
|
||||||
|
if ($vdebug) {
|
||||||
|
echo "Success\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark up only if snmp is not down too
|
||||||
|
$device->status = ($data['status'] == 'alive' && $device->status_reason != 'snmp');
|
||||||
|
$device->last_ping = Carbon::now();
|
||||||
|
$device->last_ping_timetaken = isset($data['rtt']) ? $data['rtt'] : 0;
|
||||||
|
|
||||||
|
if ($device->isDirty('status')) {
|
||||||
|
// if changed, update reason
|
||||||
|
$device->status_reason = $device->status ? '' : 'icmp';
|
||||||
|
$type = $device->status ? 'up' : 'down';
|
||||||
|
log_event('Device status changed to ' . ucfirst($type) . " from icmp check.", $device->toArray(), $type);
|
||||||
|
|
||||||
|
echo "Device $device->hostname changed status to $type, running alerts\n";
|
||||||
|
RunRules($device->device_id);
|
||||||
|
}
|
||||||
|
$device->save(); // only saves if needed (which is every time because of last_ping)
|
||||||
|
|
||||||
|
// add data to rrd
|
||||||
|
data_update($device->toArray(), 'ping-perf', $this->rrd_tags, ['ping' => $device->last_ping_timetaken]);
|
||||||
|
|
||||||
|
// done with this device
|
||||||
|
$this->complete($device->hostname);
|
||||||
|
d_echo("Recorded data for $device->hostname (tier $device->max_depth)\n");
|
||||||
|
} else {
|
||||||
|
if ($vdebug) {
|
||||||
|
echo "Deferred\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->defer($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Done processing $hostname, remove it from our active data
|
||||||
|
*
|
||||||
|
* @param $hostname
|
||||||
|
*/
|
||||||
|
private function complete($hostname)
|
||||||
|
{
|
||||||
|
$this->current->offsetUnset($hostname);
|
||||||
|
$this->deferred->each->offsetUnset($hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defer this data processing until all parent devices are complete
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
private function defer($data)
|
||||||
|
{
|
||||||
|
$device = $this->devices->get($data['hostname']);
|
||||||
|
|
||||||
|
if ($this->deferred->has($device->max_depth)) {
|
||||||
|
// add this data to the proper tier, unless it already exists...
|
||||||
|
$tier = $this->deferred->get($device->max_depth);
|
||||||
|
if (!$tier->has($device->hostname)) {
|
||||||
|
$tier->put($device->hostname, $data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// create a new tier containing this data
|
||||||
|
$this->deferred->put($device->max_depth, collect([$device->hostname => $data]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,18 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Fico7489\Laravel\Pivot\Traits\PivotEventTrait;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Query\JoinClause;
|
||||||
|
|
||||||
class Device extends BaseModel
|
class Device extends BaseModel
|
||||||
{
|
{
|
||||||
|
use PivotEventTrait;
|
||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
protected $primaryKey = 'device_id';
|
protected $primaryKey = 'device_id';
|
||||||
protected $fillable = ['hostname', 'ip', 'status', 'status_reason'];
|
protected $fillable = ['hostname', 'ip', 'status', 'status_reason'];
|
||||||
|
protected $casts = ['status' => 'boolean'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this class
|
* Initialize this class
|
||||||
@@ -20,6 +27,56 @@ class Device extends BaseModel
|
|||||||
$device->ports()->delete();
|
$device->ports()->delete();
|
||||||
$device->syslogs()->delete();
|
$device->syslogs()->delete();
|
||||||
$device->eventlogs()->delete();
|
$device->eventlogs()->delete();
|
||||||
|
|
||||||
|
// handle device dependency updates
|
||||||
|
$device->children->each->updateMaxDepth($device->device_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// handle device dependency updates
|
||||||
|
static::updated(function (Device $device) {
|
||||||
|
if ($device->isDirty('max_depth')) {
|
||||||
|
$device->children->each->updateMaxDepth();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::pivotAttached(function (Device $device, $relationName, $pivotIds, $pivotIdsAttributes) {
|
||||||
|
if ($relationName == 'parents') {
|
||||||
|
// a parent attached to this device
|
||||||
|
|
||||||
|
// update the parent's max depth incase it used to be standalone
|
||||||
|
Device::whereIn('device_id', $pivotIds)->get()->each->validateStandalone();
|
||||||
|
|
||||||
|
// make sure this device's max depth is updated
|
||||||
|
$device->updateMaxDepth();
|
||||||
|
} elseif ($relationName == 'children') {
|
||||||
|
// a child device attached to this device
|
||||||
|
|
||||||
|
// if this device used to be standalone, we need to udpate max depth
|
||||||
|
$device->validateStandalone();
|
||||||
|
|
||||||
|
// make sure the child's max depth is updated
|
||||||
|
Device::whereIn('device_id', $pivotIds)->get()->each->updateMaxDepth();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::pivotDetached(function (Device $device, $relationName, $pivotIds) {
|
||||||
|
if ($relationName == 'parents') {
|
||||||
|
// this device detached from a parent
|
||||||
|
|
||||||
|
// update this devices max depth
|
||||||
|
$device->updateMaxDepth();
|
||||||
|
|
||||||
|
// parent may now be standalone, update old parent
|
||||||
|
Device::whereIn('device_id', $pivotIds)->get()->each->validateStandalone();
|
||||||
|
} elseif ($relationName == 'children') {
|
||||||
|
// a child device detached from this device
|
||||||
|
|
||||||
|
// update the detached child's max_depth
|
||||||
|
Device::whereIn('device_id', $pivotIds)->get()->each->updateMaxDepth();
|
||||||
|
|
||||||
|
// this device may be standalone, update it
|
||||||
|
$device->validateStandalone();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +104,53 @@ class Device extends BaseModel
|
|||||||
return asset('images/os/generic.svg');
|
return asset('images/os/generic.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the max_depth field based on parents
|
||||||
|
* Performs SQL query, so make sure all parents are saved first
|
||||||
|
*
|
||||||
|
* @param int $exclude exclude a device_id from being considered (used for deleting)
|
||||||
|
*/
|
||||||
|
public function updateMaxDepth($exclude = null)
|
||||||
|
{
|
||||||
|
// optimize for memory instead of time
|
||||||
|
$query = $this->parents()->getQuery();
|
||||||
|
if (!is_null($exclude)) {
|
||||||
|
$query->where('device_id', '!=', $exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $query->count();
|
||||||
|
if ($count === 0) {
|
||||||
|
if ($this->children()->count() === 0) {
|
||||||
|
$this->max_depth = 0; // no children or parents
|
||||||
|
} else {
|
||||||
|
$this->max_depth = 1; // has children
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$parents_max_depth = $query->max('max_depth');
|
||||||
|
$this->max_depth = $parents_max_depth + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device dependency check to see if this node is standalone or not.
|
||||||
|
* Standalone is a special case where the device has no parents or children and is denoted by a max_depth of 0
|
||||||
|
*
|
||||||
|
* Only checks on root nodes (where max_depth is 1 or 0)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function validateStandalone()
|
||||||
|
{
|
||||||
|
if ($this->max_depth === 0 && $this->children()->count() > 0) {
|
||||||
|
$this->max_depth = 1; // has children
|
||||||
|
} elseif ($this->max_depth === 1 && $this->parents()->count() === 0) {
|
||||||
|
$this->max_depth = 0; // no children or parents
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -70,9 +174,9 @@ class Device extends BaseModel
|
|||||||
public function getIconAttribute($icon)
|
public function getIconAttribute($icon)
|
||||||
{
|
{
|
||||||
if (isset($icon)) {
|
if (isset($icon)) {
|
||||||
return asset("images/os/$icon");
|
return "images/os/$icon";
|
||||||
}
|
}
|
||||||
return asset('images/os/generic.svg');
|
return 'images/os/generic.svg';
|
||||||
}
|
}
|
||||||
public function getIpAttribute($ip)
|
public function getIpAttribute($ip)
|
||||||
{
|
{
|
||||||
@@ -88,6 +192,11 @@ class Device extends BaseModel
|
|||||||
$this->attributes['ip'] = inet_pton($ip);
|
$this->attributes['ip'] = inet_pton($ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setStatusAttribute($status)
|
||||||
|
{
|
||||||
|
$this->attributes['status'] = (int)$status;
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Query scopes ----
|
// ---- Query scopes ----
|
||||||
|
|
||||||
public function scopeIsUp($query)
|
public function scopeIsUp($query)
|
||||||
@@ -138,6 +247,19 @@ class Device extends BaseModel
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeCanPing(Builder $query)
|
||||||
|
{
|
||||||
|
return $query->where('disabled', 0)
|
||||||
|
->leftJoin('devices_attribs', function (JoinClause $query) {
|
||||||
|
$query->on('devices.device_id', 'devices_attribs.device_id')
|
||||||
|
->where('devices_attribs.attrib_type', 'override_icmp_disable');
|
||||||
|
})
|
||||||
|
->where(function (Builder $query) {
|
||||||
|
$query->whereNull('devices_attribs.attrib_value')
|
||||||
|
->orWhere('devices_attribs.attrib_value', '!=', 'true');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public function scopeHasAccess($query, User $user)
|
public function scopeHasAccess($query, User $user)
|
||||||
{
|
{
|
||||||
return $this->hasDeviceAccess($query, $user);
|
return $this->hasDeviceAccess($query, $user);
|
||||||
@@ -165,6 +287,11 @@ class Device extends BaseModel
|
|||||||
return $this->hasMany('App\Models\CefSwitching', 'device_id');
|
return $this->hasMany('App\Models\CefSwitching', 'device_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function children()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany('App\Models\Device', 'device_relationships', 'parent_device_id', 'child_device_id');
|
||||||
|
}
|
||||||
|
|
||||||
public function components()
|
public function components()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Models\Component', 'device_id');
|
return $this->hasMany('App\Models\Component', 'device_id');
|
||||||
@@ -190,6 +317,16 @@ class Device extends BaseModel
|
|||||||
return $this->hasMany('App\Models\Package', 'device_id', 'device_id');
|
return $this->hasMany('App\Models\Package', 'device_id', 'device_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function parents()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany('App\Models\Device', 'device_relationships', 'child_device_id', 'parent_device_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function perf()
|
||||||
|
{
|
||||||
|
return $this->hasMany('App\Models\DevicePerf', 'device_id');
|
||||||
|
}
|
||||||
|
|
||||||
public function ports()
|
public function ports()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Models\Port', 'device_id', 'device_id');
|
return $this->hasMany('App\Models\Port', 'device_id', 'device_id');
|
||||||
|
|||||||
65
app/Models/DevicePerf.php
Normal file
65
app/Models/DevicePerf.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* DevicePerf.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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @package LibreNMS
|
||||||
|
* @link http://librenms.org
|
||||||
|
* @copyright 2018 Tony Murray
|
||||||
|
* @author Tony Murray <murraytony@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class DevicePerf extends BaseModel
|
||||||
|
{
|
||||||
|
protected $table = 'device_perf';
|
||||||
|
protected $fillable = ['device_id', 'timestamp', 'xmt', 'rcv', 'loss', 'min', 'max', 'avg'];
|
||||||
|
protected $casts = [
|
||||||
|
'xmt' => 'integer',
|
||||||
|
'rcv' => 'integer',
|
||||||
|
'loss' => 'integer',
|
||||||
|
'min' => 'float',
|
||||||
|
'max' => 'float',
|
||||||
|
'avg' => 'float',
|
||||||
|
];
|
||||||
|
public $timestamps = false;
|
||||||
|
const CREATED_AT = 'timestamp';
|
||||||
|
protected $attributes = [
|
||||||
|
'min' => 0,
|
||||||
|
'max' => 0,
|
||||||
|
'avg' => 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
static::creating(function ($model) {
|
||||||
|
$model->timestamp = $model->freshTimestamp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Define Relationships ----
|
||||||
|
|
||||||
|
public function device()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\Device', 'device_id', 'device_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
"laravel/laravel": "5.4.*",
|
"laravel/laravel": "5.4.*",
|
||||||
"oriceon/toastr-5-laravel": "dev-master",
|
"oriceon/toastr-5-laravel": "dev-master",
|
||||||
"wpb/string-blade-compiler": "3.4.x-dev",
|
"wpb/string-blade-compiler": "3.4.x-dev",
|
||||||
|
"fico7489/laravel-pivot": "*",
|
||||||
|
|
||||||
"vlucas/phpdotenv": "2.4.0",
|
"vlucas/phpdotenv": "2.4.0",
|
||||||
"doctrine/inflector": "1.1.*",
|
"doctrine/inflector": "1.1.*",
|
||||||
|
|||||||
144
composer.lock
generated
144
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d962cf418393daf777aa51f999b40933",
|
"content-hash": "f57760426989ee971f25f10f73d7d661",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "amenadiel/jpgraph",
|
"name": "amenadiel/jpgraph",
|
||||||
@@ -419,6 +419,56 @@
|
|||||||
],
|
],
|
||||||
"time": "2018-02-23T01:58:20+00:00"
|
"time": "2018-02-23T01:58:20+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "fico7489/laravel-pivot",
|
||||||
|
"version": "2.0.6",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/fico7489/laravel-pivot.git",
|
||||||
|
"reference": "f4197fb797b0c544e18ee47d8a9407b2ade0930c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/fico7489/laravel-pivot/zipball/f4197fb797b0c544e18ee47d8a9407b2ade0930c",
|
||||||
|
"reference": "f4197fb797b0c544e18ee47d8a9407b2ade0930c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/database": "5.4.*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"orchestra/testbench": "3.4.*",
|
||||||
|
"phpunit/phpunit": "~5.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Fico7489\\Laravel\\Pivot\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Filip Horvat",
|
||||||
|
"email": "filip.horvat@am2studio.hr",
|
||||||
|
"homepage": "http://am2studio.hr",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "This package introduces new eloquent events for sync(), attach(), detach() or updateExistingPivot() methods on BelongsToMany relation.",
|
||||||
|
"homepage": "https://github.com/fico7489/laravel-pivot",
|
||||||
|
"keywords": [
|
||||||
|
"eloquent events",
|
||||||
|
"eloquent extra events",
|
||||||
|
"laravel BelongsToMany events",
|
||||||
|
"laravel pivot events",
|
||||||
|
"laravel sync events"
|
||||||
|
],
|
||||||
|
"time": "2018-03-08T16:05:59+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
"version": "6.3.3",
|
"version": "6.3.3",
|
||||||
@@ -2080,21 +2130,22 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ramsey/uuid",
|
"name": "ramsey/uuid",
|
||||||
"version": "3.7.3",
|
"version": "3.8.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ramsey/uuid.git",
|
"url": "https://github.com/ramsey/uuid.git",
|
||||||
"reference": "44abcdad877d9a46685a3a4d221e3b2c4b87cb76"
|
"reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/44abcdad877d9a46685a3a4d221e3b2c4b87cb76",
|
"url": "https://api.github.com/repos/ramsey/uuid/zipball/d09ea80159c1929d75b3f9c60504d613aeb4a1e3",
|
||||||
"reference": "44abcdad877d9a46685a3a4d221e3b2c4b87cb76",
|
"reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"paragonie/random_compat": "^1.0|^2.0",
|
"paragonie/random_compat": "^1.0|^2.0|9.99.99",
|
||||||
"php": "^5.4 || ^7.0"
|
"php": "^5.4 || ^7.0",
|
||||||
|
"symfony/polyfill-ctype": "^1.8"
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"rhumsaa/uuid": "self.version"
|
"rhumsaa/uuid": "self.version"
|
||||||
@@ -2102,16 +2153,17 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"codeception/aspect-mock": "^1.0 | ~2.0.0",
|
"codeception/aspect-mock": "^1.0 | ~2.0.0",
|
||||||
"doctrine/annotations": "~1.2.0",
|
"doctrine/annotations": "~1.2.0",
|
||||||
"goaop/framework": "1.0.0-alpha.2 | ^1.0 | ^2.1",
|
"goaop/framework": "1.0.0-alpha.2 | ^1.0 | ~2.1.0",
|
||||||
"ircmaxell/random-lib": "^1.1",
|
"ircmaxell/random-lib": "^1.1",
|
||||||
"jakub-onderka/php-parallel-lint": "^0.9.0",
|
"jakub-onderka/php-parallel-lint": "^0.9.0",
|
||||||
"mockery/mockery": "^0.9.9",
|
"mockery/mockery": "^0.9.9",
|
||||||
"moontoast/math": "^1.1",
|
"moontoast/math": "^1.1",
|
||||||
"php-mock/php-mock-phpunit": "^0.3|^1.1",
|
"php-mock/php-mock-phpunit": "^0.3|^1.1",
|
||||||
"phpunit/phpunit": "^4.7|^5.0",
|
"phpunit/phpunit": "^4.7|^5.0|^6.5",
|
||||||
"squizlabs/php_codesniffer": "^2.3"
|
"squizlabs/php_codesniffer": "^2.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
|
"ext-ctype": "Provides support for PHP Ctype functions",
|
||||||
"ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator",
|
"ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator",
|
||||||
"ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator",
|
"ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator",
|
||||||
"ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
"ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||||
@@ -2156,7 +2208,7 @@
|
|||||||
"identifier",
|
"identifier",
|
||||||
"uuid"
|
"uuid"
|
||||||
],
|
],
|
||||||
"time": "2018-01-20T00:28:24+00:00"
|
"time": "2018-07-19T23:38:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rmccue/requests",
|
"name": "rmccue/requests",
|
||||||
@@ -2310,16 +2362,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00"
|
"reference": "e54f84c50e3b12972e7750edfc5ca84b2284c44e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/1b97071a26d028c9bd4588264e101e14f6e7cd00",
|
"url": "https://api.github.com/repos/symfony/console/zipball/e54f84c50e3b12972e7750edfc5ca84b2284c44e",
|
||||||
"reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00",
|
"reference": "e54f84c50e3b12972e7750edfc5ca84b2284c44e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2375,11 +2427,11 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-05-23T05:02:55+00:00"
|
"time": "2018-07-10T14:02:11+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/css-selector.git",
|
"url": "https://github.com/symfony/css-selector.git",
|
||||||
@@ -2432,16 +2484,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug",
|
"name": "symfony/debug",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/debug.git",
|
"url": "https://github.com/symfony/debug.git",
|
||||||
"reference": "47e6788c5b151cf0cfdf3329116bf33800632d75"
|
"reference": "0e3ca9cbde90fffec8038f4d4e16fd4046bbd018"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/debug/zipball/47e6788c5b151cf0cfdf3329116bf33800632d75",
|
"url": "https://api.github.com/repos/symfony/debug/zipball/0e3ca9cbde90fffec8038f4d4e16fd4046bbd018",
|
||||||
"reference": "47e6788c5b151cf0cfdf3329116bf33800632d75",
|
"reference": "0e3ca9cbde90fffec8038f4d4e16fd4046bbd018",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2484,11 +2536,11 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Debug Component",
|
"description": "Symfony Debug Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-06-25T11:10:40+00:00"
|
"time": "2018-06-26T08:45:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dotenv",
|
"name": "symfony/dotenv",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/dotenv.git",
|
"url": "https://github.com/symfony/dotenv.git",
|
||||||
@@ -2545,7 +2597,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||||
@@ -2608,7 +2660,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
@@ -2657,16 +2709,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-foundation",
|
"name": "symfony/http-foundation",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-foundation.git",
|
"url": "https://github.com/symfony/http-foundation.git",
|
||||||
"reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce"
|
"reference": "2b8e08c085e2dc7449ee6d55a238be87d3727c96"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce",
|
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/2b8e08c085e2dc7449ee6d55a238be87d3727c96",
|
||||||
"reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce",
|
"reference": "2b8e08c085e2dc7449ee6d55a238be87d3727c96",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2707,20 +2759,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpFoundation Component",
|
"description": "Symfony HttpFoundation Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-06-21T11:10:19+00:00"
|
"time": "2018-07-19T07:08:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-kernel",
|
"name": "symfony/http-kernel",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-kernel.git",
|
"url": "https://github.com/symfony/http-kernel.git",
|
||||||
"reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820"
|
"reference": "22a1d000d45f09966a363223548a150aec759e61"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/cb7edcdc47cab3c61c891e6e55337f8dd470d820",
|
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/22a1d000d45f09966a363223548a150aec759e61",
|
||||||
"reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820",
|
"reference": "22a1d000d45f09966a363223548a150aec759e61",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2796,7 +2848,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpKernel Component",
|
"description": "Symfony HttpKernel Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-06-25T12:29:19+00:00"
|
"time": "2018-07-23T16:37:31+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
@@ -2973,16 +3025,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/process.git",
|
"url": "https://github.com/symfony/process.git",
|
||||||
"reference": "acc5a37c706ace827962851b69705b24e71ca17c"
|
"reference": "f741672edfcfe3a2ea77569d419006f23281d909"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/process/zipball/acc5a37c706ace827962851b69705b24e71ca17c",
|
"url": "https://api.github.com/repos/symfony/process/zipball/f741672edfcfe3a2ea77569d419006f23281d909",
|
||||||
"reference": "acc5a37c706ace827962851b69705b24e71ca17c",
|
"reference": "f741672edfcfe3a2ea77569d419006f23281d909",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3018,7 +3070,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Process Component",
|
"description": "Symfony Process Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-05-30T04:24:30+00:00"
|
"time": "2018-07-09T09:01:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/routing",
|
"name": "symfony/routing",
|
||||||
@@ -3161,16 +3213,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
"reference": "e173954a28a44a32c690815fbe4d0f2eac43accb"
|
"reference": "c501f46bb1eaf4c8d65ba070ab65a1986da1cd7f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/e173954a28a44a32c690815fbe4d0f2eac43accb",
|
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/c501f46bb1eaf4c8d65ba070ab65a1986da1cd7f",
|
||||||
"reference": "e173954a28a44a32c690815fbe4d0f2eac43accb",
|
"reference": "c501f46bb1eaf4c8d65ba070ab65a1986da1cd7f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3226,11 +3278,11 @@
|
|||||||
"debug",
|
"debug",
|
||||||
"dump"
|
"dump"
|
||||||
],
|
],
|
||||||
"time": "2018-06-15T07:47:49+00:00"
|
"time": "2018-07-09T08:21:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v2.8.42",
|
"version": "v2.8.43",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
@@ -4969,7 +5021,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/class-loader",
|
"name": "symfony/class-loader",
|
||||||
"version": "v3.4.12",
|
"version": "v3.4.13",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/class-loader.git",
|
"url": "https://github.com/symfony/class-loader.git",
|
||||||
|
|||||||
28
daily.php
28
daily.php
@@ -6,6 +6,8 @@
|
|||||||
* (c) 2013 LibreNMS Contributors
|
* (c) 2013 LibreNMS Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use App\Models\Device;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use LibreNMS\Config;
|
use LibreNMS\Config;
|
||||||
use LibreNMS\Exceptions\LockException;
|
use LibreNMS\Exceptions\LockException;
|
||||||
use LibreNMS\Util\MemcacheLock;
|
use LibreNMS\Util\MemcacheLock;
|
||||||
@@ -294,3 +296,29 @@ if ($options['f'] === 'refresh_os_cache') {
|
|||||||
echo 'Clearing OS cache' . PHP_EOL;
|
echo 'Clearing OS cache' . PHP_EOL;
|
||||||
unlink(Config::get('install_dir') . '/cache/os_defs.cache');
|
unlink(Config::get('install_dir') . '/cache/os_defs.cache');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($options['f'] === 'recalculate_device_dependencies') {
|
||||||
|
// fix broken dependency max_depth calculation in case things weren't done though eloquent
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Config::get('distributed_poller')) {
|
||||||
|
MemcacheLock::lock('recalculate_device_dependencies', 0, 86000);
|
||||||
|
}
|
||||||
|
\LibreNMS\DB\Eloquent::boot();
|
||||||
|
|
||||||
|
// update all root nodes and recurse, chunk so we don't blow up
|
||||||
|
Device::doesntHave('parents')->with('children')->chunk(100, function (Collection $devices) {
|
||||||
|
// anonymous recursive function
|
||||||
|
$recurse = function (Device $device) use (&$recurse) {
|
||||||
|
$device->updateMaxDepth();
|
||||||
|
|
||||||
|
$device->children->each($recurse);
|
||||||
|
};
|
||||||
|
|
||||||
|
$devices->each($recurse);
|
||||||
|
});
|
||||||
|
} catch (LockException $e) {
|
||||||
|
echo $e->getMessage() . PHP_EOL;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
1
daily.sh
1
daily.sh
@@ -255,6 +255,7 @@ main () {
|
|||||||
# Cleanups
|
# Cleanups
|
||||||
local options=("refresh_alert_rules"
|
local options=("refresh_alert_rules"
|
||||||
"refresh_os_cache"
|
"refresh_os_cache"
|
||||||
|
"recalculate_device_dependencies"
|
||||||
"syslog"
|
"syslog"
|
||||||
"eventlog"
|
"eventlog"
|
||||||
"authlog"
|
"authlog"
|
||||||
|
|||||||
64
doc/Extensions/Fast-Ping-Check.md
Normal file
64
doc/Extensions/Fast-Ping-Check.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
source: Extensions/Fast-Ping-Check.md
|
||||||
|
|
||||||
|
## Fast up/down checking
|
||||||
|
|
||||||
|
Normally, LibreNMS sends an ICMP ping to the device before polling to check if it is up or down.
|
||||||
|
This check is tied to the poller frequency, which is normally 5 minutes. This means it may take up to 5 minutes
|
||||||
|
to find out if a device is down.
|
||||||
|
|
||||||
|
Some users may want to know if devices stop responding to ping more quickly than that. LibreNMS offers a ping.php script
|
||||||
|
to run ping checks as quickly as possible without increasing snmp load on your devices by switching to 1 minute polling.
|
||||||
|
|
||||||
|
> **WARNING**: If you do not have an alert rule that alerts on device status, enabling this will be a waste of resources.
|
||||||
|
> You can find one in the [Alert Rules Collection](../Alerting/Rules.md#Alert Rules Collection).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Setting the ping check to 1 minute
|
||||||
|
|
||||||
|
1. Change the ping_rrd_step setting in config.php
|
||||||
|
```php
|
||||||
|
$config['ping_rrd_step'] = 60;
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Update the rrd files to change the step (step is hardcoded at file creation in rrd files)
|
||||||
|
```bash
|
||||||
|
./scripts/rrdstep.php -h all
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Add the following line to /etc/cron.d/librenms.nonroot.cron to allow 1 minute ping checks
|
||||||
|
|
||||||
|
```
|
||||||
|
* * * * * librenms /opt/librenms/ping.php >> /dev/null 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Sub minute ping check
|
||||||
|
|
||||||
|
Cron only has a resolution of one minute, so we have to use a trick to allow sub minute checks.
|
||||||
|
We add two entries, but add a delay before one.
|
||||||
|
|
||||||
|
>Alerts are only run every minute, so you will have to modify them as well. Remove the original alerts.php entry.
|
||||||
|
|
||||||
|
1. Set ping_rrd_step
|
||||||
|
```php
|
||||||
|
$config['ping_rrd_step'] = 30;
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Update the rrd files
|
||||||
|
```bash
|
||||||
|
./scripts/rrdstep.php -h all
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Update cron (removing any other ping.php or alert.php entries)
|
||||||
|
```
|
||||||
|
* * * * * librenms /opt/librenms/ping.php >> /dev/null 2>&1
|
||||||
|
* * * * * librenms sleep 30 && /opt/librenms/ping.php >> /dev/null 2>&1
|
||||||
|
* * * * * librenms sleep 15 && /opt/librenms/alerts.php >> /dev/null 2>&1
|
||||||
|
* * * * * librenms sleep 45 && /opt/librenms/alerts.php >> /dev/null 2>&1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Device dependencies
|
||||||
|
|
||||||
|
The ping.php script respects device dependencies, but the main poller does not (for technical reasons).
|
||||||
|
However, using this script does not disable the icmp check in the poller and a child may be reported as
|
||||||
|
down before the parent.
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use LibreNMS\Authentication\Auth;
|
use LibreNMS\Authentication\Auth;
|
||||||
|
|
||||||
$init_modules = array('web', 'auth', 'alerts', 'alerts-cli');
|
$init_modules = array('web', 'auth', 'alerts', 'eloquent');
|
||||||
require realpath(__DIR__ . '/..') . '/includes/init.php';
|
require realpath(__DIR__ . '/..') . '/includes/init.php';
|
||||||
|
|
||||||
set_debug(isset($_REQUEST['debug']) ? $_REQUEST['debug'] : false);
|
set_debug(isset($_REQUEST['debug']) ? $_REQUEST['debug'] : false);
|
||||||
|
|||||||
@@ -15,39 +15,34 @@
|
|||||||
use LibreNMS\Authentication\Auth;
|
use LibreNMS\Authentication\Auth;
|
||||||
|
|
||||||
if (!Auth::user()->hasGlobalAdmin()) {
|
if (!Auth::user()->hasGlobalAdmin()) {
|
||||||
$status = array('status' => 1, 'message' => 'You need to be admin');
|
$status = ['status' => 1, 'message' => 'You need to be admin'];
|
||||||
} else {
|
} else {
|
||||||
if ($_POST['device_id']) {
|
if ($_POST['device_id']) {
|
||||||
if (!is_numeric($_POST['device_id'])) {
|
if (!is_numeric($_POST['device_id'])) {
|
||||||
$status = array('status' => 1, 'message' => 'Wrong device id!');
|
$status = ['status' => 1, 'message' => 'Wrong device id!'];
|
||||||
} else {
|
} else {
|
||||||
if (dbDelete('device_relationships', '`child_device_id` = ?', array($_POST['device_id']))) {
|
$device = \App\Models\Device::find($_POST['device_id']);
|
||||||
$status = array('status' => 0, 'message' => 'Device dependency has been deleted.');
|
if ($device->parents()->detach()) {
|
||||||
|
$status = ['status' => 0, 'message' => 'Device dependency has been deleted.'];
|
||||||
} else {
|
} else {
|
||||||
$status = array('status' => 1, 'message' => 'Device dependency cannot be deleted.');
|
$status = ['status' => 1, 'message' => 'Device dependency cannot be deleted.'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($_POST['parent_ids']) {
|
} elseif ($_POST['parent_ids']) {
|
||||||
$error = false;
|
$status = ['status' => 0, 'message' => 'Device dependencies has been deleted'];
|
||||||
foreach ($_POST['parent_ids'] as $parent) {
|
foreach ($_POST['parent_ids'] as $parent) {
|
||||||
if (is_numeric($parent) && $parent != 0) {
|
if (is_numeric($parent) && $parent != 0) {
|
||||||
if (!dbDelete('device_relationships', ' `parent_device_id` = ?', array($parent))) {
|
$device = \App\Models\Device::find($_POST['device_id']);
|
||||||
$error = true;
|
if (!$device->children()->detach()) {
|
||||||
$status = array('status' => 1, 'message' => 'Device dependency cannot be deleted.');
|
$status = ['status' => 1, 'message' => 'Device dependency cannot be deleted.'];
|
||||||
}
|
}
|
||||||
} elseif ($parent == 0) {
|
} elseif ($parent == 0) {
|
||||||
$status = array('status' => 1, 'message' => 'No dependency to delete.');
|
$status = ['status' => 1, 'message' => 'No dependency to delete.'];
|
||||||
$error = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$error) {
|
|
||||||
$status = array('status' => 0, 'message' => 'Device dependencies has been deleted');
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
echo _json_encode($status);
|
echo json_encode($status);
|
||||||
|
|||||||
@@ -15,46 +15,35 @@
|
|||||||
use LibreNMS\Authentication\Auth;
|
use LibreNMS\Authentication\Auth;
|
||||||
|
|
||||||
if (!Auth::user()->hasGlobalAdmin()) {
|
if (!Auth::user()->hasGlobalAdmin()) {
|
||||||
$status = array('status' => 1, 'message' => 'You need to be admin');
|
$status = ['status' => 1, 'message' => 'You need to be admin'];
|
||||||
} else {
|
} else {
|
||||||
foreach ($_POST['parent_ids'] as $parent) {
|
$parent_ids = (array)$_POST['parent_ids'];
|
||||||
|
$device_ids = (array)$_POST['device_ids'];
|
||||||
|
|
||||||
|
foreach ($parent_ids as $parent) {
|
||||||
if (!is_numeric($parent)) {
|
if (!is_numeric($parent)) {
|
||||||
$status = array('status' => 1, 'message' => 'Parent ID must be an integer!');
|
$status = ['status' => 1, 'message' => 'Parent ID must be an integer!'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($_POST['parent_ids']) > 1 && in_array('0', $_POST['parent_ids'])) {
|
if (count($parent_ids) > 1 && in_array('0', $parent_ids)) {
|
||||||
$status = array('status' => 1, 'message' => 'Multiple parents cannot contain None-Parent!');
|
$status = ['status' => 1, 'message' => 'Multiple parents cannot contain None-Parent!'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// A bit of an effort to reuse this code with dependency editing and the dependency wizard (editing multiple hosts at the same time)
|
foreach ($device_ids as $device_id) {
|
||||||
$device_arr = array();
|
if (!is_numeric($device_id)) {
|
||||||
foreach ($_POST['device_ids'] as $dev) {
|
$status = ['status' => 1, 'message' => 'Device ID must be an integer!'];
|
||||||
if (!is_numeric($dev)) {
|
|
||||||
$status = array('status' => 1, 'message' => 'Device ID must be an integer!');
|
|
||||||
break;
|
break;
|
||||||
} elseif (in_array($dev, $_POST['parent_ids'])) {
|
} elseif (in_array($device_id, $parent_ids)) {
|
||||||
$status = array('status' => 1, 'message' => 'A device cannot depend itself');
|
$status = ['status' => 1, 'message' => 'A device cannot depend itself'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$insert = array();
|
|
||||||
foreach ($_POST['parent_ids'] as $parent) {
|
\App\Models\Device::find($device_id)->parents()->sync($parent_ids);
|
||||||
if (is_numeric($parent) && $parent != 0) {
|
|
||||||
$insert[] = array('parent_device_id' => $parent, 'child_device_id' => $dev);
|
|
||||||
} elseif ($parent == 0) {
|
|
||||||
// In case we receive a mixed array with $parent = 0 (which shouldn't happen)
|
|
||||||
// Empty the insert array so we remove any previous dependency so 'None' takes precedence
|
|
||||||
$insert = array();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbDelete('device_relationships', '`child_device_id` = ?', array($dev));
|
|
||||||
if (!empty($insert)) {
|
|
||||||
dbBulkInsert($insert, 'device_relationships');
|
|
||||||
}
|
|
||||||
$status = array('status' => 0, 'message' => 'Device dependencies have been saved');
|
$status = array('status' => 0, 'message' => 'Device dependencies have been saved');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
echo _json_encode($status);
|
echo json_encode($status);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Device;
|
||||||
use LibreNMS\Authentication\Auth;
|
use LibreNMS\Authentication\Auth;
|
||||||
|
|
||||||
if ($_POST['editing']) {
|
if ($_POST['editing']) {
|
||||||
@@ -7,13 +8,9 @@ if ($_POST['editing']) {
|
|||||||
$updated = 0;
|
$updated = 0;
|
||||||
|
|
||||||
if (isset($_POST['parent_id'])) {
|
if (isset($_POST['parent_id'])) {
|
||||||
$parent_id = array_diff((array)$_POST['parent_id'], ['0']);
|
$parents = array_diff((array)$_POST['parent_id'], ['0']);
|
||||||
$res = dbDelete('device_relationships', '`child_device_id` = ?', array($device['device_id']));
|
// TODO avoid loops!
|
||||||
if (!in_array('0', $pr)) {
|
Device::find($device['device_id'])->parents()->sync($parents);
|
||||||
foreach ($parent_id as $pr) {
|
|
||||||
dbInsert(array('parent_device_id' => $pr, 'child_device_id' => $device['device_id']), 'device_relationships');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$override_sysLocation_bool = mres($_POST['override_sysLocation']);
|
$override_sysLocation_bool = mres($_POST['override_sysLocation']);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use LibreNMS\Exceptions\LockException;
|
|||||||
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
||||||
use LibreNMS\Util\IP;
|
use LibreNMS\Util\IP;
|
||||||
use LibreNMS\Util\MemcacheLock;
|
use LibreNMS\Util\MemcacheLock;
|
||||||
|
use Monolog\Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set debugging output
|
* Set debugging output
|
||||||
|
|||||||
@@ -472,6 +472,7 @@ devices:
|
|||||||
- { Field: override_sysLocation, Type: tinyint(1), 'Null': true, Extra: '', Default: '0' }
|
- { Field: override_sysLocation, Type: tinyint(1), 'Null': true, Extra: '', Default: '0' }
|
||||||
- { Field: notes, Type: text, 'Null': true, Extra: '' }
|
- { Field: notes, Type: text, 'Null': true, Extra: '' }
|
||||||
- { Field: port_association_mode, Type: int(11), 'Null': false, Extra: '', Default: '1' }
|
- { Field: port_association_mode, Type: int(11), 'Null': false, Extra: '', Default: '1' }
|
||||||
|
- { Field: max_depth, Type: int(11), 'Null': false, Extra: '', Default: '0' }
|
||||||
Indexes:
|
Indexes:
|
||||||
PRIMARY: { Name: PRIMARY, Columns: [device_id], Unique: true, Type: BTREE }
|
PRIMARY: { Name: PRIMARY, Columns: [device_id], Unique: true, Type: BTREE }
|
||||||
status: { Name: status, Columns: [status], Unique: false, Type: BTREE }
|
status: { Name: status, Columns: [status], Unique: false, Type: BTREE }
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ pages:
|
|||||||
- Extensions/Dashboards.md
|
- Extensions/Dashboards.md
|
||||||
- 5. Advanced Setup:
|
- 5. Advanced Setup:
|
||||||
- Support/1-Minute-Polling.md
|
- Support/1-Minute-Polling.md
|
||||||
|
- Fast Ping Checking: Extensions/Fast-Ping-Check.md
|
||||||
- Configuration docs: Support/Configuration.md
|
- Configuration docs: Support/Configuration.md
|
||||||
- Authentication Options: Extensions/Authentication.md
|
- Authentication Options: Extensions/Authentication.md
|
||||||
- Two-Factor Auth: Extensions/Two-Factor-Auth.md
|
- Two-Factor Auth: Extensions/Two-Factor-Auth.md
|
||||||
|
|||||||
45
ping.php
Executable file
45
ping.php
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Jobs\PingCheck;
|
||||||
|
|
||||||
|
$init_modules = ['alerts', 'laravel', 'nodb'];
|
||||||
|
require __DIR__ . '/includes/init.php';
|
||||||
|
|
||||||
|
$options = getopt('hdvg:');
|
||||||
|
|
||||||
|
if (isset($options['h'])) {
|
||||||
|
echo <<<'END'
|
||||||
|
ping.php: Usage ping.php [-d] [-v] [-g group(s)]
|
||||||
|
-d enable debug output
|
||||||
|
-v enable verbose debug output
|
||||||
|
-g only ping devices for this poller group, may be comma separated list
|
||||||
|
|
||||||
|
END;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_debug(isset($options['d']));
|
||||||
|
|
||||||
|
if (isset($options['v'])) {
|
||||||
|
global $vdebug;
|
||||||
|
$vdebug = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($options['g'])) {
|
||||||
|
$groups = explode(',', $options['g']);
|
||||||
|
} else {
|
||||||
|
$groups = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($config['noinfluxdb'] !== true && $config['influxdb']['enable'] === true) {
|
||||||
|
$influxdb = influxdb_connect();
|
||||||
|
} else {
|
||||||
|
$influxdb = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rrdtool_initialize();
|
||||||
|
|
||||||
|
PingCheck::dispatch(new PingCheck($groups));
|
||||||
|
|
||||||
|
rrdtool_close();
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
* @author Neil Lathwood <neil@lathwood.co.uk>
|
* @author Neil Lathwood <neil@lathwood.co.uk>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use LibreNMS\Config;
|
||||||
|
|
||||||
$init_modules = array();
|
$init_modules = array();
|
||||||
require realpath(__DIR__ . '/..') . '/includes/init.php';
|
require realpath(__DIR__ . '/..') . '/includes/init.php';
|
||||||
|
|
||||||
@@ -49,26 +51,42 @@ if (empty($hostname)) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$step = $config['rrd']['step'];
|
$system_step = Config::get('rrd.step', 300);
|
||||||
$heartbeat = $config['rrd']['heartbeat'];
|
$icmp_step = Config::get('ping_rrd_step', $step);
|
||||||
$rrdtool = $config['rrdtool'];
|
$system_heartbeat = Config::get('rrd.heartbeat', $step * 2);
|
||||||
$tmp_path = $config['temp_dir'];
|
$rrdtool = Config::get('rrdtool', 'rrdtool');
|
||||||
|
$tmp_path = Config::get('temp_dir', '/tmp');
|
||||||
|
|
||||||
if ($hostname === 'all') {
|
if ($hostname === 'all') {
|
||||||
$hostname = '*';
|
$hostname = '*';
|
||||||
}
|
}
|
||||||
$files = glob(get_rrd_dir($hostname) . '/*.rrd');
|
$files = glob(get_rrd_dir($hostname) . '/*.rrd');
|
||||||
|
|
||||||
$run = readline("Are you sure you want to run this command [N/y]: ");
|
$converted = 0;
|
||||||
if (!($run == 'y' || $run == 'Y')) {
|
$skipped = 0;
|
||||||
echo "Exiting....." . PHP_EOL;
|
$failed = 0;
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$random = $tmp_path.'/'.mt_rand() . '.xml';
|
$random = $tmp_path.'/'.mt_rand() . '.xml';
|
||||||
$tmp = explode('/', $file);
|
$rrd_file = basename($file, '.rrd');
|
||||||
$rrd_file = array_pop($tmp);
|
|
||||||
|
if ($rrd_file == 'ping-perf') {
|
||||||
|
$step = $icmp_step;
|
||||||
|
$heartbeat = $icmp_step * 2;
|
||||||
|
} else {
|
||||||
|
$step = $system_step;
|
||||||
|
$heartbeat = $system_heartbeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rrd_info = shell_exec("$rrdtool info $file");
|
||||||
|
preg_match('/step = (\d+)/', $rrd_info, $matches);
|
||||||
|
|
||||||
|
if ($matches[1] == $step) {
|
||||||
|
d_echo("Skipping $file, step is already $step.\n");
|
||||||
|
$skipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
echo "Converting $file: ";
|
echo "Converting $file: ";
|
||||||
$command = "$rrdtool dump $file > $random &&
|
$command = "$rrdtool dump $file > $random &&
|
||||||
sed -i 's/<step>\([0-9]*\)/<step>$step/' $random &&
|
sed -i 's/<step>\([0-9]*\)/<step>$step/' $random &&
|
||||||
@@ -78,7 +96,11 @@ foreach ($files as $file) {
|
|||||||
exec($command, $output, $code);
|
exec($command, $output, $code);
|
||||||
if ($code === 0) {
|
if ($code === 0) {
|
||||||
echo "[OK]\n";
|
echo "[OK]\n";
|
||||||
|
$converted++;
|
||||||
} else {
|
} else {
|
||||||
echo "\033[FAIL]\n";
|
echo "\033[FAIL]\n";
|
||||||
|
$failed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo "Converted: $converted Failed: $failed Skipped: $skipped\n";
|
||||||
|
|||||||
1
sql-schema/257.sql
Normal file
1
sql-schema/257.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE devices ADD max_depth int DEFAULT 0 NOT NULL;
|
||||||
Reference in New Issue
Block a user