mirror of
https://github.com/librenms/librenms.git
synced 2024-09-21 10:28:13 +00:00
Dispatcher Service settings (#11760)
* Poller settings WIP * Poller settings WIP2 * working on SettingMultiple * setting multiple working * settings sent with all required info * fix translation * Fix keys * fix groups setting * Apply settings to service fixes and validations for setting * don't error when no poller_cluster entry exists * hid tab when no poller cluster entries * Authorization * make prod * daily maintenance toggle should be advanced * Update schema def
This commit is contained in:
parent
946e90b68d
commit
300645388f
@ -59,7 +59,7 @@ class ServiceConfig:
|
||||
services = PollerConfig(8, 300)
|
||||
discovery = PollerConfig(16, 21600)
|
||||
billing = PollerConfig(2, 300, 60)
|
||||
ping = PollerConfig(1, 120)
|
||||
ping = PollerConfig(1, 60)
|
||||
down_retry = 60
|
||||
update_enabled = True
|
||||
update_frequency = 86400
|
||||
@ -118,7 +118,7 @@ class ServiceConfig:
|
||||
self.alerting.enabled = config.get('service_alerting_enabled', True)
|
||||
self.alerting.frequency = config.get('service_alerting_frequency', ServiceConfig.alerting.frequency)
|
||||
self.ping.enabled = config.get('service_ping_enabled', False)
|
||||
self.ping.frequency = config.get('ping_rrd_step', ServiceConfig.billing.calculate)
|
||||
self.ping.frequency = config.get('ping_rrd_step', ServiceConfig.ping.frequency)
|
||||
self.down_retry = config.get('service_poller_down_retry', ServiceConfig.down_retry)
|
||||
self.log_level = config.get('service_loglevel', ServiceConfig.log_level)
|
||||
self.update_enabled = config.get('service_update_enabled', ServiceConfig.update_enabled)
|
||||
@ -155,6 +155,68 @@ class ServiceConfig:
|
||||
error("Unknown log level {}, must be one of 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'".format(self.log_level))
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
|
||||
def load_poller_config(self, db):
|
||||
try:
|
||||
settings = {}
|
||||
cursor = db.query('SELECT * FROM `poller_cluster` WHERE `node_id`=%s', self.node_id)
|
||||
if cursor.rowcount == 0:
|
||||
return
|
||||
|
||||
for index, setting in enumerate(cursor.fetchone()):
|
||||
name = cursor.description[index][0]
|
||||
settings[name] = setting
|
||||
|
||||
if settings['poller_name'] is not None:
|
||||
self.set_name(settings['poller_name'])
|
||||
if settings['poller_groups'] is not None:
|
||||
self.group = ServiceConfig.parse_group(settings['poller_groups'])
|
||||
if settings['poller_enabled'] is not None:
|
||||
self.poller.enabled = settings['poller_enabled']
|
||||
if settings['poller_frequency'] is not None:
|
||||
self.poller.frequency = settings['poller_frequency']
|
||||
if settings['poller_workers'] is not None:
|
||||
self.poller.workers = settings['poller_workers']
|
||||
if settings['poller_down_retry'] is not None:
|
||||
self.down_retry = settings['poller_down_retry']
|
||||
if settings['discovery_enabled'] is not None:
|
||||
self.discovery.enabled = settings['discovery_enabled']
|
||||
if settings['discovery_frequency'] is not None:
|
||||
self.discovery.frequency = settings['discovery_frequency']
|
||||
if settings['discovery_workers'] is not None:
|
||||
self.discovery.workers = settings['discovery_workers']
|
||||
if settings['services_enabled'] is not None:
|
||||
self.services.enabled = settings['services_enabled']
|
||||
if settings['services_frequency'] is not None:
|
||||
self.services.frequency = settings['services_frequency']
|
||||
if settings['services_workers'] is not None:
|
||||
self.services.workers = settings['services_workers']
|
||||
if settings['billing_enabled'] is not None:
|
||||
self.billing.enabled = settings['billing_enabled']
|
||||
if settings['billing_frequency'] is not None:
|
||||
self.billing.frequency = settings['billing_frequency']
|
||||
if settings['billing_calculate_frequency'] is not None:
|
||||
self.billing.calculate = settings['billing_calculate_frequency']
|
||||
if settings['alerting_enabled'] is not None:
|
||||
self.alerting.enabled = settings['alerting_enabled']
|
||||
if settings['alerting_frequency'] is not None:
|
||||
self.alerting.frequency = settings['alerting_frequency']
|
||||
if settings['ping_enabled'] is not None:
|
||||
self.ping.enabled = settings['ping_enabled']
|
||||
if settings['ping_frequency'] is not None:
|
||||
self.ping.frequency = settings['ping_frequency']
|
||||
if settings['update_enabled'] is not None:
|
||||
self.update_enabled = settings['update_enabled']
|
||||
if settings['update_frequency'] is not None:
|
||||
self.update_frequency = settings['update_frequency']
|
||||
if settings['loglevel'] is not None:
|
||||
self.log_level = settings['loglevel']
|
||||
if settings['watchdog_enabled'] is not None:
|
||||
self.watchdog_enabled = settings['watchdog_enabled']
|
||||
if settings['watchdog_log'] is not None:
|
||||
self.watchdog_logfile = settings['watchdog_log']
|
||||
except pymysql.err.Error:
|
||||
warning('Unable to load poller (%s) config', self.node_id)
|
||||
|
||||
def _get_config_data(self):
|
||||
try:
|
||||
import dotenv
|
||||
@ -205,11 +267,11 @@ class Service:
|
||||
|
||||
def __init__(self):
|
||||
self.config.populate()
|
||||
threading.current_thread().name = self.config.name # rename main thread
|
||||
|
||||
self.attach_signals()
|
||||
|
||||
self._db = LibreNMS.DB(self.config)
|
||||
self.config.load_poller_config(self._db)
|
||||
|
||||
threading.current_thread().name = self.config.name # rename main thread
|
||||
self.attach_signals()
|
||||
|
||||
self._lm = self.create_lock_manager()
|
||||
self.daily_timer = LibreNMS.RecurringTimer(self.config.update_frequency, self.run_maintenance, 'maintenance')
|
||||
|
@ -8,6 +8,7 @@ use App\Models\PollerCluster;
|
||||
use App\Models\PollerGroup;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use LibreNMS\Config;
|
||||
|
||||
class PollerController extends Controller
|
||||
@ -21,6 +22,7 @@ class PollerController extends Controller
|
||||
|
||||
public function logTab(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', PollerCluster::class);
|
||||
return view('poller.log', [
|
||||
'current_tab' => 'log',
|
||||
'filter' => $request->input('filter', 'active')
|
||||
@ -29,6 +31,7 @@ class PollerController extends Controller
|
||||
|
||||
public function groupsTab()
|
||||
{
|
||||
$this->authorize('manage', PollerCluster::class);
|
||||
return view('poller.groups', [
|
||||
'current_tab' => 'groups',
|
||||
'poller_groups' => PollerGroup::query()->withCount('devices')->get(),
|
||||
@ -39,6 +42,7 @@ class PollerController extends Controller
|
||||
|
||||
public function pollerTab()
|
||||
{
|
||||
$this->authorize('viewAny', PollerCluster::class);
|
||||
return view('poller.poller', [
|
||||
'current_tab' => 'poller',
|
||||
'pollers' => $this->poller(),
|
||||
@ -46,8 +50,20 @@ class PollerController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function settingsTab()
|
||||
{
|
||||
$this->authorize('manage', PollerCluster::class);
|
||||
$pollerClusters = PollerCluster::all()->keyBy('id');
|
||||
return view('poller.settings', [
|
||||
'current_tab' => 'settings',
|
||||
'settings' => $this->pollerSettings($pollerClusters),
|
||||
'poller_cluster' => $pollerClusters,
|
||||
]);
|
||||
}
|
||||
|
||||
public function performanceTab()
|
||||
{
|
||||
$this->authorize('viewAny', PollerCluster::class);
|
||||
return view('poller.performance', ['current_tab' => 'performance']);
|
||||
}
|
||||
|
||||
@ -85,4 +101,10 @@ class PollerController extends Controller
|
||||
|
||||
return 'success';
|
||||
}
|
||||
|
||||
private function pollerSettings($pollers): Collection
|
||||
{
|
||||
$groups = PollerGroup::list();
|
||||
return $pollers->map->configDefinition($groups);
|
||||
}
|
||||
}
|
||||
|
62
app/Http/Controllers/PollerSettingsController.php
Normal file
62
app/Http/Controllers/PollerSettingsController.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* PollerSettingsController.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 2020 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PollerCluster;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PollerSettingsController extends Controller
|
||||
{
|
||||
public function update(Request $request, $id, $setting)
|
||||
{
|
||||
$poller = PollerCluster::findOrFail($id);
|
||||
$this->authorize('update', $poller);
|
||||
|
||||
$definition = collect($poller->configDefinition())->keyBy('name');
|
||||
if (!$definition->has($setting)) {
|
||||
return response()->json(['error' => 'Invalid setting'], 422);
|
||||
}
|
||||
|
||||
$poller->$setting = $request->get('value');
|
||||
$poller->save();
|
||||
return response()->json(['value' => $poller->$setting]);
|
||||
}
|
||||
|
||||
public function destroy($id, $setting)
|
||||
{
|
||||
$poller = PollerCluster::findOrFail($id);
|
||||
$this->authorize('delete', $poller);
|
||||
|
||||
$definition = collect($poller->configDefinition())->keyBy('name');
|
||||
if (!$definition->has($setting)) {
|
||||
return response()->json(['error' => 'Invalid setting'], 422);
|
||||
}
|
||||
|
||||
$poller->$setting = $definition->get($setting)['default'];
|
||||
$poller->save();
|
||||
return response()->json(['value' => $poller->$setting]);
|
||||
}
|
||||
}
|
@ -34,6 +34,201 @@ class PollerCluster extends Model
|
||||
protected $primaryKey = 'id';
|
||||
protected $fillable = ['poller_name'];
|
||||
|
||||
// ---- Accessors/Mutators ----
|
||||
|
||||
public function setPollerGroupsAttribute($groups)
|
||||
{
|
||||
$this->attributes['poller_groups'] = is_array($groups) ? implode(',', $groups) : $groups;
|
||||
}
|
||||
|
||||
// ---- Helpers ----
|
||||
|
||||
/**
|
||||
* Get the frontend config definition for this poller
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $groups optionally supply full list of poller groups to avoid fetching multiple times
|
||||
* @return array[]
|
||||
*/
|
||||
public function configDefinition($groups = null)
|
||||
{
|
||||
if (empty($groups)) {
|
||||
$groups = PollerGroup::list();
|
||||
}
|
||||
|
||||
return [
|
||||
[
|
||||
'name' => 'poller_groups',
|
||||
'default' => \LibreNMS\Config::get('distributed_poller_group'),
|
||||
'value' => $poller->poller_groups ?? \LibreNMS\Config::get('distributed_poller_group'),
|
||||
'type' => 'multiple',
|
||||
'options' => $groups,
|
||||
],
|
||||
[
|
||||
'name' => 'poller_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_poller_enabled'),
|
||||
'value' => (bool)($poller->poller_enabled ?? \LibreNMS\Config::get('service_poller_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'poller_workers',
|
||||
'default' => \LibreNMS\Config::get('service_poller_workers'),
|
||||
'value' => $poller->poller_workers ?? \LibreNMS\Config::get('service_poller_workers'),
|
||||
'type' => 'integer',
|
||||
'units' => 'workers',
|
||||
],
|
||||
[
|
||||
'name' => 'poller_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_poller_frequency'),
|
||||
'value' => $poller->poller_workers ?? \LibreNMS\Config::get('service_poller_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'poller_down_retry',
|
||||
'default' => \LibreNMS\Config::get('service_poller_down_retry'),
|
||||
'value' => $poller->poller_down_retry ?? \LibreNMS\Config::get('service_poller_down_retry'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
],
|
||||
[
|
||||
'name' => 'discovery_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_discovery_enabled'),
|
||||
'value' => (bool)($poller->discovery_enabled ?? \LibreNMS\Config::get('service_discovery_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'discovery_workers',
|
||||
'default' => \LibreNMS\Config::get('service_discovery_workers'),
|
||||
'value' => $poller->discovery_workers ?? \LibreNMS\Config::get('service_discovery_workers'),
|
||||
'type' => 'integer',
|
||||
'units' => 'workers',
|
||||
],
|
||||
[
|
||||
'name' => 'discovery_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_discovery_frequency'),
|
||||
'value' => $poller->discovery_frequency ?? \LibreNMS\Config::get('service_discovery_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'services_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_services_enabled'),
|
||||
'value' => (bool)($poller->services_enabled ?? \LibreNMS\Config::get('service_services_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'services_workers',
|
||||
'default' => \LibreNMS\Config::get('service_services_workers'),
|
||||
'value' => $poller->services_workers ?? \LibreNMS\Config::get('service_services_workers'),
|
||||
'type' => 'integer',
|
||||
'units' => 'workers',
|
||||
],
|
||||
[
|
||||
'name' => 'services_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_services_frequency'),
|
||||
'value' => $poller->services_frequency ?? \LibreNMS\Config::get('service_services_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_billing_enabled'),
|
||||
'value' => (bool)($poller->billing_enabled ?? \LibreNMS\Config::get('service_billing_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'billing_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_billing_frequency'),
|
||||
'value' => $poller->billing_frequency ?? \LibreNMS\Config::get('service_billing_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_calculate_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_billing_calculate_frequency'),
|
||||
'value' => $poller->billing_calculate_frequency ?? \LibreNMS\Config::get('service_billing_calculate_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'alerting_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_alerting_enabled'),
|
||||
'value' => (bool)($poller->alerting_enabled ?? \LibreNMS\Config::get('service_alerting_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'alerting_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_alerting_frequency'),
|
||||
'value' => $poller->alerting_frequency ?? \LibreNMS\Config::get('service_alerting_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'ping_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_ping_enabled'),
|
||||
'value' => (bool)($poller->ping_enabled ?? \LibreNMS\Config::get('service_ping_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'ping_frequency',
|
||||
'default' => \LibreNMS\Config::get('ping_rrd_step'),
|
||||
'value' => $poller->ping_frequency ?? \LibreNMS\Config::get('ping_rrd_step'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'update_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_update_enabled'),
|
||||
'value' => (bool)($poller->update_enabled ?? \LibreNMS\Config::get('service_update_enabled')),
|
||||
'type' => 'boolean',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'update_frequency',
|
||||
'default' => \LibreNMS\Config::get('service_update_frequency'),
|
||||
'value' => $poller->update_frequency ?? \LibreNMS\Config::get('service_update_frequency'),
|
||||
'type' => 'integer',
|
||||
'units' => 'seconds',
|
||||
'advanced' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'loglevel',
|
||||
'default' => \LibreNMS\Config::get('service_loglevel'),
|
||||
'value' => $poller->loglevel ?? \LibreNMS\Config::get('service_loglevel'),
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
'DEBUG' => 'DEBUG',
|
||||
'INFO' => 'INFO',
|
||||
'WARNING' => 'WARNING',
|
||||
'ERROR' => 'ERROR',
|
||||
'CRITICAL' => 'CRITICAL'
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'watchdog_enabled',
|
||||
'default' => \LibreNMS\Config::get('service_watchdog_enabled'),
|
||||
'value' => (bool)($poller->watchdog_enabled ?? \LibreNMS\Config::get('service_watchdog_enabled')),
|
||||
'type' => 'boolean',
|
||||
],
|
||||
[
|
||||
'name' => 'watchdog_log',
|
||||
'default' => \LibreNMS\Config::get('log_file'),
|
||||
'value' => $poller->watchdog_log ?? \LibreNMS\Config::get('log_file'),
|
||||
'type' => 'text',
|
||||
'advanced' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// ---- Relationships ----
|
||||
|
||||
public function stats()
|
||||
{
|
||||
return $this->hasMany(\App\Models\PollerClusterStat::class, 'parent_poller', 'id');
|
||||
|
@ -41,12 +41,17 @@ class PollerGroup extends Model
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (PollerGroup $pollergroup) {
|
||||
// handle device pollergroup fallback to default poller
|
||||
// handle device poller group fallback to default poller
|
||||
$default_poller_id = \LibreNMS\Config::get('default_poller_group');
|
||||
$pollergroup->devices()->update(['poller_group' => $default_poller_id]);
|
||||
});
|
||||
}
|
||||
|
||||
public static function list()
|
||||
{
|
||||
return self::query()->pluck('group_name', 'id')->prepend(__('General'), 0);
|
||||
}
|
||||
|
||||
public function devices()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Device::class, 'poller_group', 'id');
|
||||
|
106
app/Policies/PollerClusterPolicy.php
Normal file
106
app/Policies/PollerClusterPolicy.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\PollerCluster;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class PollerClusterPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any poller clusters.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function viewAny(User $user)
|
||||
{
|
||||
return $user->hasGlobalAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the poller cluster.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\PollerCluster $pollerCluster
|
||||
* @return mixed
|
||||
*/
|
||||
public function view(User $user, PollerCluster $pollerCluster)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create poller clusters.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(User $user)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the poller cluster.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\PollerCluster $pollerCluster
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(User $user, PollerCluster $pollerCluster)
|
||||
{
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the poller cluster.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\PollerCluster $pollerCluster
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete(User $user, PollerCluster $pollerCluster)
|
||||
{
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the poller cluster.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\PollerCluster $pollerCluster
|
||||
* @return mixed
|
||||
*/
|
||||
public function restore(User $user, PollerCluster $pollerCluster)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the poller cluster.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\PollerCluster $pollerCluster
|
||||
* @return mixed
|
||||
*/
|
||||
public function forceDelete(User $user, PollerCluster $pollerCluster)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can manage the poller cluster.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\PollerCluster $pollerCluster
|
||||
* @return mixed
|
||||
*/
|
||||
public function manage(User $user)
|
||||
{
|
||||
return $user->isAdmin();
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
\App\Models\User::class => \App\Policies\UserPolicy::class,
|
||||
\App\Models\Device::class => \App\Policies\DevicePolicy::class,
|
||||
\App\Models\DeviceGroup::class => \App\Policies\DeviceGroupPolicy::class,
|
||||
\App\Models\PollerCluster::class => \App\Policies\PollerClusterPolicy::class,
|
||||
\App\Models\Port::class => \App\Policies\PortPolicy::class,
|
||||
];
|
||||
|
||||
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class PollerClusterSettings extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('poller_cluster', function (Blueprint $table) {
|
||||
$table->boolean('poller_enabled')->nullable();
|
||||
$table->integer('poller_frequency')->nullable();
|
||||
$table->integer('poller_workers')->nullable();
|
||||
$table->integer('poller_down_retry')->nullable();
|
||||
$table->boolean('discovery_enabled')->nullable();
|
||||
$table->integer('discovery_frequency')->nullable();
|
||||
$table->integer('discovery_workers')->nullable();
|
||||
$table->boolean('services_enabled')->nullable();
|
||||
$table->integer('services_frequency')->nullable();
|
||||
$table->integer('services_workers')->nullable();
|
||||
$table->boolean('billing_enabled')->nullable();
|
||||
$table->integer('billing_frequency')->nullable();
|
||||
$table->integer('billing_calculate_frequency')->nullable();
|
||||
$table->boolean('alerting_enabled')->nullable();
|
||||
$table->integer('alerting_frequency')->nullable();
|
||||
$table->boolean('ping_enabled')->nullable();
|
||||
$table->integer('ping_frequency')->nullable();
|
||||
$table->boolean('update_enabled')->nullable();
|
||||
$table->integer('update_frequency')->nullable();
|
||||
$table->string('loglevel', 8)->nullable();
|
||||
$table->boolean('watchdog_enabled')->nullable();
|
||||
$table->string('watchdog_log')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('poller_cluster', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'poller_enabled',
|
||||
'poller_frequency',
|
||||
'poller_workers',
|
||||
'poller_down_retry',
|
||||
'discovery_enabled',
|
||||
'discovery_frequency',
|
||||
'discovery_workers',
|
||||
'services_enabled',
|
||||
'services_frequency',
|
||||
'services_workers',
|
||||
'billing_enabled',
|
||||
'billing_frequency',
|
||||
'billing_calculate_frequency',
|
||||
'alerting_enabled',
|
||||
'alerting_frequency',
|
||||
'ping_enabled',
|
||||
'ping_frequency',
|
||||
'update_enabled',
|
||||
'update_frequency',
|
||||
'loglevel',
|
||||
'watchdog_enabled',
|
||||
'watchdog_log'
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,12 +1,12 @@
|
||||
{
|
||||
"/js/app.js": "/js/app.js?id=63189b3aa20a0043cc38",
|
||||
"/css/app.css": "/css/app.css?id=5da3bf931f2f95a17884",
|
||||
"/js/app.js": "/js/app.js?id=4d14830ae8a6dfe54711",
|
||||
"/css/app.css": "/css/app.css?id=ffec4165a9c98d892a32",
|
||||
"/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e",
|
||||
"/js/vendor.js": "/js/vendor.js?id=29212a758157c575d7f8",
|
||||
"/js/lang/de.js": "/js/lang/de.js?id=d095b82e431906ea9b0d",
|
||||
"/js/lang/en.js": "/js/lang/en.js?id=de1f054e216295f509a3",
|
||||
"/js/lang/fr.js": "/js/lang/fr.js?id=8e94b3986dc6fce2f3e5",
|
||||
"/js/lang/ru.js": "/js/lang/ru.js?id=dc6cb9314c4903b00501",
|
||||
"/js/lang/uk.js": "/js/lang/uk.js?id=669c4652f87dfd31ce7a",
|
||||
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=82383ffa183494fa4a14"
|
||||
"/js/vendor.js": "/js/vendor.js?id=c0e0ebbfd027a8baefb4",
|
||||
"/js/lang/de.js": "/js/lang/de.js?id=b96f6bf4d57d6614e18f",
|
||||
"/js/lang/en.js": "/js/lang/en.js?id=5e41e02c1021ebebaf1d",
|
||||
"/js/lang/fr.js": "/js/lang/fr.js?id=4f329163511445d92a17",
|
||||
"/js/lang/ru.js": "/js/lang/ru.js?id=f818cb1ab0a804b7bd3a",
|
||||
"/js/lang/uk.js": "/js/lang/uk.js?id=c8d4937e3ca47b60b7ac",
|
||||
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=a22406ceaffc7c936ed8"
|
||||
}
|
||||
|
@ -4515,6 +4515,172 @@
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_poller_enabled": {
|
||||
"default": true,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 5,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_poller_workers": {
|
||||
"default": 24,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 6,
|
||||
"type": "integer",
|
||||
"units": "Workers"
|
||||
},
|
||||
"service_poller_frequency": {
|
||||
"default": 300,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 7,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_poller_down_retry": {
|
||||
"default": 60,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 8,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_discovery_enabled": {
|
||||
"default": true,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 9,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_discovery_workers": {
|
||||
"default": 16,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 10,
|
||||
"type": "integer",
|
||||
"units": "Workers"
|
||||
},
|
||||
"service_discovery_frequency": {
|
||||
"default": 21600,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 11,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_services_enabled": {
|
||||
"default": true,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 12,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_services_workers": {
|
||||
"default": 8,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 13,
|
||||
"type": "integer",
|
||||
"units": "Workers"
|
||||
},
|
||||
"service_services_frequency": {
|
||||
"default": 300,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 14,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_billing_enabled": {
|
||||
"default": true,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 15,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_billing_frequency": {
|
||||
"default": 300,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 16,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_billing_calculate_frequency": {
|
||||
"default": 60,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 17,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_alerting_enabled": {
|
||||
"default": true,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 18,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_alerting_frequency": {
|
||||
"default": 60,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 19,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_ping_enabled": {
|
||||
"default": false,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 20,
|
||||
"type": "boolean"
|
||||
},
|
||||
"ping_rrd_step": {
|
||||
"default": 60,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 21,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_update_enabled": {
|
||||
"default": true,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 22,
|
||||
"type": "boolean"
|
||||
},
|
||||
"service_update_frequency": {
|
||||
"default": 86400,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 23,
|
||||
"type": "integer",
|
||||
"units": "Seconds"
|
||||
},
|
||||
"service_loglevel": {
|
||||
"default": "INFO",
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 24,
|
||||
"type": "select",
|
||||
"options": {
|
||||
"DEBUG": "DEBUG",
|
||||
"INFO": "INFO",
|
||||
"WARNING": "WARNING",
|
||||
"ERROR": "ERROR",
|
||||
"CRITICAL": "CRITICAL"
|
||||
}
|
||||
},
|
||||
"service_watchdog_enabled": {
|
||||
"default": false,
|
||||
"group": "poller",
|
||||
"section": "distributed",
|
||||
"order": 25,
|
||||
"type": "boolean"
|
||||
},
|
||||
"sfdp": {
|
||||
"default": "/usr/bin/sfdp",
|
||||
"group": "external",
|
||||
@ -4639,8 +4805,12 @@
|
||||
"type": "text"
|
||||
},
|
||||
"smokeping.pings": {
|
||||
"default": 20,
|
||||
"type": "integer"
|
||||
"default": 5,
|
||||
"group": "external",
|
||||
"section": "smokeping",
|
||||
"order": 2,
|
||||
"type": "integer",
|
||||
"units": "pings"
|
||||
},
|
||||
"snmp.community": {
|
||||
"group": "poller",
|
||||
@ -5023,14 +5193,6 @@
|
||||
"order": 1,
|
||||
"type": "text"
|
||||
},
|
||||
"smokeping.pings": {
|
||||
"default": 5,
|
||||
"group": "external",
|
||||
"section": "smokeping",
|
||||
"order": 2,
|
||||
"type": "integer",
|
||||
"units": "pings"
|
||||
},
|
||||
"smokeping.url": {
|
||||
"group": "external",
|
||||
"section": "smokeping",
|
||||
|
@ -1326,6 +1326,28 @@ poller_cluster:
|
||||
- { Field: poller_groups, Type: varchar(255), 'Null': false, Extra: '', Default: '' }
|
||||
- { Field: last_report, Type: datetime, 'Null': false, Extra: '' }
|
||||
- { Field: master, Type: tinyint, 'Null': false, Extra: '' }
|
||||
- { Field: poller_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: poller_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: poller_workers, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: poller_down_retry, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: discovery_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: discovery_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: discovery_workers, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: services_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: services_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: services_workers, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: billing_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: billing_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: billing_calculate_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: alerting_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: alerting_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: ping_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: ping_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: update_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: update_frequency, Type: int, 'Null': true, Extra: '' }
|
||||
- { Field: loglevel, Type: varchar(8), 'Null': true, Extra: '' }
|
||||
- { Field: watchdog_enabled, Type: tinyint, 'Null': true, Extra: '' }
|
||||
- { Field: watchdog_log, Type: varchar(255), 'Null': true, Extra: '' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
|
||||
poller_cluster_node_id_unique: { Name: poller_cluster_node_id_unique, Columns: [node_id], Unique: true, Type: BTREE }
|
||||
|
67
package-lock.json
generated
67
package-lock.json
generated
@ -1464,6 +1464,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-helper-vue-jsx-merge-props": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
|
||||
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
|
||||
},
|
||||
"babel-loader": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
|
||||
@ -1716,9 +1721,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
|
||||
"integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==",
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz",
|
||||
"integrity": "sha512-Z93QoXvodoVslA+PWNdk23Hze4RBYIkpb5h8I2HY2Tu2h7A0LpAgLcyrhrSUyo2/Oxm2l1fRZPs1e5hnxnliXA==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
@ -2017,9 +2022,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
|
||||
"integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==",
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
|
||||
"integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"anymatch": "~3.1.1",
|
||||
@ -2029,7 +2034,7 @@
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.3.0"
|
||||
"readdirp": "~3.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
@ -2067,9 +2072,9 @@
|
||||
}
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
|
||||
"integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
@ -2098,12 +2103,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz",
|
||||
"integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==",
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
|
||||
"integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"picomatch": "^2.0.7"
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
@ -5401,9 +5406,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.0.tgz",
|
||||
"integrity": "sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ==",
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
|
||||
"integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==",
|
||||
"dev": true
|
||||
},
|
||||
"js-levenshtein": {
|
||||
@ -7994,9 +7999,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.26.3",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.3.tgz",
|
||||
"integrity": "sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw==",
|
||||
"version": "1.26.5",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.5.tgz",
|
||||
"integrity": "sha512-FG2swzaZUiX53YzZSjSakzvGtlds0lcbF+URuU9mxOv7WBh7NhXEVDa4kPKN4hN6fC2TkOTOKqiqp6d53N9X5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": ">=2.0.0 <4.0.0"
|
||||
@ -9388,9 +9393,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"vue-i18n": {
|
||||
"version": "8.15.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.15.5.tgz",
|
||||
"integrity": "sha512-lIej02+w8lP0k1PEN1xtXqKpQ1hDh17zvDF+7Oc2qJi+cTMDlfPM771w4euVaHO67AxEz4WL9MIgkyn3tkeCtQ=="
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.18.0.tgz",
|
||||
"integrity": "sha512-7DVu8CfoyPoCRWB5TOqfw2kIhk2umagsri4L1V1c0s+lHUC0VbQYoucFprHUELyHU9Legqzt/FxyLGDpBOlX9w=="
|
||||
},
|
||||
"vue-js-toggle-button": {
|
||||
"version": "1.3.3",
|
||||
@ -9410,15 +9415,25 @@
|
||||
"vue-style-loader": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"vue-multiselect": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.6.tgz",
|
||||
"integrity": "sha512-s7jmZPlm9FeueJg1RwJtnE9KNPtME/7C8uRWSfp9/yEN4M8XcS/d+bddoyVwVnvFyRh9msFo0HWeW0vTL8Qv+w=="
|
||||
},
|
||||
"vue-nav-tabs": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-nav-tabs/-/vue-nav-tabs-0.5.7.tgz",
|
||||
"integrity": "sha512-Oqq7qnb0/JPAVSqM0haQ9TdEZaTbQq20TVn5ZCmBOu8m9qju9bI8cDdtWGHXSiMkpmhzsT83ybRb7S/+UYXRsw=="
|
||||
},
|
||||
"vue-resize": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz",
|
||||
"integrity": "sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg=="
|
||||
},
|
||||
"vue-select": {
|
||||
"version": "3.9.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-select/-/vue-select-3.9.4.tgz",
|
||||
"integrity": "sha512-91vvz2WcmlMTzKI2LbA+jxhHjVwuFhGZXV20F7XxIeF/+A7PLfBTu8mCHh51ELF/UF6YsXAvd8t7BUhx8sydzQ=="
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-select/-/vue-select-3.10.3.tgz",
|
||||
"integrity": "sha512-SgLmiSwnJwT2erxjq42AA1iTzu1uqhA5MPuF4UDtGot5YSgJLKy71H0LO0hHaBpIjb7d/nJHiufYKcrSakaupw=="
|
||||
},
|
||||
"vue-style-loader": {
|
||||
"version": "4.1.2",
|
||||
|
13
package.json
13
package.json
@ -13,24 +13,27 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"bootstrap": "^4.4.1",
|
||||
"bootstrap": "^4.5.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"jquery": "^3.5",
|
||||
"jquery": "^3.5.1",
|
||||
"laravel-mix": "^4.1.4",
|
||||
"lodash": "^4.17.15",
|
||||
"popper.js": "^1.16.1",
|
||||
"resolve-url-loader": "^2.3.1",
|
||||
"sass": "^1.26.3",
|
||||
"sass": "^1.26.5",
|
||||
"sass-loader": "^7.3.1",
|
||||
"vue": "^2.6.11",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"es6-object-assign": "^1.1.0",
|
||||
"v-tooltip": "^2.0.3",
|
||||
"vue-i18n": "^8.15.5",
|
||||
"vue-i18n": "^8.18.0",
|
||||
"vue-js-toggle-button": "^1.3.3",
|
||||
"vue-select": "^3.9.4",
|
||||
"vue-multiselect": "^2.1.6",
|
||||
"vue-nav-tabs": "^0.5.7",
|
||||
"vue-select": "^3.10.3",
|
||||
"vuedraggable": "^2.23.2"
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,17 @@ Vue.use(VTooltip);
|
||||
import vSelect from 'vue-select'
|
||||
Vue.component('v-select', vSelect);
|
||||
|
||||
Vue.mixin({
|
||||
methods: {
|
||||
route: route
|
||||
}
|
||||
});
|
||||
import Multiselect from 'vue-multiselect'
|
||||
Vue.component('multiselect', Multiselect)
|
||||
|
||||
import VueTabs from 'vue-nav-tabs'
|
||||
Vue.use(VueTabs)
|
||||
|
||||
// Vue.mixin({
|
||||
// methods: {
|
||||
// route: route
|
||||
// }
|
||||
// });
|
||||
|
||||
Vue.filter('ucfirst', function (value) {
|
||||
if (!value) return '';
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!--
|
||||
- LibrenmsSetting.vue
|
||||
-
|
||||
- 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
|
||||
@ -26,9 +26,9 @@
|
||||
<div :class="['form-group', 'has-feedback', setting.class, feedback]">
|
||||
<label :for="setting.name" class="col-sm-5 control-label" v-tooltip="{ content: setting.name }">
|
||||
{{ getDescription() }}
|
||||
<span v-if="setting.units !== null">({{ setting.units }})</span>
|
||||
<span v-if="setting.units">({{ getUnits() }})</span>
|
||||
</label>
|
||||
<div class="col-sm-5" v-tooltip="{ content: setting.disabled ? $t('settings.readonly') : false }">
|
||||
<div class="col-sm-5" v-tooltip="{ content: setting.disabled ? $t(this.prefix + '.readonly') : false }">
|
||||
<component :is="getComponent()"
|
||||
:value="value"
|
||||
:name="setting.name"
|
||||
@ -53,7 +53,9 @@
|
||||
export default {
|
||||
name: "LibrenmsSetting",
|
||||
props: {
|
||||
'setting': {type: Object, required: true}
|
||||
'setting': {type: Object, required: true},
|
||||
'prefix': {type: String, default: 'settings'},
|
||||
'id': {required: false}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -63,7 +65,7 @@
|
||||
},
|
||||
methods: {
|
||||
persistValue(value) {
|
||||
axios.put(route('settings.update', this.setting.name), {value: value})
|
||||
axios.put(route(this.prefix + '.update', this.getRouteParams()), {value: value})
|
||||
.then((response) => {
|
||||
this.value = response.data.value;
|
||||
this.$emit('setting-updated', {name: this.setting.name, value: this.value});
|
||||
@ -91,7 +93,7 @@
|
||||
this.persistValue(value)
|
||||
}, 500),
|
||||
changeValue(value) {
|
||||
if (['select', 'boolean'].includes(this.setting.type)) {
|
||||
if (['select', 'boolean', 'multiple'].includes(this.setting.type)) {
|
||||
// no need to debounce
|
||||
this.persistValue(value);
|
||||
} else {
|
||||
@ -99,24 +101,28 @@
|
||||
}
|
||||
this.value = value
|
||||
},
|
||||
getUnits() {
|
||||
let key = this.prefix + '.units.' + this.setting.units;
|
||||
return this.$te(key) ? this.$t(key) : this.setting.units
|
||||
},
|
||||
getDescription() {
|
||||
let key = 'settings.settings.' + this.setting.name + '.description';
|
||||
let key = this.prefix + '.settings.' + this.setting.name + '.description';
|
||||
return (this.$te(key) || this.$te(key, this.$i18n.fallbackLocale)) ? this.$t(key) : this.setting.name;
|
||||
},
|
||||
getHelp() {
|
||||
let help = this.$t('settings.settings.' + this.setting.name + '.help');
|
||||
let help = this.$t(this.prefix + '.settings.' + this.setting.name + '.help');
|
||||
if (this.setting.overridden) {
|
||||
help += "</p><p>" + this.$t('settings.readonly')
|
||||
help += "</p><p>" + this.$t(this.prefix + '.readonly')
|
||||
}
|
||||
|
||||
return help
|
||||
},
|
||||
hasHelp() {
|
||||
var key = 'settings.settings.' + this.setting.name + '.help';
|
||||
let key = this.prefix + '.settings.' + this.setting.name + '.help';
|
||||
return this.$te(key) || this.$te(key, this.$i18n.fallbackLocale)
|
||||
},
|
||||
resetToDefault() {
|
||||
axios.delete(route('settings.destroy', this.setting.name))
|
||||
axios.delete(route(this.prefix + '.destroy', this.getRouteParams()))
|
||||
.then((response) => {
|
||||
this.value = response.data.value;
|
||||
this.feedback = 'has-success';
|
||||
@ -138,6 +144,13 @@
|
||||
showUndo() {
|
||||
return !_.isEqual(this.setting.value, this.value);
|
||||
},
|
||||
getRouteParams() {
|
||||
let parameters = [this.setting.name];
|
||||
if (this.id) {
|
||||
parameters.unshift(this.id);
|
||||
}
|
||||
return parameters;
|
||||
},
|
||||
getComponent() {
|
||||
// snake to studly
|
||||
const component = 'Setting' + this.setting.type.toString()
|
||||
|
77
resources/js/components/PollerSettings.vue
Normal file
77
resources/js/components/PollerSettings.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<!--
|
||||
- PollerSettings.vue
|
||||
-
|
||||
- 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 2020 Tony Murray
|
||||
- @author Tony Murray <murraytony@gmail.com>
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{{ $t('Poller Settings') }}
|
||||
<span class="pull-right">Advanced <toggle-button v-model="advanced"></toggle-button></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<vue-tabs direction="vertical" type="pills">
|
||||
<v-tab :title="poller.poller_name" v-for="(poller, id) in pollers" :key="id">
|
||||
<div class="setting-container clearfix"
|
||||
v-for="setting in settings[id]"
|
||||
v-if="!setting.advanced || advanced"
|
||||
:key="setting.name">
|
||||
<librenms-setting
|
||||
prefix="poller.settings"
|
||||
:setting='setting'
|
||||
:id="poller.id"
|
||||
></librenms-setting>
|
||||
</div>
|
||||
</v-tab>
|
||||
</vue-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "PollerSettings",
|
||||
props: {
|
||||
'pollers': Object,
|
||||
'settings': Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
advanced: false
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tab-content {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.setting-container {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
75
resources/js/components/SettingMultiple.vue
Normal file
75
resources/js/components/SettingMultiple.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<!--
|
||||
- SettingMultiple.vue
|
||||
-
|
||||
- Setting for multiple select option. Value is expected to be a comma delimited string
|
||||
-
|
||||
- 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 Tony Murray
|
||||
- @author Tony Murray <murraytony@gmail.com>
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<multiselect
|
||||
@input="$emit('input', mutateInputEvent($event))"
|
||||
:value="formattedValue"
|
||||
:required="required"
|
||||
:disabled="disabled"
|
||||
:name="name"
|
||||
label="label"
|
||||
track-by="value"
|
||||
:options="formattedOptions"
|
||||
:allow-empty="false"
|
||||
:multiple="true"
|
||||
>
|
||||
</multiselect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseSetting from "./BaseSetting";
|
||||
|
||||
export default {
|
||||
name: "SettingMultiple",
|
||||
mixins: [BaseSetting],
|
||||
computed: {
|
||||
formattedValue() {
|
||||
if (this.value === undefined) {
|
||||
return []
|
||||
}
|
||||
|
||||
let values = this.value.toString().split(',')
|
||||
return this.formatOptions(_.pick(this.options, ...values))
|
||||
},
|
||||
formattedOptions() {
|
||||
return this.formatOptions(this.options)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatOptions(options) {
|
||||
return Object.entries(options).map(([k, v]) => ({label: v, value: k}))
|
||||
},
|
||||
mutateInputEvent(options) {
|
||||
return options.map(option => option.value).join(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
103
resources/lang/en/poller.php
Normal file
103
resources/lang/en/poller.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
return [
|
||||
'settings' => [
|
||||
'settings' => [
|
||||
'poller_groups' => [
|
||||
'description' => 'Assigned Groups',
|
||||
'help' => 'This node will only take action on devices in these poller groups.'
|
||||
],
|
||||
'poller_enabled' => [
|
||||
'description' => 'Poller Enabled',
|
||||
'help' => 'Enable poller workers on this node.'
|
||||
],
|
||||
'poller_workers' => [
|
||||
'description' => 'Poller Workers',
|
||||
'help' => 'Amount of poller workers to spawn on this node.'
|
||||
],
|
||||
'poller_frequency' => [
|
||||
'description' => 'Poller Frequency',
|
||||
'help' => 'How often to to poll devices on this node. Warning! Changing this is not recommended. See docs for more info.'
|
||||
],
|
||||
'poller_down_retry' => [
|
||||
'description' => 'Device Down Retry',
|
||||
'help' => 'If a device is down when polling is attempted on this node. This is the amount of time to wait before retrying.'
|
||||
],
|
||||
'discovery_enabled' => [
|
||||
'description' => 'Discovery Enabled',
|
||||
'help' => 'Enable discovery workers on this node.'
|
||||
],
|
||||
'discovery_workers' => [
|
||||
'description' => 'Discovery Workers',
|
||||
'help' => 'Amount of discovery workers to run on this node. Setting too high can cause overload.'
|
||||
],
|
||||
'discovery_frequency' => [
|
||||
'description' => 'Discovery Frequency',
|
||||
'help' => 'How often to run device discovery on this node. Default is 4 times a day.'
|
||||
],
|
||||
'services_enabled' => [
|
||||
'description' => 'Services Enabled',
|
||||
'help' => 'Enable services workers on this node.'
|
||||
],
|
||||
'services_workers' => [
|
||||
'description' => 'Services Workers',
|
||||
'help' => 'Amount of services workers on this node.'
|
||||
],
|
||||
'services_frequency' => [
|
||||
'description' => 'Services Frequency',
|
||||
'help' => 'How often to run services on this node. This should match poller frequency.'
|
||||
],
|
||||
'billing_enabled' => [
|
||||
'description' => 'Billing Enabled',
|
||||
'help' => 'Enable billing workers on this node.'
|
||||
],
|
||||
'billing_frequency' => [
|
||||
'description' => 'Billing Frequency',
|
||||
'help' => 'How often to collect billing data on this node.'
|
||||
],
|
||||
'billing_calculate_frequency' => [
|
||||
'description' => 'Billing Calculate Frequency',
|
||||
'help' => 'How often to calculate bill usage on this node.'
|
||||
],
|
||||
'alerting_enabled' => [
|
||||
'description' => 'Alerting Enabled',
|
||||
'help' => 'Enable the alerting worker on this node.'
|
||||
],
|
||||
'alerting_frequency' => [
|
||||
'description' => 'Alerting Frequency',
|
||||
'help' => 'How often alert rules are checked on this node. Note that data is only updated based on poller frequency.'
|
||||
],
|
||||
'ping_enabled' => [
|
||||
'description' => 'Fast Ping Enabled',
|
||||
'help' => 'Fast Ping just pings devices to check if they are up or down'
|
||||
],
|
||||
'ping_frequency' => [
|
||||
'description' => 'Ping Frequency',
|
||||
'help' => 'How often to check ping on this node. Warning! If you change this you must make additional changes. Check the Fast Ping docs.'
|
||||
],
|
||||
'update_enabled' => [
|
||||
'description' => 'Daily Maintenance Enabled',
|
||||
'help' => 'Run daily.sh maintenance script and restart the dispatcher service afterwards.'
|
||||
],
|
||||
'update_frequency' => [
|
||||
'description' => 'Maintenance Frequency',
|
||||
'help' => 'How often to run daily maintenance on this node. Default is 1 Day. It is highly suggested not to change this.'
|
||||
],
|
||||
'loglevel' => [
|
||||
'description' => 'Log Level',
|
||||
'help' => 'Log level of the dispatch service.'
|
||||
],
|
||||
'watchdog_enabled' => [
|
||||
'description' => 'Watchdog Enabled',
|
||||
'help' => 'Watchdog monitors the log file and restarts the service it it has not been updated'
|
||||
],
|
||||
'watchdog_log' => [
|
||||
'description' => 'Log File to Watch',
|
||||
'help' => 'Default is the LibreNMS log file.'
|
||||
],
|
||||
],
|
||||
'units' => [
|
||||
'seconds' => 'Seconds',
|
||||
'workers' => 'Workers',
|
||||
],
|
||||
],
|
||||
];
|
@ -9,3 +9,9 @@
|
||||
|
||||
// Vue Select
|
||||
@import "~vue-select/src/scss/vue-select.scss";
|
||||
|
||||
// Vue Multiselect
|
||||
@import "~vue-multiselect/dist/vue-multiselect.min.css";
|
||||
|
||||
// Vue Tabs
|
||||
@import '~vue-nav-tabs/themes/vue-tabs.css';
|
||||
|
@ -540,11 +540,12 @@
|
||||
aria-hidden="true"></i> @lang('Auth History')</a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li class="dropdown-submenu">
|
||||
<a href="{{ url('poller') }}"><i class="fa fa-th-large fa-fw fa-lg" aria-hidden="true"></i> @lang('Poller')</a>
|
||||
<a href="{{ route('poller.index') }}"><i class="fa fa-th-large fa-fw fa-lg" aria-hidden="true"></i> @lang('Poller')</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{ route('poller') }}"><i class="fa fa-th-large fa-fw fa-lg" aria-hidden="true"></i> @lang('Poller')</a></li>
|
||||
<li><a href="{{ route('poller.index') }}"><i class="fa fa-th-large fa-fw fa-lg" aria-hidden="true"></i> @lang('Poller')</a></li>
|
||||
@config('distributed_poller')
|
||||
<li><a href="{{ route('poller.groups') }}"><i class="fa fa-th fa-fw fa-lg" aria-hidden="true"></i> @lang('Groups')</a></li>
|
||||
<li><a href="{{ route('poller.settings') }}"><i class="fa fa-gears fa-fw fa-lg" aria-hidden="true"></i> @lang('Settings')</a></li>
|
||||
@endconfig
|
||||
<li><a href="{{ route('poller.performance') }}"><i class="fa fa-line-chart fa-fw fa-lg" aria-hidden="true"></i> @lang('Performance')</a></li>
|
||||
<li><a href="{{ route('poller.log') }}"><i class="fa fa-file-text fa-fw fa-lg" aria-hidden="true"></i> @lang('Log')</a></li>
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
@parent
|
||||
|
||||
<br />
|
||||
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#poller-groups">@lang('Create new poller group')</button>
|
||||
<br /><br />
|
||||
<div class="table-responsive">
|
||||
|
@ -6,12 +6,17 @@
|
||||
<div class="col-md-12">
|
||||
<ul class="nav nav-tabs">
|
||||
<li role="presentation" @if( $current_tab == 'poller' ) class="active" @endif>
|
||||
<a href="{{ route('poller') }}"><i class="fa fa-th-large fa-lg icon-theme" aria-hidden="true"></i> @lang('Poller')</a>
|
||||
<a href="{{ route('poller.index') }}"><i class="fa fa-th-large fa-lg icon-theme" aria-hidden="true"></i> @lang('Poller')</a>
|
||||
</li>
|
||||
@config('distributed_poller')
|
||||
<li role="presentation" @if( $current_tab == 'groups' ) class="active" @endif>
|
||||
<a href="{{ route('poller.groups') }}"><i class="fa fa-th fa-lg icon-theme" aria-hidden="true"></i> @lang('Groups')</a>
|
||||
</li>
|
||||
@if(\App\Models\PollerCluster::exists())
|
||||
<li role="presentation" @if( $current_tab == 'settings' ) class="active" @endif>
|
||||
<a href="{{ route('poller.settings') }}"><i class="fa fa-gears fa-lg icon-theme" aria-hidden="true"></i> @lang('Settings')</a>
|
||||
</li>
|
||||
@endif
|
||||
@endconfig
|
||||
<li role="presentation" @if( $current_tab == 'performance' ) class="active" @endif>
|
||||
<a href="{{ route('poller.performance') }}"><i class="fa fa-line-chart fa-lg icon-theme" aria-hidden="true"></i> @lang('Performance')</a>
|
||||
@ -20,6 +25,7 @@
|
||||
<a href="{{ route('poller.log') }}"><i class="fa fa-file-text fa-lg icon-theme" aria-hidden="true"></i> @lang('Log')</a>
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
@endsection
|
||||
|
||||
@section('content_footer')
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
@parent
|
||||
|
||||
<br />
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Total Poller Time</h3>
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
@parent
|
||||
|
||||
<br />
|
||||
@if( $pollers->isNotEmpty() )
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
|
29
resources/views/poller/settings.blade.php
Normal file
29
resources/views/poller/settings.blade.php
Normal file
@ -0,0 +1,29 @@
|
||||
@extends('poller.index')
|
||||
|
||||
@section('title', __('Poller Settings'))
|
||||
|
||||
@section('content')
|
||||
@parent
|
||||
<div id="app">
|
||||
<poller-settings
|
||||
:pollers='@json($poller_cluster, JSON_FORCE_OBJECT)'
|
||||
:settings='@json($settings, JSON_FORCE_OBJECT)'
|
||||
></poller-settings>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('styles')
|
||||
<link href="{{ asset(mix('/css/app.css')) }}" rel="stylesheet">
|
||||
@endpush
|
||||
|
||||
@section('javascript')
|
||||
<script src="{{ asset(mix('/js/lang/en.js')) }}"></script>
|
||||
<script src="{{ asset(mix('/js/lang/' . app()->getLocale() . '.js')) }}"></script>
|
||||
<script src="{{ asset(mix('/js/manifest.js')) }}"></script>
|
||||
<script src="{{ asset(mix('/js/vendor.js')) }}"></script>
|
||||
@routes
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="{{ asset(mix('/js/app.js')) }}"></script>
|
||||
@endpush
|
@ -19,10 +19,14 @@ Route::group(['middleware' => ['auth.web'], 'guard' => 'auth'], function () {
|
||||
|
||||
// pages
|
||||
Route::resource('device-groups', 'DeviceGroupController');
|
||||
Route::get('poller', 'PollerController@pollerTab')->name('poller');
|
||||
Route::get('poller/log', 'PollerController@logTab')->name('poller.log');
|
||||
Route::get('poller/groups', 'PollerController@groupsTab')->name('poller.groups');
|
||||
Route::get('poller/performance', 'PollerController@performanceTab')->name('poller.performance');
|
||||
Route::group(['prefix' => 'poller'], function () {
|
||||
Route::get('', 'PollerController@pollerTab')->name('poller.index');
|
||||
Route::get('log', 'PollerController@logTab')->name('poller.log');
|
||||
Route::get('groups', 'PollerController@groupsTab')->name('poller.groups');
|
||||
Route::get('settings', 'PollerController@settingsTab')->name('poller.settings');
|
||||
Route::get('performance', 'PollerController@performanceTab')->name('poller.performance');
|
||||
Route::resource('{id}/settings', 'PollerSettingsController', ['as' => 'poller'])->only(['update', 'destroy']);
|
||||
});
|
||||
Route::get('locations', 'LocationController@index');
|
||||
Route::resource('preferences', 'UserPreferencesController', ['only' => ['index', 'store']]);
|
||||
Route::resource('users', 'UserController');
|
||||
|
Loading…
Reference in New Issue
Block a user