mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
New device:add code (#13842)
* New device:add code pre-requisite for updating other code paths includes option to set display name separate validation code from device creation * remove duplicate community and v3 creds * style fixes * some lint fixes * fix phpstan * Exception cleanup improved messages and translations * port association mode to enum well, pseudo enum * defaults and cleanups * fixed/improved validation messages * fix tests * fix stupid ide refactor mistake * lint fixes
This commit is contained in:
75
LibreNMS/Enum/PortAssociationMode.php
Normal file
75
LibreNMS/Enum/PortAssociationMode.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* PortAssociationMode.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 LibreNMS\Enum;
|
||||
|
||||
class PortAssociationMode
|
||||
{
|
||||
const ifIndex = 1;
|
||||
const ifName = 2;
|
||||
const ifDescr = 3;
|
||||
const ifAlias = 4;
|
||||
|
||||
/**
|
||||
* Get mode names keyed by id
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getModes(): array
|
||||
{
|
||||
return [
|
||||
self::ifIndex => 'ifIndex',
|
||||
self::ifName => 'ifName',
|
||||
self::ifDescr => 'ifDescr',
|
||||
self::ifAlias => 'ifAlias',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a named port association mode to an integer for storage
|
||||
*
|
||||
* @param string $name
|
||||
* @return int|null
|
||||
*/
|
||||
public static function getId(string $name): ?int
|
||||
{
|
||||
$names = array_flip(self::getModes());
|
||||
|
||||
return $names[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of given port association mode id
|
||||
*
|
||||
* @param int $id
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getName(int $id): ?string
|
||||
{
|
||||
$modes = self::getModes();
|
||||
|
||||
return $modes[$id] ?? null;
|
||||
}
|
||||
}
|
@@ -27,4 +27,31 @@ namespace LibreNMS\Exceptions;
|
||||
|
||||
class HostIpExistsException extends HostExistsException
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $hostname;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $existing_hostname;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ip;
|
||||
|
||||
public function __construct(string $hostname, string $existing_hostname, string $ip)
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
$this->existing_hostname = $existing_hostname;
|
||||
$this->ip = $ip;
|
||||
|
||||
$message = trans('exceptions.host_exists.ip_exists', [
|
||||
'hostname' => $hostname,
|
||||
'existing' => $existing_hostname,
|
||||
'ip' => $ip,
|
||||
]);
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
28
LibreNMS/Exceptions/HostSysnameExistsException.php
Normal file
28
LibreNMS/Exceptions/HostSysnameExistsException.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Exceptions;
|
||||
|
||||
class HostSysnameExistsException extends HostExistsException
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $hostname;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $sysname;
|
||||
|
||||
public function __construct(string $hostname, string $sysname)
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
$this->sysname = $sysname;
|
||||
|
||||
$message = trans('exceptions.host_exists.sysname_exists', [
|
||||
'hostname' => $hostname,
|
||||
'sysname' => $sysname,
|
||||
]);
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
@@ -42,11 +42,21 @@ class HostUnreachableException extends \Exception
|
||||
/**
|
||||
* Add additional reasons
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $snmpVersion
|
||||
* @param string $credentials
|
||||
*/
|
||||
public function addReason($message)
|
||||
public function addReason(string $snmpVersion, string $credentials)
|
||||
{
|
||||
$this->reasons[] = $message;
|
||||
$vars = [
|
||||
'snmpver' => $snmpVersion,
|
||||
'credentials' => $credentials,
|
||||
];
|
||||
|
||||
if ($snmpVersion == 'v3') {
|
||||
$this->reasons[] = trans('exceptions.host_unreachable.no_reply_credentials', $vars);
|
||||
} else {
|
||||
$this->reasons[] = trans('exceptions.host_unreachable.no_reply_community', $vars);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -25,6 +25,29 @@
|
||||
|
||||
namespace LibreNMS\Exceptions;
|
||||
|
||||
use LibreNMS\Util\IP;
|
||||
|
||||
class HostUnreachablePingException extends HostUnreachableException
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $hostname;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ip;
|
||||
|
||||
public function __construct(string $hostname)
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
$this->ip = gethostbyname($hostname);
|
||||
|
||||
$message = trans('exceptions.host_unreachable.unpingable', [
|
||||
'hostname' => $hostname,
|
||||
'ip' => IP::isValid($this->ip) ? $this->ip : trans('exceptions.host_unreachable.unresolvable'),
|
||||
]);
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
@@ -27,4 +27,17 @@ namespace LibreNMS\Exceptions;
|
||||
|
||||
class HostUnreachableSnmpException extends HostUnreachableException
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $hostname;
|
||||
|
||||
public function __construct(string $hostname)
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
$message = trans('exceptions.host_unreachable.unsnmpable', [
|
||||
'hostname' => $hostname,
|
||||
]);
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
26
LibreNMS/Exceptions/HostnameExistsException.php
Normal file
26
LibreNMS/Exceptions/HostnameExistsException.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Exceptions;
|
||||
|
||||
class HostnameExistsException extends HostExistsException
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $hostname;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $existing;
|
||||
|
||||
public function __construct(string $hostname)
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
|
||||
$message = trans('exceptions.host_exists.hostname_exists', [
|
||||
'hostname' => $hostname,
|
||||
]);
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
@@ -27,4 +27,16 @@ namespace LibreNMS\Exceptions;
|
||||
|
||||
class SnmpVersionUnsupportedException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $snmpVersion;
|
||||
|
||||
public function __construct(string $snmpVersion)
|
||||
{
|
||||
$this->snmpVersion = $snmpVersion;
|
||||
$message = trans('exceptions.snmp_version_unsupported.message', ['snmpver' => $snmpVersion]);
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\Exceptions\HostUnreachableException;
|
||||
|
||||
$init_modules = [];
|
||||
@@ -39,7 +40,7 @@ if (isset($options['f']) && $options['f'] == 0) {
|
||||
}
|
||||
|
||||
$port_assoc_mode = Config::get('default_port_association_mode');
|
||||
$valid_assoc_modes = get_port_assoc_modes();
|
||||
$valid_assoc_modes = PortAssociationMode::getModes();
|
||||
if (isset($options['p'])) {
|
||||
$port_assoc_mode = $options['p'];
|
||||
if (! in_array($port_assoc_mode, $valid_assoc_modes)) {
|
||||
|
235
app/Actions/Device/ValidateDeviceAndCreate.php
Normal file
235
app/Actions/Device/ValidateDeviceAndCreate.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/*
|
||||
* ValidateDeviceAndCreate.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package LibreNMS
|
||||
* @link http://librenms.org
|
||||
* @copyright 2022 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Actions\Device;
|
||||
|
||||
use App\Models\Device;
|
||||
use Illuminate\Support\Arr;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Exceptions\HostIpExistsException;
|
||||
use LibreNMS\Exceptions\HostnameExistsException;
|
||||
use LibreNMS\Exceptions\HostSysnameExistsException;
|
||||
use LibreNMS\Exceptions\HostUnreachablePingException;
|
||||
use LibreNMS\Exceptions\HostUnreachableSnmpException;
|
||||
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
||||
use LibreNMS\Modules\Core;
|
||||
use SnmpQuery;
|
||||
|
||||
class ValidateDeviceAndCreate
|
||||
{
|
||||
/**
|
||||
* @var \App\Models\Device
|
||||
*/
|
||||
private $device;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $force;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $ping_fallback;
|
||||
/**
|
||||
* @var \LibreNMS\Polling\ConnectivityHelper
|
||||
*/
|
||||
private $connectivity;
|
||||
|
||||
public function __construct(Device $device, bool $force = false, bool $ping_fallback = false)
|
||||
{
|
||||
$this->device = $device;
|
||||
$this->force = $force;
|
||||
$this->ping_fallback = $ping_fallback;
|
||||
$this->connectivity = new \LibreNMS\Polling\ConnectivityHelper($this->device);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*
|
||||
* @throws \LibreNMS\Exceptions\HostExistsException
|
||||
* @throws \LibreNMS\Exceptions\HostUnreachablePingException
|
||||
* @throws \LibreNMS\Exceptions\HostUnreachableException
|
||||
* @throws \LibreNMS\Exceptions\SnmpVersionUnsupportedException
|
||||
*/
|
||||
public function execute(): bool
|
||||
{
|
||||
if ($this->device->exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->exceptIfHostnameExists();
|
||||
|
||||
// defaults
|
||||
$this->device->os = $this->device->os ?: 'generic';
|
||||
$this->device->status_reason = '';
|
||||
$this->device->sysName = $this->device->sysName ?: $this->device->hostname;
|
||||
|
||||
if (! $this->force) {
|
||||
$this->exceptIfIpExists();
|
||||
|
||||
if (! $this->connectivity->isPingable()->success()) {
|
||||
throw new HostUnreachablePingException($this->device->hostname);
|
||||
}
|
||||
|
||||
$this->detectCredentials();
|
||||
$this->cleanCredentials();
|
||||
|
||||
$this->device->sysName = SnmpQuery::device($this->device)->get('SNMPv2-MIB::sysName.0')->value();
|
||||
$this->exceptIfSysNameExists();
|
||||
|
||||
$this->device->os = Core::detectOS($this->device);
|
||||
}
|
||||
|
||||
return $this->device->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \LibreNMS\Exceptions\HostUnreachableException
|
||||
* @throws \LibreNMS\Exceptions\SnmpVersionUnsupportedException
|
||||
*/
|
||||
private function detectCredentials(): void
|
||||
{
|
||||
if ($this->device->snmp_disable) {
|
||||
return;
|
||||
}
|
||||
|
||||
$host_unreachable_exception = new HostUnreachableSnmpException($this->device->hostname);
|
||||
|
||||
// which snmp version should we try (and in what order)
|
||||
$snmp_versions = $this->device->snmpver ? [$this->device->snmpver] : Config::get('snmp.version');
|
||||
|
||||
$communities = \LibreNMS\Config::get('snmp.community');
|
||||
if ($this->device->community) {
|
||||
array_unshift($communities, $this->device->community);
|
||||
}
|
||||
$communities = array_unique($communities);
|
||||
|
||||
$v3_credentials = \LibreNMS\Config::get('snmp.v3');
|
||||
array_unshift($v3_credentials, $this->device->only(['authlevel', 'authname', 'authpass', 'authalgo', 'cryptopass', 'cryptoalgo']));
|
||||
$v3_credentials = array_unique($v3_credentials, SORT_REGULAR);
|
||||
|
||||
foreach ($snmp_versions as $snmp_version) {
|
||||
$this->device->snmpver = $snmp_version;
|
||||
|
||||
if ($snmp_version === 'v3') {
|
||||
// Try each set of parameters from config
|
||||
foreach ($v3_credentials as $v3) {
|
||||
$this->device->fill(Arr::only($v3, ['authlevel', 'authname', 'authpass', 'authalgo', 'cryptopass', 'cryptoalgo']));
|
||||
|
||||
if ($this->connectivity->isSNMPable()) {
|
||||
return;
|
||||
} else {
|
||||
$host_unreachable_exception->addReason($snmp_version, $this->device->authname . '/' . $this->device->authlevel);
|
||||
}
|
||||
}
|
||||
} elseif ($snmp_version === 'v2c' || $snmp_version === 'v1') {
|
||||
// try each community from config
|
||||
foreach ($communities as $community) {
|
||||
$this->device->community = $community;
|
||||
if ($this->connectivity->isSNMPable()) {
|
||||
return;
|
||||
} else {
|
||||
$host_unreachable_exception->addReason($snmp_version, $this->device->community);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new SnmpVersionUnsupportedException($snmp_version);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->ping_fallback) {
|
||||
$this->device->snmp_disable = 1;
|
||||
$this->device->os = 'ping';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw $host_unreachable_exception;
|
||||
}
|
||||
|
||||
private function cleanCredentials(): void
|
||||
{
|
||||
if ($this->device->snmpver == 'v3') {
|
||||
$this->device->community = null;
|
||||
} else {
|
||||
$this->device->authlevel = null;
|
||||
$this->device->authname = null;
|
||||
$this->device->authalgo = null;
|
||||
$this->device->cryptopass = null;
|
||||
$this->device->cryptoalgo = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \LibreNMS\Exceptions\HostExistsException
|
||||
*/
|
||||
private function exceptIfHostnameExists(): void
|
||||
{
|
||||
if (Device::where('hostname', $this->device->hostname)->exists()) {
|
||||
throw new HostnameExistsException($this->device->hostname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \LibreNMS\Exceptions\HostExistsException
|
||||
*/
|
||||
private function exceptIfIpExists(): void
|
||||
{
|
||||
if ($this->device->overwrite_ip) {
|
||||
$ip = $this->device->overwrite_ip;
|
||||
} elseif (Config::get('addhost_alwayscheckip')) {
|
||||
$ip = gethostbyname($this->device->hostname);
|
||||
} else {
|
||||
$ip = $this->device->hostname;
|
||||
}
|
||||
|
||||
$existing = Device::findByIp($ip);
|
||||
|
||||
if ($existing) {
|
||||
throw new HostIpExistsException($this->device->hostname, $existing->hostname, $ip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a device with match hostname or sysname exists in the database.
|
||||
* Throw and error if they do.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \LibreNMS\Exceptions\HostExistsException
|
||||
*/
|
||||
private function exceptIfSysNameExists(): void
|
||||
{
|
||||
if (Config::get('allow_duplicate_sysName')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Device::where('sysName', $this->device->sysName)
|
||||
->when(Config::get('mydomain'), function ($query, $domain) {
|
||||
$query->orWhere('sysName', rtrim($this->device->sysName, '.') . '.' . $domain);
|
||||
})->exists()) {
|
||||
throw new HostSysnameExistsException($this->device->hostname, $this->device->sysName);
|
||||
}
|
||||
}
|
||||
}
|
147
app/Console/Commands/DeviceAdd.php
Normal file
147
app/Console/Commands/DeviceAdd.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Actions\Device\ValidateDeviceAndCreate;
|
||||
use App\Console\LnmsCommand;
|
||||
use App\Models\Device;
|
||||
use App\Models\PollerGroup;
|
||||
use Exception;
|
||||
use Illuminate\Validation\Rule;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\Exceptions\HostExistsException;
|
||||
use LibreNMS\Exceptions\HostnameExistsException;
|
||||
use LibreNMS\Exceptions\HostUnreachableException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class DeviceAdd extends LnmsCommand
|
||||
{
|
||||
/**
|
||||
* The name of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'device:add';
|
||||
/**
|
||||
* Valid values for options
|
||||
*
|
||||
* @var string[][]|null
|
||||
*/
|
||||
protected $optionValues;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->optionValues = [
|
||||
'transport' => ['udp', 'udp6', 'tcp', 'tcp6'],
|
||||
'port-association-mode' => PortAssociationMode::getModes(),
|
||||
'auth-protocol' => \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms(),
|
||||
'privacy-protocol' => \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms(),
|
||||
];
|
||||
|
||||
$this->addArgument('device spec', InputArgument::REQUIRED);
|
||||
$this->addOption('v1', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('v2c', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('v3', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('display-name', 'd', InputOption::VALUE_REQUIRED);
|
||||
$this->addOption('force', 'f', InputOption::VALUE_NONE);
|
||||
$this->addOption('poller-group', 'g', InputOption::VALUE_REQUIRED, null, Config::get('default_poller_group'));
|
||||
$this->addOption('ping-fallback', 'b', InputOption::VALUE_NONE);
|
||||
$this->addOption('port-association-mode', 'p', InputOption::VALUE_REQUIRED, null, Config::get('default_port_association_mode'));
|
||||
$this->addOption('community', 'c', InputOption::VALUE_REQUIRED);
|
||||
$this->addOption('transport', 't', InputOption::VALUE_REQUIRED, null, 'udp');
|
||||
$this->addOption('port', 'r', InputOption::VALUE_REQUIRED, null, 161);
|
||||
$this->addOption('security-name', 'u', InputOption::VALUE_REQUIRED, null, 'root');
|
||||
$this->addOption('auth-password', 'A', InputOption::VALUE_REQUIRED);
|
||||
$this->addOption('auth-protocol', 'a', InputOption::VALUE_REQUIRED, null, 'MD5');
|
||||
$this->addOption('privacy-password', 'X', InputOption::VALUE_REQUIRED);
|
||||
$this->addOption('privacy-protocol', 'x', InputOption::VALUE_REQUIRED, null, 'AES');
|
||||
$this->addOption('ping-only', 'P', InputOption::VALUE_NONE);
|
||||
$this->addOption('os', 'o', InputOption::VALUE_REQUIRED, null, 'ping');
|
||||
$this->addOption('hardware', 'w', InputOption::VALUE_REQUIRED);
|
||||
$this->addOption('sysName', 's', InputOption::VALUE_REQUIRED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->configureOutputOptions();
|
||||
|
||||
$this->validate([
|
||||
'port' => 'numeric|between:1,65535',
|
||||
'poller-group' => ['numeric', Rule::in(PollerGroup::pluck('id')->prepend(0))],
|
||||
]);
|
||||
|
||||
$auth = $this->option('auth-password');
|
||||
$priv = $this->option('privacy-password');
|
||||
$device = new Device([
|
||||
'hostname' => $this->argument('device spec'),
|
||||
'display' => $this->option('display-name'),
|
||||
'snmpver' => $this->option('v3') ? 'v3' : ($this->option('v2c') ? 'v2c' : ($this->option('v1') ? 'v1' : '')),
|
||||
'port' => $this->option('port'),
|
||||
'transport' => $this->option('transport'),
|
||||
'poller_group' => $this->option('poller-group'),
|
||||
'port_association_mode' => PortAssociationMode::getId($this->option('port-association-mode')),
|
||||
'community' => $this->option('community'),
|
||||
'authlevel' => ($auth ? 'auth' : 'noAuth') . (($priv && $auth) ? 'Priv' : 'NoPriv'),
|
||||
'authname' => $this->option('security-name'),
|
||||
'authpass' => $this->option('auth-password'),
|
||||
'authalgo' => $this->option('auth-protocol'),
|
||||
'cryptopass' => $this->option('privacy-password'),
|
||||
'cryptoalgo' => $this->option('privacy-protocol'),
|
||||
]);
|
||||
|
||||
if ($this->option('ping-only')) {
|
||||
$device->snmp_disable = 1;
|
||||
$device->os = $this->option('os');
|
||||
$device->hardware = $this->option('hardware');
|
||||
$device->sysName = $this->option('sysName');
|
||||
}
|
||||
|
||||
try {
|
||||
$result = (new ValidateDeviceAndCreate($device, $this->option('force'), $this->option('ping-fallback')))->execute();
|
||||
|
||||
if (! $result) {
|
||||
$this->error(trans('commands.device:add.messages.save_failed', ['hostname' => $device->hostname]));
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
$this->info(trans('commands.device:add.messages.added', ['hostname' => $device->hostname, 'device_id' => $device->device_id]));
|
||||
|
||||
return 0;
|
||||
} catch (HostUnreachableException $e) {
|
||||
// host unreachable errors
|
||||
$this->error($e->getMessage() . PHP_EOL . implode(PHP_EOL, $e->getReasons()));
|
||||
$this->line(trans('commands.device:add.messages.try_force'));
|
||||
|
||||
return 1;
|
||||
} catch (HostExistsException $e) {
|
||||
// host exists errors
|
||||
$this->error($e->getMessage());
|
||||
|
||||
if (! $e instanceof HostnameExistsException) {
|
||||
$this->line(trans('commands.device:add.messages.try_force'));
|
||||
}
|
||||
|
||||
return 2;
|
||||
} catch (Exception $e) {
|
||||
// other errors?
|
||||
$this->error(get_class($e) . ': ' . $e->getMessage());
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,6 +26,7 @@
|
||||
namespace App\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use LibreNMS\Util\Debug;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
@@ -35,6 +36,9 @@ abstract class LnmsCommand extends Command
|
||||
{
|
||||
protected $developer = false;
|
||||
|
||||
/** @var string[][]|null */
|
||||
protected $optionValues;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
@@ -97,6 +101,10 @@ abstract class LnmsCommand extends Command
|
||||
$description = __('commands.' . $this->getName() . '.options.' . $name);
|
||||
}
|
||||
|
||||
if (isset($this->optionValues[$name])) {
|
||||
$description .= ' [' . implode(', ', $this->optionValues[$name]) . ']';
|
||||
}
|
||||
|
||||
parent::addOption($name, $shortcut, $mode, $description, $default);
|
||||
|
||||
return $this;
|
||||
@@ -108,6 +116,19 @@ abstract class LnmsCommand extends Command
|
||||
*/
|
||||
protected function validate(array $rules, array $messages = []): array
|
||||
{
|
||||
// auto create option value rules if they don't exist
|
||||
if (isset($this->optionValues)) {
|
||||
foreach ($this->optionValues as $option => $values) {
|
||||
if (empty($rules[$option])) {
|
||||
$rules[$option] = Rule::in($values);
|
||||
$messages[$option . '.in'] = trans('commands.lnms.validation-errors.optionValue', [
|
||||
'option' => $option,
|
||||
'values' => implode(', ', $values),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$error_messages = trans('commands.' . $this->getName() . '.validation-errors');
|
||||
$validator = Validator::make(
|
||||
$this->arguments() + $this->options(),
|
||||
|
@@ -79,7 +79,7 @@ class Device extends BaseModel
|
||||
|
||||
// ---- Helper Functions ----
|
||||
|
||||
public static function findByHostname($hostname)
|
||||
public static function findByHostname(string $hostname): ?Device
|
||||
{
|
||||
return static::where('hostname', $hostname)->first();
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class Device extends BaseModel
|
||||
return $overwrite_ip ?: $hostname;
|
||||
}
|
||||
|
||||
public static function findByIp($ip)
|
||||
public static function findByIp(?string $ip): ?Device
|
||||
{
|
||||
if (! IP::isValid($ip)) {
|
||||
return null;
|
||||
@@ -561,8 +561,8 @@ class Device extends BaseModel
|
||||
return $query->whereIn(
|
||||
$query->qualifyColumn('device_id'), function ($query) use ($deviceGroup) {
|
||||
$query->select('device_id')
|
||||
->from('device_group_device')
|
||||
->where('device_group_id', $deviceGroup);
|
||||
->from('device_group_device')
|
||||
->where('device_group_id', $deviceGroup);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -572,8 +572,8 @@ class Device extends BaseModel
|
||||
return $query->whereNotIn(
|
||||
$query->qualifyColumn('device_id'), function ($query) use ($deviceGroup) {
|
||||
$query->select('device_id')
|
||||
->from('device_group_device')
|
||||
->where('device_group_id', $deviceGroup);
|
||||
->from('device_group_device')
|
||||
->where('device_group_id', $deviceGroup);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -583,8 +583,8 @@ class Device extends BaseModel
|
||||
return $query->whereIn(
|
||||
$query->qualifyColumn('device_id'), function ($query) use ($serviceTemplate) {
|
||||
$query->select('device_id')
|
||||
->from('service_templates_device')
|
||||
->where('service_template_id', $serviceTemplate);
|
||||
->from('service_templates_device')
|
||||
->where('service_template_id', $serviceTemplate);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -594,8 +594,8 @@ class Device extends BaseModel
|
||||
return $query->whereNotIn(
|
||||
$query->qualifyColumn('device_id'), function ($query) use ($serviceTemplate) {
|
||||
$query->select('device_id')
|
||||
->from('service_templates_device')
|
||||
->where('service_template_id', $serviceTemplate);
|
||||
->from('service_templates_device')
|
||||
->where('service_template_id', $serviceTemplate);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@@ -651,47 +651,6 @@ function format_hostname($device): string
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return valid port association modes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_port_assoc_modes()
|
||||
{
|
||||
return [
|
||||
1 => 'ifIndex',
|
||||
2 => 'ifName',
|
||||
3 => 'ifDescr',
|
||||
4 => 'ifAlias',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get DB id of given port association mode name
|
||||
*
|
||||
* @param string $port_assoc_mode
|
||||
* @return int
|
||||
*/
|
||||
function get_port_assoc_mode_id($port_assoc_mode)
|
||||
{
|
||||
$modes = array_flip(get_port_assoc_modes());
|
||||
|
||||
return isset($modes[$port_assoc_mode]) ? $modes[$port_assoc_mode] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of given port association_mode ID
|
||||
*
|
||||
* @param int $port_assoc_mode_id Port association mode ID
|
||||
* @return bool
|
||||
*/
|
||||
function get_port_assoc_mode_name($port_assoc_mode_id)
|
||||
{
|
||||
$modes = get_port_assoc_modes();
|
||||
|
||||
return isset($modes[$port_assoc_mode_id]) ? $modes[$port_assoc_mode_id] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query all ports of the given device (by ID) and build port array and
|
||||
* port association maps for ifIndex, ifName, ifDescr. Query port stats
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// Build SNMP Cache Array
|
||||
use App\Models\PortGroup;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\Util\StringHelpers;
|
||||
|
||||
$descrSnmpFlags = '-OQUs';
|
||||
@@ -42,7 +43,7 @@ d_echo($port_stats);
|
||||
// compatibility reasons.
|
||||
$port_association_mode = Config::get('default_port_association_mode');
|
||||
if ($device['port_association_mode']) {
|
||||
$port_association_mode = get_port_assoc_mode_name($device['port_association_mode']);
|
||||
$port_association_mode = PortAssociationMode::getName($device['port_association_mode']);
|
||||
}
|
||||
|
||||
// Build array of ports in the database and an ifIndex/ifName -> port_id map
|
||||
|
@@ -12,15 +12,17 @@ use App\Models\Device;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\Exceptions\HostExistsException;
|
||||
use LibreNMS\Exceptions\HostIpExistsException;
|
||||
use LibreNMS\Exceptions\HostnameExistsException;
|
||||
use LibreNMS\Exceptions\HostSysnameExistsException;
|
||||
use LibreNMS\Exceptions\HostUnreachableException;
|
||||
use LibreNMS\Exceptions\HostUnreachablePingException;
|
||||
use LibreNMS\Exceptions\HostUnreachableSnmpException;
|
||||
use LibreNMS\Exceptions\InvalidPortAssocModeException;
|
||||
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
||||
use LibreNMS\Modules\Core;
|
||||
use LibreNMS\Util\IPv4;
|
||||
use LibreNMS\Util\IPv6;
|
||||
use LibreNMS\Util\Proxy;
|
||||
|
||||
function array_sort_by_column($array, $on, $order = SORT_ASC)
|
||||
@@ -112,24 +114,6 @@ function logfile($string)
|
||||
fclose($fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an array of regexes against a subject if any match, return true
|
||||
*
|
||||
* @param string $subject the string to match against
|
||||
* @param array|string $regexes an array of regexes or single regex to check
|
||||
* @return bool if any of the regexes matched, return true
|
||||
*/
|
||||
function preg_match_any($subject, $regexes)
|
||||
{
|
||||
foreach ((array) $regexes as $regex) {
|
||||
if (preg_match($regex, $subject)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform comparison of two items based on give comparison method
|
||||
* Valid comparisons: =, !=, ==, !==, >=, <=, >, <, contains, starts, ends, regex
|
||||
@@ -201,36 +185,6 @@ function percent_colour($perc)
|
||||
return sprintf('#%02x%02x%02x', $r, $b, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $device
|
||||
* @return string the logo image path for this device. Images are often wide, not square.
|
||||
*/
|
||||
function getLogo($device)
|
||||
{
|
||||
$img = getImageName($device, true, 'images/logos/');
|
||||
if (! Str::startsWith($img, 'generic')) {
|
||||
return 'images/logos/' . $img;
|
||||
}
|
||||
|
||||
return getIcon($device);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $device
|
||||
* @param string $class to apply to the image tag
|
||||
* @return string an image tag with the logo for this device. Images are often wide, not square.
|
||||
*/
|
||||
function getLogoTag($device, $class = null)
|
||||
{
|
||||
$tag = '<img src="' . url(getLogo($device)) . '" title="' . getImageTitle($device) . '"';
|
||||
if (isset($class)) {
|
||||
$tag .= " class=\"$class\" ";
|
||||
}
|
||||
$tag .= ' />';
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $device
|
||||
* @return string the path to the icon image for this device. Close to square.
|
||||
@@ -330,12 +284,12 @@ function addHost($host, $snmp_version = '', $port = 161, $transport = 'udp', $po
|
||||
{
|
||||
// Test Database Exists
|
||||
if (host_exists($host)) {
|
||||
throw new HostExistsException("Already have host $host");
|
||||
throw new HostnameExistsException($host);
|
||||
}
|
||||
|
||||
// Valid port assoc mode
|
||||
if (! in_array($port_assoc_mode, get_port_assoc_modes())) {
|
||||
throw new InvalidPortAssocModeException("Invalid port association_mode '$port_assoc_mode'. Valid modes are: " . join(', ', get_port_assoc_modes()));
|
||||
if (! in_array($port_assoc_mode, PortAssociationMode::getModes())) {
|
||||
throw new InvalidPortAssocModeException("Invalid port association_mode '$port_assoc_mode'. Valid modes are: " . join(', ', PortAssociationMode::getModes()));
|
||||
}
|
||||
|
||||
// check if we have the host by IP
|
||||
@@ -348,19 +302,14 @@ function addHost($host, $snmp_version = '', $port = 161, $transport = 'udp', $po
|
||||
} else {
|
||||
$ip = $host;
|
||||
}
|
||||
if ($force_add !== true && $device = device_has_ip($ip)) {
|
||||
$message = "Cannot add $host, already have device with this IP $ip";
|
||||
if ($ip != $device->hostname) {
|
||||
$message .= " ($device->hostname)";
|
||||
}
|
||||
$message .= '. You may force add to ignore this.';
|
||||
throw new HostIpExistsException($message);
|
||||
if ($force_add !== true && $existing = device_has_ip($ip)) {
|
||||
throw new HostIpExistsException($host, $existing->hostname, $ip);
|
||||
}
|
||||
|
||||
// Test reachability
|
||||
if (! $force_add) {
|
||||
if (! ((new \LibreNMS\Polling\ConnectivityHelper(new Device(['hostname' => $ip])))->isPingable()->success())) {
|
||||
throw new HostUnreachablePingException("Could not ping $host");
|
||||
throw new HostUnreachablePingException($host);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,7 +323,7 @@ function addHost($host, $snmp_version = '', $port = 161, $transport = 'udp', $po
|
||||
if (isset($additional['snmp_disable']) && $additional['snmp_disable'] == 1) {
|
||||
return createHost($host, '', $snmp_version, $port, $transport, [], $poller_group, 1, true, $overwrite_ip, $additional);
|
||||
}
|
||||
$host_unreachable_exception = new HostUnreachableException("Could not connect to $host, please check the snmp details and snmp reachability");
|
||||
$host_unreachable_exception = new HostUnreachableSnmpException($host);
|
||||
// try different snmp variables to add the device
|
||||
foreach ($snmpvers as $snmpver) {
|
||||
if ($snmpver === 'v3') {
|
||||
@@ -384,7 +333,7 @@ function addHost($host, $snmp_version = '', $port = 161, $transport = 'udp', $po
|
||||
if ($force_add === true || isSNMPable($device)) {
|
||||
return createHost($host, null, $snmpver, $port, $transport, $v3, $poller_group, $port_assoc_mode, $force_add, $overwrite_ip);
|
||||
} else {
|
||||
$host_unreachable_exception->addReason("SNMP $snmpver: No reply with credentials " . $v3['authname'] . '/' . $v3['authlevel']);
|
||||
$host_unreachable_exception->addReason($snmpver, $v3['authname'] . '/' . $v3['authlevel']);
|
||||
}
|
||||
}
|
||||
} elseif ($snmpver === 'v2c' || $snmpver === 'v1') {
|
||||
@@ -395,11 +344,11 @@ function addHost($host, $snmp_version = '', $port = 161, $transport = 'udp', $po
|
||||
if ($force_add === true || isSNMPable($device)) {
|
||||
return createHost($host, $community, $snmpver, $port, $transport, [], $poller_group, $port_assoc_mode, $force_add, $overwrite_ip);
|
||||
} else {
|
||||
$host_unreachable_exception->addReason("SNMP $snmpver: No reply with community $community");
|
||||
$host_unreachable_exception->addReason($snmpver, $community);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new SnmpVersionUnsupportedException("Unsupported SNMP Version \"$snmpver\", must be v1, v2c, or v3");
|
||||
throw new SnmpVersionUnsupportedException($snmpver);
|
||||
}
|
||||
}
|
||||
if (isset($additional['ping_fallback']) && $additional['ping_fallback'] == 1) {
|
||||
@@ -422,7 +371,7 @@ function deviceArray($host, $community, $snmpver, $port = 161, $transport = 'udp
|
||||
/* Get port_assoc_mode id if neccessary
|
||||
* We can work with names of IDs here */
|
||||
if (! is_int($port_assoc_mode)) {
|
||||
$port_assoc_mode = get_port_assoc_mode_id($port_assoc_mode);
|
||||
$port_assoc_mode = PortAssociationMode::getId($port_assoc_mode);
|
||||
}
|
||||
$device['port_association_mode'] = $port_assoc_mode;
|
||||
|
||||
@@ -518,7 +467,7 @@ function createHost(
|
||||
/* Get port_assoc_mode id if necessary
|
||||
* We can work with names of IDs here */
|
||||
if (! is_int($port_assoc_mode)) {
|
||||
$port_assoc_mode = get_port_assoc_mode_id($port_assoc_mode);
|
||||
$port_assoc_mode = PortAssociationMode::getId($port_assoc_mode);
|
||||
}
|
||||
|
||||
$device = new Device(array_merge([
|
||||
@@ -543,7 +492,7 @@ function createHost(
|
||||
|
||||
$device->sysName = SnmpQuery::device($device)->get('SNMPv2-MIB::sysName.0')->value();
|
||||
if (host_exists($host, $device->sysName)) {
|
||||
throw new HostExistsException("Already have host $host ({$device->sysName}) due to duplicate sysName");
|
||||
throw new HostSysnameExistsException($host, $device->sysName);
|
||||
}
|
||||
}
|
||||
if ($device->save()) {
|
||||
@@ -920,23 +869,7 @@ function fix_integer_value($value)
|
||||
*/
|
||||
function device_has_ip($ip)
|
||||
{
|
||||
if (IPv6::isValid($ip)) {
|
||||
$ip_address = \App\Models\Ipv6Address::query()
|
||||
->where('ipv6_address', IPv6::parse($ip, true)->uncompressed())
|
||||
->with('port.device')
|
||||
->first();
|
||||
} elseif (IPv4::isValid($ip)) {
|
||||
$ip_address = \App\Models\Ipv4Address::query()
|
||||
->where('ipv4_address', $ip)
|
||||
->with('port.device')
|
||||
->first();
|
||||
}
|
||||
|
||||
if (isset($ip_address) && $ip_address->port) {
|
||||
return $ip_address->port->device;
|
||||
}
|
||||
|
||||
return false; // not an ipv4 or ipv6 address...
|
||||
return Device::findByIp($ip);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1312,17 +1245,6 @@ function q_bridge_bits2indices($hex_data)
|
||||
return $indices;
|
||||
}
|
||||
|
||||
function update_device_logo(&$device)
|
||||
{
|
||||
$icon = getImageName($device, false);
|
||||
if ($icon != $device['icon']) {
|
||||
log_event('Device Icon changed ' . $device['icon'] . " => $icon", $device, 'system', 3);
|
||||
$device['icon'] = $icon;
|
||||
dbUpdate(['icon' => $icon], 'devices', 'device_id=?', [$device['device_id']]);
|
||||
echo "Changed Icon! : $icon\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to generate Mac OUI Cache
|
||||
*/
|
||||
|
@@ -95,3 +95,23 @@ if (! function_exists('trans_fb')) {
|
||||
return ($key === ($translation = trans($key, $replace, $locale))) ? $fallback : $translation;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('preg_match_any')) {
|
||||
/**
|
||||
* Check an array of regexes against a subject if any match, return true
|
||||
*
|
||||
* @param string $subject the string to match against
|
||||
* @param array|string $regexes an array of regexes or single regex to check
|
||||
* @return bool if any of the regexes matched, return true
|
||||
*/
|
||||
function preg_match_any($subject, $regexes)
|
||||
{
|
||||
foreach ((array) $regexes as $regex) {
|
||||
if (preg_match($regex, $subject)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\Exceptions\HostUnreachableException;
|
||||
use LibreNMS\Util\IP;
|
||||
|
||||
@@ -181,7 +182,7 @@ foreach (Config::get('snmp.transports') as $transport) {
|
||||
<select name="port_assoc_mode" id="port_assoc_mode" class="form-control input-sm">
|
||||
<?php
|
||||
|
||||
foreach (get_port_assoc_modes() as $mode) {
|
||||
foreach (PortAssociationMode::getModes() as $mode) {
|
||||
$selected = '';
|
||||
if ($mode == Config::get('default_port_association_mode')) {
|
||||
$selected = 'selected';
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
|
||||
if ($_POST['editing']) {
|
||||
if (Auth::user()->hasGlobalAdmin()) {
|
||||
@@ -286,7 +287,7 @@ echo " </select>
|
||||
<select name='port_assoc_mode' id='port_assoc_mode' class='form-control input-sm'>
|
||||
";
|
||||
|
||||
foreach (get_port_assoc_modes() as $pam_id => $pam) {
|
||||
foreach (PortAssociationMode::getModes() as $pam_id => $pam) {
|
||||
echo " <option value='$pam_id'";
|
||||
|
||||
if ($pam_id == $device['port_association_mode']) {
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// Build SNMP Cache Array
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\RRD\RrdDefinition;
|
||||
use LibreNMS\Util\Debug;
|
||||
use LibreNMS\Util\Number;
|
||||
@@ -460,7 +461,7 @@ d_echo($port_stats);
|
||||
// compatibility reasons.
|
||||
$port_association_mode = Config::get('default_port_association_mode');
|
||||
if ($device['port_association_mode']) {
|
||||
$port_association_mode = get_port_assoc_mode_name($device['port_association_mode']);
|
||||
$port_association_mode = PortAssociationMode::getName($device['port_association_mode']);
|
||||
}
|
||||
|
||||
$ports_found = [];
|
||||
|
@@ -7190,6 +7190,11 @@ parameters:
|
||||
count: 1
|
||||
path: LibreNMS/Validator.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Device\\:\\:\\$authlevel \\('authNoPriv'\\|'authPriv'\\|'noAuthNoPriv'\\) does not accept null\\.$#"
|
||||
count: 1
|
||||
path: app/Actions/Device/ValidateDeviceAndCreate.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\ApiClients\\\\BaseApi\\:\\:\\$base_uri has no type specified\\.$#"
|
||||
count: 1
|
||||
@@ -9020,26 +9025,6 @@ parameters:
|
||||
count: 1
|
||||
path: app/Models/Config.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\Device\\:\\:findByHostname\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/Device.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\Device\\:\\:findByHostname\\(\\) has parameter \\$hostname with no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/Device.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\Device\\:\\:findByIp\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/Device.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\Device\\:\\:findByIp\\(\\) has parameter \\$ip with no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Models/Device.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Models\\\\Device\\:\\:forgetAttrib\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
@@ -10210,71 +10195,6 @@ parameters:
|
||||
count: 1
|
||||
path: database/migrations/2021_02_09_122930_migrate_to_utf8mb4.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testCLIping\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testCLIsnmpV1\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testCLIsnmpV2\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testCLIsnmpV3UserAndPW\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testPortAssociationMode\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testSnmpTransport\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testSnmpV3AuthProtocol\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:testSnmpV3PrivacyProtocol\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Property LibreNMS\\\\Tests\\\\AddHostCliTest\\:\\:\\$hostName has no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostCliTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostTest\\:\\:testAddping\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostTest\\:\\:testAddsnmpV1\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostTest\\:\\:testAddsnmpV2\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostTest.php
|
||||
|
||||
-
|
||||
message: "#^Method LibreNMS\\\\Tests\\\\AddHostTest\\:\\:testAddsnmpV3\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/AddHostTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$transport of function addHost expects string, int given\\.$#"
|
||||
count: 1
|
||||
|
@@ -64,6 +64,43 @@ return [
|
||||
'removed' => 'Device :id removed',
|
||||
'updated' => 'Device :hostname (:id) updated',
|
||||
],
|
||||
'device:add' => [
|
||||
'description' => 'Add a new device',
|
||||
'arguments' => [
|
||||
'device spec' => 'Hostname or IP to add',
|
||||
],
|
||||
'options' => [
|
||||
'v1' => 'Use SNMP v1',
|
||||
'v2c' => 'Use SNMP v2c',
|
||||
'v3' => 'Use SNMP v3',
|
||||
'display-name' => 'A string to display as the name of this device, defaults to hostname. May be a simple template using replacements: {{ $hostname }}, {{ $sysName }}, {{ $sysName_fallback }}, {{ $ip }}',
|
||||
'force' => 'Just add the device, do not make any safety checks',
|
||||
'group' => 'Poller group (for distributed polling)',
|
||||
'ping-fallback' => 'Add the device as ping only if it does not respond to SNMP',
|
||||
'port-association-mode' => 'Sets how ports are mapped. ifName is suggested for Linux/Unix',
|
||||
'community' => 'SNMP v1 or v2 community',
|
||||
'transport' => 'Transport to connect to the device',
|
||||
'port' => 'SNMP transport port',
|
||||
'security-name' => 'SNMPv3 security username',
|
||||
'auth-password' => 'SNMPv3 authentication password',
|
||||
'auth-protocol' => 'SNMPv3 authentication protocol',
|
||||
'privacy-protocol' => 'SNMPv3 privacy protocol',
|
||||
'privacy-password' => 'SNMPv3 privacy password',
|
||||
'ping-only' => 'Add a ping only device',
|
||||
'os' => 'Ping only: specify OS',
|
||||
'hardware' => 'Ping only: specify hardware',
|
||||
'sysName' => 'Ping only: specify sysName',
|
||||
],
|
||||
'validation-errors' => [
|
||||
'port.between' => 'Port should be 1-65535',
|
||||
'poller-group.in' => 'The given poller-group does not exist',
|
||||
],
|
||||
'messages' => [
|
||||
'save_failed' => 'Failed to save device :hostname',
|
||||
'try_force' => 'You my try with the --force option to skip safety checks',
|
||||
'added' => 'Added device :hostname (:device_id)',
|
||||
],
|
||||
],
|
||||
'device:ping' => [
|
||||
'description' => 'Ping device and record data for response',
|
||||
'arguments' => [
|
||||
@@ -104,6 +141,11 @@ return [
|
||||
'required' => 'Either old key or --generate-new-key is required.',
|
||||
],
|
||||
],
|
||||
'lnms' => [
|
||||
'validation-errors' => [
|
||||
'optionValue' => 'Selected :option is invalid. Should be one of: :values',
|
||||
],
|
||||
],
|
||||
'smokeping:generate' => [
|
||||
'args-nonsense' => 'Use one of --probes and --targets',
|
||||
'config-insufficient' => 'In order to generate a smokeping configuration, you must have set "smokeping.probes", "fping", and "fping6" set in your configuration',
|
||||
|
@@ -16,6 +16,18 @@ return [
|
||||
'title' => 'Error: Could not write to file',
|
||||
'message' => 'Failed to write to file (:file). Please check permissions and SELinux/AppArmor if applicable.',
|
||||
],
|
||||
'host_exists' => [
|
||||
'hostname_exists' => 'Device :hostname already exists',
|
||||
'ip_exists' => 'Cannot add :hostname, already have device :existing with this IP :ip',
|
||||
'sysname_exists' => 'Already have device :hostname due to duplicate sysName: :sysname',
|
||||
],
|
||||
'host_unreachable' => [
|
||||
'unpingable' => 'Could not ping :hostname (:ip)',
|
||||
'unsnmpable' => 'Could not connect to :hostname, please check the snmp details and snmp reachability',
|
||||
'unresolvable' => 'Hostname did not resolve to IP',
|
||||
'no_reply_community' => 'SNMP :version: No reply with community :credentials',
|
||||
'no_reply_credentials' => 'SNMP :version: No reply with credentials :credentials',
|
||||
],
|
||||
'ldap_missing' => [
|
||||
'title' => 'PHP LDAP support missing',
|
||||
'message' => 'PHP does not support LDAP, please install or enable the PHP LDAP extension',
|
||||
@@ -28,4 +40,7 @@ return [
|
||||
'title' => 'Error caused by PHP version mismatch',
|
||||
'message' => 'The version of PHP your web server is running (:web_version) does not match the CLI version (:cli_version)',
|
||||
],
|
||||
'snmp_version_unsupported' => [
|
||||
'message' => 'Unsupported SNMP Version ":snmpver", must be v1, v2c, or v3',
|
||||
],
|
||||
];
|
||||
|
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Device;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use LibreNMS\Exceptions\HostUnreachableException;
|
||||
use LibreNMS\Util\Debug;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/*
|
||||
@@ -29,117 +26,6 @@ Artisan::command('device:rename
|
||||
]))->setTimeout(null)->setIdleTimeout(null)->setTty(true)->run();
|
||||
})->purpose(__('Rename a device, this can be used to change the hostname or IP of a device'));
|
||||
|
||||
Artisan::command('device:add
|
||||
{device spec : Hostname or IP to add}
|
||||
{--v1 : ' . __('Use SNMP v1') . '}
|
||||
{--v2c : ' . __('Use SNMP v2c') . '}
|
||||
{--v3 : ' . __('Use SNMP v3') . '}
|
||||
{--f|force : ' . __('Just add the device, do not make any safety checks') . '}
|
||||
{--g|group= : ' . __('Poller group (for distributed polling)') . '}
|
||||
{--b|ping-fallback : ' . __('Add the device as ping only if it does not respond to SNMP') . '}
|
||||
{--p|port-association-mode=ifIndex : ' . __('Sets how ports are mapped :modes, ifName is suggested for Linux/Unix', ['modes' => '[ifIndex, ifName, ifDescr, ifAlias]']) . '}
|
||||
{--c|community= : ' . __('SNMP v1 or v2 community') . '}
|
||||
{--t|transport=udp : ' . __('Transport to connect to the device') . ' [udp, udp6, tcp, tcp6]}
|
||||
{--r|port=161 : ' . __('SNMP transport port') . '}
|
||||
{--u|security-name=root : ' . __('SNMPv3 security username') . '}
|
||||
{--A|auth-password= : ' . __('SNMPv3 authentication password') . '}
|
||||
{--a|auth-protocol=md5 : ' . __('SNMPv3 authentication protocol') . ' [' . implode(', ', \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms()) . ']}
|
||||
{--x|privacy-protocol=aes : ' . __('SNMPv3 privacy protocol') . ' [' . implode(', ', \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms()) . ']}
|
||||
{--X|privacy-password= : ' . __('SNMPv3 privacy password') . '}
|
||||
{--P|ping-only : ' . __('Add a ping only device') . '}
|
||||
{--o|os=ping : ' . __('Ping only: specify OS') . '}
|
||||
{--w|hardware= : ' . __('Ping only: specify hardware') . '}
|
||||
{--s|sysName= : ' . __('Ping only: specify sysName') . '}
|
||||
', function () {
|
||||
/** @var \Illuminate\Console\Command $this */
|
||||
// Value Checks
|
||||
if (! in_array($this->option('port-association-mode'), ['ifIndex', 'ifName', 'ifDescr', 'ifAlias'])) {
|
||||
$this->error(__('Invalid port association mode'));
|
||||
}
|
||||
|
||||
if (! in_array($this->option('transport'), ['udp', 'udp6', 'tcp', 'tcp6'])) {
|
||||
$this->error(__('Invalid SNMP transport'));
|
||||
}
|
||||
|
||||
if (! in_array($this->option('auth-protocol'), \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms())) {
|
||||
$this->error(__('Invalid authentication protocol'));
|
||||
}
|
||||
|
||||
if (! in_array($this->option('privacy-protocol'), \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms())) {
|
||||
$this->error(__('Invalid privacy protocol'));
|
||||
}
|
||||
|
||||
$port = (int) $this->option('port');
|
||||
if ($port < 1 || $port > 65535) {
|
||||
$this->error(__('Port should be 1-65535'));
|
||||
}
|
||||
|
||||
// build additional
|
||||
$additional = [
|
||||
'os' => $this->option('os'),
|
||||
'hardware' => $this->option('hardware'),
|
||||
'sysName' => $this->option('sysName'),
|
||||
];
|
||||
if ($this->option('ping-only')) {
|
||||
$additional['snmp_disable'] = 1;
|
||||
} elseif ($this->option('ping-fallback')) {
|
||||
$additional['ping_fallback'] = 1;
|
||||
}
|
||||
|
||||
if ($this->option('community')) {
|
||||
$community_config = \LibreNMS\Config::get('snmp.community');
|
||||
array_unshift($community_config, $this->option('community'));
|
||||
\LibreNMS\Config::set('snmp.community', $community_config);
|
||||
}
|
||||
$auth = $this->option('auth-password');
|
||||
$priv = $this->option('privacy-password');
|
||||
$v3_config = \LibreNMS\Config::get('snmp.v3');
|
||||
array_unshift($v3_config, [
|
||||
'authlevel' => ($auth ? 'auth' : 'noAuth') . (($priv && $auth) ? 'Priv' : 'NoPriv'),
|
||||
'authname' => $this->option('security-name'),
|
||||
'authpass' => $this->option('auth-password'),
|
||||
'authalgo' => $this->option('auth-protocol'),
|
||||
'cryptopass' => $this->option('privacy-password'),
|
||||
'cryptoalgo' => $this->option('privacy-protocol'),
|
||||
]);
|
||||
\LibreNMS\Config::set('snmp.v3', $v3_config);
|
||||
|
||||
try {
|
||||
$init_modules = [];
|
||||
include base_path('includes/init.php');
|
||||
|
||||
if (($verbosity = $this->getOutput()->getVerbosity()) >= 128) {
|
||||
Debug::set();
|
||||
if ($verbosity >= 256) {
|
||||
Debug::setVerbose();
|
||||
}
|
||||
}
|
||||
|
||||
$device_id = addHost(
|
||||
$this->argument('device spec'),
|
||||
$this->option('v3') ? 'v3' : ($this->option('v2c') ? 'v2c' : ($this->option('v1') ? 'v1' : '')),
|
||||
$port,
|
||||
$this->option('transport'),
|
||||
$this->option('group'),
|
||||
$this->option('force'),
|
||||
$this->option('port-association-mode'),
|
||||
$additional
|
||||
);
|
||||
$hostname = Device::where('device_id', $device_id)->value('hostname');
|
||||
$this->info("Added device $hostname ($device_id)");
|
||||
|
||||
return 0;
|
||||
} catch (HostUnreachableException $e) {
|
||||
$this->error($e->getMessage() . PHP_EOL . implode(PHP_EOL, $e->getReasons()));
|
||||
|
||||
return 1;
|
||||
} catch (Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
|
||||
return 3;
|
||||
}
|
||||
})->purpose('Add a new device');
|
||||
|
||||
Artisan::command('device:remove
|
||||
{device spec : ' . __('Hostname, IP, or device id to remove') . '}
|
||||
', function () {
|
||||
|
@@ -31,12 +31,16 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
class AddHostCliTest extends DBTestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/** @var string */
|
||||
private $hostName = 'testHost';
|
||||
|
||||
public function testCLIsnmpV1()
|
||||
public function testCLIsnmpV1(): void
|
||||
{
|
||||
$result = \Artisan::call('device:add ' . $this->hostName . ' -force -ccommunity --v1');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $this->hostName, '--force' => true, '-c' => 'community', '--v1' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($this->hostName);
|
||||
$this->assertNotNull($device);
|
||||
|
||||
@@ -45,10 +49,12 @@ class AddHostCliTest extends DBTestCase
|
||||
$this->assertEquals('v1', $device->snmpver, 'Wrong snmp version');
|
||||
}
|
||||
|
||||
public function testCLIsnmpV2()
|
||||
public function testCLIsnmpV2(): void
|
||||
{
|
||||
$result = \Artisan::call('device:add ' . $this->hostName . ' -force -ccommunity --v2c');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $this->hostName, '--force' => true, '-c' => 'community', '--v2c' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($this->hostName);
|
||||
$this->assertNotNull($device);
|
||||
|
||||
@@ -57,10 +63,12 @@ class AddHostCliTest extends DBTestCase
|
||||
$this->assertEquals('v2c', $device->snmpver, 'Wrong snmp version');
|
||||
}
|
||||
|
||||
public function testCLIsnmpV3UserAndPW()
|
||||
public function testCLIsnmpV3UserAndPW(): void
|
||||
{
|
||||
$result = \Artisan::call('device:add ' . $this->hostName . ' -force -uSecName -AAuthPW -XPrivPW --v3');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $this->hostName, '--force' => true, '-u' => 'SecName', '-A' => 'AuthPW', '-X' => 'PrivPW', '--v3' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($this->hostName);
|
||||
$this->assertNotNull($device);
|
||||
|
||||
@@ -72,26 +80,30 @@ class AddHostCliTest extends DBTestCase
|
||||
$this->assertEquals('v3', $device->snmpver, 'Wrong snmp version');
|
||||
}
|
||||
|
||||
public function testPortAssociationMode()
|
||||
public function testPortAssociationMode(): void
|
||||
{
|
||||
$modes = ['ifIndex', 'ifName', 'ifDescr', 'ifAlias'];
|
||||
foreach ($modes as $index => $mode) {
|
||||
$host = 'hostName' . $mode;
|
||||
$result = \Artisan::call('device:add ' . $host . ' -force -p ' . $mode . ' --v1');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $host, '--force' => true, '-p' => $mode, '--v1' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($host);
|
||||
$this->assertNotNull($device);
|
||||
$this->assertEquals($index + 1, $device->port_association_mode, 'Wrong port association mode ' . $mode);
|
||||
}
|
||||
}
|
||||
|
||||
public function testSnmpTransport()
|
||||
public function testSnmpTransport(): void
|
||||
{
|
||||
$modes = ['udp', 'udp6', 'tcp', 'tcp6'];
|
||||
foreach ($modes as $mode) {
|
||||
$host = 'hostName' . $mode;
|
||||
$result = \Artisan::call('device:add ' . $host . ' -force -t ' . $mode . ' --v1');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $host, '--force' => true, '-t' => $mode, '--v1' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($host);
|
||||
$this->assertNotNull($device);
|
||||
|
||||
@@ -99,13 +111,15 @@ class AddHostCliTest extends DBTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testSnmpV3AuthProtocol()
|
||||
public function testSnmpV3AuthProtocol(): void
|
||||
{
|
||||
$modes = ['MD5', 'SHA', 'SHA-224', 'SHA-256', 'SHA-384', 'SHA-512'];
|
||||
$modes = \LibreNMS\SNMPCapabilities::supportedAuthAlgorithms();
|
||||
foreach ($modes as $mode) {
|
||||
$host = 'hostName' . $mode;
|
||||
$result = \Artisan::call('device:add ' . $host . ' -force -a ' . $mode . ' --v3');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $host, '--force' => true, '-a' => $mode, '--v3' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($host);
|
||||
$this->assertNotNull($device);
|
||||
|
||||
@@ -113,13 +127,15 @@ class AddHostCliTest extends DBTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testSnmpV3PrivacyProtocol()
|
||||
public function testSnmpV3PrivacyProtocol(): void
|
||||
{
|
||||
$modes = ['DES', 'AES', 'AES-192', 'AES-256', 'AES-256-C'];
|
||||
$modes = \LibreNMS\SNMPCapabilities::supportedCryptoAlgorithms();
|
||||
foreach ($modes as $mode) {
|
||||
$host = 'hostName' . $mode;
|
||||
$result = \Artisan::call('device:add ' . $host . ' -force -x ' . $mode . ' --v3');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $host, '--force' => true, '-x' => $mode, '--v3' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($host);
|
||||
$this->assertNotNull($device);
|
||||
|
||||
@@ -127,10 +143,11 @@ class AddHostCliTest extends DBTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testCLIping()
|
||||
public function testCLIping(): void
|
||||
{
|
||||
$result = \Artisan::call('device:add ' . $this->hostName . ' -force -P -onameOfOS -whardware -sSystem --v1');
|
||||
$this->assertEquals(0, $result, 'command returned non zero value');
|
||||
$this->artisan('device:add', ['device spec' => $this->hostName, '--force' => true, '-P' => true, '-o' => 'nameOfOS', '-w' => 'hardware', '-s' => 'System', '--v1' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
|
||||
$device = Device::findByHostname($this->hostName);
|
||||
$this->assertNotNull($device);
|
||||
@@ -140,4 +157,14 @@ class AddHostCliTest extends DBTestCase
|
||||
$this->assertEquals('nameOfOS', $device->os, 'Wrong os name');
|
||||
$this->assertEquals('system', $device->sysName, 'Wrong system name');
|
||||
}
|
||||
|
||||
public function testExistingDevice(): void
|
||||
{
|
||||
$this->artisan('device:add', ['device spec' => 'existing', '--force' => true])
|
||||
->assertExitCode(0)
|
||||
->execute();
|
||||
$this->artisan('device:add', ['device spec' => 'existing'])
|
||||
->assertExitCode(2)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ class AddHostTest extends DBTestCase
|
||||
use DatabaseTransactions;
|
||||
private $host = 'testHost';
|
||||
|
||||
public function testAddsnmpV1()
|
||||
public function testAddsnmpV1(): void
|
||||
{
|
||||
addHost($this->host, 'v1', 111, 'tcp', 0, true, 'ifIndex');
|
||||
$device = Device::findByHostname($this->host);
|
||||
@@ -47,7 +47,7 @@ class AddHostTest extends DBTestCase
|
||||
$this->assertEquals('tcp', $device->transport, 'Wrong snmp transport (udp/tcp)');
|
||||
}
|
||||
|
||||
public function testAddsnmpV2()
|
||||
public function testAddsnmpV2(): void
|
||||
{
|
||||
addHost($this->host, 'v2c', 111, 'tcp', 0, true, 'ifName');
|
||||
$device = Device::findByHostname($this->host);
|
||||
@@ -59,7 +59,7 @@ class AddHostTest extends DBTestCase
|
||||
$this->assertEquals('v2c', $device->snmpver, 'Wrong snmp version');
|
||||
}
|
||||
|
||||
public function testAddsnmpV3()
|
||||
public function testAddsnmpV3(): void
|
||||
{
|
||||
addHost($this->host, 'v3', 111, 'tcp', 0, true, 'ifIndex');
|
||||
$device = Device::findByHostname($this->host);
|
||||
@@ -73,7 +73,7 @@ class AddHostTest extends DBTestCase
|
||||
$this->assertEquals(Config::get('snmp.v3')[0]['authpass'], $device->authpass, 'Wrong snmp v3 password');
|
||||
}
|
||||
|
||||
public function testAddping()
|
||||
public function testAddping(): void
|
||||
{
|
||||
$additional = [
|
||||
'snmp_disable' => 1,
|
||||
|
@@ -27,6 +27,7 @@ namespace LibreNMS\Tests;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Enum\PortAssociationMode;
|
||||
use LibreNMS\Util\Clean;
|
||||
use LibreNMS\Util\Validate;
|
||||
|
||||
@@ -232,10 +233,10 @@ class CommonFunctionsTest extends TestCase
|
||||
4 => 'ifAlias',
|
||||
];
|
||||
|
||||
$this->assertEquals($modes, get_port_assoc_modes());
|
||||
$this->assertEquals('ifIndex', get_port_assoc_mode_name(1));
|
||||
$this->assertEquals(1, get_port_assoc_mode_id('ifIndex'));
|
||||
$this->assertFalse(get_port_assoc_mode_name(666));
|
||||
$this->assertFalse(get_port_assoc_mode_id('lucifer'));
|
||||
$this->assertEquals($modes, PortAssociationMode::getModes());
|
||||
$this->assertEquals('ifIndex', PortAssociationMode::getName(1));
|
||||
$this->assertEquals(1, PortAssociationMode::getId('ifIndex'));
|
||||
$this->assertNull(PortAssociationMode::getName(666));
|
||||
$this->assertNull(PortAssociationMode::getId('lucifer'));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user