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:
parent
29ff20d7eb
commit
b6a8b602b8
|
@ -125,7 +125,9 @@ class Core implements Module
|
|||
];
|
||||
|
||||
// check yaml files
|
||||
\LibreNMS\Util\OS::loadAllDefinitions();
|
||||
$os_defs = Config::get('os');
|
||||
|
||||
foreach ($os_defs as $os => $def) {
|
||||
if (isset($def['discovery']) && ! in_array($os, $generic_os)) {
|
||||
if (self::discoveryIsSlow($def)) {
|
||||
|
|
|
@ -25,20 +25,21 @@
|
|||
|
||||
namespace App\ApiClients;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use LibreNMS\Util\Proxy;
|
||||
|
||||
class BaseApi
|
||||
{
|
||||
protected $base_uri;
|
||||
private $client;
|
||||
|
||||
protected function getClient()
|
||||
protected function getClient(): \Illuminate\Http\Client\PendingRequest
|
||||
{
|
||||
if (is_null($this->client)) {
|
||||
$this->client = new Client([
|
||||
'base_uri' => $this->base_uri,
|
||||
'timeout' => 2,
|
||||
]);
|
||||
$this->client = Http::withOptions([
|
||||
'proxy' => Proxy::forGuzzle($this->base_uri),
|
||||
])->baseUrl($this->base_uri)
|
||||
->timeout(3);
|
||||
}
|
||||
|
||||
return $this->client;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
namespace App\ApiClients;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Geocoder;
|
||||
|
||||
|
@ -75,13 +76,9 @@ class BingApi extends BaseApi implements Geocoder
|
|||
|
||||
/**
|
||||
* 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']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,17 +25,14 @@
|
|||
namespace App\ApiClients;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use LibreNMS\Config;
|
||||
use Log;
|
||||
|
||||
trait GeocodingHelper
|
||||
{
|
||||
/**
|
||||
* From BaseApi...
|
||||
*
|
||||
* @return \GuzzleHttp\Client
|
||||
*/
|
||||
abstract protected function getClient();
|
||||
abstract protected function getClient(): PendingRequest;
|
||||
|
||||
/**
|
||||
* Try to get the coordinates of a given address.
|
||||
|
@ -56,7 +53,7 @@ trait GeocodingHelper
|
|||
$options = $this->buildGeocodingOptions($address);
|
||||
|
||||
$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)) {
|
||||
return $this->parseLatLng($response_data);
|
||||
} else {
|
||||
|
@ -71,14 +68,10 @@ trait GeocodingHelper
|
|||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
namespace App\ApiClients;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Geocoder;
|
||||
|
||||
|
@ -89,15 +90,9 @@ class GoogleMapsApi extends BaseApi implements Geocoder
|
|||
|
||||
/**
|
||||
* 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';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
namespace App\ApiClients;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Interfaces\Geocoder;
|
||||
|
||||
|
@ -76,13 +77,9 @@ class MapquestApi extends BaseApi implements Geocoder
|
|||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -77,8 +77,7 @@ class RipeApi extends BaseApi
|
|||
private function makeApiCall(string $uri, array $options)
|
||||
{
|
||||
try {
|
||||
$response = $this->getClient()->get($uri, $options);
|
||||
$response_data = json_decode($response->getBody(), true);
|
||||
$response_data = $this->getClient()->get($uri, $options)->json();
|
||||
if (isset($response_data['status']) && $response_data['status'] == 'ok') {
|
||||
return $response_data;
|
||||
} else {
|
||||
|
|
|
@ -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';
|
||||
}
|
|
@ -612,9 +612,9 @@ class Device extends BaseModel
|
|||
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
|
||||
|
@ -627,6 +627,16 @@ class Device extends BaseModel
|
|||
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
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
public function diskIo(): HasMany
|
||||
{
|
||||
return $this->hasMany(\App\Models\DiskIo::class, 'device_id');
|
||||
}
|
||||
|
||||
public function hostResources(): HasMany
|
||||
{
|
||||
return $this->hasMany(HrDevice::class, 'device_id');
|
||||
|
@ -662,6 +677,11 @@ class Device extends BaseModel
|
|||
return $this->hasMany(EntPhysical::class, 'device_id');
|
||||
}
|
||||
|
||||
public function entityState(): HasMany
|
||||
{
|
||||
return $this->hasMany(EntityState::class, 'device_id');
|
||||
}
|
||||
|
||||
public function eventlogs(): HasMany
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
public function isisAdjacencies(): HasMany
|
||||
{
|
||||
return $this->hasMany(\App\Models\IsisAdjacency::class, 'device_id', 'device_id');
|
||||
}
|
||||
|
||||
public function location(): BelongsTo
|
||||
{
|
||||
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
|
||||
{
|
||||
return $this->hasMany(MefInfo::class, 'device_id');
|
||||
|
@ -707,6 +737,11 @@ class Device extends BaseModel
|
|||
return $this->hasMany(\App\Models\MuninPlugin::class, 'device_id');
|
||||
}
|
||||
|
||||
public function netscalerVservers(): HasMany
|
||||
{
|
||||
return $this->hasMany(NetscalerVserver::class, 'device_id');
|
||||
}
|
||||
|
||||
public function ospfAreas(): HasMany
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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');
|
||||
}
|
||||
|
||||
public function tnmsNeInfo(): HasMany
|
||||
{
|
||||
return $this->hasMany(TnmsneInfo::class, 'device_id');
|
||||
}
|
||||
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
// FIXME does not include global read
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class Process extends DeviceRelatedModel
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace App\Observers;
|
||||
|
||||
use App;
|
||||
use App\ApiClients\Oxidized;
|
||||
use App\Models\Device;
|
||||
use Illuminate\Support\Str;
|
||||
use Log;
|
||||
|
||||
class DeviceObserver
|
||||
|
@ -13,9 +16,10 @@ class DeviceObserver
|
|||
* @param \App\Models\Device $device
|
||||
* @return void
|
||||
*/
|
||||
public function created(Device $device)
|
||||
public function created(Device $device): void
|
||||
{
|
||||
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
|
||||
* @return void
|
||||
*/
|
||||
public function updated(Device $device)
|
||||
public function updated(Device $device): void
|
||||
{
|
||||
// handle device dependency updates
|
||||
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.
|
||||
*
|
||||
* @param \App\Models\Device $device
|
||||
* @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
|
||||
$device->ports()->delete();
|
||||
$device->syslogs()->delete();
|
||||
$device->eventlogs()->delete();
|
||||
$device->accessPoints()->delete();
|
||||
$device->alerts()->delete();
|
||||
\DB::table('alert_device_map')->where('device_id', $device->device_id)->delete();
|
||||
$device->alertLogs()->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
|
||||
$device->children->each->updateMaxDepth($device->device_id);
|
||||
|
|
|
@ -122,13 +122,6 @@ $end = microtime(true);
|
|||
$run = ($end - $start);
|
||||
$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)) {
|
||||
$new_discovery_lock->release();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ use LibreNMS\Exceptions\HostUnreachablePingException;
|
|||
use LibreNMS\Exceptions\InvalidPortAssocModeException;
|
||||
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
||||
use LibreNMS\Modules\Core;
|
||||
use LibreNMS\Util\Debug;
|
||||
use LibreNMS\Util\IPv4;
|
||||
use LibreNMS\Util\IPv6;
|
||||
use LibreNMS\Util\Proxy;
|
||||
|
@ -295,68 +294,16 @@ function device_discovery_trigger($id)
|
|||
|
||||
function delete_device($id)
|
||||
{
|
||||
if (App::runningInConsole() === false) {
|
||||
ignore_user_abort(true);
|
||||
set_time_limit(0);
|
||||
$device = DeviceCache::get($id);
|
||||
if (! $device->exists) {
|
||||
return 'No such device.';
|
||||
}
|
||||
|
||||
$ret = '';
|
||||
|
||||
$host = dbFetchCell('SELECT hostname FROM devices WHERE device_id = ?', [$id]);
|
||||
if (empty($host)) {
|
||||
return 'No such host.';
|
||||
if ($device->delete()) {
|
||||
return "Removed device $device->hostname\n";
|
||||
}
|
||||
|
||||
// Remove IPv4/IPv6 addresses before removing ports as they depend on port_id
|
||||
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;
|
||||
return "Failed to remove device $device->hostname";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1019,23 +966,6 @@ function host_exists($hostname, $sysName = null)
|
|||
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
|
||||
*
|
||||
|
@ -1671,32 +1601,6 @@ function is_disk_valid($disk, $device)
|
|||
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
|
||||
*
|
||||
|
|
|
@ -14,7 +14,7 @@ header('Content-type: application/json');
|
|||
|
||||
$device_hostname = strip_tags($_POST['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';
|
||||
$message = 'Queued refresh in oxidized for device ' . $device_hostname;
|
||||
} else {
|
||||
|
|
|
@ -14,7 +14,7 @@ if (! Auth::user()->hasGlobalAdmin()) {
|
|||
$status = 'error';
|
||||
$message = 'ERROR: You need to be admin to reload Oxidized node list';
|
||||
} else {
|
||||
oxidized_reload_nodes();
|
||||
(new \App\ApiClients\Oxidized())->reloadNodes();
|
||||
$status = 'ok';
|
||||
$message = 'Oxidized node list was reloaded';
|
||||
}
|
||||
|
|
|
@ -7200,11 +7200,6 @@ parameters:
|
|||
count: 1
|
||||
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\\.$#"
|
||||
count: 1
|
||||
|
|
|
@ -8,22 +8,23 @@ $hostname = $argv[1];
|
|||
$os = $argv[2];
|
||||
$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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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
|
||||
oxidized_node_update($hostname, $msg);
|
||||
$oxidized_api->updateNode($hostname, $msg);
|
||||
} 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)) {
|
||||
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)) {
|
||||
oxidized_node_update($hostname, $msg); //ScreenOS
|
||||
$oxidized_api->updateNode($hostname, $msg); //ScreenOS
|
||||
} 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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue