Developer device simulation (#12577)
* Developer device simulation lnms dev:simulate handy helper to start snmpsim with test data and optionally add and remove a device to LibreNMS * doc update
This commit is contained in:
parent
0a8f24c5b1
commit
e4e2113585
|
@ -173,7 +173,7 @@ class Snmpsim
|
|||
unset($this->proc);
|
||||
}
|
||||
|
||||
private function findSnmpsimd()
|
||||
public function findSnmpsimd()
|
||||
{
|
||||
$cmd = Config::locateBinary('snmpsimd');
|
||||
if (! is_executable($cmd)) {
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Console\LnmsCommand;
|
||||
use App\Models\Device;
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Util\Snmpsim;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class DevSimulate extends LnmsCommand
|
||||
{
|
||||
protected $name = 'dev:simulate';
|
||||
protected $developer = true;
|
||||
/**
|
||||
* @var Snmpsim
|
||||
*/
|
||||
protected $snmpsim = null;
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Simulate devices using test data';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->addArgument('file', InputArgument::OPTIONAL);
|
||||
$this->addOption('multiple', 'm', InputOption::VALUE_NONE);
|
||||
$this->addOption('remove', 'r', InputOption::VALUE_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->snmpsim = new Snmpsim();
|
||||
$snmprec_dir = $this->snmpsim->getDir();
|
||||
$listen = $this->snmpsim->getIp() . ':' . $this->snmpsim->getPort();
|
||||
|
||||
$snmpsim = new Process([
|
||||
$this->snmpsim->findSnmpsimd(),
|
||||
"--data-dir=$snmprec_dir",
|
||||
"--agent-udpv4-endpoint=$listen",
|
||||
]);
|
||||
$snmpsim->setTimeout(null);
|
||||
|
||||
$snmpsim->run(function ($type, $buffer) use ($listen) {
|
||||
if (Process::ERR === $type) {
|
||||
if (Str::contains($buffer, $listen)) {
|
||||
$this->line(trim($buffer));
|
||||
$this->started();
|
||||
$this->line(trans('commands.dev:simulate.exit'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function started()
|
||||
{
|
||||
if ($file = $this->argument('file')) {
|
||||
$this->addDevice($file);
|
||||
}
|
||||
}
|
||||
|
||||
private function addDevice($community)
|
||||
{
|
||||
$hostname = $this->option('new') ? $community : 'snmpsim';
|
||||
$device = Device::firstOrNew(['hostname' => $hostname]);
|
||||
$action = $device->exists ? 'updated' : 'added';
|
||||
|
||||
$device->overwrite_ip = $this->snmpsim->getIp();
|
||||
$device->port = $this->snmpsim->getPort();
|
||||
$device->snmpver = 'v2c';
|
||||
$device->transport = 'udp';
|
||||
$device->community = $community;
|
||||
$device->last_discovered = null;
|
||||
$device->status_reason = '';
|
||||
$device->save();
|
||||
|
||||
$this->info(trans("commands.dev:simulate.$action", ['hostname' => $device->hostname, 'id' => $device->device_id]));
|
||||
|
||||
// set up removal shutdown function if requested
|
||||
if ($this->option('remove')) {
|
||||
$this->queueRemoval($device->device_id);
|
||||
}
|
||||
}
|
||||
|
||||
private function queueRemoval($device_id)
|
||||
{
|
||||
if (function_exists('pcntl_signal')) {
|
||||
pcntl_signal(SIGINT, function () {
|
||||
exit(); // exit normally on SIGINT
|
||||
});
|
||||
}
|
||||
|
||||
register_shutdown_function(function () use ($device_id) {
|
||||
Device::findOrNew($device_id)->delete();
|
||||
$this->info(trans('commands.dev:simulate.removed', ['id' => $device_id]));
|
||||
exit();
|
||||
});
|
||||
}
|
||||
|
||||
public function completeArgument($name, $value)
|
||||
{
|
||||
if ($name == 'file') {
|
||||
return collect(glob(base_path('tests/snmpsim/*.snmprec')))->map(function ($file) {
|
||||
return basename($file, '.snmprec');
|
||||
})->filter(function ($snmprec) use ($value) {
|
||||
return ! $value || Str::startsWith($snmprec, $value);
|
||||
})->all();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ make sure it is modified in a consistent manner.
|
|||
> testing. For OS discovery, we can mock snmpsim, but for other tests
|
||||
> you will need it installed and functioning. We run snmpsim during
|
||||
> our integration tests, but not by default when running
|
||||
> `./lnms dev:check`. You can install snmpsim with the
|
||||
> `lnms dev:check`. You can install snmpsim with the
|
||||
> command `pip3 install snmpsim`.
|
||||
|
||||
## Capturing test data
|
||||
|
@ -58,23 +58,26 @@ After you have the data you need in the snmprec file, you can just use save-test
|
|||
directory. This will read composer.json and install any dependencies required.
|
||||
|
||||
After you have saved your test data, you should run
|
||||
`./lnms dev:check` verify they pass.
|
||||
`lnms dev:check` verify they pass.
|
||||
|
||||
To run the full suite of tests enable database and snmpsim reliant
|
||||
tests: `./lnms dev:check unit --db --snmpsim`
|
||||
tests: `lnms dev:check unit --db --snmpsim`
|
||||
|
||||
### Specific OS
|
||||
|
||||
`./lnms dev:check unit -o osname`
|
||||
`lnms dev:check unit -o osname`
|
||||
|
||||
### Specific Module
|
||||
|
||||
`./lnms dev:check unit -m modulename`
|
||||
`lnms dev:check unit -m modulename`
|
||||
|
||||
## Using snmpsim for testing
|
||||
|
||||
You can run snmpsim to access test data by running
|
||||
`./scripts/collect-snmp-data.php --snmpsim`
|
||||
|
||||
```bash
|
||||
lnms dev:simulate
|
||||
```
|
||||
|
||||
You may then run snmp queries against it using the os (and variant) as
|
||||
the community and 127.1.6.1:1161 as the host.
|
||||
|
@ -143,7 +146,7 @@ must use a variant to store your test data (-v).
|
|||
1. If there is additional snmp data required, run `./scripts/collect-snmp-data.php -h 42`
|
||||
1. Run `./scripts/save-test-data.php -o example-os` to update the dumped database data.
|
||||
1. Review data. If you modified the snmprec or code (don't modify json manually) run `./scripts/save-test-data.php -o example-os -m os`
|
||||
1. Run `./lnms dev:check unit --db --snmpsim`
|
||||
1. Run `lnms dev:check unit --db --snmpsim`
|
||||
1. If the tests succeed submit a pull request
|
||||
|
||||
### Additional module support or test data
|
||||
|
@ -153,5 +156,5 @@ must use a variant to store your test data (-v).
|
|||
more data to the snmprec file
|
||||
1. Review data. If you modified the snmprec (don't modify json
|
||||
manually) run `./scripts/save-test-data.php -o example-os -m <module>`
|
||||
1. Run `./lnms dev:check unit --db --snmpsim`
|
||||
1. Run `lnms dev:check unit --db --snmpsim`
|
||||
1. If the tests succeed submit a pull request
|
||||
|
|
|
@ -43,6 +43,20 @@ return [
|
|||
'snmpsim' => 'Use snmpsim for unit tests',
|
||||
],
|
||||
],
|
||||
'dev:simulate' => [
|
||||
'description' => 'Simulate devices using test data',
|
||||
'arguments' => [
|
||||
'file' => 'The file name (only base name) of the snmprec file to update or add to LibreNMS. If file not specified, no device will be added or updated.',
|
||||
],
|
||||
'options' => [
|
||||
'multiple' => 'Use community name for hostname instead of snmpsim',
|
||||
'remove' => 'Remove the device after stopping',
|
||||
],
|
||||
'added' => 'Device :hostname (:id) added',
|
||||
'exit' => 'Ctrl-C to stop',
|
||||
'removed' => 'Device :id removed',
|
||||
'updated' => 'Device :hostname (:id) updated',
|
||||
],
|
||||
'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',
|
||||
|
|
Loading…
Reference in New Issue