diff --git a/LibreNMS/Interfaces/Module.php b/LibreNMS/Interfaces/Module.php index 3a493a73c2..35c6078dd6 100644 --- a/LibreNMS/Interfaces/Module.php +++ b/LibreNMS/Interfaces/Module.php @@ -65,13 +65,18 @@ interface Module */ public function poll(OS $os, DataStorageInterface $datastore): void; + /** + * Check if data exists for this module + */ + public function dataExists(Device $device): bool; + /** * Remove all DB data for this module. * This will be run when the module is disabled. * * @param \App\Models\Device $device */ - public function cleanup(Device $device): void; + public function cleanup(Device $device): int; /** * Dump current module data for the given device for tests. diff --git a/LibreNMS/Modules/Availability.php b/LibreNMS/Modules/Availability.php index 8654c54b37..ee283453cc 100644 --- a/LibreNMS/Modules/Availability.php +++ b/LibreNMS/Modules/Availability.php @@ -100,12 +100,17 @@ class Availability implements Module $os->getDevice()->availability()->whereNotIn('availability_id', $valid_ids)->delete(); } + public function dataExists(Device $device): bool + { + return $device->availability()->exists(); + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->availability()->delete(); + return $device->availability()->delete(); } /** diff --git a/LibreNMS/Modules/Core.php b/LibreNMS/Modules/Core.php index 4a34a414df..281af8bf32 100644 --- a/LibreNMS/Modules/Core.php +++ b/LibreNMS/Modules/Core.php @@ -125,9 +125,14 @@ class Core implements Module $device->save(); } - public function cleanup(Device $device): void + public function dataExists(Device $device): bool { - // nothing to cleanup + return false; // no module specific data + } + + public function cleanup(Device $device): int + { + return 0; // nothing to cleanup } /** diff --git a/LibreNMS/Modules/EntityPhysical.php b/LibreNMS/Modules/EntityPhysical.php index 4996c247f8..8bb32ab9cc 100644 --- a/LibreNMS/Modules/EntityPhysical.php +++ b/LibreNMS/Modules/EntityPhysical.php @@ -58,12 +58,17 @@ class EntityPhysical implements Module // no polling } + public function dataExists(Device $device): bool + { + return $device->entityPhysical()->exists(); + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->entityPhysical()->delete(); + return $device->entityPhysical()->delete(); } /** diff --git a/LibreNMS/Modules/Isis.php b/LibreNMS/Modules/Isis.php index 8da0665932..5166b6c97f 100644 --- a/LibreNMS/Modules/Isis.php +++ b/LibreNMS/Modules/Isis.php @@ -107,18 +107,6 @@ class Isis implements Module $updated->each->save(); } - /** - * Remove all DB data for this module. - * This will be run when the module is disabled. - */ - public function cleanup(Device $device): void - { - $device->isisAdjacencies()->delete(); - - // clean up legacy components from old code - $device->components()->where('type', 'ISIS')->delete(); - } - public function discoverIsIsMib(OS $os): Collection { // Check if the device has any ISIS enabled interfaces @@ -197,6 +185,23 @@ class Isis implements Module return (int) (max($data['isisISAdjLastUpTime'] ?? 1, 1) / 100); } + public function dataExists(Device $device): bool + { + return $device->isisAdjacencies()->exists() || $device->components()->where('type', 'ISIS')->exists(); + } + + /** + * Remove all DB data for this module. + * This will be run when the module is disabled. + */ + public function cleanup(Device $device): int + { + // clean up legacy components from old code + $legacyDeleted = $device->components()->where('type', 'ISIS')->delete(); + + return $device->isisAdjacencies()->delete() + $legacyDeleted; + } + /** * @inheritDoc */ diff --git a/LibreNMS/Modules/LegacyModule.php b/LibreNMS/Modules/LegacyModule.php index c87d9e3af5..9640822312 100644 --- a/LibreNMS/Modules/LegacyModule.php +++ b/LibreNMS/Modules/LegacyModule.php @@ -117,9 +117,14 @@ class LegacyModule implements Module Debug::enableErrorReporting(); // and back to normal } - public function cleanup(Device $device): void + public function dataExists(Device $device): bool { - // TODO: Implement cleanup() method. + return false; // impossible to determine for legacy modules + } + + public function cleanup(Device $device): int + { + return 0; // Not possible to cleanup legacy modules } /** diff --git a/LibreNMS/Modules/Mempools.php b/LibreNMS/Modules/Mempools.php index ce4c22e9dc..111dc3d055 100644 --- a/LibreNMS/Modules/Mempools.php +++ b/LibreNMS/Modules/Mempools.php @@ -148,9 +148,14 @@ class Mempools implements Module return $mempools; } - public function cleanup(Device $device): void + public function dataExists(Device $device): bool { - $device->mempools()->delete(); + return $device->mempools()->exists(); + } + + public function cleanup(Device $device): int + { + return $device->mempools()->delete(); } /** diff --git a/LibreNMS/Modules/Mpls.php b/LibreNMS/Modules/Mpls.php index 9afa7b4d84..b2cf1bf1c4 100644 --- a/LibreNMS/Modules/Mpls.php +++ b/LibreNMS/Modules/Mpls.php @@ -165,20 +165,34 @@ class Mpls implements Module } } + public function dataExists(Device $device): bool + { + return $device->mplsLsps()->exists() + || $device->mplsLspPaths()->exists() + || $device->mplsSdps()->exists() + || $device->mplsServices()->exists() + || $device->mplsSaps()->exists() + || $device->mplsSdpBinds()->exists() + || $device->mplsTunnelArHops()->exists() + || $device->mplsTunnelCHops()->exists(); + } + /** * Remove all DB data for this module. * This will be run when the module is disabled. */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->mplsLsps()->delete(); - $device->mplsLspPaths()->delete(); - $device->mplsSdps()->delete(); - $device->mplsServices()->delete(); - $device->mplsSaps()->delete(); - $device->mplsSdpBinds()->delete(); - $device->mplsTunnelArHops()->delete(); - $device->mplsTunnelCHops()->delete(); + $deleted = $device->mplsLsps()->delete(); + $deleted += $device->mplsLspPaths()->delete(); + $deleted += $device->mplsSdps()->delete(); + $deleted += $device->mplsServices()->delete(); + $deleted += $device->mplsSaps()->delete(); + $deleted += $device->mplsSdpBinds()->delete(); + $deleted += $device->mplsTunnelArHops()->delete(); + $deleted += $device->mplsTunnelCHops()->delete(); + + return $deleted; } /** diff --git a/LibreNMS/Modules/Nac.php b/LibreNMS/Modules/Nac.php index e83c904af5..9f830cf977 100644 --- a/LibreNMS/Modules/Nac.php +++ b/LibreNMS/Modules/Nac.php @@ -113,13 +113,18 @@ class Nac implements Module } } + public function dataExists(Device $device): bool + { + return $device->portsNac()->exists(); + } + /** * Remove all DB data for this module. * This will be run when the module is disabled. */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->portsNac()->delete(); + return $device->portsNac()->delete(); } /** diff --git a/LibreNMS/Modules/Netstats.php b/LibreNMS/Modules/Netstats.php index 912480f884..dbff4387c7 100644 --- a/LibreNMS/Modules/Netstats.php +++ b/LibreNMS/Modules/Netstats.php @@ -227,12 +227,17 @@ class Netstats implements Module } } + public function dataExists(Device $device): bool + { + return false; // no database data + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - // no cleanup + return 0; // no cleanup } /** diff --git a/LibreNMS/Modules/Os.php b/LibreNMS/Modules/Os.php index 8b00046c3d..8ae3ef75d4 100644 --- a/LibreNMS/Modules/Os.php +++ b/LibreNMS/Modules/Os.php @@ -109,12 +109,17 @@ class Os implements Module $this->handleChanges($os); } + public function dataExists(Device $device): bool + { + return false; // data part of device + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - // no cleanup needed + return 0; // no cleanup needed } /** diff --git a/LibreNMS/Modules/Ospf.php b/LibreNMS/Modules/Ospf.php index 321b4b840e..a839e593c1 100644 --- a/LibreNMS/Modules/Ospf.php +++ b/LibreNMS/Modules/Ospf.php @@ -243,15 +243,25 @@ class Ospf implements Module } } + public function dataExists(Device $device): bool + { + return $device->ospfPorts()->exists() + || $device->ospfNbrs()->exists() + || $device->ospfAreas()->exists() + || $device->ospfInstances()->exists(); + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->ospfPorts()->delete(); - $device->ospfNbrs()->delete(); - $device->ospfAreas()->delete(); - $device->ospfInstances()->delete(); + $deleted = $device->ospfPorts()->delete(); + $deleted += $device->ospfNbrs()->delete(); + $deleted += $device->ospfAreas()->delete(); + $deleted += $device->ospfInstances()->delete(); + + return $deleted; } /** diff --git a/LibreNMS/Modules/PortsStack.php b/LibreNMS/Modules/PortsStack.php index fe70a2147c..13fb79edb5 100644 --- a/LibreNMS/Modules/PortsStack.php +++ b/LibreNMS/Modules/PortsStack.php @@ -101,12 +101,17 @@ class PortsStack implements Module // no polling } + public function dataExists(Device $device): bool + { + return $device->portsStack()->exists(); + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->portsStack()->delete(); + return $device->portsStack()->delete(); } /** diff --git a/LibreNMS/Modules/PrinterSupplies.php b/LibreNMS/Modules/PrinterSupplies.php index 5812efbeba..39e845198f 100644 --- a/LibreNMS/Modules/PrinterSupplies.php +++ b/LibreNMS/Modules/PrinterSupplies.php @@ -135,13 +135,18 @@ class PrinterSupplies implements Module } } + public function dataExists(Device $device): bool + { + return $device->printerSupplies()->exists(); + } + /** * Remove all DB data for this module. * This will be run when the module is disabled. */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->printerSupplies()->delete(); + return $device->printerSupplies()->delete(); } /** diff --git a/LibreNMS/Modules/Slas.php b/LibreNMS/Modules/Slas.php index 123da19de2..8d9c092c1a 100644 --- a/LibreNMS/Modules/Slas.php +++ b/LibreNMS/Modules/Slas.php @@ -102,13 +102,18 @@ class Slas implements Module } } + public function dataExists(Device $device): bool + { + return $device->slas()->exists(); + } + /** * Remove all DB data for this module. * This will be run when the module is disabled. */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->slas()->delete(); + return $device->slas()->delete(); } /** diff --git a/LibreNMS/Modules/Stp.php b/LibreNMS/Modules/Stp.php index 4d00d43db0..4755e123d0 100644 --- a/LibreNMS/Modules/Stp.php +++ b/LibreNMS/Modules/Stp.php @@ -88,10 +88,17 @@ class Stp implements Module $this->syncModels($device, 'stpPorts', $ports); } - public function cleanup(Device $device): void + public function dataExists(Device $device): bool { - $device->stpInstances()->delete(); - $device->stpPorts()->delete(); + return $device->stpInstances()->exists() || $device->stpPorts()->exists(); + } + + public function cleanup(Device $device): int + { + $deleted = $device->stpInstances()->delete(); + $deleted += $device->stpPorts()->delete(); + + return $deleted; } /** diff --git a/LibreNMS/Modules/Vminfo.php b/LibreNMS/Modules/Vminfo.php index c8cebc9b3b..077f653bdb 100644 --- a/LibreNMS/Modules/Vminfo.php +++ b/LibreNMS/Modules/Vminfo.php @@ -93,12 +93,17 @@ class Vminfo implements \LibreNMS\Interfaces\Module $this->discover($os); } + public function dataExists(Device $device): bool + { + return $device->vminfo()->exists(); + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->vminfo()->delete(); + return $device->vminfo()->delete(); } /** diff --git a/LibreNMS/Modules/Xdsl.php b/LibreNMS/Modules/Xdsl.php index 16950881e0..bdd6c37396 100644 --- a/LibreNMS/Modules/Xdsl.php +++ b/LibreNMS/Modules/Xdsl.php @@ -101,13 +101,20 @@ class Xdsl implements Module } } + public function dataExists(Device $device): bool + { + return $device->portsAdsl()->exists() || $device->portsVdsl()->exists(); + } + /** * @inheritDoc */ - public function cleanup(Device $device): void + public function cleanup(Device $device): int { - $device->portsAdsl()->delete(); - $device->portsVdsl()->delete(); + $deleted = $device->portsAdsl()->delete(); + $deleted += $device->portsVdsl()->delete(); + + return $deleted; } /** diff --git a/app/Http/Controllers/Device/Tabs/ModuleController.php b/app/Http/Controllers/Device/Tabs/ModuleController.php new file mode 100644 index 0000000000..8d642736cc --- /dev/null +++ b/app/Http/Controllers/Device/Tabs/ModuleController.php @@ -0,0 +1,59 @@ +validate($request, [ + 'discovery' => 'in:true,false,clear', + 'polling' => 'in:true,false,clear', + ]); + + if ($request->has('discovery')) { + $discovery = $request->get('discovery'); + if ($discovery == 'clear') { + $device->forgetAttrib('discover_' . $module); + } else { + $device->setAttrib('discover_' . $module, $discovery == 'true' ? 1 : 0); + } + } + + if ($request->has('polling')) { + $polling = $request->get('polling'); + if ($polling == 'clear') { + $device->forgetAttrib('poll_' . $module); + } else { + $device->setAttrib('poll_' . $module, $polling == 'true' ? 1 : 0); + } + } + + // return the module status + return response()->json([ + 'discovery' => (bool) $device->getAttrib('discover_' . $module, Config::getCombined($device->os, 'discovery_modules')[$module] ?? false), + 'polling' => (bool) $device->getAttrib('poll_' . $module, Config::getCombined($device->os, 'poller_modules')[$module] ?? false), + ]); + } + + public function delete(Device $device, string $module): JsonResponse + { + Gate::authorize('delete', $device); + + $deleted = Module::fromName($module)->cleanup($device); + + return response()->json([ + 'deleted' => $deleted, + ]); + } +} diff --git a/app/Models/Device.php b/app/Models/Device.php index 842e5a7715..d43fd1f4bb 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -406,9 +406,9 @@ class Device extends BaseModel $this->save(); } - public function getAttrib($name) + public function getAttrib($name, $default = null) { - return $this->attribs->pluck('attrib_value', 'attrib_type')->get($name); + return $this->attribs->pluck('attrib_value', 'attrib_type')->get($name, $default); } public function setAttrib($name, $value) diff --git a/includes/html/forms/discovery-module-update.inc.php b/includes/html/forms/discovery-module-update.inc.php deleted file mode 100644 index cf36002ad0..0000000000 --- a/includes/html/forms/discovery-module-update.inc.php +++ /dev/null @@ -1,27 +0,0 @@ -hasGlobalAdmin()) { - exit('ERROR: You need to be admin'); -} - -$device['device_id'] = $_POST['device_id']; -$module = 'discover_' . $_POST['discovery_module']; - -if (! isset($module) && validate_device_id($device['device_id']) === false) { - echo 'error with data'; - exit; -} else { - if ($_POST['state'] == 'true') { - $state = 1; - } elseif ($_POST['state'] == 'false') { - $state = 0; - } else { - $state = 0; - } - - set_dev_attrib($device, $module, $state); -} diff --git a/includes/html/forms/poller-module-update.inc.php b/includes/html/forms/poller-module-update.inc.php deleted file mode 100644 index d8f6e9f7e4..0000000000 --- a/includes/html/forms/poller-module-update.inc.php +++ /dev/null @@ -1,26 +0,0 @@ -hasGlobalAdmin()) { - exit('ERROR: You need to be admin'); -} - -// FUA -$device['device_id'] = $_POST['device_id']; -$module = 'poll_' . $_POST['poller_module']; - -if (! isset($module) && validate_device_id($device['device_id']) === false) { - echo 'error with data'; - exit; -} else { - if ($_POST['state'] == 'true') { - $state = 1; - } elseif ($_POST['state'] == 'false') { - $state = 0; - } else { - $state = 0; - } - - set_dev_attrib($device, $module, $state); -} diff --git a/includes/html/pages/device/edit/modules.inc.php b/includes/html/pages/device/edit/modules.inc.php index 1b12a626f2..4f8de0bdf7 100644 --- a/includes/html/pages/device/edit/modules.inc.php +++ b/includes/html/pages/device/edit/modules.inc.php @@ -14,16 +14,18 @@