mirror of
https://github.com/librenms/librenms.git
synced 2024-09-21 02:18:39 +00:00
Rewrite smokeping script to be an lnms command (#11585)
* Rewrite smokeping script to be an lnms command * Add a default number of probes for smokeping * Formatting fixes * Refactor to simplify a couple of methods * Fix a name collision when using more than 60 threads * Simplify * First pass at documentation A few climate fixes too. I'm a little dubious about the + LibreNMS fix - it could be included in /etc/smokeping/config if it is really needed, but it sounds like (looking at git blame) it's needed for if the script generates a broken configuration file. I'm thinking we should just not generate broken config. * Improve testability and add some tests * Load laravel to make translations available * Second pass at documentation * Fix brace * Extend the device factory to include the type Also adds a device group fake I created before I realised I didn't need it * Mimic gen_smokeping.php a little more closely * Update tests to properly verify old and new behaviour against each other * Replace gen_smokeping with a wrapper * Don't double whitespace Render does this automatically. Explicitly order by hostname too. * Make faker less likely to generate duplicates I tried adding a unique constraint here, but it didn't have the intended effect. Extending the hostname like this seems to work fine - I tried generating 10 million hosts and got no duplicates, compared to duplicates appearing with as few as 100 hosts without this change. A true fix would be to add an 'fqdn' fake upstream. * Make the tests more robust * Assorted bug fixes * Style corrections * Handle 'generic' devices * Fix an issue that came up during rebase Co-authored-by: Tony Murray <murraytony@gmail.com>
This commit is contained in:
parent
5e63c34d19
commit
bbdb1a2a5d
388
app/Console/Commands/SmokepingGenerateCommand.php
Normal file
388
app/Console/Commands/SmokepingGenerateCommand.php
Normal file
@ -0,0 +1,388 @@
|
||||
<?php
|
||||
/**
|
||||
* SmokepingGenerateCommand.php
|
||||
*
|
||||
* CLI command to generate a smokeping configuration.
|
||||
*
|
||||
* 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 2020 Adam Bishop
|
||||
* @author Adam Bishop <adam@omega.org.uk>
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Console\LnmsCommand;
|
||||
use App\Models\Device;
|
||||
use LibreNMS\Config;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class SmokepingGenerateCommand extends LnmsCommand
|
||||
{
|
||||
protected $name = 'smokeping:generate';
|
||||
protected $dnsLookup = true;
|
||||
|
||||
private $ip4count = 0;
|
||||
private $ip6count = 0;
|
||||
private $warnings = [];
|
||||
|
||||
const IP4PROBE = 'lnmsFPing-';
|
||||
const IP6PROBE = 'lnmsFPing6-';
|
||||
|
||||
// These entries are solely used to appease the smokeping config parser and serve no function
|
||||
const DEFAULTIP4PROBE = 'FPing';
|
||||
const DEFAULTIP6PROBE = 'FPing6';
|
||||
const DEFAULTPROBE = self::DEFAULTIP4PROBE;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->setDescription(__('commands.smokeping:generate.description'));
|
||||
|
||||
$this->addOption('probes', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('targets', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('no-header', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('single-process', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('no-dns', null, InputOption::VALUE_NONE);
|
||||
$this->addOption('compat', null, InputOption::VALUE_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (!$this->validateOptions()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$devices = Device::isNotDisabled()->orderBy('type')->orderBy('hostname')->get();
|
||||
|
||||
if (sizeof($devices) < 1) {
|
||||
$this->error(__('commands.smokeping:generate.no-devices'));
|
||||
return 3;
|
||||
}
|
||||
|
||||
if ($this->option('probes')) {
|
||||
return $this->buildProbesConfiguration();
|
||||
} elseif ($this->option('targets')) {
|
||||
return $this->buildTargetsConfiguration($devices);
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable DNS lookups by the configuration builder
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function disableDNSLookup()
|
||||
{
|
||||
return $this->dnsLookup = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and output the probe configuration
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function buildProbesConfiguration()
|
||||
{
|
||||
$probes = $this->assembleProbes(Config::get('smokeping.probes'));
|
||||
$header = $this->buildHeader($this->option('no-header'), $this->option('compat'));
|
||||
|
||||
return $this->render($header, $probes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and output the target configuration
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function buildTargetsConfiguration($devices)
|
||||
{
|
||||
// Take the devices array and build it into a hierarchical list
|
||||
foreach ($devices as $device) {
|
||||
$smokelist[$device->type][$device->hostname] = ['transport' => $device->transport];
|
||||
}
|
||||
|
||||
$targets = $this->buildTargets($smokelist, Config::get('smokeping.probes'), $this->option('single-process'));
|
||||
$header = $this->buildHeader($this->option('no-header'), $this->option('compat'));
|
||||
|
||||
return $this->render($header, $targets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a warning to be emitted
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setWarning($warning)
|
||||
{
|
||||
$this->warnings[] = sprintf('# %s', $warning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring together the probe lists
|
||||
*
|
||||
* @param int $probeCount Number of processes to create
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function assembleProbes($probeCount)
|
||||
{
|
||||
if ($probeCount < 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
$this->buildProbes('FPing', self::DEFAULTIP4PROBE, self::IP4PROBE, Config::get('fping'), $probeCount),
|
||||
$this->buildProbes('FPing6', self::DEFAULTIP6PROBE, self::IP6PROBE, Config::get('fping6'), $probeCount)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a list of probes is needed, and write one if so
|
||||
*
|
||||
* @param string $module The smokeping module to use for this probe (FPing or FPing6, typically)
|
||||
* @param string $defaultProbe A default probe, needed by the smokeping configuration parser
|
||||
* @param string $probe The first part of the probe name, e.g. 'lnmsFPing' or 'lnmsFPing6'
|
||||
* @param string $binary Path to the relevant probe binary (i.e. the output of `which fping` or `which fping6`)
|
||||
* @param int $probeCount Number of processes to create
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function buildProbes($module, $defaultProbe, $probe, $binary, $probeCount)
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
$lines[] = sprintf('+ %s', $module);
|
||||
$lines[] = sprintf(' binary = %s', $binary);
|
||||
$lines[] = ' blazemode = true';
|
||||
$lines[] = sprintf('++ %s', $defaultProbe);
|
||||
|
||||
for ($i = 0; $i < $probeCount; $i++) {
|
||||
$lines[] = sprintf('++ %s%s', $probe, $i);
|
||||
}
|
||||
|
||||
$lines[] = '';
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a header to append to the smokeping configuration file
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function buildHeader($noHeader, $compat)
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
if ($compat) {
|
||||
$lines[] = '';
|
||||
$lines[] = 'menu = Top';
|
||||
$lines[] = 'title = Network Latency Grapher';
|
||||
$lines[] = '';
|
||||
}
|
||||
|
||||
if (!$noHeader) {
|
||||
$lines[] = sprintf('# %s', __('commands.smokeping:generate.header-first'));
|
||||
$lines[] = sprintf('# %s', __('commands.smokeping:generate.header-second'));
|
||||
$lines[] = sprintf('# %s', __('commands.smokeping:generate.header-third'));
|
||||
|
||||
return array_merge($lines, $this->warnings, ['']);
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a list of targets is needed, and write one if so
|
||||
*
|
||||
* @param array $devices A list of devices to create a a config block for
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function buildTargets($smokelist, $probeCount, $singleProcess)
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
foreach ($smokelist as $type => $devices) {
|
||||
if (empty($type)) {
|
||||
$type = 'Ungrouped';
|
||||
}
|
||||
|
||||
$lines[] = sprintf('+ %s', $this->buildMenuEntry($type));
|
||||
$lines[] = sprintf(' menu = %s', $type);
|
||||
$lines[] = sprintf(' title = %s', $type);
|
||||
|
||||
$lines[] = '';
|
||||
|
||||
$lines = array_merge($lines, $this->buildDevices($devices, $probeCount, $singleProcess));
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check arguments passed are sensible
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function validateOptions()
|
||||
{
|
||||
if (!Config::has('smokeping.probes') ||
|
||||
!Config::has('fping') ||
|
||||
!Config::has('fping6')
|
||||
) {
|
||||
$this->error(__('commands.smokeping:generate.config-insufficient'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!($this->option('probes') xor $this->option('targets'))) {
|
||||
$this->error(__('commands.smokeping:generate.args-nonsense'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Config::get('smokeping.probes') < 1) {
|
||||
$this->error(__('commands.smokeping:generate.no-probes'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->option('compat') && !$this->option('targets')) {
|
||||
$this->error(__('commands.smokeping:generate.args-nonsense'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->option('no-dns')) {
|
||||
$this->disableDNSLookup();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take config lines and output them to stdout
|
||||
*
|
||||
* @param array ...$blocks Blocks of smokeping configuration arranged in arrays of strings
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function render(...$blocks)
|
||||
{
|
||||
foreach (array_merge(...$blocks) as $line) {
|
||||
$this->line($line);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the configuration for a set of devices inside a type block
|
||||
*
|
||||
* @param array $devices A list of devices to create a a config block for
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function buildDevices($devices, $probeCount, $singleProcess)
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
foreach ($devices as $hostname => $config) {
|
||||
if (!$this->dnsLookup || $this->deviceIsResolvable($hostname)) {
|
||||
$lines[] = sprintf('++ %s', $this->buildMenuEntry($hostname));
|
||||
$lines[] = sprintf(' menu = %s', $hostname);
|
||||
$lines[] = sprintf(' title = %s', $hostname);
|
||||
|
||||
if (!$singleProcess) {
|
||||
$lines[] = sprintf(' probe = %s', $this->balanceProbes($config['transport'], $probeCount));
|
||||
}
|
||||
|
||||
$lines[] = sprintf(' host = %s', $hostname);
|
||||
$lines[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smokeping refuses to load if it has an unresolvable host, so check for this
|
||||
*
|
||||
* @param string $hostname Hostname to be checked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function deviceIsResolvable($hostname)
|
||||
{
|
||||
// First we check for IP literals, then for a dns entry, finally for a hosts entry due to a PHP/libc limitation
|
||||
// We look for the hosts entry last (and separately) as this only works for v4 - v6 host entries won't be found
|
||||
if (filter_var($hostname, FILTER_VALIDATE_IP) || checkdnsrr($hostname, 'ANY') || is_array(gethostbynamel($hostname))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->setWarning(sprintf('"%s" %s', $hostname, __('commands.smokeping:generate.dns-fail')));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite menu entries to a format that smokeping finds acceptable
|
||||
*
|
||||
* @param string $entry The LibreNMS device hostname to rewrite
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildMenuEntry($entry)
|
||||
{
|
||||
return str_replace(['.', ' '], '_', $entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a probe to use deterministically.
|
||||
*
|
||||
* @param string $transport The transport (udp or udp6) as per the device database entry
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function balanceProbes($transport, $probeCount)
|
||||
{
|
||||
if ($transport === 'udp') {
|
||||
if ($probeCount === $this->ip4count) {
|
||||
$this->ip4count = 0;
|
||||
}
|
||||
|
||||
return sprintf('%s%s', self::IP4PROBE, $this->ip4count++);
|
||||
}
|
||||
|
||||
if ($probeCount === $this->ip6count) {
|
||||
$this->ip6count = 0;
|
||||
}
|
||||
|
||||
return sprintf('%s%s', self::IP6PROBE, $this->ip6count++);
|
||||
}
|
||||
}
|
@ -49,13 +49,41 @@ $factory->define(\App\Models\Bill::class, function (Faker\Generator $faker) {
|
||||
|
||||
$factory->define(\App\Models\Device::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'hostname' => $faker->domainWord . '.' . $faker->domainName,
|
||||
'hostname' => $faker->domainWord . '-' . $faker->domainWord . '-' . $faker->domainWord . '.' . $faker->domainName,
|
||||
'ip' => $faker->randomElement([$faker->ipv4, $faker->ipv6]),
|
||||
'type' => $faker->randomElement([
|
||||
'appliance',
|
||||
'camera',
|
||||
'collaboration',
|
||||
'encoder',
|
||||
'environment',
|
||||
'firewall',
|
||||
'loadbalancer',
|
||||
'management',
|
||||
'network',
|
||||
'power',
|
||||
'printer',
|
||||
'proxy',
|
||||
'sensor',
|
||||
'server',
|
||||
'storage',
|
||||
'timing',
|
||||
'wireless',
|
||||
'workstation'
|
||||
]),
|
||||
'status' => $status = random_int(0, 1),
|
||||
'status_reason' => $status == 0 ? $faker->randomElement(['snmp', 'icmp']) : '', // allow invalid states?
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(\App\Models\DeviceGroup::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->domainWord,
|
||||
'desc' => $faker->text(255),
|
||||
'type' =>'static',
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define(\App\Models\Port::class, function (Faker\Generator $faker) {
|
||||
return [
|
||||
'ifIndex' => $faker->unique()->numberBetween(),
|
||||
|
@ -3,35 +3,154 @@ path: blob/master/doc/
|
||||
|
||||
# Smokeping integration
|
||||
|
||||
[SmokePing](https://oss.oetiker.ch/smokeping/) is a tool which lets us
|
||||
keep track of network latency, and visualise this through RRD graphs.
|
||||
[SmokePing](https://oss.oetiker.ch/smokeping/) is a tool which lets us keep
|
||||
track of network latency, and visualise this through RRD graphs.
|
||||
|
||||
LibreNMS has support for both new and pre-existing SmokePing installations.
|
||||
|
||||
For new installations, we can use the included
|
||||
`scripts/gen_smokeping.php` script to generate a Smokeping config file.
|
||||
For new installations, we can use the `lnms` cli to generate a Smokeping
|
||||
configuration file.
|
||||
|
||||
## New Smokeping installation
|
||||
## Pre-Existing Smokeping Installation
|
||||
|
||||
### Install and integrate Smokeping - Debian/Ubuntu
|
||||
If you have an existing smokeping server, follow the instructions, you only need
|
||||
to look at [Configure LibreNMS - All Operating Systems](#configure-librenms-all-operating-systems).
|
||||
|
||||
This guide assumes you have already [installed
|
||||
librenms](http://docs.librenms.org/Installation/Installing-LibreNMS/),
|
||||
and is working with either **Apache** or
|
||||
**nginx**.
|
||||
## New Installation
|
||||
|
||||
Note: You may need to install `fcgiwrap` as well (at least with `nginx`).
|
||||
All installation steps assume a clean configuration - if you have an existing
|
||||
smokeping setup, you'll need to adapt these steps somewhat.
|
||||
|
||||
### Install Smokeping
|
||||
### Install and integrate Smokeping Backend - RHEL, CentOS and alike
|
||||
|
||||
Smokeping is available via EPEL, which if you're running LibreNMS, you probably
|
||||
already have. If you want to do something like run Smokeping on a seperate host
|
||||
and ship data via RRCached though, here's the install command:
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt install smokeping
|
||||
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
|
||||
sudo yum install smokeping
|
||||
```
|
||||
|
||||
## Configure SmokePing
|
||||
Once installed, you should need a cron script installed to make sure that the
|
||||
configuration file is updated. You can find an example in `misc/librenms-smokeping-rhel.example`.
|
||||
Put this into /etc/cron.d/hourly, and mark it executable:
|
||||
|
||||
Smokeping has several configuration files. By default, these are
|
||||
located in `/etc/smokeping/config.d/`
|
||||
```
|
||||
sudo cp /opt/librenms/misc/smokeping-rhel.example /etc/cron.hourly/librenms-smokeping
|
||||
sudo chmod +x /etc/cron.hourly/librenms-smokeping
|
||||
```
|
||||
|
||||
Finally, update the default configuration. Strip *everything* from the
|
||||
`*** Probes ***` and `*** Targets ***` stanza's, and replace with:
|
||||
|
||||
```
|
||||
*** Probes ***
|
||||
|
||||
@include /etc/smokeping/librenms-probes.conf
|
||||
```
|
||||
|
||||
```
|
||||
*** Targets ***
|
||||
|
||||
probe = FPing
|
||||
|
||||
menu = Top
|
||||
title = Network Latency Grapher
|
||||
remark = Welcome to the SmokePing website of <b>Insert Company Name Here</b>. \
|
||||
Here you will learn all about the latency of our network.
|
||||
|
||||
@include /etc/smokeping/librenms-targets.conf
|
||||
```
|
||||
|
||||
Note there may be other stanza's (possibly `*** Slaves ***`) between the
|
||||
`*** Probes ***` and `*** Targets ***` stanza's - leave these intact.
|
||||
|
||||
Leave everything else untouched. If you need to add other confiruation, make
|
||||
sure it comes *after* the LibreNMS configuration, and keep in mind that
|
||||
Smokeping does not allow duplicate modules, and cares about the configuration
|
||||
file sequence.
|
||||
|
||||
Once you're happy, manually kick off the cron once, then enable and start
|
||||
smokeping:
|
||||
|
||||
```bash
|
||||
sudo /etc/cron.hourly/librenms-smokeping
|
||||
sudo systemctl enable --now smokeping
|
||||
```
|
||||
|
||||
### Install and integrate Smokeping Backend - Ubuntu, Debian and alike
|
||||
|
||||
Smokeping is available via the default repositories.
|
||||
|
||||
```bash
|
||||
sudo apt-get install smokeping
|
||||
```
|
||||
|
||||
Once installed, you should need a cron script installed to make sure that the
|
||||
configuration file is updated. You can find an example in `misc/librenms-smokeping-debian.example`.
|
||||
Put this into /etc/cron.d/hourly, and mark it executable:
|
||||
|
||||
```
|
||||
sudo cp /opt/librenms/misc/smokeping-debian.example /etc/cron.hourly/librenms-smokeping
|
||||
sudo chmod +x /etc/cron.hourly/librenms-smokeping
|
||||
```
|
||||
|
||||
Finally, update the default configuration. Strip *everything* from
|
||||
`/etc/smokeping/config.d/Probes` and replace with:
|
||||
|
||||
```
|
||||
*** Probes ***
|
||||
|
||||
@include /etc/smokeping/config.d/librenms-probes.conf
|
||||
```
|
||||
|
||||
Strip *everything* from `/etc/smokeping/config.d/Targets` and replace with:
|
||||
|
||||
```
|
||||
*** Targets ***
|
||||
|
||||
probe = FPing
|
||||
|
||||
menu = Top
|
||||
title = Network Latency Grapher
|
||||
remark = Welcome to the SmokePing website of <b>Insert Company Name Here</b>. \
|
||||
Here you will learn all about the latency of our network.
|
||||
|
||||
@include /etc/smokeping/config.d/librenms-targets.conf
|
||||
```
|
||||
|
||||
Leave everything else untouched. If you need to add other confiruation, make
|
||||
sure it comes *after* the LibreNMS configuration, and keep in mind that
|
||||
Smokeping does not allow duplicate modules, and cares about the configuration
|
||||
file sequence.
|
||||
|
||||
## Configure LibreNMS - All Operating Systems
|
||||
|
||||
Edit `/opt/librenms/config.php` and add the following:
|
||||
|
||||
```php
|
||||
$config['smokeping']['dir'] = '/var/lib/smokeping';
|
||||
$config['smokeping']['pings'] = 20;
|
||||
$config['smokeping']['probes'] = 2;
|
||||
$config['smokeping']['integration'] = true;
|
||||
$config['smokeping']['url'] = 'smokeping/'; // If you have a specific URL or path for smokeping
|
||||
```
|
||||
`dir` should match the location that smokeping writes RRD's to
|
||||
`pings` should match the default smokeping value, default 20
|
||||
`probes` should be the number of processes to spread pings over, default 2
|
||||
|
||||
These settings can also be set in the Web UI.
|
||||
|
||||
## Configure Smokeping's Web UI - Optional
|
||||
|
||||
This section covers the required configuration for your web server of
|
||||
choice. This covers the required configuration for either Apache or Nginx.
|
||||
|
||||
LibreNMS does not need the Web UI - you can find the graphs in LibreNMS on the
|
||||
*latency* tab.
|
||||
|
||||
### Apache Configuration - Ubuntu, Debian and alike
|
||||
|
||||
Edit the `General` configuration file's **Owner** and **contact**, and
|
||||
**cgiurl hostname** details:
|
||||
@ -43,80 +162,7 @@ contact = admin@ACME.xxx
|
||||
cgiurl = http://yourlibrenms/cgi-bin/smokeping.cgi
|
||||
```
|
||||
|
||||
### Configure Smokeping to use LibreNMS list of nodes
|
||||
|
||||
Add the following line to `/etc/smokeping/config` config file:
|
||||
|
||||
```bash
|
||||
@include /etc/smokeping/config.d/librenms.conf
|
||||
```
|
||||
|
||||
We will generate the conf file in the next step.
|
||||
|
||||
### Generate LibreNMS list of Smokeping Nodes
|
||||
|
||||
LibreNMS comes equipped with a script which exports our list of nodes
|
||||
from LibreNMS into a configuration file in the format required by
|
||||
Smokeping.
|
||||
|
||||
To generate the config file once:
|
||||
|
||||
```bash
|
||||
(echo "+ LibreNMS"; php -f /opt/librenms/scripts/gen_smokeping.php) | sudo tee /etc/smokeping/config.d/librenms.conf
|
||||
```
|
||||
|
||||
**However**, it is more desirable to set up a cron job which
|
||||
regenerates our list of nodes and adds these into Smokeping. You can
|
||||
add the following to the end of your librenms cron job, e.g. `nano /etc/cron.d/librenms`
|
||||
|
||||
**Ubuntu 16.04** Sample cron (will run daily at 00:05) :
|
||||
|
||||
```bash
|
||||
05 00 * * * root (echo "+ LibreNMS"; php -f /opt/librenms/scripts/gen_smokeping.php) > /etc/smokeping/config.d/librenms.conf && systemctl reload smokeping.service >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
**Ubuntu 14.04** Sample cron (will run daily at 00:05):
|
||||
|
||||
```bash
|
||||
05 00 * * * root (echo "+ LibreNMS"; php -f /opt/librenms/scripts/gen_smokeping.php) > /opt/smokeping/etc/librenms.conf && /opt/smokeping/bin/smokeping --reload >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
**Why echo "+ LibreNMS" ?**
|
||||
|
||||
This is in the cron job because the `gen_smokeping.php` script contains
|
||||
|
||||
```
|
||||
menu = Top
|
||||
title = Network Latency Grapher
|
||||
```
|
||||
|
||||
Which can cause Smokeping to not start. `echo "+ LibreNMS"` prepends
|
||||
this in our smokeping config file. We could remove the above from the
|
||||
gen_smokeping script, however this may cause issues with LibreNMS
|
||||
failing to update with `daily.sh` due config files being modified.
|
||||
|
||||
## Configure LibreNMS
|
||||
|
||||
Edit `/opt/librenms/config.php` and add the following:
|
||||
|
||||
**Note:** Make sure you point dir to the correct Smokeping data directory:
|
||||
|
||||
```php
|
||||
$config['smokeping']['dir'] = '/var/lib/smokeping'; // Ubuntu 16.04 and newer Location
|
||||
#$config['smokeping']['dir'] = '/opt/smokeping/data';
|
||||
$config['smokeping']['pings'] = 20; // should be equal to "pings" in your smokeping config
|
||||
$config['smokeping']['integration'] = true;
|
||||
$config['smokeping']['url'] = 'smokeping/'; // If you have a specific URL or path for smokeping
|
||||
```
|
||||
|
||||
## Configure web server
|
||||
|
||||
This section covers the required configuration for your web server of
|
||||
choice. This covers the required configuration for either Apache or Nginx.
|
||||
|
||||
### Apache Configuration
|
||||
|
||||
Smokeping should automatically install an Apache config file in
|
||||
Smokeping should automatically install an Apache configuration file in
|
||||
`/etc/apache2/conf-available/`. Verify this using :
|
||||
|
||||
```bash
|
||||
@ -124,7 +170,8 @@ librenms@librenms:~/scripts$ ls /etc/apache2/conf-available/ | grep smokeping
|
||||
smokeping.conf
|
||||
```
|
||||
|
||||
If you don't see `smokeping.conf` listed, you'll need to create a symlink for it:
|
||||
If you don't see `smokeping.conf` listed, you'll need to create a symlink for
|
||||
it:
|
||||
|
||||
```bash
|
||||
ln -s /etc/smokeping/apache2.conf /etc/apache2/conf-available/smokeping.conf
|
||||
@ -134,7 +181,7 @@ After creating the symlink, restart Apache with `sudo systemctl apache2 restart`
|
||||
|
||||
You should be able to load the Smokeping web interface at `http://yourhost/cgi-bin/smokeping.cgi`
|
||||
|
||||
### Nginx Configuration
|
||||
### Nginx Configuration - Ubuntu, Debian and alike
|
||||
|
||||
This section assumes you have configured LibreNMS with Nginx as
|
||||
specified in [Configure Nginx](https://docs.librenms.org/Installation/Installation-Ubuntu-1804-Nginx/).
|
||||
@ -177,8 +224,8 @@ The following will configure Nginx to respond to `http://yourlibrenms/smokeping`
|
||||
}
|
||||
```
|
||||
|
||||
After saving the config file, verify your Nginx config file syntax is
|
||||
OK with `sudo nginx -t`, then restart Nginx with `sudo systemctl restart nginx`
|
||||
After saving the configuration file, verify your Nginx configuration file syntax
|
||||
is OK with `sudo nginx -t`, then restart Nginx with `sudo systemctl restart nginx`
|
||||
|
||||
You should be able to load the Smokeping web interface at `http://yourhost/smokeping`
|
||||
|
||||
@ -216,128 +263,68 @@ Then you just need to add to your config `auth_basic` parameters
|
||||
}
|
||||
```
|
||||
|
||||
### Start SmokePing
|
||||
## Common Problems
|
||||
|
||||
Use the below commands to start and verify smokeping is running.
|
||||
### RRDs::update ERROR: opening ... Permission denied
|
||||
There is a problem writing to the RRD directory. This is somewhat out of scope
|
||||
of LibreNMS, but make sure that file permissions and SELinux labels allow the
|
||||
smokeping user to write to the directory.
|
||||
|
||||
**Ubuntu 14.04:** `sudo service smokeping start`
|
||||
If you're using RRDCacheD, make sure that the permissions are correct there too,
|
||||
and that if you're using -B that the smokeping RRD's are inside the base
|
||||
directory; update the smokeping rrd directory if required.
|
||||
|
||||
Verify: `sudo service smokeping status`
|
||||
It's not recommended to run RRDCachedD without the -B switch.
|
||||
|
||||
**Ubuntu 16.04 and newer:** `sudo systemctl start smokeping`
|
||||
|
||||
Verify: `sudo systemctl status smokeping`
|
||||
|
||||
## Verify in LibreNMS
|
||||
|
||||
Within LibreNMS, you should now see the Smokeping graphs under Latency tab.
|
||||
|
||||
--------------
|
||||
# Pre-Existing Smokeping Installation
|
||||
|
||||
The following section covers the requirements for an existing
|
||||
SmokePing installation. The primary difference is this section does
|
||||
not cover using the LibreNMS Smokeping config script, and assumes an
|
||||
existing Smokeping server is set up and working correctly.
|
||||
|
||||
In terms of configuration, simply add the location of where smokeping
|
||||
data such as RRD files are stored. If this is on a separate server,
|
||||
ensure there is a mount point reachable, along with the server's hostname.
|
||||
|
||||
**Note:** The location should be the RRD root folder, NOT the
|
||||
sub-directory such as network.
|
||||
|
||||
```php
|
||||
$config['smokeping']['dir'] = '/var/lib/smokeping'; // Ubuntu 16.04 and newer Location
|
||||
#$config['smokeping']['dir'] = '/opt/smokeping/data';
|
||||
$config['smokeping']['pings'] = 20; // should be equal to "pings" in your smokeping config
|
||||
$config['smokeping']['integration'] = true;
|
||||
```
|
||||
|
||||
You should now see a new tab in your device page called ping.
|
||||
|
||||
# Issues
|
||||
|
||||
## `ERROR: /etc/smokeping/config.d/pathnames, line 1: File '/usr/sbin/sendmail' does not exist`
|
||||
|
||||
If you got this error at the end of the installation, simply edit
|
||||
smokeping's config file like so:
|
||||
|
||||
```diff
|
||||
nano /etc/smokeping/config.d/pathnames
|
||||
|
||||
-sendmail = /usr/sbin/sendmail
|
||||
+#sendmail = /usr/sbin/sendmail
|
||||
```
|
||||
|
||||
## Smokeping and RRDCached
|
||||
|
||||
If you are using the standard smokeping data dir
|
||||
(`/etc/smokeping/data`) then you may need to alter the rrdcached
|
||||
config slightly.
|
||||
|
||||
In the standard configuration the -B argument may have been used to
|
||||
restrict rrdcached to read only from a single base dir.
|
||||
|
||||
If this is true, when you try an open one of the smokeping graphs from
|
||||
within LibreNMS you will see something like this error at the end of
|
||||
the rrdcached command:
|
||||
|
||||
```bash
|
||||
ERROR: rrdcached: /var/lib/smokeping/<device name>.rrd: Permission denied
|
||||
```
|
||||
|
||||
You will need to either change the dir in which smokeping saves its
|
||||
rrd files to be the same as the main librenms dir or you can remove
|
||||
the -B argument from the rrdcached config to allow it to read from
|
||||
more than one dir.
|
||||
|
||||
### To remove the -B switch:
|
||||
|
||||
```bash
|
||||
sudo nano /etc/default/rrdcached
|
||||
```
|
||||
|
||||
then find:
|
||||
|
||||
```bash
|
||||
BASE_OPTIONS=
|
||||
```
|
||||
|
||||
If -B is in the list of arguments delete it.
|
||||
|
||||
### To store smokeping rrd in librenms rrd folder
|
||||
#### Share RRDCached with LibreNMS
|
||||
|
||||
Move the RRD's and give smokeping access rights to the LibreNMS RRD directory:
|
||||
```bash
|
||||
sudo systemctl stop smokeping
|
||||
sudo mv /var/lib/smokeping/ /opt/librenms/rrd/
|
||||
sudo nano /etc/smokeping/config.d/pathnames
|
||||
```
|
||||
Then update the config file:
|
||||
|
||||
```bash
|
||||
datadir = /opt/librenms/rrd/smokeping
|
||||
dyndir = /opt/librenms/rrd/smokeping/__cgi
|
||||
```
|
||||
And give to smokeping rights to access files
|
||||
|
||||
```bash
|
||||
sudo mv /var/lib/smokeping /opt/librenms/rrd/
|
||||
sudo usermod -a -G librenms smokeping
|
||||
```
|
||||
|
||||
Restart smokeping service
|
||||
Update data directory in */etc/smokeping*:
|
||||
|
||||
```
|
||||
datadir = /opt/librenms/rrd/smokeping
|
||||
dyndir = /opt/librenms/rrd/smokeping/__cgi
|
||||
```
|
||||
|
||||
Finally restart the smokeping service:
|
||||
|
||||
```bash
|
||||
sudo systemctl start smokeping
|
||||
```
|
||||
|
||||
Finally update smokeping rrd path in librenms
|
||||
Remember to update *config.php* with the new locations.
|
||||
|
||||
```bash
|
||||
nano /opt/librenms/config.php
|
||||
```
|
||||
### Probe FPing missing missing from the probes section
|
||||
|
||||
```php
|
||||
$config['smokeping']['dir'] = '/opt/librenms/rrd/smokeping';
|
||||
#$config['smokeping']['dir'] = '/var/lib/smokeping';
|
||||
```
|
||||
Take a look at the instructions again - something isn't correct in your
|
||||
configuration.
|
||||
|
||||
### Section or variable already exists
|
||||
|
||||
Most likely, content wasn't fully removed from the `*** Probes ***`
|
||||
`*** Targets***` stanza's as instructed.
|
||||
If you're trying to integrate LibreNMS, smokeping *and* another source of
|
||||
configuration, you're probably trying to redefine a module (e.g. '+ FPing' more
|
||||
than once) or stanza. Otherwise, look again at the instructions.
|
||||
|
||||
### Mandatory variable 'probe' not defined
|
||||
The target block must have a default probe. If you follow the instructions you
|
||||
will have one. If you're trying to integrate LibreNMS, smokeping *and* another
|
||||
source of configuration, you need to make sure there are no duplicate or missing
|
||||
definitions.
|
||||
|
||||
### File '/usr/sbin/sendmail' does not exist`
|
||||
|
||||
If you got this error at the end of the installation, simply edit
|
||||
commend out the sendmail entry in the configuration:
|
||||
|
||||
```diff
|
||||
-sendmail = /usr/sbin/sendmail
|
||||
+#sendmail = /usr/sbin/sendmail
|
||||
```
|
@ -4900,6 +4900,10 @@
|
||||
"type": "integer",
|
||||
"units": "pings"
|
||||
},
|
||||
"smokeping.probes": {
|
||||
"default": 2,
|
||||
"type": "integer"
|
||||
},
|
||||
"snmp.community": {
|
||||
"group": "poller",
|
||||
"section": "snmp",
|
||||
|
6
misc/smokeping-debian.example
Normal file
6
misc/smokeping-debian.example
Normal file
@ -0,0 +1,6 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
sudo -u librenms /opt/librenms/lnms smokeping:generate --targets > /etc/smokeping/config.d/librenms-targets.conf
|
||||
sudo -u librenms /opt/librenms/lnms smokeping:generate --probes > /etc/smokeping/config.d/librenms-probes.conf
|
||||
|
||||
systemctl reload smokeping > /dev/null 2<&1
|
6
misc/smokeping-rhel.example
Normal file
6
misc/smokeping-rhel.example
Normal file
@ -0,0 +1,6 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
sudo -u librenms /opt/librenms/lnms smokeping:generate --targets > /etc/smokeping/librenms-targets.conf
|
||||
sudo -u librenms /opt/librenms/lnms smokeping:generate --probes > /etc/smokeping/librenms-probes.conf
|
||||
|
||||
systemctl reload smokeping > /dev/null 2<&1
|
@ -41,7 +41,29 @@ return [
|
||||
'os' => 'Specific OS to run tests on. Implies unit, --db, --snmpsim',
|
||||
'quiet' => 'Hide output unless there is an error',
|
||||
'snmpsim' => 'Use snmpsim for unit tests',
|
||||
]
|
||||
],
|
||||
],
|
||||
'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',
|
||||
'dns-fail' => 'was not resolvable and was omitted from the configuration',
|
||||
'description' => 'Generate a configuration suitable for use with smokeping',
|
||||
'header-first' => 'This file was automatically generated by "lnms smokeping:generate',
|
||||
'header-second' => 'Local changes may be overwritten without notice or backups being taken',
|
||||
'header-third' => 'For more information see https://docs.librenms.org/Extensions/Smokeping/"',
|
||||
'no-devices' => 'No eligible devices found - devices must not be disabled.',
|
||||
'no-probes' => 'At least one probe is required.',
|
||||
'options' => [
|
||||
'probes' => 'Generate probe list - used for splitting the smokeping configuration into multiple files. Conflicts with "--targets"',
|
||||
'targets' => 'Generate the target list - used for splitting the smokeping configuration into multiple files. Conflicts with "--probes"',
|
||||
'no-header' => 'Don\'t add the boilerplate comment to the start of the generated file',
|
||||
'no-dns' => 'Skip DNS lookups',
|
||||
'single-process' => 'Only use a single process for smokeping',
|
||||
'compat' => '[deprecated] Mimic the behaviour of gen_smokeping.php',
|
||||
],
|
||||
],
|
||||
'translation:generate' => [
|
||||
'description' => 'Generate updated json language files for use in the web frontend',
|
||||
],
|
||||
'user:add' => [
|
||||
'description' => 'Add a local user, you can only log in with this user if auth is set to mysql',
|
||||
@ -58,8 +80,5 @@ return [
|
||||
'password-request' => "Please enter the user's password",
|
||||
'success' => 'Successfully added user: :username',
|
||||
'wrong-auth' => 'Warning! You will not be able to log in with this user because you are not using MySQL auth',
|
||||
],
|
||||
'translation:generate' => [
|
||||
'description' => 'Generate updated json language files for use in the web frontend',
|
||||
]
|
||||
];
|
||||
|
@ -1,34 +1,37 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* Copyright (c) 2015 Søren Friis Rosiak <sorenrosiak@gmail.com>
|
||||
* 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. Please see LICENSE.txt at the top level of
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
/**
|
||||
* gen_smokeping.php
|
||||
*
|
||||
* Legacy wrapper for generating smokeping configurations
|
||||
*
|
||||
* 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 2020 Adam Bishop
|
||||
* @author Adam Bishop <adam@omega.org.uk>
|
||||
*/
|
||||
|
||||
$init_modules = array();
|
||||
require realpath(__DIR__ . '/..') . '/includes/init.php';
|
||||
?>
|
||||
if (php_sapi_name() === 'cli') {
|
||||
$init_modules = [];
|
||||
require realpath(__DIR__ . '/..') . '/includes/init.php';
|
||||
|
||||
menu = Top
|
||||
title = Network Latency Grapher
|
||||
|
||||
<?php
|
||||
|
||||
foreach (dbFetchRows("SELECT `type` FROM `devices` WHERE `disabled` = 0 AND `type` != '' GROUP BY `type`") as $groups) {
|
||||
//Dot and space need to be replaced, since smokeping doesn't accept it at this level
|
||||
echo '+ ' . str_replace(['.', ' '], '_', $groups['type']) . PHP_EOL;
|
||||
echo 'menu = ' . $groups['type'] . PHP_EOL;
|
||||
echo 'title = ' . $groups['type'] . PHP_EOL;
|
||||
foreach (dbFetchRows("SELECT `hostname` FROM `devices` WHERE `type` = ? AND `disabled` = 0", array($groups['type'])) as $devices) {
|
||||
echo '++ ' . str_replace(['.', ' '], '_', $devices['hostname']) . PHP_EOL;
|
||||
echo 'menu = ' . $devices['hostname'] . PHP_EOL;
|
||||
echo 'title = ' . $devices['hostname'] . PHP_EOL;
|
||||
echo 'host = ' . $devices['hostname'] . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
$return = \Artisan::call('smokeping:generate --targets --no-header --no-dns --single-process --compat');
|
||||
echo \Artisan::Output();
|
||||
|
||||
exit($return);
|
||||
}
|
||||
|
||||
exit();
|
||||
|
393
tests/SmokepingCliTest.php
Normal file
393
tests/SmokepingCliTest.php
Normal file
@ -0,0 +1,393 @@
|
||||
<?php
|
||||
/**
|
||||
* SmokepingCliTest.php
|
||||
*
|
||||
* Checks that smokeping configuration output is consistent
|
||||
*
|
||||
* 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 https://librenms.org
|
||||
* @copyright 2020 Adam Bishop
|
||||
* @author Adam Bishop <adam@omega.org.uk>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Tests;
|
||||
|
||||
use app\Console\Commands\SmokepingGenerateCommand;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\arr;
|
||||
use Illuminate\Translation\Translator;
|
||||
use LibreNMS\Config;
|
||||
use App\Models\Device;
|
||||
|
||||
class SmokepingCliTest extends DBTestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
protected $groups = [
|
||||
'Le23HKVMvN' => [
|
||||
'Cl09bZU4sn' => [
|
||||
'transport' => 'udp'
|
||||
],
|
||||
'c559TvthzY' => [
|
||||
'transport' => 'udp6'
|
||||
],
|
||||
'sNtzSdxdw8' => [
|
||||
'transport' => 'udp6'
|
||||
],
|
||||
'10.0.0.3' => [
|
||||
'transport' => 'udp'
|
||||
],
|
||||
'2600::' => [
|
||||
'transport' => 'udp'
|
||||
]
|
||||
],
|
||||
'Psv9oZcxdC' => [
|
||||
'oHiPfLzrmU' => [
|
||||
'transport' => 'udp'
|
||||
],
|
||||
'kEn7hZ7N37' => [
|
||||
'transport' => 'udp6'
|
||||
],
|
||||
'PcbZ5FKtS3' => [
|
||||
'transport' => 'udp6'
|
||||
],
|
||||
'192.168.1.1' => [
|
||||
'transport' => 'udp'
|
||||
],
|
||||
'fe80::' => [
|
||||
'transport' => 'udp'
|
||||
]
|
||||
],
|
||||
'4diY0pWFik' => [
|
||||
'example.org' => [
|
||||
'transport' => 'udp'
|
||||
],
|
||||
'host_with_under_score.example.org' => [
|
||||
'transport' => 'udp6'
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
private $instance = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
// We need an app instance available for these tests to load the translation machinary
|
||||
$this->app = $this->createApplication();
|
||||
|
||||
$this->instance = new SmokePingGenerateCommand();
|
||||
$this->instance->disableDNSLookup();
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testNonsense()
|
||||
{
|
||||
$this->assertNotEquals(0, \Artisan::call('smokeping:generate --probes --targets --no-header'));
|
||||
$this->assertNotEquals(0, \Artisan::call('smokeping:generate --probes --targets --single-process'));
|
||||
$this->assertNotEquals(0, \Artisan::call('smokeping:generate --probes --targets'));
|
||||
$this->assertNotEquals(0, \Artisan::call('smokeping:generate --no-header'));
|
||||
$this->assertNotEquals(0, \Artisan::call('smokeping:generate --single-process'));
|
||||
$this->assertNotEquals(0, \Artisan::call('smokeping:generate'));
|
||||
|
||||
$this->expectException('RuntimeException');
|
||||
\Artisan::call('smokeping:generate --foobar');
|
||||
}
|
||||
|
||||
public function testBuildHeader()
|
||||
{
|
||||
$warnings = ['rpPvjwdI0M0hlg6ZgZA', '2aUjOMql6ZWN7H0DthWDOyCvkXs0kVShhnASnc', 'HYMWbDplSW9PLNK9o9tySeJF4Ac61uTRHUUxxBXHiCl'];
|
||||
|
||||
$this->instance->setWarning($warnings[0]);
|
||||
$this->instance->setWarning($warnings[1]);
|
||||
$this->instance->setWarning($warnings[2]);
|
||||
|
||||
$header = $this->instance->buildHeader(false, false);
|
||||
|
||||
$this->assertEmpty(array_pop($header));
|
||||
|
||||
foreach ($header as $line) {
|
||||
$this->assertTrue(Str::startsWith($line, '# '), $line);
|
||||
$this->assertTrue(Str::contains($line, array_merge($warnings, [__('commands.smokeping:generate.header-first'), __('commands.smokeping:generate.header-second'), __('commands.smokeping:generate.header-third')])), $line);
|
||||
}
|
||||
|
||||
$this->assertEquals($this->instance->buildHeader(true, false), []);
|
||||
}
|
||||
|
||||
public function testAssembleProbes()
|
||||
{
|
||||
$tests = [0, -1];
|
||||
|
||||
foreach ($tests as $test) {
|
||||
$this->assertEmpty($this->instance->assembleProbes($test));
|
||||
}
|
||||
}
|
||||
|
||||
public function testBuildProbe()
|
||||
{
|
||||
$saved = ['+ Pl0JnP2vfE',
|
||||
' binary = /usr/bin/G28F3fFeew',
|
||||
' blazemode = true',
|
||||
'++ Xq93BufZAU',
|
||||
'++ etzY41dSRj0',
|
||||
'++ etzY41dSRj1',
|
||||
'++ etzY41dSRj2',
|
||||
''
|
||||
];
|
||||
|
||||
$output = $this->instance->buildProbes('Pl0JnP2vfE', 'Xq93BufZAU', 'etzY41dSRj', '/usr/bin/G28F3fFeew', 3);
|
||||
|
||||
$this->assertEquals(implode(PHP_EOL, $saved), implode(PHP_EOL, $output));
|
||||
}
|
||||
|
||||
public function testBuildTargets()
|
||||
{
|
||||
$saved = [
|
||||
'+ Le23HKVMvN',
|
||||
' menu = Le23HKVMvN',
|
||||
' title = Le23HKVMvN',
|
||||
'',
|
||||
'++ Cl09bZU4sn',
|
||||
' menu = Cl09bZU4sn',
|
||||
' title = Cl09bZU4sn',
|
||||
' probe = lnmsFPing-0',
|
||||
' host = Cl09bZU4sn',
|
||||
'',
|
||||
'++ c559TvthzY',
|
||||
' menu = c559TvthzY',
|
||||
' title = c559TvthzY',
|
||||
' probe = lnmsFPing6-0',
|
||||
' host = c559TvthzY',
|
||||
'',
|
||||
'++ sNtzSdxdw8',
|
||||
' menu = sNtzSdxdw8',
|
||||
' title = sNtzSdxdw8',
|
||||
' probe = lnmsFPing6-1',
|
||||
' host = sNtzSdxdw8',
|
||||
'',
|
||||
'++ 10_0_0_3',
|
||||
' menu = 10.0.0.3',
|
||||
' title = 10.0.0.3',
|
||||
' probe = lnmsFPing-1',
|
||||
' host = 10.0.0.3',
|
||||
'',
|
||||
'++ 2600::',
|
||||
' menu = 2600::',
|
||||
' title = 2600::',
|
||||
' probe = lnmsFPing-2',
|
||||
' host = 2600::',
|
||||
'',
|
||||
'+ Psv9oZcxdC',
|
||||
' menu = Psv9oZcxdC',
|
||||
' title = Psv9oZcxdC',
|
||||
'',
|
||||
'++ oHiPfLzrmU',
|
||||
' menu = oHiPfLzrmU',
|
||||
' title = oHiPfLzrmU',
|
||||
' probe = lnmsFPing-3',
|
||||
' host = oHiPfLzrmU',
|
||||
'',
|
||||
'++ kEn7hZ7N37',
|
||||
' menu = kEn7hZ7N37',
|
||||
' title = kEn7hZ7N37',
|
||||
' probe = lnmsFPing6-2',
|
||||
' host = kEn7hZ7N37',
|
||||
'',
|
||||
'++ PcbZ5FKtS3',
|
||||
' menu = PcbZ5FKtS3',
|
||||
' title = PcbZ5FKtS3',
|
||||
' probe = lnmsFPing6-3',
|
||||
' host = PcbZ5FKtS3',
|
||||
'',
|
||||
'++ 192_168_1_1',
|
||||
' menu = 192.168.1.1',
|
||||
' title = 192.168.1.1',
|
||||
' probe = lnmsFPing-0',
|
||||
' host = 192.168.1.1',
|
||||
'',
|
||||
'++ fe80::',
|
||||
' menu = fe80::',
|
||||
' title = fe80::',
|
||||
' probe = lnmsFPing-1',
|
||||
' host = fe80::',
|
||||
'',
|
||||
'+ 4diY0pWFik',
|
||||
' menu = 4diY0pWFik',
|
||||
' title = 4diY0pWFik',
|
||||
'',
|
||||
'++ example_org',
|
||||
' menu = example.org',
|
||||
' title = example.org',
|
||||
' probe = lnmsFPing-2',
|
||||
' host = example.org',
|
||||
'',
|
||||
'++ host_with_under_score_example_org',
|
||||
' menu = host_with_under_score.example.org',
|
||||
' title = host_with_under_score.example.org',
|
||||
' probe = lnmsFPing6-0',
|
||||
' host = host_with_under_score.example.org',
|
||||
''
|
||||
];
|
||||
|
||||
$output = $this->instance->buildTargets($this->groups, 4, false);
|
||||
|
||||
$this->assertEquals(implode(PHP_EOL, $saved), implode(PHP_EOL, $output));
|
||||
}
|
||||
|
||||
public function testSingleProccess()
|
||||
{
|
||||
$saved = [
|
||||
'+ Le23HKVMvN',
|
||||
' menu = Le23HKVMvN',
|
||||
' title = Le23HKVMvN',
|
||||
'',
|
||||
'++ Cl09bZU4sn',
|
||||
' menu = Cl09bZU4sn',
|
||||
' title = Cl09bZU4sn',
|
||||
' host = Cl09bZU4sn',
|
||||
'',
|
||||
'++ c559TvthzY',
|
||||
' menu = c559TvthzY',
|
||||
' title = c559TvthzY',
|
||||
' host = c559TvthzY',
|
||||
'',
|
||||
'++ sNtzSdxdw8',
|
||||
' menu = sNtzSdxdw8',
|
||||
' title = sNtzSdxdw8',
|
||||
' host = sNtzSdxdw8',
|
||||
'',
|
||||
'++ 10_0_0_3',
|
||||
' menu = 10.0.0.3',
|
||||
' title = 10.0.0.3',
|
||||
' host = 10.0.0.3',
|
||||
'',
|
||||
'++ 2600::',
|
||||
' menu = 2600::',
|
||||
' title = 2600::',
|
||||
' host = 2600::',
|
||||
'',
|
||||
'+ Psv9oZcxdC',
|
||||
' menu = Psv9oZcxdC',
|
||||
' title = Psv9oZcxdC',
|
||||
'',
|
||||
'++ oHiPfLzrmU',
|
||||
' menu = oHiPfLzrmU',
|
||||
' title = oHiPfLzrmU',
|
||||
' host = oHiPfLzrmU',
|
||||
'',
|
||||
'++ kEn7hZ7N37',
|
||||
' menu = kEn7hZ7N37',
|
||||
' title = kEn7hZ7N37',
|
||||
' host = kEn7hZ7N37',
|
||||
'',
|
||||
'++ PcbZ5FKtS3',
|
||||
' menu = PcbZ5FKtS3',
|
||||
' title = PcbZ5FKtS3',
|
||||
' host = PcbZ5FKtS3',
|
||||
'',
|
||||
'++ 192_168_1_1',
|
||||
' menu = 192.168.1.1',
|
||||
' title = 192.168.1.1',
|
||||
' host = 192.168.1.1',
|
||||
'',
|
||||
'++ fe80::',
|
||||
' menu = fe80::',
|
||||
' title = fe80::',
|
||||
' host = fe80::',
|
||||
'',
|
||||
'+ 4diY0pWFik',
|
||||
' menu = 4diY0pWFik',
|
||||
' title = 4diY0pWFik',
|
||||
'',
|
||||
'++ example_org',
|
||||
' menu = example.org',
|
||||
' title = example.org',
|
||||
' host = example.org',
|
||||
'',
|
||||
'++ host_with_under_score_example_org',
|
||||
' menu = host_with_under_score.example.org',
|
||||
' title = host_with_under_score.example.org',
|
||||
' host = host_with_under_score.example.org',
|
||||
''
|
||||
];
|
||||
|
||||
$output = $this->instance->buildTargets($this->groups, 4, true);
|
||||
|
||||
$this->assertEquals(implode(PHP_EOL, $saved), implode(PHP_EOL, $output));
|
||||
}
|
||||
|
||||
public function testCompareLegacy()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
// Generate a ridiculous number of random devices for testing
|
||||
foreach (range(1, 1000) as $i) {
|
||||
$device = factory(Device::class)->create();
|
||||
$data[$device->type][] = $device->hostname;
|
||||
}
|
||||
|
||||
// Sort the data so the output matches the one from the database
|
||||
$data = Arr::sortRecursive($data);
|
||||
|
||||
// Disable DNS lookups
|
||||
\Artisan::call('smokeping:generate --targets --no-header --no-dns --single-process --compat');
|
||||
$new = \Artisan::Output();
|
||||
$old = $this->legacyAlgo($data);
|
||||
|
||||
$this->assertEquals($this->canonicalise($new), $this->canonicalise($old));
|
||||
}
|
||||
|
||||
public function legacyAlgo($data)
|
||||
{
|
||||
// This is the code taken from the old gen_smokeping script, with echos and sql queries replaced
|
||||
$lines = [];
|
||||
$lines[] = '' . PHP_EOL;
|
||||
$lines[] = 'menu = Top' . PHP_EOL;
|
||||
$lines[] = 'title = Network Latency Grapher' . PHP_EOL;
|
||||
$lines[] = '' . PHP_EOL;
|
||||
|
||||
foreach ($data as $groupName => $devices) {
|
||||
//Dot and space need to be replaced, since smokeping doesn't accept it at this level
|
||||
$lines[] = '+ ' . str_replace(['.', ' '], '_', $groupName) . PHP_EOL;
|
||||
$lines[] = 'menu = ' . $groupName . PHP_EOL;
|
||||
$lines[] = 'title = ' . $groupName . PHP_EOL;
|
||||
foreach ($devices as $device) {
|
||||
$lines[] = '++ ' . str_replace(['.', ' '], '_', $device) . PHP_EOL;
|
||||
$lines[] = 'menu = ' . $device . PHP_EOL;
|
||||
$lines[] = 'title = ' . $device . PHP_EOL;
|
||||
$lines[] = 'host = ' . $device . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a string as we need to evaluate the entire thing as a block
|
||||
return implode('', $lines);
|
||||
}
|
||||
|
||||
public function canonicalise($input)
|
||||
{
|
||||
$input = explode(PHP_EOL, $input);
|
||||
|
||||
$output = [];
|
||||
|
||||
foreach ($input as $line) {
|
||||
if (trim($line) !== '') {
|
||||
$output[] = trim($line);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, $output);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user