mirror of
https://github.com/librenms/librenms.git
synced 2024-09-21 10:28:13 +00:00
Merge pull request #5 from librenms/master
Merge librenms master into this fork
This commit is contained in:
commit
d5c94b43e3
@ -478,9 +478,6 @@ class Config
|
||||
}
|
||||
|
||||
self::populateTime();
|
||||
|
||||
// populate legacy DB credentials, just in case something external uses them. Maybe remove this later
|
||||
self::populateLegacyDbCredentials();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -561,18 +558,6 @@ class Config
|
||||
self::set('time.twoyear', $now - 63072000); // time() - (2 * 365 * 24 * 60 * 60);
|
||||
}
|
||||
|
||||
public static function populateLegacyDbCredentials()
|
||||
{
|
||||
$db = config('database.default');
|
||||
|
||||
self::set('db_host', config("database.connections.$db.host", 'localhost'));
|
||||
self::set('db_name', config("database.connections.$db.database", 'librenms'));
|
||||
self::set('db_user', config("database.connections.$db.username", 'librenms'));
|
||||
self::set('db_pass', config("database.connections.$db.password"));
|
||||
self::set('db_port', config("database.connections.$db.port", 3306));
|
||||
self::set('db_socket', config("database.connections.$db.unix_socket"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the config has been loaded yet
|
||||
*
|
||||
|
@ -26,7 +26,6 @@
|
||||
namespace LibreNMS\DB;
|
||||
|
||||
use App\Models\Device;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Support\Collection;
|
||||
use LibreNMS\Interfaces\Models\Keyable;
|
||||
@ -37,15 +36,15 @@ trait SyncsModels
|
||||
* Sync several models for a device's relationship
|
||||
* Model must implement \LibreNMS\Interfaces\Models\Keyable interface
|
||||
*
|
||||
* @param \App\Models\Device $device
|
||||
* @param \Illuminate\Database\Eloquent\Model $parentModel
|
||||
* @param string $relationship
|
||||
* @param \Illuminate\Support\Collection<Keyable> $models \LibreNMS\Interfaces\Models\Keyable
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function syncModels($device, $relationship, $models, $existing = null): Collection
|
||||
protected function syncModels($parentModel, $relationship, $models, $existing = null): Collection
|
||||
{
|
||||
$models = $models->keyBy->getCompositeKey();
|
||||
$existing = ($existing ?? $device->$relationship)->groupBy->getCompositeKey();
|
||||
$existing = ($existing ?? $parentModel->$relationship)->groupBy->getCompositeKey();
|
||||
|
||||
foreach ($existing as $exist_key => $existing_rows) {
|
||||
if ($models->offsetExists($exist_key)) {
|
||||
@ -67,12 +66,12 @@ trait SyncsModels
|
||||
}
|
||||
|
||||
$new = $models->diffKeys($existing);
|
||||
if (is_a($device->$relationship(), HasManyThrough::class)) {
|
||||
if (is_a($parentModel->$relationship(), HasManyThrough::class)) {
|
||||
// if this is a distant relation, the models need the intermediate relationship set
|
||||
// just save assuming things are correct
|
||||
$new->each->save();
|
||||
} else {
|
||||
$device->$relationship()->saveMany($new);
|
||||
$parentModel->$relationship()->saveMany($new);
|
||||
}
|
||||
|
||||
return $existing->map->first()->merge($new);
|
||||
|
@ -167,7 +167,7 @@ def get_config_data(base_dir):
|
||||
)
|
||||
logger.debug("Traceback:", exc_info=True)
|
||||
|
||||
config_cmd = ["/usr/bin/env", "php", "%s/config_to_json.php" % base_dir]
|
||||
config_cmd = ["/usr/bin/env", "php", "%s/lnms" % base_dir, "config:get", "--dump"]
|
||||
try:
|
||||
exit_code, output = command_runner(config_cmd, timeout=300, stderr=False)
|
||||
if exit_code != 0:
|
||||
|
@ -1,3 +1,6 @@
|
||||
import os
|
||||
|
||||
|
||||
class DBConfig:
|
||||
"""
|
||||
Bare minimal config class for LibreNMS.DB class usage
|
||||
@ -14,10 +17,17 @@ class DBConfig:
|
||||
db_ssl_ca = "/etc/ssl/certs/ca-certificates.crt"
|
||||
|
||||
def populate(self, _config):
|
||||
for key, val in _config.items():
|
||||
if key == "db_port":
|
||||
# Special case: port number
|
||||
self.db_port = int(val)
|
||||
elif key.startswith("db_"):
|
||||
# Prevent prototype pollution by enforcing prefix
|
||||
setattr(DBConfig, key, val)
|
||||
self.db_host = os.getenv("DB_HOST", _config.get("db_host", self.db_host))
|
||||
self.db_name = os.getenv("DB_DATABASE", _config.get("db_name", self.db_name))
|
||||
self.db_pass = os.getenv("DB_PASSWORD", _config.get("db_pass", self.db_pass))
|
||||
self.db_port = int(os.getenv("DB_PORT", _config.get("db_port", self.db_port)))
|
||||
self.db_socket = os.getenv(
|
||||
"DB_SOCKET", _config.get("db_socket", self.db_socket)
|
||||
)
|
||||
self.db_user = os.getenv("DB_USERNAME", _config.get("db_user", self.db_user))
|
||||
self.db_sslmode = os.getenv(
|
||||
"DB_SSLMODE", _config.get("db_sslmode", self.db_sslmode)
|
||||
)
|
||||
self.db_ssl_ca = os.getenv(
|
||||
"MYSQL_ATTR_SSL_CA", _config.get("db_ssl_ca", self.db_ssl_ca)
|
||||
)
|
||||
|
@ -26,8 +26,16 @@
|
||||
namespace App\Discovery;
|
||||
|
||||
use App\Models\Device;
|
||||
use App\Models\Eventlog;
|
||||
use App\Models\SensorToStateIndex;
|
||||
use App\Models\StateIndex;
|
||||
use App\Models\StateTranslation;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\DB\SyncsModels;
|
||||
use LibreNMS\Enum\Severity;
|
||||
|
||||
class Sensor
|
||||
{
|
||||
@ -38,6 +46,8 @@ class Sensor
|
||||
private array $discovered = [];
|
||||
private string $relationship = 'sensors';
|
||||
private Device $device;
|
||||
/** @var array<string, Collection<StateTranslation>> */
|
||||
private array $states = [];
|
||||
|
||||
public function __construct(Device $device)
|
||||
{
|
||||
@ -47,10 +57,31 @@ class Sensor
|
||||
|
||||
public function discover(\App\Models\Sensor $sensor): static
|
||||
{
|
||||
if ($this->canSkip($sensor)) {
|
||||
Log::info('~');
|
||||
Log::debug("Skipped Sensor: $sensor");
|
||||
|
||||
return $this;
|
||||
}
|
||||
$sensor->device_id ??= \DeviceCache::getPrimary()->device_id;
|
||||
$this->models->push($sensor);
|
||||
$this->discovered[$sensor->syncGroup()] = false;
|
||||
|
||||
Log::debug("Discovered Sensor: $sensor");
|
||||
Log::info("$sensor->sensor_descr: Cur $sensor->sensor_current, Low: $sensor->sensor_limit_low, Low Warn: $sensor->sensor_limit_low_warn, Warn: $sensor->sensor_limit_warn, High: $sensor->sensor_limit");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $stateName
|
||||
* @param StateTranslation[]|Collection<StateTranslation> $states
|
||||
* @return $this
|
||||
*/
|
||||
public function withStateTranslations(string $stateName, array|Collection $states): static
|
||||
{
|
||||
$this->states[$stateName] = new Collection($states);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -67,6 +98,8 @@ class Sensor
|
||||
$synced = $this->syncModelsByGroup($this->device, 'sensors', $this->getModels(), $params);
|
||||
$this->discovered[$type] = true;
|
||||
|
||||
$this->syncStates($synced);
|
||||
|
||||
return $synced;
|
||||
}
|
||||
|
||||
@ -77,4 +110,80 @@ class Sensor
|
||||
{
|
||||
return $this->models;
|
||||
}
|
||||
|
||||
public function canSkip(\App\Models\Sensor $sensor): bool
|
||||
{
|
||||
if (! empty($sensor->sensor_class) && (Config::getOsSetting($this->device->os, "disabled_sensors.$sensor->sensor_class") || Config::get("disabled_sensors.$sensor->sensor_class"))) {
|
||||
return true;
|
||||
}
|
||||
foreach (Config::getCombined($this->device->os, 'disabled_sensors_regex') as $skipRegex) {
|
||||
if (! empty($sensor->sensor_descr) && preg_match($skipRegex, $sensor->sensor_descr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
foreach (Config::getCombined($this->device->os, "disabled_sensors_regex.$sensor->sensor_class") as $skipRegex) {
|
||||
if (! empty($sensor->sensor_descr) && preg_match($skipRegex, $sensor->sensor_descr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function syncStates(Collection $sensors): void
|
||||
{
|
||||
$stateSensors = $sensors->where('sensor_class', 'state');
|
||||
|
||||
if ($stateSensors->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$usedStates = $stateSensors->pluck('sensor_type');
|
||||
$existingStateIndexes = StateIndex::whereIn('state_name', $usedStates)->get()->keyBy('state_name');
|
||||
|
||||
foreach ($usedStates as $stateName) {
|
||||
// make sure the state translations were given for this state name
|
||||
if (! isset($this->states[$stateName])) {
|
||||
Log::error("Non existent state name ($stateName) set by sensor: " . $stateSensors->where('sensor_type', $stateName)->first()?->sensor_descr);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$stateIndex = $existingStateIndexes->get($stateName);
|
||||
|
||||
// create new state indexes
|
||||
if ($stateIndex == null) {
|
||||
try {
|
||||
$stateIndex = StateIndex::create(['state_name' => $stateName]);
|
||||
$existingStateIndexes->put($stateName, $stateIndex);
|
||||
} catch (UniqueConstraintViolationException) {
|
||||
Eventlog::log("Duplicate state name $stateName (with case mismatch)", $this->device, 'sensor', Severity::Error, $stateSensors->where('sensor_type', $stateName)->first()?->sensor_id);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// set state_index_id
|
||||
$stateTranslations = $this->states[$stateName];
|
||||
foreach ($stateTranslations as $translation) {
|
||||
$translation->state_index_id = $stateIndex->state_index_id;
|
||||
}
|
||||
|
||||
// sync the translations to make sure they are up to date
|
||||
$this->syncModels($stateIndex, 'translations', $stateTranslations);
|
||||
}
|
||||
|
||||
// update sensor to state indexes
|
||||
foreach ($stateSensors as $stateSensor) {
|
||||
$state_index_id = $existingStateIndexes->get($stateSensor->sensor_type)?->state_index_id;
|
||||
|
||||
// only map if sensor gave a valid state name
|
||||
if ($state_index_id) {
|
||||
SensorToStateIndex::updateOrCreate(
|
||||
['sensor_id' => $stateSensor->sensor_id],
|
||||
['state_index_id' => $state_index_id],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use LibreNMS\Interfaces\Models\Keyable;
|
||||
|
||||
@ -99,7 +100,7 @@ class Sensor extends DeviceRelatedModel implements Keyable
|
||||
|
||||
public function guessLimits(): void
|
||||
{
|
||||
$this->sensor_limit = match ($this->sensor_class) {
|
||||
$this->sensor_limit_low = match ($this->sensor_class) {
|
||||
'temperature' => $this->sensor_current - 10,
|
||||
'voltage' => $this->sensor_current * 0.85,
|
||||
'humidity' => 30,
|
||||
@ -110,7 +111,7 @@ class Sensor extends DeviceRelatedModel implements Keyable
|
||||
default => null,
|
||||
};
|
||||
|
||||
$this->sensor_limit_low = match ($this->sensor_class) {
|
||||
$this->sensor_limit = match ($this->sensor_class) {
|
||||
'temperature' => $this->sensor_current + 20,
|
||||
'voltage' => $this->sensor_current * 1.15,
|
||||
'humidity' => 70,
|
||||
@ -129,9 +130,14 @@ class Sensor extends DeviceRelatedModel implements Keyable
|
||||
return $this->morphMany(Eventlog::class, 'events', 'type', 'reference');
|
||||
}
|
||||
|
||||
public function stateIndex(): HasOneThrough
|
||||
{
|
||||
return $this->hasOneThrough(StateIndex::class, SensorToStateIndex::class, 'sensor_id', 'state_index_id', 'sensor_id', 'state_index_id');
|
||||
}
|
||||
|
||||
public function translations(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(StateTranslation::class, 'sensors_to_state_indexes', 'sensor_id', 'state_index_id');
|
||||
return $this->belongsToMany(StateTranslation::class, 'sensors_to_state_indexes', 'sensor_id', 'state_index_id', 'sensor_id', 'state_index_id');
|
||||
}
|
||||
|
||||
public function getCompositeKey(): string
|
||||
@ -143,4 +149,23 @@ class Sensor extends DeviceRelatedModel implements Keyable
|
||||
{
|
||||
return "$this->sensor_class-$this->poller_type";
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$data = $this->only([
|
||||
'sensor_oid',
|
||||
'sensor_index',
|
||||
'sensor_type',
|
||||
'sensor_descr',
|
||||
'poller_type',
|
||||
'sensor_divisor',
|
||||
'sensor_multiplier',
|
||||
'entPhysicalIndex',
|
||||
'sensor_current',
|
||||
]);
|
||||
$data[] = "(limits: LL: $this->sensor_limit_low, LW: $this->sensor_limit_low_warn, W: $this->sensor_limit_warn, H: $this->sensor_limit)";
|
||||
$data[] = "rrd_type = $this->rrd_type";
|
||||
|
||||
return implode(', ', $data);
|
||||
}
|
||||
}
|
||||
|
24
app/Models/SensorToStateIndex.php
Normal file
24
app/Models/SensorToStateIndex.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
class SensorToStateIndex extends Model
|
||||
{
|
||||
protected $table = 'sensors_to_state_indexes';
|
||||
protected $primaryKey = 'sensors_to_state_translations_id';
|
||||
public $timestamps = false;
|
||||
protected $fillable = ['sensor_id', 'state_index_id'];
|
||||
|
||||
public function sensor(): HasOne
|
||||
{
|
||||
return $this->hasOne(Sensor::class, 'sensor_id', 'sensor_id');
|
||||
}
|
||||
|
||||
public function stateIndex(): HasOne
|
||||
{
|
||||
return $this->hasOne(StateIndex::class, 'state_index_id', 'state_index_id');
|
||||
}
|
||||
}
|
28
app/Models/StateIndex.php
Normal file
28
app/Models/StateIndex.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
|
||||
class StateIndex extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public $timestamps = false;
|
||||
protected $table = 'state_indexes';
|
||||
protected $fillable = ['state_name'];
|
||||
protected $primaryKey = 'state_index_id';
|
||||
|
||||
public function sensors(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Sensor::class, SensorToStateIndex::class, 'state_index_id', 'sensor_id', 'state_index_id', 'sensor_id');
|
||||
}
|
||||
|
||||
public function translations(): HasMany
|
||||
{
|
||||
return $this->hasMany(StateTranslation::class, 'state_index_id', 'state_index_id');
|
||||
}
|
||||
}
|
@ -26,9 +26,28 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use LibreNMS\Interfaces\Models\Keyable;
|
||||
|
||||
class StateTranslation extends Model
|
||||
class StateTranslation extends Model implements Keyable
|
||||
{
|
||||
public $timestamps = false;
|
||||
protected $primaryKey = 'state_index_id';
|
||||
const CREATED_AT = null;
|
||||
const UPDATED_AT = 'state_lastupdated';
|
||||
protected $primaryKey = 'state_translation_id';
|
||||
protected $fillable = [
|
||||
'state_descr',
|
||||
'state_draw_graph',
|
||||
'state_value',
|
||||
'state_generic_value',
|
||||
];
|
||||
|
||||
public function stateIndex(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(StateIndex::class, 'state_index_id', 'state_index_id');
|
||||
}
|
||||
|
||||
public function getCompositeKey()
|
||||
{
|
||||
return $this->state_value;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace App\Observers;
|
||||
use App\Models\Eventlog;
|
||||
use App\Models\Sensor;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use LibreNMS\Enum\Severity;
|
||||
|
||||
class SensorObserver
|
||||
@ -20,6 +21,8 @@ class SensorObserver
|
||||
{
|
||||
// fix inverted limits
|
||||
if ($sensor->sensor_limit !== null && $sensor->sensor_limit_low !== null && $sensor->sensor_limit_low > $sensor->sensor_limit) {
|
||||
Log::error('Fixing swapped sensor limits');
|
||||
|
||||
// Fix high/low thresholds (i.e. on negative numbers)
|
||||
[$sensor->sensor_limit, $sensor->sensor_limit_low] = [$sensor->sensor_limit_low, $sensor->sensor_limit];
|
||||
}
|
||||
@ -29,6 +32,14 @@ class SensorObserver
|
||||
}
|
||||
}
|
||||
|
||||
public function creating(Sensor $sensor): void
|
||||
{
|
||||
$guess_limits = \LibreNMS\Config::get('sensors.guess_limits', true);
|
||||
if ($guess_limits && $sensor->sensor_current !== null && $sensor->sensor_limit === null && $sensor->sensor_limit_low === null) {
|
||||
$sensor->guessLimits();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the service "created" event.
|
||||
*
|
||||
@ -37,11 +48,6 @@ class SensorObserver
|
||||
*/
|
||||
public function created(Sensor $sensor): void
|
||||
{
|
||||
$guess_limits = \LibreNMS\Config::get('sensors.guess_limits', true);
|
||||
if ($guess_limits && $sensor->sensor_current !== null && $sensor->sensor_limit === null && $sensor->sensor_limit_low === null) {
|
||||
$sensor->guessLimits();
|
||||
}
|
||||
|
||||
EventLog::log('Sensor Added: ' . $sensor->sensor_class . ' ' . $sensor->sensor_type . ' ' . $sensor->sensor_index . ' ' . $sensor->sensor_descr, $sensor->device_id, 'sensor', Severity::Notice, $sensor->sensor_id);
|
||||
|
||||
if ($this->runningInConsole) {
|
||||
|
@ -13,8 +13,5 @@ $init_modules = ['nodb'];
|
||||
require __DIR__ . '/includes/init.php';
|
||||
|
||||
if (App::runningInConsole()) {
|
||||
// fill in db variables for legacy external scripts
|
||||
Config::populateLegacyDbCredentials();
|
||||
|
||||
echo Config::toJson();
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ modules:
|
||||
- { value: 4096, generic: 2, graph: 0, descr: macSpoof }
|
||||
- { value: 8192, generic: 2, graph: 0, descr: cpuHigh }
|
||||
- { value: 16384, generic: 2, graph: 0, descr: memoryUsageHigh }
|
||||
- { value: 32768, generic: 2, graph: 0, descr: packetBufferUsageHigh }
|
||||
# - { value: 32768, generic: 2, graph: 0, descr: packetBufferUsageHigh } # state value larger than smallint 32767
|
||||
-
|
||||
oid: ledAlarmStatus
|
||||
value: ledAlarmStatus
|
||||
|
@ -8,7 +8,7 @@ mib_dir: eaton
|
||||
over:
|
||||
- { graph: device_voltage, text: Voltage }
|
||||
- { graph: device_current, text: Current }
|
||||
- { graph: device_frequency, text: Load }
|
||||
- { graph: device_load, text: Load }
|
||||
discovery:
|
||||
-
|
||||
sysObjectID: .1.3.6.1.4.1.534.1
|
||||
|
@ -208,11 +208,6 @@ function discover_sensor($unused, $class, $device, $oid, $index, $type, $descr,
|
||||
if (! is_numeric($divisor)) {
|
||||
$divisor = 1;
|
||||
}
|
||||
if (can_skip_sensor($device, $class, $descr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
d_echo("Discover sensor: $oid, $index, $type, $descr, $poller_type, $divisor, $multiplier, $entPhysicalIndex, $current, (limits: LL: $low_limit, LW: $low_warn_limit, W: $warn_limit, H: $high_limit), rrd_type = $rrd_type \n");
|
||||
|
||||
app('sensor-discovery')->discover(new \App\Models\Sensor([
|
||||
'poller_type' => $poller_type,
|
||||
@ -635,7 +630,7 @@ function discovery_process($os, $sensor_class, $pre_cache)
|
||||
$discovery = $os->getDiscovery('sensors');
|
||||
$device = $os->getDeviceArray();
|
||||
|
||||
if (! empty($discovery[$sensor_class]) && ! can_skip_sensor($device, $sensor_class, '')) {
|
||||
if (! empty($discovery[$sensor_class]) && ! app('sensor-discovery')->canSkip(new \App\Models\Sensor(['sensor_class' => $sensor_class]))) {
|
||||
$sensor_options = [];
|
||||
if (isset($discovery[$sensor_class]['options'])) {
|
||||
$sensor_options = $discovery[$sensor_class]['options'];
|
||||
@ -747,7 +742,6 @@ function discovery_process($os, $sensor_class, $pre_cache)
|
||||
$value = ($value / $divisor) * $multiplier;
|
||||
}
|
||||
|
||||
echo "$descr: Cur $value, Low: $low_limit, Low Warn: $low_warn_limit, Warn: $warn_limit, High: $high_limit" . PHP_EOL;
|
||||
$entPhysicalIndex = YamlDiscovery::replaceValues('entPhysicalIndex', $index, null, $data, $pre_cache) ?: null;
|
||||
$entPhysicalIndex_measured = isset($data['entPhysicalIndex_measured']) ? $data['entPhysicalIndex_measured'] : null;
|
||||
|
||||
@ -974,33 +968,6 @@ function add_cbgp_peer($device, $peer, $afi, $safi)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if we should skip this sensor from discovery
|
||||
*
|
||||
* @param $device
|
||||
* @param string $sensor_class
|
||||
* @param string $sensor_descr
|
||||
* @return bool
|
||||
*/
|
||||
function can_skip_sensor($device, $sensor_class = '', $sensor_descr = '')
|
||||
{
|
||||
if (! empty($sensor_class) && (Config::getOsSetting($device['os'], "disabled_sensors.$sensor_class") || Config::get("disabled_sensors.$sensor_class"))) {
|
||||
return true;
|
||||
}
|
||||
foreach (Config::getCombined($device['os'], 'disabled_sensors_regex') as $skipRegex) {
|
||||
if (! empty($sensor_descr) && preg_match($skipRegex, $sensor_descr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
foreach (Config::getCombined($device['os'], "disabled_sensors_regex.$sensor_class") as $skipRegex) {
|
||||
if (! empty($sensor_descr) && preg_match($skipRegex, $sensor_descr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if we should skip this device from discovery
|
||||
*
|
||||
|
@ -8,6 +8,7 @@
|
||||
* @copyright (C) 2006 - 2012 Adam Armstrong
|
||||
*/
|
||||
|
||||
use App\Models\StateTranslation;
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\Severity;
|
||||
@ -493,106 +494,23 @@ function dnslookup($device, $type = false, $return = false)
|
||||
*
|
||||
* @param string $state_name the unique name for this state translation
|
||||
* @param array $states array of states, each must contain keys: descr, graph, value, generic
|
||||
* @return int|null
|
||||
* @return void
|
||||
*/
|
||||
function create_state_index($state_name, $states = [])
|
||||
function create_state_index($state_name, $states = []): void
|
||||
{
|
||||
$state_index_id = dbFetchCell('SELECT `state_index_id` FROM state_indexes WHERE state_name = ? LIMIT 1', [$state_name]);
|
||||
if (! is_numeric($state_index_id)) {
|
||||
$state_index_id = dbInsert(['state_name' => $state_name], 'state_indexes');
|
||||
|
||||
// legacy code, return index so states are created
|
||||
if (empty($states)) {
|
||||
return $state_index_id;
|
||||
}
|
||||
}
|
||||
|
||||
// check or synchronize states
|
||||
if (empty($states)) {
|
||||
$translations = dbFetchRows('SELECT * FROM `state_translations` WHERE `state_index_id` = ?', [$state_index_id]);
|
||||
if (count($translations) == 0) {
|
||||
// If we don't have any translations something has gone wrong so return the state_index_id so they get created.
|
||||
return $state_index_id;
|
||||
}
|
||||
} else {
|
||||
sync_sensor_states($state_index_id, $states);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the sensor state translations with the database
|
||||
*
|
||||
* @param int $state_index_id index of the state
|
||||
* @param array $states array of states, each must contain keys: descr, graph, value, generic
|
||||
*/
|
||||
function sync_sensor_states($state_index_id, $states)
|
||||
{
|
||||
$new_translations = array_reduce($states, function ($array, $state) use ($state_index_id) {
|
||||
$array[$state['value']] = [
|
||||
'state_index_id' => $state_index_id,
|
||||
app('sensor-discovery')->withStateTranslations($state_name, array_map(function ($state) {
|
||||
return new StateTranslation([
|
||||
'state_descr' => $state['descr'],
|
||||
'state_draw_graph' => $state['graph'],
|
||||
'state_value' => $state['value'],
|
||||
'state_generic_value' => $state['generic'],
|
||||
];
|
||||
|
||||
return $array;
|
||||
}, []);
|
||||
|
||||
$existing_translations = dbFetchRows(
|
||||
'SELECT `state_index_id`,`state_descr`,`state_draw_graph`,`state_value`,`state_generic_value` FROM `state_translations` WHERE `state_index_id`=?',
|
||||
[$state_index_id]
|
||||
);
|
||||
|
||||
foreach ($existing_translations as $translation) {
|
||||
$value = $translation['state_value'];
|
||||
if (isset($new_translations[$value])) {
|
||||
if ($new_translations[$value] != $translation) {
|
||||
dbUpdate(
|
||||
$new_translations[$value],
|
||||
'state_translations',
|
||||
'`state_index_id`=? AND `state_value`=?',
|
||||
[$state_index_id, $value]
|
||||
);
|
||||
}
|
||||
|
||||
// this translation is synchronized, it doesn't need to be inserted
|
||||
unset($new_translations[$value]);
|
||||
} else {
|
||||
dbDelete('state_translations', '`state_index_id`=? AND `state_value`=?', [$state_index_id, $value]);
|
||||
}
|
||||
}
|
||||
|
||||
// insert any new translations
|
||||
dbBulkInsert($new_translations, 'state_translations');
|
||||
]);
|
||||
}, $states));
|
||||
}
|
||||
|
||||
function create_sensor_to_state_index($device, $state_name, $index)
|
||||
{
|
||||
$sensor_entry = dbFetchRow('SELECT sensor_id FROM `sensors` WHERE `sensor_class` = ? AND `device_id` = ? AND `sensor_type` = ? AND `sensor_index` = ?', [
|
||||
'state',
|
||||
$device['device_id'],
|
||||
$state_name,
|
||||
$index,
|
||||
]);
|
||||
$state_indexes_entry = dbFetchRow('SELECT state_index_id FROM `state_indexes` WHERE `state_name` = ?', [
|
||||
$state_name,
|
||||
]);
|
||||
if (! empty($sensor_entry['sensor_id']) && ! empty($state_indexes_entry['state_index_id'])) {
|
||||
$insert = [
|
||||
'sensor_id' => $sensor_entry['sensor_id'],
|
||||
'state_index_id' => $state_indexes_entry['state_index_id'],
|
||||
];
|
||||
foreach ($insert as $key => $val_check) {
|
||||
if (! isset($val_check)) {
|
||||
unset($insert[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
dbInsert($insert, 'sensors_to_state_indexes');
|
||||
}
|
||||
// no op
|
||||
}
|
||||
|
||||
function delta_to_bits($delta, $period)
|
||||
|
122
package-lock.json
generated
122
package-lock.json
generated
@ -3107,9 +3107,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
||||
"version": "1.20.3",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
||||
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
@ -3120,7 +3120,7 @@
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.11.0",
|
||||
"qs": "6.13.0",
|
||||
"raw-body": "2.5.2",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
@ -3154,21 +3154,6 @@
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/body-parser/node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/bonjour-service": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz",
|
||||
@ -4487,9 +4472,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
@ -4704,37 +4689,37 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.19.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
|
||||
"integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.2",
|
||||
"body-parser": "1.20.3",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.6.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.2.0",
|
||||
"finalhandler": "1.3.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"merge-descriptors": "1.0.3",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"path-to-regexp": "0.1.10",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.11.0",
|
||||
"qs": "6.13.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.2.1",
|
||||
"send": "0.18.0",
|
||||
"serve-static": "1.15.0",
|
||||
"send": "0.19.0",
|
||||
"serve-static": "1.16.2",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"type-is": "~1.6.18",
|
||||
@ -4760,21 +4745,6 @@
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/express/node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@ -4893,13 +4863,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
|
||||
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
@ -6368,10 +6338,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
|
||||
"dev": true
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-source-map": {
|
||||
"version": "1.1.0",
|
||||
@ -7083,9 +7056,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
@ -7886,9 +7859,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.12.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
|
||||
"integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==",
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
||||
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.6"
|
||||
@ -8455,9 +8428,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
|
||||
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
@ -8493,6 +8466,15 @@
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/send/node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -8587,15 +8569,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
|
||||
"version": "1.16.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
|
||||
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.18.0"
|
||||
"send": "0.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
|
@ -33,6 +33,7 @@ from sys import stdout
|
||||
from time import time
|
||||
|
||||
Result = namedtuple("Result", ["ip", "hostname", "outcome", "output"])
|
||||
args = {}
|
||||
|
||||
|
||||
class Outcome:
|
||||
@ -263,7 +264,9 @@ Example: 192.168.0.1/32 will be treated as a single host address""",
|
||||
chdir(install_dir)
|
||||
try:
|
||||
CONFIG = json.loads(
|
||||
check_output(["/usr/bin/env", "php", "config_to_json.php"]).decode()
|
||||
check_output(
|
||||
["/usr/bin/env", "php", "lnms", "config:get", "--dump"]
|
||||
).decode()
|
||||
)
|
||||
except CalledProcessError as e:
|
||||
parser.error(
|
||||
|
@ -118,7 +118,7 @@ class OSModulesTest extends DBTestCase
|
||||
// output all discovery and poller output if debug mode is enabled for phpunit
|
||||
$phpunit_debug = in_array('--debug', $_SERVER['argv'], true);
|
||||
|
||||
foreach ($modules as $module) {
|
||||
foreach ($modules as $module => $module_status) {
|
||||
$expected = $expected_data[$module]['discovery'] ?? [];
|
||||
$actual = $results[$module]['discovery'] ?? [];
|
||||
$this->checkTestData($expected, $actual, 'Discovered', $os, $module, $filename, $helper, $phpunit_debug);
|
||||
|
Loading…
Reference in New Issue
Block a user