Oxidized update and Device remove (#13730)

* Oxidized + Device remove
Was just working on oxidized, but then to properly update nodes after delete, updated delete_device()

* revert dumb style changes

* baseline update and no DI there...

* Fix OS first load and device deletion missing tables
This commit is contained in:
Tony Murray
2022-01-29 21:09:05 -06:00
committed by GitHub
parent 29ff20d7eb
commit b6a8b602b8
19 changed files with 315 additions and 184 deletions

View File

@@ -125,7 +125,9 @@ class Core implements Module
]; ];
// check yaml files // check yaml files
\LibreNMS\Util\OS::loadAllDefinitions();
$os_defs = Config::get('os'); $os_defs = Config::get('os');
foreach ($os_defs as $os => $def) { foreach ($os_defs as $os => $def) {
if (isset($def['discovery']) && ! in_array($os, $generic_os)) { if (isset($def['discovery']) && ! in_array($os, $generic_os)) {
if (self::discoveryIsSlow($def)) { if (self::discoveryIsSlow($def)) {

View File

@@ -25,20 +25,21 @@
namespace App\ApiClients; namespace App\ApiClients;
use GuzzleHttp\Client; use Illuminate\Support\Facades\Http;
use LibreNMS\Util\Proxy;
class BaseApi class BaseApi
{ {
protected $base_uri; protected $base_uri;
private $client; private $client;
protected function getClient() protected function getClient(): \Illuminate\Http\Client\PendingRequest
{ {
if (is_null($this->client)) { if (is_null($this->client)) {
$this->client = new Client([ $this->client = Http::withOptions([
'base_uri' => $this->base_uri, 'proxy' => Proxy::forGuzzle($this->base_uri),
'timeout' => 2, ])->baseUrl($this->base_uri)
]); ->timeout(3);
} }
return $this->client; return $this->client;

View File

@@ -26,6 +26,7 @@
namespace App\ApiClients; namespace App\ApiClients;
use Exception; use Exception;
use Illuminate\Http\Client\Response;
use LibreNMS\Config; use LibreNMS\Config;
use LibreNMS\Interfaces\Geocoder; use LibreNMS\Interfaces\Geocoder;
@@ -75,13 +76,9 @@ class BingApi extends BaseApi implements Geocoder
/** /**
* Checks if the request was a success * Checks if the request was a success
*
* @param \Psr\Http\Message\ResponseInterface $response
* @param array $data decoded response data
* @return bool
*/ */
protected function checkResponse($response, $data) protected function checkResponse(Response $response, array $data): bool
{ {
return $response->getStatusCode() == 200 && ! empty($data['resourceSets'][0]['resources']); return $response->successful() && ! empty($data['resourceSets'][0]['resources']);
} }
} }

View File

@@ -25,17 +25,14 @@
namespace App\ApiClients; namespace App\ApiClients;
use Exception; use Exception;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Response;
use LibreNMS\Config; use LibreNMS\Config;
use Log; use Log;
trait GeocodingHelper trait GeocodingHelper
{ {
/** abstract protected function getClient(): PendingRequest;
* From BaseApi...
*
* @return \GuzzleHttp\Client
*/
abstract protected function getClient();
/** /**
* Try to get the coordinates of a given address. * Try to get the coordinates of a given address.
@@ -56,7 +53,7 @@ trait GeocodingHelper
$options = $this->buildGeocodingOptions($address); $options = $this->buildGeocodingOptions($address);
$response = $this->getClient()->get($this->geocoding_uri, $options); $response = $this->getClient()->get($this->geocoding_uri, $options);
$response_data = json_decode($response->getBody(), true); $response_data = $response->json();
if ($this->checkResponse($response, $response_data)) { if ($this->checkResponse($response, $response_data)) {
return $this->parseLatLng($response_data); return $this->parseLatLng($response_data);
} else { } else {
@@ -71,14 +68,10 @@ trait GeocodingHelper
/** /**
* Checks if the request was a success * Checks if the request was a success
*
* @param \Psr\Http\Message\ResponseInterface $response
* @param array $data decoded response data
* @return bool
*/ */
protected function checkResponse($response, $data) protected function checkResponse(Response $response, array $data): bool
{ {
return $response->getStatusCode() == 200; return $response->successful();
} }
/** /**

View File

@@ -26,6 +26,7 @@
namespace App\ApiClients; namespace App\ApiClients;
use Exception; use Exception;
use Illuminate\Http\Client\Response;
use LibreNMS\Config; use LibreNMS\Config;
use LibreNMS\Interfaces\Geocoder; use LibreNMS\Interfaces\Geocoder;
@@ -89,15 +90,9 @@ class GoogleMapsApi extends BaseApi implements Geocoder
/** /**
* Checks if the request was a success * Checks if the request was a success
*
* @param \Psr\Http\Message\ResponseInterface $response
* @param array $data decoded response data
* @return bool
*
* @throws Exception you may throw an Exception if validation fails
*/ */
protected function checkResponse($response, $data) protected function checkResponse(Response $response, array $data): bool
{ {
return $response->getStatusCode() == 200 && $data['status'] == 'OK'; return $response->successful() && $data['status'] == 'OK';
} }
} }

View File

@@ -26,6 +26,7 @@
namespace App\ApiClients; namespace App\ApiClients;
use Exception; use Exception;
use Illuminate\Http\Client\Response;
use LibreNMS\Config; use LibreNMS\Config;
use LibreNMS\Interfaces\Geocoder; use LibreNMS\Interfaces\Geocoder;
@@ -76,13 +77,9 @@ class MapquestApi extends BaseApi implements Geocoder
/** /**
* Checks if the request was a success * Checks if the request was a success
*
* @param \Psr\Http\Message\ResponseInterface $response
* @param array $data decoded response data
* @return bool
*/ */
protected function checkResponse($response, $data) protected function checkResponse(Response $response, array $data): bool
{ {
return $response->getStatusCode() == 200 && $data['info']['statuscode'] == 0; return $response->successful() && $data['info']['statuscode'] == 0;
} }
} }

View File

@@ -0,0 +1,69 @@
<?php
/**
* Oxidized.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 App\ApiClients;
use LibreNMS\Config;
class Oxidized extends BaseApi
{
/**
* @var bool if Oxidized is enabled
*/
private $enabled;
public function __construct()
{
$this->base_uri = Config::get('oxidized.url');
$this->enabled = Config::get('oxidized.enabled') === true && $this->base_uri;
}
/**
* Ask oxidized to refresh the node list for the source (likely the LibreNMS API).
*/
public function reloadNodes(): void
{
if ($this->enabled && Config::get('oxidized.reload_nodes') === true) {
$this->getClient()->get('/reload.json');
}
}
/**
* Queues a hostname to be refreshed by Oxidized
*/
public function updateNode(string $hostname, string $msg, string $username = 'not_provided'): bool
{
if ($this->enabled) {
// Work around https://github.com/rack/rack/issues/337
$msg = str_replace('%', '', $msg);
return $this->getClient()
->put("/node/next/$hostname", ['user' => $username, 'msg' => $msg])
->successful();
}
return false;
}
}

View File

@@ -77,8 +77,7 @@ class RipeApi extends BaseApi
private function makeApiCall(string $uri, array $options) private function makeApiCall(string $uri, array $options)
{ {
try { try {
$response = $this->getClient()->get($uri, $options); $response_data = $this->getClient()->get($uri, $options)->json();
$response_data = json_decode($response->getBody(), true);
if (isset($response_data['status']) && $response_data['status'] == 'ok') { if (isset($response_data['status']) && $response_data['status'] == 'ok') {
return $response_data; return $response_data;
} else { } else {

14
app/Models/AlertLog.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class AlertLog extends DeviceRelatedModel
{
use HasFactory;
public const UPDATED_AT = null;
public const CREATED_AT = 'time_logged';
protected $table = 'alert_log';
}

View File

@@ -612,9 +612,9 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\Alert::class, 'device_id'); return $this->hasMany(\App\Models\Alert::class, 'device_id');
} }
public function attribs(): HasMany public function alertLogs(): HasMany
{ {
return $this->hasMany(\App\Models\DeviceAttrib::class, 'device_id'); return $this->hasMany(\App\Models\AlertLog::class, 'device_id');
} }
public function alertSchedules(): MorphToMany public function alertSchedules(): MorphToMany
@@ -627,6 +627,16 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\Application::class, 'device_id'); return $this->hasMany(\App\Models\Application::class, 'device_id');
} }
public function attribs(): HasMany
{
return $this->hasMany(\App\Models\DeviceAttrib::class, 'device_id');
}
public function availability(): HasMany
{
return $this->hasMany(\App\Models\Availability::class, 'device_id');
}
public function bgppeers(): HasMany public function bgppeers(): HasMany
{ {
return $this->hasMany(\App\Models\BgpPeer::class, 'device_id'); return $this->hasMany(\App\Models\BgpPeer::class, 'device_id');
@@ -647,6 +657,11 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\Component::class, 'device_id'); return $this->hasMany(\App\Models\Component::class, 'device_id');
} }
public function diskIo(): HasMany
{
return $this->hasMany(\App\Models\DiskIo::class, 'device_id');
}
public function hostResources(): HasMany public function hostResources(): HasMany
{ {
return $this->hasMany(HrDevice::class, 'device_id'); return $this->hasMany(HrDevice::class, 'device_id');
@@ -662,6 +677,11 @@ class Device extends BaseModel
return $this->hasMany(EntPhysical::class, 'device_id'); return $this->hasMany(EntPhysical::class, 'device_id');
} }
public function entityState(): HasMany
{
return $this->hasMany(EntityState::class, 'device_id');
}
public function eventlogs(): HasMany public function eventlogs(): HasMany
{ {
return $this->hasMany(\App\Models\Eventlog::class, 'device_id', 'device_id'); return $this->hasMany(\App\Models\Eventlog::class, 'device_id', 'device_id');
@@ -692,11 +712,21 @@ class Device extends BaseModel
return $this->hasManyThrough(\App\Models\Ipv6Address::class, \App\Models\Port::class, 'device_id', 'port_id', 'device_id', 'port_id'); return $this->hasManyThrough(\App\Models\Ipv6Address::class, \App\Models\Port::class, 'device_id', 'port_id', 'device_id', 'port_id');
} }
public function isisAdjacencies(): HasMany
{
return $this->hasMany(\App\Models\IsisAdjacency::class, 'device_id', 'device_id');
}
public function location(): BelongsTo public function location(): BelongsTo
{ {
return $this->belongsTo(\App\Models\Location::class, 'location_id', 'id'); return $this->belongsTo(\App\Models\Location::class, 'location_id', 'id');
} }
public function macs(): HasMany
{
return $this->hasMany(Ipv4Mac::class, 'device_id');
}
public function mefInfo(): HasMany public function mefInfo(): HasMany
{ {
return $this->hasMany(MefInfo::class, 'device_id'); return $this->hasMany(MefInfo::class, 'device_id');
@@ -707,6 +737,11 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\MuninPlugin::class, 'device_id'); return $this->hasMany(\App\Models\MuninPlugin::class, 'device_id');
} }
public function netscalerVservers(): HasMany
{
return $this->hasMany(NetscalerVserver::class, 'device_id');
}
public function ospfAreas(): HasMany public function ospfAreas(): HasMany
{ {
return $this->hasMany(\App\Models\OspfArea::class, 'device_id'); return $this->hasMany(\App\Models\OspfArea::class, 'device_id');
@@ -727,16 +762,6 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\OspfPort::class, 'device_id'); return $this->hasMany(\App\Models\OspfPort::class, 'device_id');
} }
public function isisAdjacencies(): HasMany
{
return $this->hasMany(\App\Models\IsisAdjacency::class, 'device_id', 'device_id');
}
public function netscalerVservers(): HasMany
{
return $this->hasMany(NetscalerVserver::class, 'device_id');
}
public function packages(): HasMany public function packages(): HasMany
{ {
return $this->hasMany(\App\Models\Package::class, 'device_id', 'device_id'); return $this->hasMany(\App\Models\Package::class, 'device_id', 'device_id');
@@ -767,6 +792,21 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\PortsNac::class, 'device_id', 'device_id'); return $this->hasMany(\App\Models\PortsNac::class, 'device_id', 'device_id');
} }
public function portsStp(): HasMany
{
return $this->hasMany(\App\Models\PortStp::class, 'device_id', 'device_id');
}
public function portsVlan(): HasMany
{
return $this->hasMany(\App\Models\PortVlan::class, 'device_id', 'device_id');
}
public function processes(): HasMany
{
return $this->hasMany(\App\Models\Process::class, 'device_id');
}
public function processors(): HasMany public function processors(): HasMany
{ {
return $this->hasMany(\App\Models\Processor::class, 'device_id'); return $this->hasMany(\App\Models\Processor::class, 'device_id');
@@ -882,6 +922,11 @@ class Device extends BaseModel
return $this->hasMany(\App\Models\Syslog::class, 'device_id', 'device_id'); return $this->hasMany(\App\Models\Syslog::class, 'device_id', 'device_id');
} }
public function tnmsNeInfo(): HasMany
{
return $this->hasMany(TnmsneInfo::class, 'device_id');
}
public function users(): BelongsToMany public function users(): BelongsToMany
{ {
// FIXME does not include global read // FIXME does not include global read

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class EntityState extends DeviceRelatedModel
{
use HasFactory;
protected $table = 'entityState';
protected $primaryKey = 'entity_state_id';
public $timestamps = false;
}

10
app/Models/Process.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Process extends DeviceRelatedModel
{
use HasFactory;
}

View File

@@ -2,7 +2,10 @@
namespace App\Observers; namespace App\Observers;
use App;
use App\ApiClients\Oxidized;
use App\Models\Device; use App\Models\Device;
use Illuminate\Support\Str;
use Log; use Log;
class DeviceObserver class DeviceObserver
@@ -13,9 +16,10 @@ class DeviceObserver
* @param \App\Models\Device $device * @param \App\Models\Device $device
* @return void * @return void
*/ */
public function created(Device $device) public function created(Device $device): void
{ {
Log::event("Device $device->hostname has been created", $device, 'system', 3); Log::event("Device $device->hostname has been created", $device, 'system', 3);
(new Oxidized)->reloadNodes();
} }
/** /**
@@ -24,7 +28,7 @@ class DeviceObserver
* @param \App\Models\Device $device * @param \App\Models\Device $device
* @return void * @return void
*/ */
public function updated(Device $device) public function updated(Device $device): void
{ {
// handle device dependency updates // handle device dependency updates
if ($device->isDirty('max_depth')) { if ($device->isDirty('max_depth')) {
@@ -49,19 +53,118 @@ class DeviceObserver
} }
} }
/**
* Handle the device "deleted" event.
*/
public function deleted(Device $device): void
{
// delete rrd files
$host_dir = addcslashes(escapeshellarg(\Rrd::dirFromHost($device->hostname)), '\'');
$result = trim(shell_exec("bash -c '( [ ! -d $host_dir ] || rm -vrf $host_dir 2>&1 ) && echo -n OK'"));
if (! Str::endsWith($result, 'OK')) {
Log::debug("Could not $device->hostname files: $result");
}
Log::event("Device $device->hostname has been removed", 0, 'system', 3);
(new Oxidized)->reloadNodes();
}
/** /**
* Handle the device "deleting" event. * Handle the device "deleting" event.
* *
* @param \App\Models\Device $device * @param \App\Models\Device $device
* @return void * @return void
*/ */
public function deleting(Device $device) public function deleting(Device $device): void
{ {
// prevent abort from the webserver
if (App::runningInConsole() === false) {
ignore_user_abort(true);
set_time_limit(0);
}
// delete related data // delete related data
$device->ports()->delete(); $device->accessPoints()->delete();
$device->syslogs()->delete(); $device->alerts()->delete();
$device->eventlogs()->delete(); \DB::table('alert_device_map')->where('device_id', $device->device_id)->delete();
$device->alertLogs()->delete();
$device->applications()->delete(); $device->applications()->delete();
$device->attribs()->delete();
$device->availability()->delete();
$device->bgppeers()->delete();
\DB::table('bgpPeers_cbgp')->where('device_id', $device->device_id)->delete();
$device->cefSwitching()->delete();
\DB::table('ciscoASA')->where('device_id', $device->device_id)->delete();
$device->components()->delete();
\DB::table('customoids')->where('device_id', $device->device_id)->delete();
\DB::table('devices_perms')->where('device_id', $device->device_id)->delete();
$device->graphs()->delete();
\DB::table('device_group_device')->where('device_id', $device->device_id)->delete();
$device->diskIo()->delete();
$device->entityState()->delete();
$device->entityPhysical()->delete();
\DB::table('entPhysical_state')->where('device_id', $device->device_id)->delete();
$device->eventlogs()->delete();
$device->hostResources()->delete();
$device->hostResourceValues()->delete();
$device->ipsecTunnels()->delete();
$device->ipv4()->delete();
$device->ipv6()->delete();
$device->isisAdjacencies()->delete();
$device->isisAdjacencies()->delete();
$device->macs()->delete();
$device->mefInfo()->delete();
$device->mempools()->delete();
$device->mplsLsps()->delete();
$device->mplsLspPaths()->delete();
$device->mplsSaps()->delete();
$device->mplsSdps()->delete();
$device->mplsSdpBinds()->delete();
$device->mplsServices()->delete();
$device->mplsTunnelArHops()->delete();
$device->mplsTunnelCHops()->delete();
$device->muninPlugins()->delete();
\DB::table('netscaler_vservers')->where('device_id', $device->device_id)->delete();
$device->ospfAreas()->delete();
$device->ospfInstances()->delete();
$device->ospfNbrs()->delete();
$device->ospfPorts()->delete();
$device->outages()->delete();
$device->packages()->delete();
$device->perf()->delete();
$device->portsFdb()->delete();
$device->portsNac()->delete();
\DB::table('ports_stack')->where('device_id', $device->device_id)->delete();
$device->portsStp()->delete();
$device->portsVlan()->delete();
$device->printerSupplies()->delete();
$device->processes()->delete();
$device->processors()->delete();
$device->pseudowires()->delete();
$device->routes()->delete();
$device->rServers()->delete();
$device->sensors()->delete(); // delete sensor state indexes first?
$device->services()->delete();
\DB::table('service_templates_device')->where('device_id', $device->device_id)->delete();
$device->storage()->delete();
$device->stpInstances()->delete();
$device->syslogs()->delete();
$device->tnmsNeInfo()->delete();
$device->vlans()->delete();
$device->vminfo()->delete();
$device->vrfs()->delete();
$device->vrfLites()->delete();
$device->vServers()->delete();
$device->wirelessSensors()->delete();
$device->ports()
->select(['port_id', 'device_id', 'ifIndex', 'ifName', 'ifAlias', 'ifDescr'])
->chunk(100, function ($ports) {
foreach ($ports as $port) {
$port->delete();
}
});
// handle device dependency updates // handle device dependency updates
$device->children->each->updateMaxDepth($device->device_id); $device->children->each->updateMaxDepth($device->device_id);

View File

@@ -122,13 +122,6 @@ $end = microtime(true);
$run = ($end - $start); $run = ($end - $start);
$proctime = substr($run, 0, 5); $proctime = substr($run, 0, 5);
if ($discovered_devices) {
if ($doing === 'new') {
// We have added a new device by this point so we might want to do some other work
oxidized_reload_nodes();
}
}
if (isset($new_discovery_lock)) { if (isset($new_discovery_lock)) {
$new_discovery_lock->release(); $new_discovery_lock->release();
} }

View File

@@ -19,7 +19,6 @@ use LibreNMS\Exceptions\HostUnreachablePingException;
use LibreNMS\Exceptions\InvalidPortAssocModeException; use LibreNMS\Exceptions\InvalidPortAssocModeException;
use LibreNMS\Exceptions\SnmpVersionUnsupportedException; use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
use LibreNMS\Modules\Core; use LibreNMS\Modules\Core;
use LibreNMS\Util\Debug;
use LibreNMS\Util\IPv4; use LibreNMS\Util\IPv4;
use LibreNMS\Util\IPv6; use LibreNMS\Util\IPv6;
use LibreNMS\Util\Proxy; use LibreNMS\Util\Proxy;
@@ -295,68 +294,16 @@ function device_discovery_trigger($id)
function delete_device($id) function delete_device($id)
{ {
if (App::runningInConsole() === false) { $device = DeviceCache::get($id);
ignore_user_abort(true); if (! $device->exists) {
set_time_limit(0); return 'No such device.';
} }
$ret = ''; if ($device->delete()) {
return "Removed device $device->hostname\n";
$host = dbFetchCell('SELECT hostname FROM devices WHERE device_id = ?', [$id]);
if (empty($host)) {
return 'No such host.';
} }
// Remove IPv4/IPv6 addresses before removing ports as they depend on port_id return "Failed to remove device $device->hostname";
dbQuery('DELETE `ipv4_addresses` FROM `ipv4_addresses` INNER JOIN `ports` ON `ports`.`port_id`=`ipv4_addresses`.`port_id` WHERE `device_id`=?', [$id]);
dbQuery('DELETE `ipv6_addresses` FROM `ipv6_addresses` INNER JOIN `ports` ON `ports`.`port_id`=`ipv6_addresses`.`port_id` WHERE `device_id`=?', [$id]);
//Remove IsisAdjacencies
\App\Models\IsisAdjacency::where('device_id', $id)->delete();
//Remove Outages
\App\Models\Availability::where('device_id', $id)->delete();
\App\Models\DeviceOutage::where('device_id', $id)->delete();
\App\Models\Port::where('device_id', $id)
->with('device')
->select(['port_id', 'device_id', 'ifIndex', 'ifName', 'ifAlias', 'ifDescr'])
->chunk(100, function ($ports) use (&$ret) {
foreach ($ports as $port) {
$port->delete();
$ret .= "Removed interface $port->port_id (" . $port->getLabel() . ")\n";
}
});
// Remove sensors manually due to constraints
foreach (dbFetchRows('SELECT * FROM `sensors` WHERE `device_id` = ?', [$id]) as $sensor) {
$sensor_id = $sensor['sensor_id'];
dbDelete('sensors_to_state_indexes', '`sensor_id` = ?', [$sensor_id]);
}
$fields = ['device_id', 'host'];
$db_name = dbFetchCell('SELECT DATABASE()');
foreach ($fields as $field) {
foreach (dbFetch('SELECT TABLE_NAME FROM information_schema.columns WHERE table_schema = ? AND column_name = ?', [$db_name, $field]) as $table) {
$table = $table['TABLE_NAME'];
$entries = (int) dbDelete($table, "`$field` = ?", [$id]);
if ($entries > 0 && Debug::isEnabled()) {
$ret .= "$field@$table = #$entries\n";
}
}
}
$ex = shell_exec("bash -c '( [ ! -d " . trim(Rrd::dirFromHost($host)) . ' ] || rm -vrf ' . trim(Rrd::dirFromHost($host)) . " 2>&1 ) && echo -n OK'");
$tmp = explode("\n", $ex);
if ($tmp[sizeof($tmp) - 1] != 'OK') {
$ret .= "Could not remove files:\n$ex\n";
}
$ret .= "Removed device $host\n";
log_event("Device $host has been removed", 0, 'system', 3);
oxidized_reload_nodes();
return $ret;
} }
/** /**
@@ -1019,23 +966,6 @@ function host_exists($hostname, $sysName = null)
return dbFetchCell($query, $params) > 0; return dbFetchCell($query, $params) > 0;
} }
function oxidized_reload_nodes()
{
if (Config::get('oxidized.enabled') === true && Config::get('oxidized.reload_nodes') === true && Config::has('oxidized.url')) {
$oxidized_reload_url = Config::get('oxidized.url') . '/reload.json';
$ch = curl_init($oxidized_reload_url);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_exec($ch);
curl_close($ch);
}
}
/** /**
* Perform DNS lookup * Perform DNS lookup
* *
@@ -1671,32 +1601,6 @@ function is_disk_valid($disk, $device)
return true; return true;
} }
/**
* Queues a hostname to be refreshed by Oxidized
* Settings: oxidized.url
*
* @param string $hostname
* @param string $msg
* @param string $username
* @return bool
*/
function oxidized_node_update($hostname, $msg, $username = 'not_provided')
{
// Work around https://github.com/rack/rack/issues/337
$msg = str_replace('%', '', $msg);
$postdata = ['user' => $username, 'msg' => $msg];
$oxidized_url = Config::get('oxidized.url');
if (! empty($oxidized_url)) {
$response = Http::withOptions(['proxy' => Proxy::forGuzzle($oxidized_url)])->put("$oxidized_url/node/next/$hostname", $postdata);
if ($response->successful()) {
return true;
}
}
return false;
}//end oxidized_node_update()
/** /**
* Take a BGP error code and subcode to return a string representation of it * Take a BGP error code and subcode to return a string representation of it
* *

View File

@@ -14,7 +14,7 @@ header('Content-type: application/json');
$device_hostname = strip_tags($_POST['device_hostname']); $device_hostname = strip_tags($_POST['device_hostname']);
if (Auth::user()->hasGlobalAdmin() && isset($device_hostname)) { if (Auth::user()->hasGlobalAdmin() && isset($device_hostname)) {
if (oxidized_node_update($device_hostname, 'LibreNMS GUI refresh', Auth::user()->username)) { if ((new \App\ApiClients\Oxidized())->updateNode($device_hostname, 'LibreNMS GUI refresh', Auth::user()->username)) {
$status = 'ok'; $status = 'ok';
$message = 'Queued refresh in oxidized for device ' . $device_hostname; $message = 'Queued refresh in oxidized for device ' . $device_hostname;
} else { } else {

View File

@@ -14,7 +14,7 @@ if (! Auth::user()->hasGlobalAdmin()) {
$status = 'error'; $status = 'error';
$message = 'ERROR: You need to be admin to reload Oxidized node list'; $message = 'ERROR: You need to be admin to reload Oxidized node list';
} else { } else {
oxidized_reload_nodes(); (new \App\ApiClients\Oxidized())->reloadNodes();
$status = 'ok'; $status = 'ok';
$message = 'Oxidized node list was reloaded'; $message = 'Oxidized node list was reloaded';
} }

View File

@@ -7200,11 +7200,6 @@ parameters:
count: 1 count: 1
path: LibreNMS/Validator.php path: LibreNMS/Validator.php
-
message: "#^Method App\\\\ApiClients\\\\BaseApi\\:\\:getClient\\(\\) has no return type specified\\.$#"
count: 1
path: app/ApiClients/BaseApi.php
- -
message: "#^Property App\\\\ApiClients\\\\BaseApi\\:\\:\\$base_uri has no type specified\\.$#" message: "#^Property App\\\\ApiClients\\\\BaseApi\\:\\:\\$base_uri has no type specified\\.$#"
count: 1 count: 1

View File

@@ -8,22 +8,23 @@ $hostname = $argv[1];
$os = $argv[2]; $os = $argv[2];
$msg = $argv[3]; $msg = $argv[3];
$oxidized_api = new \App\ApiClients\Oxidized();
if (preg_match('/(SYS-(SW[0-9]+-)?5-CONFIG_I|VSHD-5-VSHD_SYSLOG_CONFIG_I): Configured from .+ by (?P<user>.+) on .*/', $msg, $matches)) { if (preg_match('/(SYS-(SW[0-9]+-)?5-CONFIG_I|VSHD-5-VSHD_SYSLOG_CONFIG_I): Configured from .+ by (?P<user>.+) on .*/', $msg, $matches)) {
oxidized_node_update($hostname, $msg, $matches['user']); $oxidized_api->updateNode($hostname, $msg, $matches['user']);
} elseif (preg_match('/GBL-CONFIG-6-DB_COMMIT : Configuration committed by user \\\\\'(?P<user>.+?)\\\\\'..*/', $msg, $matches)) { } elseif (preg_match('/GBL-CONFIG-6-DB_COMMIT : Configuration committed by user \\\\\'(?P<user>.+?)\\\\\'..*/', $msg, $matches)) {
oxidized_node_update($hostname, $msg, $matches['user']); $oxidized_api->updateNode($hostname, $msg, $matches['user']);
} elseif (preg_match('/ASA-(config-)?5-111005: (?P<user>.+) end configuration: OK/', $msg, $matches)) { } elseif (preg_match('/ASA-(config-)?5-111005: (?P<user>.+) end configuration: OK/', $msg, $matches)) {
oxidized_node_update($hostname, $msg, $matches['user']); $oxidized_api->updateNode($hostname, $msg, $matches['user']);
} elseif (preg_match('/startup-config was changed by (?P<user>.+) from telnet client .*/', $msg, $matches)) { } elseif (preg_match('/startup-config was changed by (?P<user>.+) from telnet client .*/', $msg, $matches)) {
oxidized_node_update($hostname, $msg, $matches['user']); $oxidized_api->updateNode($hostname, $msg, $matches['user']);
} elseif (preg_match('/HWCM\/4\/CFGCHANGE/', $msg, $matches)) { //Huawei VRP devices CFGCHANGE syslog } elseif (preg_match('/HWCM\/4\/CFGCHANGE/', $msg, $matches)) { //Huawei VRP devices CFGCHANGE syslog
oxidized_node_update($hostname, $msg); $oxidized_api->updateNode($hostname, $msg);
} elseif (preg_match('/UI_COMMIT: User \\\\\'(?P<user>.+?)\\\\\' .*/', $msg, $matches)) { } elseif (preg_match('/UI_COMMIT: User \\\\\'(?P<user>.+?)\\\\\' .*/', $msg, $matches)) {
oxidized_node_update($hostname, $msg, $matches['user']); $oxidized_api->updateNode($hostname, $msg, $matches['user']);
} elseif (preg_match('/IMI.+.Startup-config saved on .+ by (?P<user>.+) via .*/', $msg, $matches)) { } elseif (preg_match('/IMI.+.Startup-config saved on .+ by (?P<user>.+) via .*/', $msg, $matches)) {
oxidized_node_update($hostname, $msg, $matches['user']); //Alliedware Plus devices. Requires at least V5.4.8-2.1 $oxidized_api->updateNode($hostname, $msg, $matches['user']); //Alliedware Plus devices. Requires at least V5.4.8-2.1
} elseif (preg_match('/System configuration saved/', $msg, $matches)) { } elseif (preg_match('/System configuration saved/', $msg, $matches)) {
oxidized_node_update($hostname, $msg); //ScreenOS $oxidized_api->updateNode($hostname, $msg); //ScreenOS
} elseif (preg_match('/Running Config Change/', $msg, $matches)) { } elseif (preg_match('/Running Config Change/', $msg, $matches)) {
oxidized_node_update($hostname, $msg); //HPE and Aruba Procurve devices $oxidized_api->updateNode($hostname, $msg); //HPE and Aruba Procurve devices
} }