Alternate Poller IP instead of Hostname (#10981)

* optional alternative poller ip

* add missing schema update

* .

* enhance API Call 'add_device' with overwrite_ip key

* .

* .

* updating docs
This commit is contained in:
SourceDoctor
2020-01-30 06:20:30 -06:00
committed by GitHub
parent dc60edd8bf
commit 7950893cd1
14 changed files with 103 additions and 12 deletions
+18
View File
@@ -103,6 +103,24 @@ class Device extends BaseModel
return static::where('hostname', $hostname)->first();
}
/**
* Returns IP/Hostname where polling will be targeted to
*
* @param string $hostname hostname which will be triggered
* @return string IP/Hostname to which Device polling is targeted
*/
public static function pollerTarget($hostname)
{
$ret = static::where('hostname', $hostname)->first(['hostname', 'overwrite_ip']);
if (empty($ret)) {
return $hostname;
}
$_overwrite_ip = $ret->overwrite_ip;
$_hostname = $ret->hostname;
return $_overwrite_ip ?: $_hostname;
}
public static function findByIp($ip)
{
if (!IP::isValid($ip)) {
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddOverwriteIpToDevices extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('devices', function (Blueprint $table) {
$table->string('overwrite_ip', 40)->nullable()->after('ip');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('devices', function (Blueprint $table) {
$table->dropColumn('overwrite_ip');
});
}
}
+1
View File
@@ -1018,6 +1018,7 @@ Route: `/api/v0/devices`
Input (JSON):
- hostname: device hostname
- overwrite_ip: alternate polling IP. Will be use instead of hostname (optional)
- port: SNMP port (defaults to port defined in config).
- transport: SNMP protocol (defaults to transport defined in config).
- version: SNMP version to use, v1, v2c or v3. Defaults to v2c.
+5 -1
View File
@@ -33,7 +33,11 @@ Using the web interface, go to Devices and click Add Device. Enter the
details required for the device that you want to add and then click
'Add Host'. As an example, if your device is configured to use the
community `my_company` using snmp `v2c` then you would enter: SNMP
Port defaults to 161
Port defaults to 161.
By default Hostname will be used for polling data. If you want
to get polling Device data via a specific IP-Addresse (e.g. Management IP)
fill out the optional field `Overwrite IP` with it's IP-Addresse.
![Add device](/img/webui_add_device.png)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 29 KiB

+17 -7
View File
@@ -11,6 +11,7 @@
*
*/
use App\Models\Device;
use LibreNMS\Config;
use LibreNMS\Exceptions\HostExistsException;
use LibreNMS\Exceptions\HostIpExistsException;
@@ -542,8 +543,14 @@ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $
throw new InvalidPortAssocModeException("Invalid port association_mode '$port_assoc_mode'. Valid modes are: " . join(', ', get_port_assoc_modes()));
}
if ($additional['overwrite_ip']) {
$overwrite_ip = $additional['overwrite_ip'];
}
// check if we have the host by IP
if (Config::get('addhost_alwayscheckip') === true) {
if (!empty($overwrite_ip)) {
$ip = $overwrite_ip;
} elseif (Config::get('addhost_alwayscheckip') === true) {
$ip = gethostbyname($host);
} else {
$ip = $host;
@@ -560,7 +567,7 @@ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $
// Test reachability
if (!$force_add) {
$address_family = snmpTransportToAddressFamily($transport);
$ping_result = isPingable($host, $address_family);
$ping_result = isPingable($ip, $address_family);
if (!$ping_result['result']) {
throw new HostUnreachablePingException("Could not ping $host");
}
@@ -574,7 +581,7 @@ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $
}
if (isset($additional['snmp_disable']) && $additional['snmp_disable'] == 1) {
return createHost($host, '', $snmp_version, $port, $transport, array(), $poller_group, 1, true, $additional);
return createHost($host, '', $snmp_version, $port, $transport, array(), $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");
// try different snmp variables to add the device
@@ -584,7 +591,7 @@ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $
foreach (Config::get('snmp.v3') as $v3) {
$device = deviceArray($host, null, $snmpver, $port, $transport, $v3, $port_assoc_mode);
if ($force_add === true || isSNMPable($device)) {
return createHost($host, null, $snmpver, $port, $transport, $v3, $poller_group, $port_assoc_mode, $force_add);
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']);
}
@@ -595,7 +602,7 @@ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $
$device = deviceArray($host, $community, $snmpver, $port, $transport, null, $port_assoc_mode);
if ($force_add === true || isSNMPable($device)) {
return createHost($host, $community, $snmpver, $port, $transport, array(), $poller_group, $port_assoc_mode, $force_add);
return createHost($host, $community, $snmpver, $port, $transport, array(), $poller_group, $port_assoc_mode, $force_add, $overwrite_ip);
} else {
$host_unreachable_exception->addReason("SNMP $snmpver: No reply with community $community");
}
@@ -607,7 +614,7 @@ function addHost($host, $snmp_version = '', $port = '161', $transport = 'udp', $
if (isset($additional['ping_fallback']) && $additional['ping_fallback'] == 1) {
$additional['snmp_disable'] = 1;
$additional['os'] = "ping";
return createHost($host, '', $snmp_version, $port, $transport, array(), $poller_group, 1, true, $additional);
return createHost($host, '', $snmp_version, $port, $transport, array(), $poller_group, 1, true, $overwrite_ip, $additional);
}
throw $host_unreachable_exception;
}
@@ -751,6 +758,7 @@ function createHost(
$poller_group = 0,
$port_assoc_mode = 'ifIndex',
$force_add = false,
$overwrite_ip = null,
$additional = array()
) {
$host = trim(strtolower($host));
@@ -765,6 +773,7 @@ function createHost(
$device = array(
'hostname' => $host,
'overwrite_ip' => $overwrite_ip,
'sysName' => $additional['sysName'] ? $additional['sysName'] : $host,
'os' => $additional['os'] ? $additional['os'] : 'generic',
'hardware' => $additional['hardware'] ? $additional['hardware'] : null,
@@ -2231,7 +2240,8 @@ function runTraceroute($device)
function device_is_up($device, $record_perf = false)
{
$address_family = snmpTransportToAddressFamily($device['transport']);
$ping_response = isPingable($device['hostname'], $address_family, $device['attribs']);
$poller_target = Device::pollerTarget($device['hostname']);
$ping_response = isPingable($poller_target, $address_family, $device['attribs']);
$device_perf = $ping_response['db'];
$device_perf['device_id'] = $device['device_id'];
$device_perf['timestamp'] = array('NOW()');
+3
View File
@@ -405,6 +405,9 @@ function add_device(\Illuminate\Http\Request $request)
} else {
return api_error(400, 'You haven\'t specified an SNMP version to use');
}
$additional['overwrite_ip'] = $data['overwrite_ip'] ?: null;
try {
$device_id = addHost($hostname, $snmpver, $port, $transport, $poller_group, $force_add, 'ifIndex', $additional);
} catch (Exception $e) {
+3 -1
View File
@@ -41,7 +41,9 @@ echo '<div class="row">
<div class="col-sm-8">'.$device['sysName'].' </div>
</div>';
if (!empty($device['ip'])) {
if (!empty($device['overwrite_ip'])) {
echo "<div class='row'><div class='col-sm-4'>Assigned IP</div><div class='col-sm-8'>{$device['overwrite_ip']}</div></div>";
} elseif (!empty($device['ip'])) {
echo "<div class='row'><div class='col-sm-4'>Resolved IP</div><div class='col-sm-8'>{$device['ip']}</div></div>";
} elseif (Config::get('force_ip_to_sysname') === true) {
try {
+9
View File
@@ -75,6 +75,9 @@ if (!empty($_POST['hostname'])) {
} else {
print_error('Unsupported SNMP Version. There was a dropdown menu, how did you reach this error ?');
}//end if
$additional['overwrite_ip'] = $_POST['overwrite_ip'];
$poller_group = clean($_POST['poller_group']);
$force_add = ($_POST['force_add'] == 'on');
@@ -119,6 +122,12 @@ $pagetitle[] = 'Add host';
<input type="text" id="hostname" name="hostname" class="form-control input-sm" placeholder="Hostname">
</div>
</div>
<div class="form-group">
<label for="overwrite_ip" class="col-sm-3 control-label">Overwrite IP</label>
<div class="col-sm-9">
<input type="text" id="overwrite_ip" name="overwrite_ip" class="form-control input-sm" placeholder="Overwrite IP">
</div>
</div>
<div class='form-group'>
<label for='hardware' class='col-sm-3 control-label'>SNMP</label>
<div class='col-sm-4'>
@@ -35,6 +35,7 @@ if ($_POST['editing']) {
$device_model->disabled = (int)isset($_POST['disabled']);
$device_model->disable_notify = (int)isset($_POST['disable_notify']);
$device_model->type = $_POST['type'];
$device_model->overwrite_ip = $_POST['overwrite_ip'];
if ($device_model->isDirty('type')) {
set_dev_attrib($device, 'override_device_type', true);
@@ -123,6 +124,12 @@ $disable_notify = get_dev_attrib($device, 'disable_notify');
<div class="col-sm-2">
<button name="hostname-edit-button" id="hostname-edit-button" class="btn btn-danger"> <i class="fa fa-pencil"></i> </button>
</div>
</div>
<div class="form-group" data-toggle="tooltip" data-container="body" data-placement="bottom" title="Use this IP instead of resolved one for polling" >
<label for="edit-overwrite_ip-input" class="col-sm-2 control-label" >Overwrite IP:</label>
<div class="col-sm-6">
<input type="text" id="edit-overwrite_up-input" name="overwrite_ip" class="form-control" value=<?php echo($device_model->overwrite_ip); ?>>
</div>
</div>
<div class="form-group">
<label for="descr" class="col-sm-2 control-label">Description:</label>
+3 -1
View File
@@ -1,5 +1,6 @@
<?php
use App\Models\Device;
use LibreNMS\RRD\RrdDefinition;
if ($device['os_group'] == 'unix') {
@@ -11,7 +12,8 @@ if ($device['os_group'] == 'unix') {
}
$agent_start = microtime(true);
$agent = fsockopen($device['hostname'], $agent_port, $errno, $errstr, \LibreNMS\Config::get('unix-agent.connection-timeout'));
$polling_target = Device::pollingTarget($device['hostname']);
$agent = fsockopen($polling_target, $agent_port, $errno, $errstr, \LibreNMS\Config::get('unix-agent.connection-timeout'));
// Set stream timeout (for timeouts during agent fetch
stream_set_timeout($agent, \LibreNMS\Config::get('unix-agent.read-timeout'));
+2 -1
View File
@@ -1,5 +1,6 @@
<?php
use App\Models\Device;
use LibreNMS\Config;
use LibreNMS\RRD\RrdDefinition;
@@ -43,7 +44,7 @@ function add_service($device, $type, $desc, $ip = 'localhost', $param = "", $ign
}
if (empty($ip)) {
$ip = $device['hostname'];
$ip = Device::pollerTarget($device['hostname']);
}
$insert = array('device_id' => $device['device_id'], 'service_ip' => $ip, 'service_type' => $type, 'service_changed' => array('UNIX_TIMESTAMP(NOW())'), 'service_desc' => $desc, 'service_param' => $param, 'service_ignore' => $ignore, 'service_status' => 3, 'service_message' => 'Service not yet checked', 'service_ds' => '{}', 'service_disabled' => $disabled);
+3 -1
View File
@@ -15,6 +15,7 @@
* the source code distribution for details.
*/
use App\Models\Device;
use LibreNMS\Config;
use LibreNMS\RRD\RrdDefinition;
@@ -171,7 +172,8 @@ function gen_snmp_cmd($cmd, $device, $oids, $options = null, $mib = null, $mibdi
array_push($cmd, '-r', $retries);
}
$cmd[] = $device['transport'].':'.$device['hostname'].':'.$device['port'];
$pollertarget = Device::pollerTarget($device['hostname']);
$cmd[] = $device['transport'].':'.$pollertarget.':'.$device['port'];
$cmd = array_merge($cmd, (array)$oids);
return $cmd;
+1
View File
@@ -454,6 +454,7 @@ devices:
- { Field: hostname, Type: varchar(128), 'Null': false, Extra: '' }
- { Field: sysName, Type: varchar(128), 'Null': true, Extra: '' }
- { Field: ip, Type: varbinary(16), 'Null': true, Extra: '' }
- { Field: overwrite_ip, Type: varchar(40), 'Null': true, Extra: '' }
- { Field: community, Type: varchar(255), 'Null': true, Extra: '' }
- { Field: authlevel, Type: 'enum(''noAuthNoPriv'',''authNoPriv'',''authPriv'')', 'Null': true, Extra: '' }
- { Field: authname, Type: varchar(64), 'Null': true, Extra: '' }