From 53bfb24ef9ca62b0e596f295748da33c29e17e23 Mon Sep 17 00:00:00 2001 From: PipoCanaja <38363551+PipoCanaja@users.noreply.github.com> Date: Thu, 8 Sep 2022 02:29:17 +0200 Subject: [PATCH] Migrate xDSL code to module, and add support for VDSL2 MIB (#14207) * use component to discover if xDSL polling is needed use component to discover if xDSL polling is needed * Components OK, Polling in correct files, no DB for VDSL * GUI GUI_suite * per port as well * rename * interface listing * draytek_snmpsim * fix arraymerge fix names and max value * schema schema style * remove one dbFetchRows remove 2x dbFetchCell style style remove Legacy dbFetchRow tests tests eloquent more eloquent more eloquent one more gone * fix properties access eloquent_insert_update style tests tests tests tests * tests tests tests * adslLineCoding * Models * fix not nullable cols in DB from code default values typo rename typo schema fix fix vdsl fix now typo typo fix size fix size * Power values for VDSL Power values for VDSL Power values for VDSL DB * cleanup * Rrd::checkRrdExists * always enable DSL discovery style * xdsl module * cleanup and move to Module cleanup and move to Module cleanup and move to Module cleanup and move to Module * Fix display * fix polling and tenth * remove legacy poller * Style and Cosmetics Cosmetics Cleanup * Translations Translations * exists exists * add test support for xdsl * remove last component call unused * translations * remove non standard onclick event on xdsl line * Update Discovery Support.md Update Poller Support.md toner_gone * Notification for removal of lnms config:set enable_ports_adsl true * enable on devices with potential DSL interfaces * tests are working now fix teldat tests * os_schema * teldat * move to new module structure * move to new module structure * wrong dump function * wrong dump function * laravel_through_key hidden * Update notifications.rss * Update notifications.rss Co-authored-by: Tony Murray --- LibreNMS/DB/SyncsModels.php | 9 +- LibreNMS/Modules/Xdsl.php | 296 ++ LibreNMS/OS/Traits/ResolvesPortIds.php | 17 + app/Models/Device.php | 10 + app/Models/Port.php | 6 + app/Models/PortAdsl.php | 32 +- app/Models/PortVdsl.php | 29 + ...2_08_15_091314_create_ports_vdsl_table.php | 36 + ..._update_ports_adsl_table_with_defaults.php | 63 + doc/Support/Configuration.md | 1 - doc/Support/Discovery Support.md | 7 +- doc/Support/Poller Support.md | 7 +- html/mix-manifest.json | 8 +- includes/definitions/anyos.yaml | 4 + includes/definitions/draytek.yaml | 4 + includes/definitions/gaia.yaml | 4 + includes/definitions/ies.yaml | 4 + includes/definitions/ies5000.yaml | 5 +- includes/definitions/ies52xxM.yaml | 4 + includes/definitions/ios.yaml | 2 + includes/definitions/iosxe.yaml | 2 + includes/definitions/occamos.yaml | 4 + includes/definitions/oneaccess.yaml | 4 + includes/definitions/pegasus.yaml | 4 + includes/definitions/teldat.yaml | 4 + includes/definitions/vrp.yaml | 2 + includes/definitions/zxdsl.yaml | 4 + includes/definitions/zyxelac.yaml | 4 + includes/discovery/xdsl.inc.php | 8 + .../html/graphs/port/vdsl_attainable.inc.php | 25 + includes/html/graphs/port/vdsl_power.inc.php | 25 + includes/html/graphs/port/vdsl_speed.inc.php | 25 + includes/html/pages/device/port.inc.php | 14 +- .../port/{adsl.inc.php => xdsl.inc.php} | 19 +- includes/html/pages/device/ports.inc.php | 6 +- includes/html/pages/device/ports/adsl.inc.php | 15 - includes/html/pages/device/ports/xdsl.inc.php | 28 + includes/html/pages/ports.inc.php | 11 +- includes/html/print-interface-adsl.inc.php | 5 +- includes/html/print-interface-vdsl.inc.php | 117 + includes/html/print-interface.inc.php | 25 +- includes/polling/ports.inc.php | 14 - includes/polling/ports/port-adsl.inc.php | 167 -- includes/polling/xdsl.inc.php | 8 + misc/config_definitions.json | 14 + misc/db_schema.yaml | 46 +- misc/notifications.rss | 5 + misc/os_schema.json | 6 + resources/lang/en/settings.php | 18 +- resources/lang/fr/settings.php | 162 +- tests/data/draytek_vdsl.json | 2399 +++++++++++++++++ tests/data/teldat.json | 28 +- tests/data/teldat_rs123w-4g.json | 21 + tests/data/teldat_teldatvdsl2.json | 67 + tests/data/teldat_tv-base-vdsl2-adsl.json | 88 + tests/snmpsim/draytek_vdsl.snmprec | 415 +++ 56 files changed, 4079 insertions(+), 278 deletions(-) create mode 100644 LibreNMS/Modules/Xdsl.php create mode 100644 app/Models/PortVdsl.php create mode 100644 database/migrations/2022_08_15_091314_create_ports_vdsl_table.php create mode 100644 database/migrations/2022_09_03_091314_update_ports_adsl_table_with_defaults.php create mode 100644 includes/discovery/xdsl.inc.php create mode 100644 includes/html/graphs/port/vdsl_attainable.inc.php create mode 100644 includes/html/graphs/port/vdsl_power.inc.php create mode 100644 includes/html/graphs/port/vdsl_speed.inc.php rename includes/html/pages/device/port/{adsl.inc.php => xdsl.inc.php} (53%) delete mode 100644 includes/html/pages/device/ports/adsl.inc.php create mode 100644 includes/html/pages/device/ports/xdsl.inc.php create mode 100644 includes/html/print-interface-vdsl.inc.php delete mode 100644 includes/polling/ports/port-adsl.inc.php create mode 100644 includes/polling/xdsl.inc.php create mode 100644 tests/data/draytek_vdsl.json create mode 100644 tests/snmpsim/draytek_vdsl.snmprec diff --git a/LibreNMS/DB/SyncsModels.php b/LibreNMS/DB/SyncsModels.php index 951535ee3e..7b3f59834e 100644 --- a/LibreNMS/DB/SyncsModels.php +++ b/LibreNMS/DB/SyncsModels.php @@ -25,6 +25,7 @@ namespace LibreNMS\DB; +use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Support\Collection; trait SyncsModels @@ -63,7 +64,13 @@ trait SyncsModels } $new = $models->diffKeys($existing); - $device->$relationship()->saveMany($new); + if (is_a($device->$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); + } return $existing->map->first()->merge($new); } diff --git a/LibreNMS/Modules/Xdsl.php b/LibreNMS/Modules/Xdsl.php new file mode 100644 index 0000000000..4bc3f317d1 --- /dev/null +++ b/LibreNMS/Modules/Xdsl.php @@ -0,0 +1,296 @@ +. + * + * @link https://www.librenms.org + * + * @copyright 2022 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Modules; + +use App\Facades\Rrd; +use App\Models\Device; +use App\Models\PortAdsl; +use App\Models\PortVdsl; +use App\Observers\ModuleModelObserver; +use Illuminate\Support\Collection; +use LibreNMS\DB\SyncsModels; +use LibreNMS\Interfaces\Module; +use LibreNMS\OS; +use LibreNMS\RRD\RrdDefinition; +use LibreNMS\Util\Number; + +class Xdsl implements Module +{ + use SyncsModels; + + /** @var string[] */ + private $trimAdminString = ['adslAtucInvVendorID', 'adslAturInvVendorID', 'adslAturInvVersionNumber', 'adslAtucInvVersionNumber']; + /** @var string[] */ + private $adslTenthValues = ['adslAtucCurrSnrMgn', 'adslAtucCurrAtn', 'adslAtucCurrOutputPwr', 'adslAturCurrSnrMgn', 'adslAturCurrAtn', 'adslAturCurrOutputPwr']; + /** @var string[] */ + private $vdslTenthValues = ['xdsl2LineStatusActAtpDs', 'xdsl2LineStatusActAtpUs']; + /** @var string[] */ + private $ifNameMap; + + /** + * @inheritDoc + */ + public function dependencies(): array + { + return ['ports']; + } + + /** + * @inheritDoc + */ + public function discover(OS $os): void + { + //discover if any port has dsl data. We use the pollXdsl functions, with the store parameter set to false + $this->pollAdsl($os, false); + $this->pollVdsl($os, false); + } + + /** + * Poll data for this module and update the DB / RRD. + * Try to keep this efficient and only run if discovery has indicated there is a reason to run. + * Run frequently (default every 5 minutes) + * + * @param \LibreNMS\OS $os + */ + public function poll(OS $os): void + { + //only do polling if at least one portAdsl was discovered + if ($os->getDevice()->portsAdsl()->exists()) { + $this->pollAdsl($os); + } + + if ($os->getDevice()->portsVdsl()->exists()) { + $this->pollVdsl($os); + } + } + + /** + * @inheritDoc + */ + public function cleanup(Device $device): void + { + $device->portsAdsl()->delete(); + $device->portsVdsl()->delete(); + } + + /** + * @inheritDoc + */ + public function dump(Device $device) + { + return [ + 'ports_adsl' => $device->portsAdsl()->orderBy('ifIndex') + ->select(['ports_adsl.*', 'ifIndex']) + ->get()->map->makeHidden(['laravel_through_key', 'port_adsl_updated', 'port_id']), + 'ports_vdsl' => $device->portsVdsl()->orderBy('ifIndex') + ->select(['ports_vdsl.*', 'ifIndex']) + ->get()->map->makeHidden(['laravel_through_key', 'port_vdsl_updated', 'port_id']), + ]; + } + + /** + * Poll data for this module and update the DB / RRD. + * Try to keep this efficient and only run if discovery has indicated there is a reason to run. + * Run frequently (default every 5 minutes) + * + * @param \LibreNMS\OS $os + * @param bool $store + */ + private function pollAdsl(OS $os, $store = true): Collection + { + $adsl = \SnmpQuery::hideMib()->walk('ADSL-LINE-MIB::adslMibObjects')->table(1); + $adslPorts = new Collection; + + foreach ($adsl as $ifIndex => $data) { + // Values are 1/10 + foreach ($this->adslTenthValues as $oid) { + if (isset($data[$oid])) { + $data[$oid] = $data[$oid] / 10; + } + } + + $portAdsl = new PortAdsl($data); + + // trim SnmpAdminStrings + foreach ($this->trimAdminString as $oid) { + $portAdsl->$oid = rtrim($portAdsl->$oid, '.'); + } + + $portAdsl->port_id = $os->ifIndexToId($ifIndex); + + if ($store) { + $this->storeAdsl($portAdsl, $data, (int) $ifIndex, $os); + echo ' ADSL(' . $portAdsl->adslLineCoding . '/' . Number::formatSi($portAdsl->adslAtucChanCurrTxRate, 2, 3, 'bps') . '/' . Number::formatSi($portAdsl->adslAturChanCurrTxRate, 2, 3, 'bps') . ') '; + } + + $adslPorts->push($portAdsl); + } + + ModuleModelObserver::observe(PortAdsl::class); + + return $this->syncModels($os->getDevice(), 'portsAdsl', $adslPorts); + } + + /** + * Poll data for this module and update the DB / RRD. + * Try to keep this efficient and only run if discovery has indicated there is a reason to run. + * Run frequently (default every 5 minutes) + * + * @param \LibreNMS\OS $os + * @param bool $store + */ + private function pollVdsl(OS $os, $store = true): Collection + { + $vdsl = \SnmpQuery::hideMib()->walk(['VDSL2-LINE-MIB::xdsl2ChannelStatusTable', 'VDSL2-LINE-MIB::xdsl2LineTable'])->table(1); + $vdslPorts = new Collection; + + foreach ($vdsl as $ifIndex => $data) { + $portVdsl = new PortVdsl([ + 'port_id' => $os->ifIndexToId($ifIndex), + 'xdsl2ChStatusActDataRateXtur' => $data['xdsl2ChStatusActDataRate']['xtur'] ?? 0, + 'xdsl2ChStatusActDataRateXtuc' => $data['xdsl2ChStatusActDataRate']['xtuc'] ?? 0, + ]); + + foreach ($this->vdslTenthValues as $oid) { + if (isset($data[$oid])) { + $data[$oid] = $data[$oid] / 10; + } + } + + $portVdsl->fill($data); // fill oids that are one to one + + if ($store) { + $this->storeVdsl($portVdsl, $data, (int) $ifIndex, $os); + echo ' VDSL(' . $os->ifIndexToName($ifIndex) . '/' . Number::formatSi($portVdsl->xdsl2LineStatusAttainableRateDs, 2, 3, 'bps') . '/' . Number::formatSi($portVdsl->xdsl2LineStatusAttainableRateUs, 2, 3, 'bps') . ') '; + } + + $vdslPorts->push($portVdsl); + } + + ModuleModelObserver::observe(PortVdsl::class); + + return $this->syncModels($os->getDevice(), 'portsVdsl', $vdslPorts); + } + + private function storeAdsl(PortAdsl $port, array $data, int $ifIndex, OS $os): void + { + $rrd_def = RrdDefinition::make() + ->addDataset('AtucCurrSnrMgn', 'GAUGE', 0, 635) + ->addDataset('AtucCurrAtn', 'GAUGE', 0, 635) + ->addDataset('AtucCurrOutputPwr', 'GAUGE', 0, 635) + ->addDataset('AtucCurrAttainableR', 'GAUGE', 0) + ->addDataset('AtucChanCurrTxRate', 'GAUGE', 0) + ->addDataset('AturCurrSnrMgn', 'GAUGE', 0, 635) + ->addDataset('AturCurrAtn', 'GAUGE', 0, 635) + ->addDataset('AturCurrOutputPwr', 'GAUGE', 0, 635) + ->addDataset('AturCurrAttainableR', 'GAUGE', 0) + ->addDataset('AturChanCurrTxRate', 'GAUGE', 0) + ->addDataset('AtucPerfLofs', 'COUNTER', null, 100000000000) + ->addDataset('AtucPerfLoss', 'COUNTER', null, 100000000000) + ->addDataset('AtucPerfLprs', 'COUNTER', null, 100000000000) + ->addDataset('AtucPerfESs', 'COUNTER', null, 100000000000) + ->addDataset('AtucPerfInits', 'COUNTER', null, 100000000000) + ->addDataset('AturPerfLofs', 'COUNTER', null, 100000000000) + ->addDataset('AturPerfLoss', 'COUNTER', null, 100000000000) + ->addDataset('AturPerfLprs', 'COUNTER', null, 100000000000) + ->addDataset('AturPerfESs', 'COUNTER', null, 100000000000) + ->addDataset('AtucChanCorrectedBl', 'COUNTER', null, 100000000000) + ->addDataset('AtucChanUncorrectBl', 'COUNTER', null, 100000000000) + ->addDataset('AturChanCorrectedBl', 'COUNTER', null, 100000000000) + ->addDataset('AturChanUncorrectBl', 'COUNTER', null, 100000000000); + + $fields = [ + 'AtucCurrSnrMgn' => ($data['adslAtucCurrSnrMgn'] ?? 0) > 1280 ? null : ($data['adslAtucCurrSnrMgn'] ?? null), + 'AtucCurrAtn' => $data['adslAtucCurrAtn'] ?? null, + 'AtucCurrOutputPwr' => $data['adslAtucCurrOutputPwr'] ?? null, + 'AtucCurrAttainableRate' => $data['adslAtucCurrAttainableRate'] ?? null, + 'AtucChanCurrTxRate' => $data['adslAtucChanCurrTxRate'] ?? null, + 'AturCurrSnrMgn' => ($data['adslAturCurrSnrMgn'] ?? 0) > 1280 ? null : ($data['adslAturCurrSnrMgn'] ?? null), + 'AturCurrAtn' => $data['adslAturCurrAtn'] ?? null, + 'AturCurrOutputPwr' => $data['adslAturCurrOutputPwr'] ?? null, + 'AturCurrAttainableRate' => $data['adslAturCurrAttainableRate'] ?? null, + 'AturChanCurrTxRate' => $data['adslAturChanCurrTxRate'] ?? null, + 'AtucPerfLofs' => $data['adslAtucPerfLofs'] ?? null, + 'AtucPerfLoss' => $data['adslAtucPerfLoss'] ?? null, + 'AtucPerfLprs' => $data['adslAtucPerfLprs'] ?? null, + 'AtucPerfESs' => $data['adslAtucPerfESs'] ?? null, + 'AtucPerfInits' => $data['adslAtucPerfInits'] ?? null, + 'AturPerfLofs' => $data['adslAturPerfLofs'] ?? null, + 'AturPerfLoss' => $data['adslAturPerfLoss'] ?? null, + 'AturPerfLprs' => $data['adslAturPerfLprs'] ?? null, + 'AturPerfESs' => $data['adslAturPerfESs'] ?? null, + 'AtucChanCorrectedBlks' => $data['adslAtucChanCorrectedBlks'] ?? null, + 'AtucChanUncorrectBlks' => $data['adslAtucChanUncorrectBlks'] ?? null, + 'AturChanCorrectedBlks' => $data['adslAturChanCorrectedBlks'] ?? null, + 'AturChanUncorrectBlks' => $data['adslAturChanUncorrectBlks'] ?? null, + ]; + + data_update($os->getDeviceArray(), 'adsl', [ + 'ifName' => $os->ifIndexToName($ifIndex), + 'rrd_name' => Rrd::portName($port->port_id, 'adsl'), + 'rrd_def' => $rrd_def, + ], $fields); + } + + private function storeVdsl(PortVdsl $port, array $data, int $ifIndex, OS $os): void + { + // Attainable + data_update($os->getDeviceArray(), 'xdsl2LineStatusAttainableRate', [ + 'ifName' => $os->ifIndexToName($ifIndex), + 'rrd_name' => Rrd::portName($port->port_id, 'xdsl2LineStatusAttainableRate'), + 'rrd_def' => RrdDefinition::make() + ->addDataset('ds', 'GAUGE', 0) + ->addDataset('us', 'GAUGE', 0), + ], [ + 'ds' => $data['xdsl2LineStatusAttainableRateDs'] ?? null, + 'us' => $data['xdsl2LineStatusAttainableRateUs'] ?? null, + ]); + + // actual data rates + data_update($os->getDeviceArray(), 'xdsl2LineStatusActRate', [ + 'ifName' => $os->ifIndexToName($ifIndex), + 'rrd_name' => Rrd::portName($port->port_id, 'xdsl2ChStatusActDataRate'), + 'rrd_dev' => RrdDefinition::make() + ->addDataset('xtuc', 'GAUGE', 0) + ->addDataset('xtur', 'GAUGE', 0), + ], [ + 'xtuc' => $data['xdsl2ChStatusActDataRate']['xtuc'] ?? null, + 'xtur' => $data['xdsl2ChStatusActDataRate']['xtur'] ?? null, + ]); + + // power levels + data_update($os->getDeviceArray(), 'xdsl2LineStatusActAtp', [ + 'ifName' => $os->ifIndexToName($ifIndex), + 'rrd_name' => Rrd::portName($port->port_id, 'xdsl2LineStatusActAtp'), + 'rrd_def' => RrdDefinition::make() + ->addDataset('ds', 'GAUGE', 0) + ->addDataset('us', 'GAUGE', 0), + ], [ + 'ds' => $data['xdsl2LineStatusActAtpDs'] ?? null, + 'us' => $data['xdsl2LineStatusActAtpUs'] ?? null, + ]); + } +} diff --git a/LibreNMS/OS/Traits/ResolvesPortIds.php b/LibreNMS/OS/Traits/ResolvesPortIds.php index 9a5e296832..c68ce08e31 100644 --- a/LibreNMS/OS/Traits/ResolvesPortIds.php +++ b/LibreNMS/OS/Traits/ResolvesPortIds.php @@ -35,6 +35,8 @@ trait ResolvesPortIds * @var array */ private $basePortIdMap; + /** @var string[] */ + private $ifIndexToNameMap; /** * Figure out the port_id from the BRIDGE-MIB::dot1dBasePort @@ -58,6 +60,21 @@ trait ResolvesPortIds return $this->ifIndexToPortIdMap()[$ifIndex] ?? 0; } + /** + * Get IF-MIB::ifName from IF-MIB::ifIndex + * + * @param int|string $ifIndex + * @return string + */ + public function ifIndexToName($ifIndex): string + { + if ($this->ifIndexToNameMap === null) { + $this->ifIndexToNameMap = $this->getDevice()->ports()->pluck('ifName', 'ifIndex')->all(); + } + + return $this->ifIndexToNameMap[$ifIndex] ?? ''; + } + private function ifIndexToPortIdMap(): array { if ($this->ifIndexPortIdMap === null) { diff --git a/app/Models/Device.php b/app/Models/Device.php index bf970557f8..31b34866f0 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -782,6 +782,11 @@ class Device extends BaseModel return $this->hasMany(\App\Models\Port::class, 'device_id', 'device_id'); } + public function portsAdsl(): HasManyThrough + { + return $this->hasManyThrough(\App\Models\PortAdsl::class, \App\Models\Port::class, 'device_id', 'port_id'); + } + public function portsFdb(): HasMany { return $this->hasMany(\App\Models\PortsFdb::class, 'device_id', 'device_id'); @@ -797,6 +802,11 @@ class Device extends BaseModel return $this->hasMany(\App\Models\PortStp::class, 'device_id', 'device_id'); } + public function portsVdsl(): HasManyThrough + { + return $this->hasManyThrough(\App\Models\PortVdsl::class, \App\Models\Port::class, 'device_id', 'port_id'); + } + public function portsVlan(): HasMany { return $this->hasMany(\App\Models\PortVlan::class, 'device_id', 'device_id'); diff --git a/app/Models/Port.php b/app/Models/Port.php index 9b4e9aa7b5..e83c0810db 100644 --- a/app/Models/Port.php +++ b/app/Models/Port.php @@ -29,6 +29,7 @@ class Port extends DeviceRelatedModel static::deleting(function (Port $port) { // delete related data $port->adsl()->delete(); + $port->vdsl()->delete(); $port->fdbEntries()->delete(); $port->ipv4()->delete(); $port->ipv6()->delete(); @@ -279,6 +280,11 @@ class Port extends DeviceRelatedModel return $this->hasMany(PortAdsl::class, 'port_id'); } + public function vdsl(): HasMany + { + return $this->hasMany(PortVdsl::class, 'port_id'); + } + public function events(): MorphMany { return $this->morphMany(Eventlog::class, 'events', 'type', 'reference'); diff --git a/app/Models/PortAdsl.php b/app/Models/PortAdsl.php index 4a9ec5228b..c66aaa66f5 100644 --- a/app/Models/PortAdsl.php +++ b/app/Models/PortAdsl.php @@ -2,9 +2,39 @@ namespace App\Models; -class PortAdsl extends PortRelatedModel +use LibreNMS\Interfaces\Models\Keyable; + +class PortAdsl extends PortRelatedModel implements Keyable { protected $table = 'ports_adsl'; protected $primaryKey = 'port_id'; public $timestamps = false; + protected $fillable = [ + 'port_id', + 'adslLineCoding', + 'adslLineType', + 'adslAtucInvVendorID', + 'adslAtucInvVersionNumber', + 'adslAtucCurrSnrMgn', + 'adslAtucCurrAtn', + 'adslAtucCurrOutputPwr', + 'adslAtucCurrAttainableRate', + 'adslAtucChanCurrTxRate', + 'adslAturInvSerialNumber', + 'adslAturInvVendorID', + 'adslAturInvVersionNumber', + 'adslAturChanCurrTxRate', + 'adslAturCurrSnrMgn', + 'adslAturCurrAtn', + 'adslAturCurrOutputPwr', + 'adslAturCurrAttainableRate', + ]; + + /** + * @inheritDoc + */ + public function getCompositeKey() + { + return $this->port_id; + } } diff --git a/app/Models/PortVdsl.php b/app/Models/PortVdsl.php new file mode 100644 index 0000000000..7158d7abd5 --- /dev/null +++ b/app/Models/PortVdsl.php @@ -0,0 +1,29 @@ +port_id; + } +} diff --git a/database/migrations/2022_08_15_091314_create_ports_vdsl_table.php b/database/migrations/2022_08_15_091314_create_ports_vdsl_table.php new file mode 100644 index 0000000000..679c06ed54 --- /dev/null +++ b/database/migrations/2022_08_15_091314_create_ports_vdsl_table.php @@ -0,0 +1,36 @@ +unsignedInteger('port_id')->unique(); + $table->timestamp('port_vdsl_updated')->useCurrent(); + $table->integer('xdsl2LineStatusAttainableRateDs')->default(0); + $table->integer('xdsl2LineStatusAttainableRateUs')->default(0); + $table->integer('xdsl2ChStatusActDataRateXtur')->default(0); + $table->integer('xdsl2ChStatusActDataRateXtuc')->default(0); + $table->decimal('xdsl2LineStatusActAtpDs')->default(0); + $table->decimal('xdsl2LineStatusActAtpUs')->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('ports_vdsl'); + } +} diff --git a/database/migrations/2022_09_03_091314_update_ports_adsl_table_with_defaults.php b/database/migrations/2022_09_03_091314_update_ports_adsl_table_with_defaults.php new file mode 100644 index 0000000000..5c0ddaa36e --- /dev/null +++ b/database/migrations/2022_09_03_091314_update_ports_adsl_table_with_defaults.php @@ -0,0 +1,63 @@ +string('adslLineCoding', 8)->default('')->change(); + $table->string('adslLineType', 16)->default('')->change(); + $table->string('adslAtucInvVendorID', 16)->default('')->change(); + $table->string('adslAtucInvVersionNumber', 16)->default('')->change(); + $table->decimal('adslAtucCurrSnrMgn', 5, 1)->default(0)->change(); + $table->decimal('adslAtucCurrAtn', 5, 1)->default(0)->change(); + $table->decimal('adslAtucCurrOutputPwr', 5, 1)->default(0)->change(); + $table->integer('adslAtucCurrAttainableRate')->default(0)->change(); + $table->integer('adslAtucChanCurrTxRate')->default(0)->change(); + $table->string('adslAturInvSerialNumber', 32)->default('')->change(); + $table->string('adslAturInvVendorID', 16)->default('')->change(); + $table->string('adslAturInvVersionNumber', 16)->default('')->change(); + $table->integer('adslAturChanCurrTxRate')->default(0)->change(); + $table->decimal('adslAturCurrSnrMgn', 5, 1)->default(0)->change(); + $table->decimal('adslAturCurrAtn', 5, 1)->default(0)->change(); + $table->decimal('adslAturCurrOutputPwr', 5, 1)->default(0)->change(); + $table->integer('adslAturCurrAttainableRate')->default(0)->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('ports_adsl', function (Blueprint $table) { + $table->string('adslLineCoding', 8)->change(); + $table->string('adslLineType', 16)->change(); + $table->string('adslAtucInvVendorID', 8)->change(); + $table->string('adslAtucInvVersionNumber', 8)->change(); + $table->decimal('adslAtucCurrSnrMgn', 5, 1)->change(); + $table->decimal('adslAtucCurrAtn', 5, 1)->change(); + $table->decimal('adslAtucCurrOutputPwr', 5, 1)->change(); + $table->integer('adslAtucCurrAttainableRate')->change(); + $table->integer('adslAtucChanCurrTxRate')->change(); + $table->string('adslAturInvSerialNumber', 8)->change(); + $table->string('adslAturInvVendorID', 8)->change(); + $table->string('adslAturInvVersionNumber', 8)->change(); + $table->integer('adslAturChanCurrTxRate')->change(); + $table->decimal('adslAturCurrSnrMgn', 5, 1)->change(); + $table->decimal('adslAturCurrAtn', 5, 1)->change(); + $table->decimal('adslAturCurrOutputPwr', 5, 1)->change(); + $table->integer('adslAturCurrAttainableRate')->change(); + }); + } +} diff --git a/doc/Support/Configuration.md b/doc/Support/Configuration.md index 00082abc28..b568373fb4 100644 --- a/doc/Support/Configuration.md +++ b/doc/Support/Configuration.md @@ -639,7 +639,6 @@ Please refer to [Port-Description-Parser](../Extensions/Interface-Description-Pa ```bash lnms config:set enable_ports_etherlike false lnms config:set enable_ports_junoseatmvp false -lnms config:set enable_ports_adsl true lnms config:set enable_ports_poe false ``` diff --git a/doc/Support/Discovery Support.md b/doc/Support/Discovery Support.md index 6270c16f3f..b9d3cdd6e1 100644 --- a/doc/Support/Discovery Support.md +++ b/doc/Support/Discovery Support.md @@ -93,7 +93,7 @@ $config['discovery_modules']['bgp-peers'] = true; $config['discovery_modules']['vlans'] = true; $config['discovery_modules']['vmware-vminfo'] = false; $config['discovery_modules']['libvirt-vminfo'] = false; -$config['discovery_modules']['toner'] = false; +$config['discovery_modules']['printer-supplies'] = false; $config['discovery_modules']['ucd-diskio'] = true; $config['discovery_modules']['applications'] = false; $config['discovery_modules']['services'] = true; @@ -103,6 +103,7 @@ $config['discovery_modules']['loadbalancers'] = false; $config['discovery_modules']['mef'] = false; $config['discovery_modules']['wireless'] = true; $config['discovery_modules']['fdb-table'] = true; +$config['discovery_modules']['xdsl'] = false; ``` ## OS based Discovery config @@ -130,6 +131,8 @@ configured to be ignored by config options. `ports-stack`: Same as ports except for stacks. +`xdsl`: Module to collect more metrics for xDSL interfaces. + `entity-physical`: Module to pick up the devices hardware support. `processors`: Processor support for devices. @@ -181,7 +184,7 @@ device, with history data. `libvirt-vminfo`: Detection of libvirt guests. -`toner`: Toner levels support. +`printer-supplies`: Toner levels support. `ucd-diskio`: Disk I/O support. diff --git a/doc/Support/Poller Support.md b/doc/Support/Poller Support.md index c4a5a98f43..368e830b39 100644 --- a/doc/Support/Poller Support.md +++ b/doc/Support/Poller Support.md @@ -74,7 +74,7 @@ $config['poller_modules']['ports'] = true; $config['poller_modules']['nac'] = false; $config['poller_modules']['bgp-peers'] = true; $config['poller_modules']['junose-atm-vp'] = false; -$config['poller_modules']['toner'] = false; +$config['poller_modules']['printer-supplies'] = false; $config['poller_modules']['ucd-diskio'] = true; $config['poller_modules']['wireless'] = true; $config['poller_modules']['ospf'] = true; @@ -102,6 +102,7 @@ $config['poller_modules']['ntp'] = true; $config['poller_modules']['services'] = true; $config['poller_modules']['loadbalancers'] = false; $config['poller_modules']['mef'] = false; +$config['poller_modules']['mef'] = false; ``` ## OS based Poller config @@ -149,13 +150,15 @@ $config['os']['linux']['poller_modules']['unix-agent'] = true; `ports`: This module will detect all ports on a device excluding ones configured to be ignored by config options. +`xdsl`: This module will collect more metrics for xdsl interfaces. + `nac`: Network Access Control (NAC) or 802.1X support. `bgp-peers`: BGP detection and support. `junose-atm-vp`: Juniper ATM support. -`toner`: Toner levels support. +`printer-supplies`: Toner levels support. `ucd-diskio`: Disk I/O support. diff --git a/html/mix-manifest.json b/html/mix-manifest.json index 439f47be48..82e2263402 100644 --- a/html/mix-manifest.json +++ b/html/mix-manifest.json @@ -5,12 +5,12 @@ "/css/app.css": "/css/app.css?id=bd093a6a2e2682bb59ef", "/js/vendor.js": "/js/vendor.js?id=c5fd3d75a63757080dbb", "/js/lang/de.js": "/js/lang/de.js?id=613b5ca9cd06ca15e384", - "/js/lang/en.js": "/js/lang/en.js?id=b4dc5539b25bf7a31718", - "/js/lang/fr.js": "/js/lang/fr.js?id=982d149de32e1867610c", - "/js/lang/it.js": "/js/lang/it.js?id=e24bb9bad83e288b4617", + "/js/lang/en.js": "/js/lang/en.js?id=efa23897934359283288", + "/js/lang/fr.js": "/js/lang/fr.js?id=4540d71a19d8ca7c824b", + "/js/lang/it.js": "/js/lang/it.js?id=71c68fae57a4a3647e43", "/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c", "/js/lang/sr.js": "/js/lang/sr.js?id=388e38b41f63e3517506", - "/js/lang/uk.js": "/js/lang/uk.js?id=34f8698ff09b869db2f5", + "/js/lang/uk.js": "/js/lang/uk.js?id=72f81fcbf77df09d0c82", "/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=4e081fbac70d969894bf", "/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=ed26425647721a42ee9d" } diff --git a/includes/definitions/anyos.yaml b/includes/definitions/anyos.yaml index aa0c0fb1a1..8b37b7f15e 100644 --- a/includes/definitions/anyos.yaml +++ b/includes/definitions/anyos.yaml @@ -12,3 +12,7 @@ discovery: sysDescr: - 'AATO' - 'AAJZ' +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/draytek.yaml b/includes/definitions/draytek.yaml index 2ecde9c704..776ee952ee 100644 --- a/includes/definitions/draytek.yaml +++ b/includes/definitions/draytek.yaml @@ -13,3 +13,7 @@ discovery: - sysDescr_regex: - '/^DrayTek/' +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/gaia.yaml b/includes/definitions/gaia.yaml index 17fb2e1544..eb3dae4282 100644 --- a/includes/definitions/gaia.yaml +++ b/includes/definitions/gaia.yaml @@ -20,3 +20,7 @@ discovery: mib_dir: checkpoint op: contains value: Gaia +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/ies.yaml b/includes/definitions/ies.yaml index 81ac86b456..4eb7e5f7b7 100644 --- a/includes/definitions/ies.yaml +++ b/includes/definitions/ies.yaml @@ -11,3 +11,7 @@ discovery: - .1.3.6.1.4.1.890.1.5.13.7 sysDescr: - IES +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/ies5000.yaml b/includes/definitions/ies5000.yaml index cd6a14643a..ca403a6ddd 100644 --- a/includes/definitions/ies5000.yaml +++ b/includes/definitions/ies5000.yaml @@ -8,4 +8,7 @@ discovery: sysObjectID: - .1.3.6.1.4.1.890.1.5.13.7 - .1.3.6.1.4.1.890.1.5.13.10 - +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/ies52xxM.yaml b/includes/definitions/ies52xxM.yaml index bdc5504488..c4794a7316 100644 --- a/includes/definitions/ies52xxM.yaml +++ b/includes/definitions/ies52xxM.yaml @@ -14,3 +14,7 @@ discovery: - .1.3.6.1.4.1.890.1.5.13.15 - .1.3.6.1.4.1.890.1.5.13.13 - .1.3.6.1.4.1.890.1.5.13.16 +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/ios.yaml b/includes/definitions/ios.yaml index f60e9faa21..2722cfffaa 100644 --- a/includes/definitions/ios.yaml +++ b/includes/definitions/ios.yaml @@ -39,6 +39,7 @@ poller_modules: cisco-otv: true cisco-vpdn: true ipmi: false + xdsl: true discovery_modules: cisco-cef: true slas: true @@ -47,3 +48,4 @@ discovery_modules: cisco-pw: true vrf: true cisco-vrf-lite: true + xdsl: true diff --git a/includes/definitions/iosxe.yaml b/includes/definitions/iosxe.yaml index 61e46bcc91..8bab7b60bf 100644 --- a/includes/definitions/iosxe.yaml +++ b/includes/definitions/iosxe.yaml @@ -24,6 +24,7 @@ poller_modules: ipmi: false cisco-vpdn: true cisco-qfp: true + xdsl: true discovery_modules: cisco-cef: true slas: true @@ -33,6 +34,7 @@ discovery_modules: vrf: true cisco-vrf-lite: true cisco-qfp: true + xdsl: true discovery: - sysDescr: diff --git a/includes/definitions/occamos.yaml b/includes/definitions/occamos.yaml index c5fe7971c1..0c5cf02b73 100644 --- a/includes/definitions/occamos.yaml +++ b/includes/definitions/occamos.yaml @@ -10,3 +10,7 @@ discovery: - sysObjectID: - .1.3.6.1.4.1.6066.1. +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/oneaccess.yaml b/includes/definitions/oneaccess.yaml index 56507d95ce..adfdcc89bb 100644 --- a/includes/definitions/oneaccess.yaml +++ b/includes/definitions/oneaccess.yaml @@ -10,3 +10,7 @@ over: discovery: - sysObjectID: - .1.3.6.1.4.1.13191. +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/pegasus.yaml b/includes/definitions/pegasus.yaml index cabdd83f26..14fbf65583 100644 --- a/includes/definitions/pegasus.yaml +++ b/includes/definitions/pegasus.yaml @@ -10,3 +10,7 @@ discovery: - sysObjectID: - .1.3.6.1.4.1.6368.2 +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/teldat.yaml b/includes/definitions/teldat.yaml index c144f2eb23..e6b5b91c01 100644 --- a/includes/definitions/teldat.yaml +++ b/includes/definitions/teldat.yaml @@ -11,3 +11,7 @@ discovery: - sysObjectID: - .1.3.6.1.4.1.2007. +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/vrp.yaml b/includes/definitions/vrp.yaml index 3d6626dd23..0ac05f80f7 100644 --- a/includes/definitions/vrp.yaml +++ b/includes/definitions/vrp.yaml @@ -17,5 +17,7 @@ discovery: - Versatile Routing Platform Software poller_modules: slas: true + xdsl: true discovery_modules: slas: true + xdsl: true diff --git a/includes/definitions/zxdsl.yaml b/includes/definitions/zxdsl.yaml index ccd0acb2ff..6d9da9a61f 100644 --- a/includes/definitions/zxdsl.yaml +++ b/includes/definitions/zxdsl.yaml @@ -9,3 +9,7 @@ over: discovery: - sysObjectID: [ .1.3.6.1.4.1.3902.1004., .1.3.6.1.4.1.3902.1015. ] +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/definitions/zyxelac.yaml b/includes/definitions/zyxelac.yaml index 5aa68ad2ed..bc0c1e4595 100644 --- a/includes/definitions/zyxelac.yaml +++ b/includes/definitions/zyxelac.yaml @@ -9,3 +9,7 @@ discovery: - '/^AC/' sysObjectID: - '.1.3.6.1.4.1.890' +poller_modules: + xdsl: true +discovery_modules: + xdsl: true diff --git a/includes/discovery/xdsl.inc.php b/includes/discovery/xdsl.inc.php new file mode 100644 index 0000000000..f9ffe90458 --- /dev/null +++ b/includes/discovery/xdsl.inc.php @@ -0,0 +1,8 @@ +discover($os); diff --git a/includes/html/graphs/port/vdsl_attainable.inc.php b/includes/html/graphs/port/vdsl_attainable.inc.php new file mode 100644 index 0000000000..8e024b172f --- /dev/null +++ b/includes/html/graphs/port/vdsl_attainable.inc.php @@ -0,0 +1,25 @@ +port_id . "'")) { - $menu_options['adsl'] = 'ADSL'; +if (PortAdsl::where('port_id', $port->port_id)->exists()) { + $menu_options['xdsl'] = 'xDSL'; +} elseif (PortVdsl::where('port_id', $port->port_id)->exists()) { + $menu_options['xdsl'] = 'xDSL'; } -if (dbFetchCell("SELECT COUNT(*) FROM `ports` WHERE `pagpGroupIfIndex` = '" . $port->ifIndex . "' and `device_id` = '" . $device['device_id'] . "'")) { +if (DeviceCache::getPrimary()->ports()->where('pagpGroupIfIndex', $port->ifIndex)->exists()) { $menu_options['pagp'] = 'PAgP'; } @@ -103,7 +109,7 @@ if (count($components) > 0) { $menu_options['cbqos'] = 'CBQoS'; } -$portModel = \App\Models\Port::find($port->port_id); +$portModel = Port::find($port->port_id); if (LibreNMS\Plugins::countHooks('port_container') || \PluginManager::hasHooks(PortTabHook::class, ['port' => $portModel])) { // Checking if any plugin implements the port_container. If yes, allow to display the menu_option diff --git a/includes/html/pages/device/port/adsl.inc.php b/includes/html/pages/device/port/xdsl.inc.php similarity index 53% rename from includes/html/pages/device/port/adsl.inc.php rename to includes/html/pages/device/port/xdsl.inc.php index 779acf2a4d..18fb1ebe4b 100644 --- a/includes/html/pages/device/port/adsl.inc.php +++ b/includes/html/pages/device/port/xdsl.inc.php @@ -1,6 +1,6 @@ ADSL Current Line Speed'; $graph_type = 'port_adsl_speed'; @@ -26,3 +26,20 @@ if (file_exists(get_port_rrdfile_path($device['hostname'], $port['port_id'], 'ad include 'includes/html/print-interface-graphs.inc.php'; } + +if (Rrd::checkRrdExists(Rrd::name($device['hostname'], Rrd::portName($port['port_id'], 'xdsl2LineStatusAttainableRate')))) { + echo '
VDSL Current Line Speed
'; + $graph_type = 'port_vdsl_speed'; + + include 'includes/html/print-interface-graphs.inc.php'; + + echo '
VDSL Attainable Speed
'; + $graph_type = 'port_vdsl_attainable'; + + include 'includes/html/print-interface-graphs.inc.php'; + + echo '
VDSL Output Powers
'; + $graph_type = 'port_vdsl_power'; + + include 'includes/html/print-interface-graphs.inc.php'; +} diff --git a/includes/html/pages/device/ports.inc.php b/includes/html/pages/device/ports.inc.php index e12ae623b1..5e91f2cafa 100644 --- a/includes/html/pages/device/ports.inc.php +++ b/includes/html/pages/device/ports.inc.php @@ -33,8 +33,8 @@ if (dbFetchCell("SELECT * FROM links AS L, ports AS I WHERE I.device_id = '" . $ $menu_options['neighbours'] = 'Neighbours'; } -if (dbFetchCell("SELECT COUNT(*) FROM `ports` WHERE `ifType` = 'adsl'")) { - $menu_options['adsl'] = 'ADSL'; +if (DeviceCache::getPrimary()->portsAdsl()->exists() || DeviceCache::getPrimary()->portsVdsl()->exists()) { + $menu_options['xdsl'] = 'xDSL'; } $sep = ''; @@ -123,7 +123,7 @@ if ($vars['view'] == 'minigraphs') { } echo ''; -} elseif ($vars['view'] == 'arp' || $vars['view'] == 'adsl' || $vars['view'] == 'neighbours' || $vars['view'] == 'fdb') { +} elseif ($vars['view'] == 'arp' || $vars['view'] == 'xdsl' || $vars['view'] == 'neighbours' || $vars['view'] == 'fdb') { include 'ports/' . $vars['view'] . '.inc.php'; } else { if ($vars['view'] == 'details') { diff --git a/includes/html/pages/device/ports/adsl.inc.php b/includes/html/pages/device/ports/adsl.inc.php deleted file mode 100644 index 86b50f64fd..0000000000 --- a/includes/html/pages/device/ports/adsl.inc.php +++ /dev/null @@ -1,15 +0,0 @@ -"; - -echo ''; -$i = '0'; -$ports = dbFetchRows("select * from `ports` AS P, `ports_adsl` AS A WHERE P.device_id = ? AND A.port_id = P.port_id AND P.deleted = '0' ORDER BY `ifIndex` ASC", [$device['device_id']]); - -foreach ($ports as $port) { - include 'includes/html/print-interface-adsl.inc.php'; - $i++; -} - -echo '
PortTrafficSync SpeedAttainable SpeedAttenuationSNR MarginOutput Powers
'; -echo "
"; diff --git a/includes/html/pages/device/ports/xdsl.inc.php b/includes/html/pages/device/ports/xdsl.inc.php new file mode 100644 index 0000000000..ad1ad232aa --- /dev/null +++ b/includes/html/pages/device/ports/xdsl.inc.php @@ -0,0 +1,28 @@ +"; + +echo ''; +$i = '0'; + +$ports = DeviceCache::getPrimary()->ports()->join('ports_adsl', 'ports.port_id', 'ports_adsl.port_id') + ->where('ports.deleted', '0') + ->orderby('ports.ifIndex', 'ASC') + ->get(); + +foreach ($ports as $port) { + include 'includes/html/print-interface-adsl.inc.php'; + $i++; +} + +$ports = DeviceCache::getPrimary()->ports()->join('ports_vdsl', 'ports.port_id', '=', 'ports_vdsl.port_id') + ->where('ports.deleted', '0') + ->orderby('ports.ifIndex', 'ASC') + ->get(); + +foreach ($ports as $port) { + include 'includes/html/print-interface-vdsl.inc.php'; + $i++; +} +echo '
PortTrafficSync SpeedAttainable SpeedAttenuationSNR MarginOutput Powers
'; +echo "
"; diff --git a/includes/html/pages/ports.inc.php b/includes/html/pages/ports.inc.php index 13993e3fab..a569df45d3 100644 --- a/includes/html/pages/ports.inc.php +++ b/includes/html/pages/ports.inc.php @@ -13,6 +13,7 @@ * @author LibreNMS Contributors */ +use App\Models\Device; use App\Models\Port; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -92,11 +93,11 @@ if ((isset($vars['searchbar']) && $vars['searchbar'] != 'hide') || ! isset($vars $output .= "