mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Rewrite ISIS Adjacency discovery/polling (#13155)
* Rewrite ISIS Adjacency discovery/polling hopefully much faster now, do most work in discovery and just check up/down in poller. * unused variable * Implement option for OS override * fix an incorrect typehint * test data * work around stupid migration name * update schema * better handling for the on-demand discovery * more detailed phpdoc * fix when adjacency is not found * don't clear out data when adjacency goes away * Adjust nullable fields * fixes * fix class name * correct migration * fix bug causing adjacency data to always be blank * port popups for port links * isisISAdjState does not need to be nullable * remove extra space * default off * If port is missing return $text * update schema * Cleanup old components * correc copy paste error
This commit is contained in:
@@ -24,18 +24,20 @@
|
||||
|
||||
namespace LibreNMS\DB;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
trait SyncsModels
|
||||
{
|
||||
/**
|
||||
* Sync several models for a device's relationship
|
||||
* Model must implement \LibreNMS\Interfaces\Models\Keyable interface
|
||||
*
|
||||
* @param \App\Models\Device $device
|
||||
* @param string $relationship
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @param \App\Models\Device $device
|
||||
* @param string $relationship
|
||||
* @param \Illuminate\Support\Collection $models \LibreNMS\Interfaces\Models\Keyable
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function syncModels($device, $relationship, $models)
|
||||
protected function syncModels($device, $relationship, $models): Collection
|
||||
{
|
||||
$models = $models->keyBy->getCompositeKey();
|
||||
$existing = $device->$relationship->keyBy->getCompositeKey();
|
||||
@@ -56,4 +58,26 @@ trait SyncsModels
|
||||
|
||||
return $existing->merge($new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine a list of existing and potentially new models
|
||||
* If the model exists fill any new data from the new models
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $existing \LibreNMS\Interfaces\Models\Keyable
|
||||
* @param \Illuminate\Support\Collection $discovered \LibreNMS\Interfaces\Models\Keyable
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function fillNew(Collection $existing, Collection $discovered): Collection
|
||||
{
|
||||
$all = $existing->keyBy->getCompositeKey();
|
||||
foreach ($discovered as $new) {
|
||||
if ($found = $all->get($new->getCompositeKey())) {
|
||||
$found->fill($new->getAttributes());
|
||||
} else {
|
||||
$all->put($new->getCompositeKey(), $new);
|
||||
}
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
}
|
||||
|
37
LibreNMS/Interfaces/Discovery/IsIsDiscovery.php
Normal file
37
LibreNMS/Interfaces/Discovery/IsIsDiscovery.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/*
|
||||
* IsIsDiscovery.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 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Interfaces\Discovery;
|
||||
|
||||
interface IsIsDiscovery
|
||||
{
|
||||
/**
|
||||
* Discover a Collection of IsIsAdjacency models.
|
||||
* Will be keyed by ifIndex
|
||||
*
|
||||
* @return \Illuminate\Support\Collection \App\Models\IsIsAdjacency
|
||||
*/
|
||||
public function discoverIsIs();
|
||||
}
|
35
LibreNMS/Interfaces/Polling/IsIsPolling.php
Normal file
35
LibreNMS/Interfaces/Polling/IsIsPolling.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* IsIsPolling.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 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Interfaces\Polling;
|
||||
|
||||
interface IsIsPolling
|
||||
{
|
||||
/**
|
||||
* @param \Illuminate\Support\Collection $adjacencies \App\Models\IsIsAdjacency
|
||||
* @return \Illuminate\Support\Collection \App\Models\IsIsAdjacency
|
||||
*/
|
||||
public function pollIsIs($adjacencies);
|
||||
}
|
@@ -24,60 +24,43 @@
|
||||
|
||||
namespace LibreNMS\Modules;
|
||||
|
||||
use App\Models\Device;
|
||||
use App\Models\IsisAdjacency;
|
||||
use App\Observers\ModuleModelObserver;
|
||||
use Illuminate\Support\Arr;
|
||||
use LibreNMS\Component;
|
||||
use Illuminate\Support\Collection;
|
||||
use LibreNMS\DB\SyncsModels;
|
||||
use LibreNMS\Interfaces\Discovery\IsIsDiscovery;
|
||||
use LibreNMS\Interfaces\Module;
|
||||
use LibreNMS\Interfaces\Polling\IsIsPolling;
|
||||
use LibreNMS\OS;
|
||||
use LibreNMS\OS\Junos;
|
||||
use LibreNMS\Util\IP;
|
||||
|
||||
class Isis implements Module
|
||||
{
|
||||
use SyncsModels;
|
||||
|
||||
protected $isis_codes = [
|
||||
'l1IntermediateSystem' => 'L1',
|
||||
'l2IntermediateSystem' => 'L2',
|
||||
'l1L2IntermediateSystem' => 'L1L2',
|
||||
'unknown' => 'unknown',
|
||||
];
|
||||
|
||||
/**
|
||||
* Discover this module. Heavier processes can be run here
|
||||
* Run infrequently (default 4 times a day)
|
||||
*
|
||||
* @param OS $os
|
||||
* @param OS $os
|
||||
*/
|
||||
public function discover(OS $os)
|
||||
{
|
||||
$device_array = $os->getDeviceArray();
|
||||
$device_id = $os->getDeviceId();
|
||||
$options = [
|
||||
'filter' => [
|
||||
'device_id' => ['=', $device_id],
|
||||
'type' => ['=', 'ISIS'],
|
||||
],
|
||||
];
|
||||
$adjacencies = $os instanceof IsIsDiscovery
|
||||
? $os->discoverIsIs()
|
||||
: $this->discoverIsIsMib($os);
|
||||
|
||||
$component = new Component();
|
||||
$components = $component->getComponents($device_id, $options);
|
||||
|
||||
// Check if the device has any ISIS enabled interfaces
|
||||
$circuits_poll = snmpwalk_group($device_array, 'ISIS-MIB::isisCirc', 'ISIS-MIB');
|
||||
|
||||
// No ISIS enabled interfaces -> delete the component
|
||||
if (empty($circuits_poll)) {
|
||||
if (isset($components[$device_id])) {
|
||||
foreach ($components[$device_id] as $component_id => $_unused) {
|
||||
$component->deleteComponent($component_id);
|
||||
}
|
||||
echo "\nISIS components deleted";
|
||||
}
|
||||
|
||||
// ISIS enabled interfaces found -> create the component
|
||||
} else {
|
||||
if (isset($components[$device_id])) {
|
||||
$isis_component = $components[$device_id];
|
||||
} else {
|
||||
$isis_component = $component->createComponent($device_id, 'ISIS');
|
||||
}
|
||||
|
||||
$component->setComponentPrefs($device_id, $isis_component);
|
||||
echo "\nISIS component updated";
|
||||
}
|
||||
ModuleModelObserver::observe('\App\Models\IsisAdjacency');
|
||||
$this->syncModels($os->getDevice(), 'isisAdjacencies', $adjacencies);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,132 +68,111 @@ class Isis implements Module
|
||||
* Try to keep this efficient and only run if discovery has indicated there is a reason to run.
|
||||
* Run frequently (default every 5 minutes)
|
||||
*
|
||||
* @param OS $os
|
||||
* @param OS $os
|
||||
*/
|
||||
public function poll(OS $os)
|
||||
{
|
||||
// Translate system state codes into meaningful strings
|
||||
$isis_codes = ['1' => 'L1',
|
||||
'2' => 'L2',
|
||||
'3' => 'L1L2',
|
||||
'4' => 'unknown',
|
||||
];
|
||||
$adjacencies = $os->getDevice()->isisAdjacencies;
|
||||
|
||||
// Get device objects
|
||||
$device_array = $os->getDeviceArray();
|
||||
$device = $os->getDevice();
|
||||
$device_id = $os->getDeviceId();
|
||||
|
||||
// Check if device has any ISIS enabled circuits previously discovered
|
||||
$options = [
|
||||
'filter' => [
|
||||
'device_id' => ['=', $device_id],
|
||||
'type' => ['=', 'ISIS'],
|
||||
],
|
||||
];
|
||||
|
||||
$component = new Component();
|
||||
$components = $component->getComponents($device_id, $options);
|
||||
|
||||
if (! empty($components)) {
|
||||
|
||||
// Poll all ISIS enabled interfaces from the device
|
||||
$circuits_poll = snmpwalk_group($device_array, 'ISIS-MIB::isisCirc', 'ISIS-MIB');
|
||||
|
||||
// Poll all available adjacencies
|
||||
$adjacencies_poll = snmpwalk_group($device_array, 'ISIS-MIB::isisISAdj', 'ISIS-MIB');
|
||||
$adjacencies = collect();
|
||||
$isis_data = [];
|
||||
|
||||
if ($os instanceof Junos) {
|
||||
// Do not poll loopback interface
|
||||
unset($circuits_poll['16']);
|
||||
}
|
||||
|
||||
// Loop through all configured adjacencies on the device
|
||||
foreach ($circuits_poll as $circuit => $circuit_data) {
|
||||
if (is_numeric($circuit)) {
|
||||
echo "\nAdjacency found on ifIndex: " . $circuit;
|
||||
$port_id = (int) $device->ports()->where('ifIndex', $circuit)->value('port_id');
|
||||
|
||||
if ($circuit_data['isisCircPassiveCircuit'] != '1') {
|
||||
// Adjacency is UP
|
||||
if (! empty($adjacencies_poll[$circuit]) && Arr::last($adjacencies_poll[$circuit]['isisISAdjState']) == '3') {
|
||||
$isis_data['isisISAdjState'] = Arr::last($adjacencies_poll[$circuit]['isisISAdjState']);
|
||||
$isis_data['isisISAdjNeighSysID'] = Arr::last($adjacencies_poll[$circuit]['isisISAdjNeighSysID']);
|
||||
$isis_data['isisISAdjNeighSysType'] = Arr::last($adjacencies_poll[$circuit]['isisISAdjNeighSysType']);
|
||||
$isis_data['isisISAdjNeighPriority'] = Arr::last($adjacencies_poll[$circuit]['isisISAdjNeighPriority']);
|
||||
$isis_data['isisISAdjLastUpTime'] = Arr::last($adjacencies_poll[$circuit]['isisISAdjLastUpTime']);
|
||||
$isis_data['isisISAdjAreaAddress'] = Arr::last(Arr::last($adjacencies_poll[$circuit]['isisISAdjAreaAddress']));
|
||||
$isis_data['isisISAdjIPAddrType'] = Arr::last(Arr::last($adjacencies_poll[$circuit]['isisISAdjIPAddrType']));
|
||||
$isis_data['isisISAdjIPAddrAddress'] = Arr::last(Arr::last($adjacencies_poll[$circuit]['isisISAdjIPAddrAddress']));
|
||||
|
||||
// Format data
|
||||
$isis_data['isisISAdjNeighSysID'] = str_replace(' ', '.', $isis_data['isisISAdjNeighSysID']);
|
||||
$isis_data['isisISAdjLastUpTime'] = (int) $isis_data['isisISAdjLastUpTime'] / 100;
|
||||
$isis_data['isisISAdjAreaAddress'] = str_replace(' ', '.', $isis_data['isisISAdjAreaAddress']);
|
||||
|
||||
// Save data into the DB
|
||||
$adjacency = IsisAdjacency::updateOrCreate([
|
||||
'device_id' => $device_id,
|
||||
'ifIndex' => $circuit,
|
||||
], [
|
||||
'device_id' => $device_id,
|
||||
'ifIndex' => $circuit,
|
||||
'port_id' => $port_id,
|
||||
'isisISAdjState' => 'up',
|
||||
'isisISAdjNeighSysType' => $isis_codes[$isis_data['isisISAdjNeighSysType']],
|
||||
'isisISAdjNeighSysID' => $isis_data['isisISAdjNeighSysID'],
|
||||
'isisISAdjNeighPriority' => $isis_data['isisISAdjNeighPriority'],
|
||||
'isisISAdjLastUpTime' => $isis_data['isisISAdjLastUpTime'],
|
||||
'isisISAdjAreaAddress' => $isis_data['isisISAdjAreaAddress'],
|
||||
'isisISAdjIPAddrType' => $isis_data['isisISAdjIPAddrType'],
|
||||
'isisISAdjIPAddrAddress' => IP::fromHexstring($isis_data['isisISAdjIPAddrAddress']),
|
||||
]);
|
||||
} else {
|
||||
/*
|
||||
* Adjacency is configured on the device but not available
|
||||
* Update existing record to down state
|
||||
* Set the status of the adjacency to down
|
||||
* Also if the adjacency was never up, create a record
|
||||
*/
|
||||
if ($circuit_data['isisCircAdminState'] != '1') {
|
||||
$state = 'disabled';
|
||||
} else {
|
||||
$state = 'down';
|
||||
}
|
||||
$adjacency = IsisAdjacency::updateOrCreate([
|
||||
'device_id' => $device_id,
|
||||
'ifIndex' => $circuit,
|
||||
], [
|
||||
'device_id' => $device_id,
|
||||
'ifIndex' => $circuit,
|
||||
'port_id' => $port_id,
|
||||
'isisISAdjState' => $state,
|
||||
]);
|
||||
}
|
||||
$adjacencies->push($adjacency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "\nFound " . $adjacencies->count() . ' configured adjacencies';
|
||||
|
||||
// Cleanup
|
||||
IsisAdjacency::query()
|
||||
->where(['device_id' => $device['device_id']])
|
||||
->whereNotIn('ifIndex', $adjacencies->pluck('ifIndex'))->delete();
|
||||
if (empty($adjacencies)) {
|
||||
return; // no data to poll
|
||||
}
|
||||
|
||||
$updated = $os instanceof IsIsPolling
|
||||
? $os->pollIsIs($adjacencies)
|
||||
: $this->pollIsIsMib($adjacencies, $os);
|
||||
|
||||
$updated->each->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all DB data for this module.
|
||||
* This will be run when the module is disabled.
|
||||
*
|
||||
* @param OS $os
|
||||
* @param OS $os
|
||||
*/
|
||||
public function cleanup(OS $os)
|
||||
{
|
||||
$os->getDevice()->isisAdjacencies()->delete();
|
||||
|
||||
// clean up legacy components from old code
|
||||
$os->getDevice()->components()->where('type', 'ISIS')->delete();
|
||||
}
|
||||
|
||||
public function discoverIsIsMib(OS $os): Collection
|
||||
{
|
||||
// Check if the device has any ISIS enabled interfaces
|
||||
$circuits = snmpwalk_cache_oid($os->getDeviceArray(), 'ISIS-MIB::isisCirc', []);
|
||||
$adjacencies = new Collection;
|
||||
|
||||
if (! empty($circuits)) {
|
||||
$adjacencies_data = snmpwalk_cache_twopart_oid($os->getDeviceArray(), 'ISIS-MIB::isisISAdj', [], null, null, '-OQUstx');
|
||||
$ifIndex_port_id_map = $os->getDevice()->ports()->pluck('port_id', 'ifIndex');
|
||||
|
||||
// No ISIS enabled interfaces -> delete the component
|
||||
foreach ($circuits as $circuit_id => $circuit_data) {
|
||||
if (! isset($circuit_data['isisCircIfIndex'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($os instanceof Junos && $circuit_id == 16) {
|
||||
continue; // Do not poll loopback interface
|
||||
}
|
||||
|
||||
$adjacency_data = Arr::last($adjacencies_data[$circuit_id] ?? [[]]);
|
||||
|
||||
$attributes = [
|
||||
'device_id' => $os->getDeviceId(),
|
||||
'ifIndex' => $circuit_data['isisCircIfIndex'],
|
||||
'port_id' => $ifIndex_port_id_map[$circuit_data['isisCircIfIndex']] ?? null,
|
||||
'isisCircAdminState' => $circuit_data['isisCircAdminState'] ?? 'down',
|
||||
'isisISAdjState' => $adjacency_data['isisISAdjState'] ?? 'down',
|
||||
];
|
||||
|
||||
if (! empty($adjacency_data)) {
|
||||
$attributes = array_merge($attributes, [
|
||||
'isisISAdjNeighSysType' => Arr::get($this->isis_codes, $adjacency_data['isisISAdjNeighSysType'] ?? 'unknown', 'unknown'),
|
||||
'isisISAdjNeighSysID' => str_replace(' ', '.', trim($adjacency_data['isisISAdjNeighSysID'] ?? '')),
|
||||
'isisISAdjNeighPriority' => $adjacency_data['isisISAdjNeighPriority'] ?? '',
|
||||
'isisISAdjLastUpTime' => $this->parseAdjacencyTime($adjacency_data),
|
||||
'isisISAdjAreaAddress' => str_replace(' ', '.', trim($adjacency_data['isisISAdjAreaAddress'] ?? '')),
|
||||
'isisISAdjIPAddrType' => $adjacency_data['isisISAdjIPAddrType'] ?? '',
|
||||
'isisISAdjIPAddrAddress' => (string) IP::fromHexstring($adjacency_data['isisISAdjIPAddrAddress'] ?? null, true),
|
||||
]);
|
||||
}
|
||||
|
||||
$adjacencies->push(new IsisAdjacency($attributes));
|
||||
}
|
||||
}
|
||||
|
||||
return $adjacencies;
|
||||
}
|
||||
|
||||
public function pollIsIsMib(Collection $adjacencies, OS $os): Collection
|
||||
{
|
||||
$data = snmpwalk_cache_twopart_oid($os->getDeviceArray(), 'isisISAdjState', [], 'ISIS-MIB');
|
||||
|
||||
if (count($data) !== $adjacencies->where('isisISAdjState', 'up')->count()) {
|
||||
echo 'New Adjacencies, running discovery';
|
||||
// don't enable, might be a bad heuristic
|
||||
return $this->fillNew($adjacencies, $this->discoverIsIsMib($os));
|
||||
}
|
||||
|
||||
$data = snmpwalk_cache_twopart_oid($os->getDeviceArray(), 'isisISAdjLastUpTime', $data, 'ISIS-MIB', null, '-OQUst');
|
||||
|
||||
$adjacencies->each(function (IsisAdjacency $adjacency) use (&$data) {
|
||||
$adjacency_data = Arr::last($data[$adjacency->ifIndex]);
|
||||
$adjacency->isisISAdjState = $adjacency_data['isisISAdjState'] ?? $adjacency->isisISAdjState;
|
||||
$adjacency->isisISAdjLastUpTime = $this->parseAdjacencyTime($adjacency_data);
|
||||
$adjacency->save();
|
||||
unset($data[$adjacency->ifIndex]);
|
||||
});
|
||||
|
||||
return $adjacencies;
|
||||
}
|
||||
|
||||
protected function parseAdjacencyTime($data): int
|
||||
{
|
||||
return (int) max($data['isisISAdjLastUpTime'] ?? 1, 1) / 100;
|
||||
}
|
||||
}
|
||||
|
@@ -56,13 +56,14 @@ class ModuleTestHelper
|
||||
private $exclude_from_all = ['arp-table', 'fdb-table'];
|
||||
private static $module_deps = [
|
||||
'arp-table' => ['ports', 'arp-table'],
|
||||
'cisco-mac-accounting' => ['ports', 'cisco-mac-accounting'],
|
||||
'fdb-table' => ['ports', 'vlans', 'fdb-table'],
|
||||
'vlans' => ['ports', 'vlans'],
|
||||
'vrf' => ['ports', 'vrf'],
|
||||
'isis' => ['ports', 'isis'],
|
||||
'mpls' => ['ports', 'vrf', 'mpls'],
|
||||
'nac' => ['ports', 'nac'],
|
||||
'ospf' => ['ports', 'ospf'],
|
||||
'cisco-mac-accounting' => ['ports', 'cisco-mac-accounting'],
|
||||
'vlans' => ['ports', 'vlans'],
|
||||
'vrf' => ['ports', 'vrf'],
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -129,6 +129,10 @@ class Url
|
||||
*/
|
||||
public static function portLink($port, $text = null, $type = null, $overlib = true, $single_graph = false)
|
||||
{
|
||||
if ($port === null) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$label = Rewrite::normalizeIfName($port->getLabel());
|
||||
if (! $text) {
|
||||
$text = $label;
|
||||
|
@@ -25,8 +25,9 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use LibreNMS\Interfaces\Models\Keyable;
|
||||
|
||||
class IsisAdjacency extends PortRelatedModel
|
||||
class IsisAdjacency extends PortRelatedModel implements Keyable
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
@@ -37,6 +38,7 @@ class IsisAdjacency extends PortRelatedModel
|
||||
'device_id',
|
||||
'port_id',
|
||||
'ifIndex',
|
||||
'isisCircAdminState',
|
||||
'isisISAdjState',
|
||||
'isisISAdjNeighSysType',
|
||||
'isisISAdjNeighSysID',
|
||||
@@ -53,4 +55,9 @@ class IsisAdjacency extends PortRelatedModel
|
||||
{
|
||||
return $this->belongsTo(\App\Models\Port::class, 'device_id');
|
||||
}
|
||||
|
||||
public function getCompositeKey()
|
||||
{
|
||||
return $this->ifIndex;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class IsisAdjacenciesAddAdminStatus extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('isis_adjacencies', function (Blueprint $table) {
|
||||
$table->string('isisCircAdminState', 16)->default('off');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropColumns('isis_adjacencies', 'isisCircAdminState');
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class IsisAdjacenciesNullable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('isis_adjacencies', function (Blueprint $table) {
|
||||
$table->integer('port_id')->nullable()->change();
|
||||
$table->string('isisISAdjNeighSysType', 128)->nullable()->change();
|
||||
$table->string('isisISAdjNeighSysID', 128)->nullable()->change();
|
||||
$table->string('isisISAdjNeighPriority', 128)->nullable()->change();
|
||||
$table->unsignedBigInteger('isisISAdjLastUpTime')->nullable()->change();
|
||||
$table->string('isisISAdjAreaAddress', 128)->nullable()->change();
|
||||
$table->string('isisISAdjIPAddrType', 128)->nullable()->change();
|
||||
$table->string('isisISAdjIPAddrAddress', 128)->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('isis_adjacencies', function (Blueprint $table) {
|
||||
$table->integer('port_id')->change();
|
||||
$table->string('isisISAdjNeighSysType', 128)->change();
|
||||
$table->string('isisISAdjNeighSysID', 128)->change();
|
||||
$table->string('isisISAdjNeighPriority', 128)->change();
|
||||
$table->unsignedBigInteger('isisISAdjLastUpTime')->change();
|
||||
$table->string('isisISAdjAreaAddress', 128)->change();
|
||||
$table->string('isisISAdjIPAddrType', 128)->change();
|
||||
$table->string('isisISAdjIPAddrAddress', 128)->change();
|
||||
});
|
||||
}
|
||||
}
|
@@ -10,14 +10,15 @@ echo '
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>Local device</th>
|
||||
<th>Local interface</th>
|
||||
<th>Local Device</th>
|
||||
<th>Local Interface</th>
|
||||
<th>Adjacent</th>
|
||||
<th>System ID</th>
|
||||
<th>Area</th>
|
||||
<th>System type</th>
|
||||
<th>System Type</th>
|
||||
<th>Admin</th>
|
||||
<th>State</th>
|
||||
<th>Last uptime</th>
|
||||
<th>Last Uptime</th>
|
||||
</tr>
|
||||
</thead>';
|
||||
|
||||
@@ -34,16 +35,12 @@ foreach (IsisAdjacency::where('device_id', $device['device_id'])->with('port')->
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>' . generate_device_link($device, 0, ['tab' => 'routing', 'proto' => 'isis']) . '</td>
|
||||
<td><a href="' . \LibreNMS\Util\Url::generate([
|
||||
'page'=>'device',
|
||||
'device'=>$adj->device_id,
|
||||
'tab'=>'port',
|
||||
'port'=>$adj->port_id,
|
||||
]) . '">' . $interface_name . '</a></td>
|
||||
<td>' . \LibreNMS\Util\Url::portLink($adj->port) . '</td>
|
||||
<td>' . $adj->isisISAdjIPAddrAddress . '</td>
|
||||
<td>' . $adj->isisISAdjNeighSysID . '</td>
|
||||
<td>' . $adj->isisISAdjAreaAddress . '</td>
|
||||
<td>' . $adj->isisISAdjNeighSysType . '</td>
|
||||
<td>' . $adj->isisCircAdminState . '</td>
|
||||
<td><strong><span style="color: ' . $color . ';">' . $adj->isisISAdjState . '</span></strong></td>
|
||||
<td>' . \LibreNMS\Util\Time::formatInterval($adj->isisISAdjLastUpTime) . '</td>
|
||||
</tr>
|
||||
|
@@ -63,14 +63,15 @@ if (! Auth::user()->hasGlobalRead()) {
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>Local device</th>
|
||||
<th>Local interface</th>
|
||||
<th>Local Device</th>
|
||||
<th>Local Interface</th>
|
||||
<th>Adjacent</th>
|
||||
<th>System ID</th>
|
||||
<th>Area</th>
|
||||
<th>System type</th>
|
||||
<th>System Type</th>
|
||||
<th>Admin</th>
|
||||
<th>State</th>
|
||||
<th>Last uptime</th>
|
||||
<th>Last Uptime</th>
|
||||
</tr>
|
||||
</thead>';
|
||||
|
||||
@@ -89,16 +90,12 @@ if (! Auth::user()->hasGlobalRead()) {
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>' . generate_device_link($device, 0, ['tab' => 'routing', 'proto' => 'isis']) . '</td>
|
||||
<td><a href="' . \LibreNMS\Util\Url::generate([
|
||||
'page'=>'device',
|
||||
'device'=>$adj->device_id,
|
||||
'tab'=>'port',
|
||||
'port'=>$adj->port_id,
|
||||
]) . '">' . $interface_name . '</a></td>
|
||||
<td>' . \LibreNMS\Util\Url::portLink($adj->port) . '</td>
|
||||
<td>' . $adj->isisISAdjIPAddrAddress . '</td>
|
||||
<td>' . $adj->isisISAdjNeighSysID . '</td>
|
||||
<td>' . $adj->isisISAdjAreaAddress . '</td>
|
||||
<td>' . $adj->isisISAdjNeighSysType . '</td>
|
||||
<td>' . $adj->isisCircAdminState . '</td>
|
||||
<td><strong><span style="color: ' . $color . ';">' . $adj->isisISAdjState . '</span></strong></td>
|
||||
<td>' . \LibreNMS\Util\Time::formatInterval($adj->isisISAdjLastUpTime) . '</td>
|
||||
</tr>
|
||||
|
@@ -796,16 +796,17 @@ isis_adjacencies:
|
||||
Columns:
|
||||
- { Field: id, Type: 'int unsigned', 'Null': false, Extra: auto_increment }
|
||||
- { Field: device_id, Type: int, 'Null': false, Extra: '' }
|
||||
- { Field: port_id, Type: int, 'Null': false, Extra: '' }
|
||||
- { Field: port_id, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: ifIndex, Type: int, 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjState, Type: varchar(13), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjNeighSysType, Type: varchar(128), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjNeighSysID, Type: varchar(128), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjNeighPriority, Type: varchar(128), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjLastUpTime, Type: 'bigint unsigned', 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjAreaAddress, Type: varchar(128), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjIPAddrType, Type: varchar(128), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjIPAddrAddress, Type: varchar(128), 'Null': false, Extra: '' }
|
||||
- { Field: isisISAdjNeighSysType, Type: varchar(128), 'Null': true, Extra: '' }
|
||||
- { Field: isisISAdjNeighSysID, Type: varchar(128), 'Null': true, Extra: '' }
|
||||
- { Field: isisISAdjNeighPriority, Type: varchar(128), 'Null': true, Extra: '' }
|
||||
- { Field: isisISAdjLastUpTime, Type: 'bigint unsigned', 'Null': true, Extra: '' }
|
||||
- { Field: isisISAdjAreaAddress, Type: varchar(128), 'Null': true, Extra: '' }
|
||||
- { Field: isisISAdjIPAddrType, Type: varchar(128), 'Null': true, Extra: '' }
|
||||
- { Field: isisISAdjIPAddrAddress, Type: varchar(128), 'Null': true, Extra: '' }
|
||||
- { Field: isisCircAdminState, Type: varchar(16), 'Null': false, Extra: '', Default: 'off' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
|
||||
isis_adjacencies_device_id_index: { Name: isis_adjacencies_device_id_index, Columns: [device_id], Unique: false, Type: BTREE }
|
||||
|
@@ -13016,5 +13016,36 @@
|
||||
],
|
||||
"ports_vlans": []
|
||||
}
|
||||
},
|
||||
"isis": {
|
||||
"discovery": {
|
||||
"isis_adjacencies": [
|
||||
{
|
||||
"ifIndex": 559,
|
||||
"isisISAdjState": "up",
|
||||
"isisISAdjNeighSysType": "L2",
|
||||
"isisISAdjNeighSysID": "01.00.99.19.12.55",
|
||||
"isisISAdjNeighPriority": "0",
|
||||
"isisISAdjLastUpTime": 1224167,
|
||||
"isisISAdjAreaAddress": "49.00.01",
|
||||
"isisISAdjIPAddrType": "ipv4",
|
||||
"isisISAdjIPAddrAddress": "10.99.252.255",
|
||||
"isisCircAdminState": "on"
|
||||
},
|
||||
{
|
||||
"ifIndex": 572,
|
||||
"isisISAdjState": "up",
|
||||
"isisISAdjNeighSysType": "L2",
|
||||
"isisISAdjNeighSysID": "10.99.20.40.00.51",
|
||||
"isisISAdjNeighPriority": "0",
|
||||
"isisISAdjLastUpTime": 1206503,
|
||||
"isisISAdjAreaAddress": "49.00.01",
|
||||
"isisISAdjIPAddrType": "ipv4",
|
||||
"isisISAdjIPAddrAddress": "10.99.252.253",
|
||||
"isisCircAdminState": "on"
|
||||
}
|
||||
]
|
||||
},
|
||||
"poller": "matches discovery"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user