From 4e349efd11ad4e6949ae56c9cad3a83e8002978b Mon Sep 17 00:00:00 2001 From: SourceDoctor Date: Fri, 13 Mar 2020 20:58:37 +0100 Subject: [PATCH] Rewrite Poller Management to Blade/Eloquent (#11277) * Rewrite Poller Management to Blade/Eloquent * remove further no more needed file * Code Climate * Code Climate * hardcode tabs * change URL style * change prefix from poller-groups to poller * . * parameter fix * Refactor to use more direct routing. remove switch statement. Co-authored-by: Tony Murray --- LibreNMS/Util/Html.php | 8 +- LibreNMS/Validations/Poller.php | 160 ---------------- app/Checks.php | 2 +- app/Http/Controllers/PollerController.php | 129 +++++++++++++ app/Models/Poller.php | 35 ++++ app/Models/PollerCluster.php | 41 ++++ app/Models/PollerClusterStats.php | 35 ++++ app/Models/PollerGroups.php | 40 ++++ doc/Support/1-Minute-Polling.md | 2 +- includes/html/pages/pollers.inc.php | 55 ------ includes/html/pages/pollers/groups.inc.php | 72 ------- includes/html/pages/pollers/log.inc.php | 68 ------- .../html/pages/pollers/performance.inc.php | 37 ---- includes/html/pages/pollers/pollers.inc.php | 175 ------------------ resources/views/layouts/menu.blade.php | 10 +- .../views/poller/groups.blade.php | 91 +++++---- resources/views/poller/index.blade.php | 26 +++ resources/views/poller/log.blade.php | 47 +++++ resources/views/poller/performance.blade.php | 29 +++ resources/views/poller/poller.blade.php | 159 ++++++++++++++++ routes/web.php | 6 +- 21 files changed, 617 insertions(+), 610 deletions(-) delete mode 100644 LibreNMS/Validations/Poller.php create mode 100644 app/Http/Controllers/PollerController.php create mode 100644 app/Models/Poller.php create mode 100644 app/Models/PollerCluster.php create mode 100644 app/Models/PollerClusterStats.php create mode 100644 app/Models/PollerGroups.php delete mode 100644 includes/html/pages/pollers.inc.php delete mode 100644 includes/html/pages/pollers/groups.inc.php delete mode 100644 includes/html/pages/pollers/log.inc.php delete mode 100644 includes/html/pages/pollers/performance.inc.php delete mode 100644 includes/html/pages/pollers/pollers.inc.php rename includes/html/modal/poller_groups.inc.php => resources/views/poller/groups.blade.php (65%) create mode 100644 resources/views/poller/index.blade.php create mode 100644 resources/views/poller/log.blade.php create mode 100644 resources/views/poller/performance.blade.php create mode 100644 resources/views/poller/poller.blade.php diff --git a/LibreNMS/Util/Html.php b/LibreNMS/Util/Html.php index 893c489eee..8b4ea83e7b 100644 --- a/LibreNMS/Util/Html.php +++ b/LibreNMS/Util/Html.php @@ -41,21 +41,21 @@ class Html public static function graphRow($graph_array, $print = false) { if (session('widescreen')) { - if (!$graph_array['height']) { + if (!array_key_exists('height', $graph_array)) { $graph_array['height'] = '110'; } - if (!$graph_array['width']) { + if (!array_key_exists('width', $graph_array)) { $graph_array['width'] = '215'; } $periods = Config::get('graphs.mini.widescreen'); } else { - if (!$graph_array['height']) { + if (!array_key_exists('height', $graph_array)) { $graph_array['height'] = '100'; } - if (!$graph_array['width']) { + if (!array_key_exists('width', $graph_array)) { $graph_array['width'] = '215'; } diff --git a/LibreNMS/Validations/Poller.php b/LibreNMS/Validations/Poller.php deleted file mode 100644 index d4f3d0a2ec..0000000000 --- a/LibreNMS/Validations/Poller.php +++ /dev/null @@ -1,160 +0,0 @@ -. - * - * @package LibreNMS - * @link http://librenms.org - * @copyright 2017 Tony Murray - * @author Tony Murray - */ - -namespace LibreNMS\Validations; - -use LibreNMS\Config; -use LibreNMS\ValidationResult; -use LibreNMS\Validator; - -class Poller extends BaseValidation -{ - /** - * Validate this module. - * To return ValidationResults, call ok, warn, fail, or result methods on the $validator - * - * @param Validator $validator - */ - public function validate(Validator $validator) - { - if (!dbIsConnected()) { - $validator->warn("Could not check poller/discovery, db is not connected."); - return; - } - - if (dbFetchCell('SELECT COUNT(*) FROM `devices`') == 0) { - $result = ValidationResult::warn("You have not added any devices yet."); - - if (isCli()) { - $result->setFix("You can add a device in the webui or with ./addhost.php"); - } else { - $base_url = $validator->getBaseURL(); - $result->setFix("You can add a device by visiting $base_url/addhost"); - } - - $validator->result($result); - return; // can't check poller/discovery if there are no devices. - } - - $this->checkDuplicatePollerEntries($validator); - $this->checkLastPolled($validator); - $this->checkDeviceLastPolled($validator); - $this->checkDevicePollDuration($validator); - $this->checkLastDiscovered($validator); - } - - private function checkDuplicatePollerEntries(Validator $validator) - { - $sql = "SELECT TRIM(TRAILING '\n' FROM `poller_name`) as `name`, COUNT(*) as `count` FROM `pollers` GROUP BY `name`;"; - foreach (dbFetchRows($sql) as $poller) { - if ($poller['count'] > 1) { - $validator->warn( - 'Duplicate poller entries', - "Remove duplicates manually or with: DELETE FROM `pollers` WHERE `poller_name` LIKE '%\\n'" - ); - } - } - } - - private function checkLastPolled(Validator $validator) - { - $period = (int)Config::get('rrd.step', 300); - // pollers table is only updated by poller-wrapper.py - if (dbFetchCell('SELECT COUNT(*) FROM `pollers`')) { - $dedupe_sql = "SELECT TRIM(TRAILING '\\n' FROM `poller_name`) AS `name`, MAX(`last_polled`) AS `polled` FROM `pollers` GROUP BY `name`"; - $sql = "SELECT `name` FROM ($dedupe_sql) AS pt WHERE `polled` <= DATE_ADD(NOW(), INTERVAL - $period SECOND)"; - - $pollers = dbFetchColumn($sql); - if (count($pollers) > 0) { - foreach ($pollers as $poller) { - $validator->fail("The poller ($poller) has not completed within the last $period seconds, check the cron job."); - } - } - } elseif (dbFetchCell('SELECT COUNT(*) FROM `poller_cluster`')) { - $sql = "SELECT `node_id` FROM `poller_cluster` WHERE `last_report` <= DATE_ADD(NOW(), INTERVAL - $period SECOND)"; - - $pollers = dbFetchColumn($sql); - if (count($pollers) > 0) { - foreach ($pollers as $poller) { - $validator->fail("The poller cluster member ($poller) has not checked in within the last $period seconds, check that it is running and healthy."); - } - } - } else { - $validator->fail('The poller has never run or you are not using poller-wrapper.py, check the cron job.'); - } - } - - private function checkDeviceLastPolled(Validator $validator) - { - $overdue = (int)(Config::get('rrd.step', 300) * 1.2); - if (count($devices = dbFetchColumn("SELECT `hostname` FROM `devices` WHERE (`last_polled` < DATE_ADD(NOW(), INTERVAL - $overdue SECOND) OR `last_polled` IS NULL) AND `ignore` = 0 AND `disabled` = 0 AND `status` = 1")) > 0) { - $result = ValidationResult::warn("Some devices have not been polled in the last 5 minutes. You may have performance issues.") - ->setList('Devices', $devices); - - if (isCli()) { - $result->setFix('Check your poll log and see: http://docs.librenms.org/Support/Performance/'); - } else { - $base_url = $validator->getBaseURL(); - $result->setFix("Check $base_url/pollers/tab=log and see: http://docs.librenms.org/Support/Performance/"); - } - - $validator->result($result); - } - } - - - private function checkDevicePollDuration(Validator $validator) - { - $period = (int)Config::get('rrd.step', 300); - if (count($devices = dbFetchColumn("SELECT `hostname` FROM `devices` WHERE last_polled_timetaken > $period AND `ignore` = 0 AND `disabled` = 0 AND `status` = 1")) > 0) { - $result = ValidationResult::fail("Some devices have not completed their polling run in 5 minutes, this will create gaps in data.") - ->setList('Devices', $devices); - - if (isCli()) { - $result->setFix('Check your poll log and see: http://docs.librenms.org/Support/Performance/'); - } else { - $base_url = $validator->getBaseURL(); - $result->setFix("Check $base_url/pollers/tab=log/ and see: http://docs.librenms.org/Support/Performance/"); - } - - $validator->result($result); - } - } - - private function checkLastDiscovered(Validator $validator) - { - $incomplete_sql = "SELECT 1 FROM `devices` WHERE `last_discovered` <= DATE_ADD(NOW(), INTERVAL - 24 HOUR) - AND `ignore` = 0 AND `disabled` = 0 AND `status` = 1 AND `snmp_disable` = 0"; - - if (!dbFetchCell('SELECT 1 FROM `devices` WHERE `last_discovered` IS NOT NULL')) { - $validator->fail('Discovery has never run. Check the cron job'); - } elseif (dbFetchCell($incomplete_sql)) { - $validator->fail( - "Discovery has not completed in the last 24 hours.", - "Check the cron job to make sure it is running and using discovery-wrapper.py" - ); - } - } -} diff --git a/app/Checks.php b/app/Checks.php index 21c5837d98..63014c6ec6 100644 --- a/app/Checks.php +++ b/app/Checks.php @@ -98,7 +98,7 @@ class Checks $warn_sec = Config::get('rrd.step', 300) * 3; if (Device::isUp()->where('last_polled', '<=', Carbon::now()->subSeconds($warn_sec))->exists()) { $warn_min = $warn_sec / 60; - Toastr::warning('It appears as though you have some devices that haven\'t completed polling within the last ' . $warn_min . ' minutes, you may want to check that out :)', 'Devices unpolled'); + Toastr::warning('It appears as though you have some devices that haven\'t completed polling within the last ' . $warn_min . ' minutes, you may want to check that out :)', 'Devices unpolled'); } // Directory access checks diff --git a/app/Http/Controllers/PollerController.php b/app/Http/Controllers/PollerController.php new file mode 100644 index 0000000000..ec825b986f --- /dev/null +++ b/app/Http/Controllers/PollerController.php @@ -0,0 +1,129 @@ + 0, + 'group_name' => 'General', + 'descr' => '' + ]; + public $defaultPollerMarker = '(default Poller)'; + + public function __construct() + { + $this->authorizeResource(PollerGroups::class, 'poller_groups'); // FIXME is this correct? not a resource anymore + $this->rrdstep = \LibreNMS\Config::get('rrd.step'); + $this->defaultPollerId = \LibreNMS\Config::get('distributed_poller_group'); + } + + public function logTab(Request $request) + { + return view('poller.log', [ + 'current_tab' => 'log', + 'filter' => $request->input('filter', 'active') + ]); + } + + // output for poller groups + public function groupsTab() + { + $group_list = PollerGroups::get(); + + # default poller_group + $defaultGroup = $this->defaultGroup; + $defaultGroup['devices'] = Device::where('poller_group', $defaultGroup['id'])->get(); + $defaultGroup['is_default_poller'] = ($defaultGroup['id'] == $this->defaultPollerId) ? true : false; + + # poller_groups + $poller_group_list = []; + foreach ($group_list as $group) { + $group['is_default_poller'] = ($group['id'] == $this->defaultPollerId) ? true : false; + + $poller_group_list[] = $group; + } + + return view('poller.groups', [ + 'current_tab' => 'groups', + 'default_poller_marker' => $this->defaultPollerMarker, + 'poller_groups' => $poller_group_list, + 'default_poller_group' => $defaultGroup, + ]); + } + + // data output for poller view + public function pollerTab() + { + return view('poller.poller', [ + 'current_tab' => 'poller', + 'pollers' => $this->poller(), + 'poller_cluster' => $this->pollerCluster(), + ]); + } + + public function performanceTab() + { + return view('poller.performance', ['current_tab' => 'performance']); + } + + protected function pollerStatus($poller) + { + $old = $poller['now'] - strtotime($poller['last_polled']); + + if ($old >= $this->rrdstep) { + $poller['row_class'] = 'danger'; + } elseif ($old >= ($this->rrdstep * 0.95)) { + $poller['row_class'] = 'warning'; + } else { + $poller['row_class'] = 'success'; + } + + $poller['long_not_polled'] = (\Auth::user()->hasGlobalAdmin() && ($old > ($this->rrdstep * 2))) ? true : false; + + return $poller; + } + + private function poller() + { + $rows = Poller::orderBy('poller_name')->get(); + + $time = time(); + + $groups = []; + + foreach ($rows as $poller) { + $poller['now'] = $time; + + $poller = $this->pollerStatus($poller); + + $groups[] = $poller; + } + + return $groups; + } + + private function pollerCluster() + { + $rows = PollerCluster::orderBy('poller_name')->get(); + + $cluster = []; + + foreach ($rows as $poller) { + $poller = $this->pollerStatus($poller); + + $cluster[] = $poller; + } + + return $cluster; + } +} diff --git a/app/Models/Poller.php b/app/Models/Poller.php new file mode 100644 index 0000000000..dcc2f32bf7 --- /dev/null +++ b/app/Models/Poller.php @@ -0,0 +1,35 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2020 Thomas Berberich + * @author Thomas Berberich + */ + +namespace App\Models; + +use Illuminate\Database\Eloquent\Model; + +class Poller extends Model +{ + public $timestamps = false; + protected $primaryKey = 'id'; + protected $fillable = ['poller_name']; +} diff --git a/app/Models/PollerCluster.php b/app/Models/PollerCluster.php new file mode 100644 index 0000000000..34e9fe24c3 --- /dev/null +++ b/app/Models/PollerCluster.php @@ -0,0 +1,41 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2020 Thomas Berberich + * @author Thomas Berberich + */ + +namespace App\Models; + +use Illuminate\Database\Eloquent\Model; + +class PollerCluster extends Model +{ + public $timestamps = false; + protected $table = 'poller_cluster'; + protected $primaryKey = 'id'; + protected $fillable = ['poller_name']; + + public function stats() + { + return $this->hasMany('App\Models\PollerClusterStats', 'parent_poller', 'id'); + } +} diff --git a/app/Models/PollerClusterStats.php b/app/Models/PollerClusterStats.php new file mode 100644 index 0000000000..76601e9631 --- /dev/null +++ b/app/Models/PollerClusterStats.php @@ -0,0 +1,35 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2020 Thomas Berberich + * @author Thomas Berberich + */ + +namespace App\Models; + +use Illuminate\Database\Eloquent\Model; + +class PollerClusterStats extends Model +{ + public $timestamps = false; + protected $primaryKey = 'id'; +# protected $fillable = ['poller_name']; +} diff --git a/app/Models/PollerGroups.php b/app/Models/PollerGroups.php new file mode 100644 index 0000000000..e6e42a0ddd --- /dev/null +++ b/app/Models/PollerGroups.php @@ -0,0 +1,40 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2020 Thomas Berberich + * @author Thomas Berberich + */ + +namespace App\Models; + +use Illuminate\Database\Eloquent\Model; + +class PollerGroups extends Model +{ + public $timestamps = false; + protected $primaryKey = 'id'; + protected $fillable = ['group_name', 'descr']; + + public function devices() + { + return $this->hasMany('App\Models\Device', 'poller_group', 'id'); + } +} diff --git a/doc/Support/1-Minute-Polling.md b/doc/Support/1-Minute-Polling.md index 75cef47149..4d7ddf7cd1 100644 --- a/doc/Support/1-Minute-Polling.md +++ b/doc/Support/1-Minute-Polling.md @@ -10,7 +10,7 @@ We now have support for polling data at intervals to fit your needs. - You must also change your cron entry for `poller-wrapper.py` for this to work (if you change from the default 300 seconds). - Your polling _MUST_ complete in the time you configure for the - heartbeat step value. See `/pollers/tab=pollers/` in your WebUI for + heartbeat step value. See `/poller` in your WebUI for your current value. - This will only affect RRD files created from the moment you change your settings. diff --git a/includes/html/pages/pollers.inc.php b/includes/html/pages/pollers.inc.php deleted file mode 100644 index 43dab01c99..0000000000 --- a/includes/html/pages/pollers.inc.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * 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. - */ - -$no_refresh = true; - - -echo ''; - -include_once "includes/html/pages/pollers/$current_tab.inc.php"; diff --git a/includes/html/pages/pollers/groups.inc.php b/includes/html/pages/pollers/groups.inc.php deleted file mode 100644 index a41bca3247..0000000000 --- a/includes/html/pages/pollers/groups.inc.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * 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. - */ - -use \LibreNMS\Config; - -$pagetitle[] = 'Poller Groups'; - -require_once 'includes/html/modal/poller_groups.inc.php'; - -?> -
- -

-
- - - - - - - - - 0, - 'group_name' => 'General', - 'descr' => '']; - -$group_list = dbFetchRows('SELECT * FROM `poller_groups`'); - -$default_poller = Config::get('distributed_poller_group'); - -array_unshift($group_list, $default_group); - -foreach ($group_list as $group) { - $group_device_count = dbFetchCell('SELECT COUNT(*) FROM devices WHERE `poller_group`=?', $group['id']); - - $group_name = $group['group_name']; - if ($group['id'] == $default_poller) { - $group_name .= ' (default Poller)'; - } - - echo ' - - - - - '; - echo ' - -'; -} - -?> - -
IDGroup NameDevicesDescriptionAction
'.$group['id'].''.$group_name.''.$group_device_count.''.$group['descr'].''; - if ($group['id']) { - echo ' '; - } - echo '
-
diff --git a/includes/html/pages/pollers/log.inc.php b/includes/html/pages/pollers/log.inc.php deleted file mode 100644 index 43080ceb47..0000000000 --- a/includes/html/pages/pollers/log.inc.php +++ /dev/null @@ -1,68 +0,0 @@ -. - * - * @package LibreNMS - * @link http://librenms.org - * @copyright 2018 Tony Murray - * @author Tony Murray - */ - -$no_refresh = true; -$pagetitle[] = 'Poll Log'; -if (isset($vars['filter'])) { - $type = $vars['filter']; -} -?> - - - - - - - - - -
HostnameLast PolledPoller GroupPolling Duration (Seconds)
- - diff --git a/includes/html/pages/pollers/performance.inc.php b/includes/html/pages/pollers/performance.inc.php deleted file mode 100644 index c24481140d..0000000000 --- a/includes/html/pages/pollers/performance.inc.php +++ /dev/null @@ -1,37 +0,0 @@ - -
-
-
-

Total Poller Time

-
-
- 'global_poller_perf', - 'legend' => 'yes', - 'height' => 100, - ]; - require 'includes/html/print-graphrow.inc.php'; - ?> -
-
-
-
-

Total Poller Time Per Module

-
-
- 'global_poller_modules_perf', - 'legend' => 'yes', - 'height' => 100, - ]; - require 'includes/html/print-graphrow.inc.php'; - ?> -
-
diff --git a/includes/html/pages/pollers/pollers.inc.php b/includes/html/pages/pollers/pollers.inc.php deleted file mode 100644 index 69984f3dbe..0000000000 --- a/includes/html/pages/pollers/pollers.inc.php +++ /dev/null @@ -1,175 +0,0 @@ - - * - * 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. - */ - -use LibreNMS\Config; - -$pagetitle[] = 'Pollers'; - -require_once 'includes/html/modal/delete_poller.inc.php'; - -?> -
- - -
-

Standard Pollers

-
-
-
- - - - - - - - '; - - foreach ($rows as $poller) { - $old = ($poller['now'] - $poller['then']); - $step = Config::get('rrd.step', 300); - - if ($old >= $step) { - $row_class = 'danger'; - } elseif ($old >= ($step * 0.95)) { - $row_class = 'warning'; - } else { - $row_class = 'success'; - } - - $actions = ""; - if (\Auth::user()->hasGlobalAdmin() && $old > ($step * 2)) { - // missed 2 polls show delete button - $actions .= ""; - } - - echo ' - - - - - - - - '; - } - - echo ' -
Poller NameDevices PolledTotal Poll TimeLast RanActions
'.$poller['poller_name'].''.$poller['devices'].''.$poller['time_taken'].' Seconds'.$poller['last_polled'].''.$actions.'
-
-
-'; -} - -$query = 'SELECT *,UNIX_TIMESTAMP(NOW()) AS `now`, UNIX_TIMESTAMP(`last_report`) AS `then` FROM `poller_cluster` ORDER BY poller_name'; -$rows = dbFetchRows($query); - -if (count($rows) !== 0) { - echo ' -
-
-

Poller Cluster Health

-
-
-
- - - - - - - - - - - - - - - '; - - foreach ($rows as $poller) { - $old = ($poller['now'] - $poller['then']); - $step = Config::get('rrd.step', 300); - - if ($old >= $step) { - $row_class = 'danger'; - } elseif ($old >= ($step * 0.95)) { - $row_class = 'warning'; - } else { - $row_class = 'success'; - } - - $actions = ""; - if (\Auth::user()->hasGlobalAdmin() && $old > ($step * 2)) { - // missed 2 polls show delete button - $actions .= ""; - } - - $stat_query = 'SELECT * FROM `poller_cluster_stats` WHERE `parent_poller`=' . $poller['id'] . ';'; - $stat_row = dbFetchRows($stat_query); - $stat_count = count($stat_row); - - $first_row = true; - - foreach ($stat_row as $stats) { - // Emit the row container - echo ''; - - if ($first_row) { - // On the first iteration, print some rowspanned columns - echo ' - - - - - - '; - } - - // Emit the job stats - echo ' - - - - - '; - - if ($first_row) { - // On the first iteration, print some rowspanned columns - echo ''; - } - - // End the row - echo ''; - $first_row = false; - } - } - echo ' -
NameNode IDVersionGroups ServedLast CheckinCluster MasterJobWorkersDevices Actioned
Last Interval
Devices PendingWorker Seconds
Consumed/Maximum
Actions
'.$poller['poller_name'].''.$poller['node_id'].''.$poller['poller_version'].''.$poller['poller_groups'].''.$poller['last_report'].''. ($poller['master'] ? "Yes" : "No") .''.$stats['poller_type'].''.$stats['workers'].''.$stats['devices'].''.$stats['depth'].''.$stats['worker_seconds'].' / '.$stats['frequency']*$stats['workers'].''.$actions.'
- - Worker seconds indicates the maximum polling throughput a node can achieve in perfect conditions. If the consumed is close to the maximum, consider adding more threads, or better tuning your groups.
- If there are devices pending but consumed worker seconds is low, your hardware is not sufficient for the number of devices and the poller cannot reach maximum throughput. -
-
-
-
'; -} -?> diff --git a/resources/views/layouts/menu.blade.php b/resources/views/layouts/menu.blade.php index de888bd5d0..bf88f4db5b 100644 --- a/resources/views/layouts/menu.blade.php +++ b/resources/views/layouts/menu.blade.php @@ -526,14 +526,14 @@ aria-hidden="true"> @lang('Auth History') diff --git a/includes/html/modal/poller_groups.inc.php b/resources/views/poller/groups.blade.php similarity index 65% rename from includes/html/modal/poller_groups.inc.php rename to resources/views/poller/groups.blade.php index 03adad3fd0..43baf37953 100644 --- a/includes/html/modal/poller_groups.inc.php +++ b/resources/views/poller/groups.blade.php @@ -1,36 +1,63 @@ - - * - * 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. - */ +@extends('poller.index') -if (!Auth::user()->hasGlobalAdmin()) { - echo ('ERROR: You need to be admin'); -} else { -?> +@section('title', __('Poller Groups')) +@section('content') + +@parent + +
+ +

+
+ + + + + + + + + + + + + + + @foreach ($poller_groups as $group) + + + + + + + @endforeach + +
@lang('ID')@lang('Group Name')@lang('Devices')@lang('Description')@lang('Action')
{{ $default_poller_group['id'] }}{{ $default_poller_group['group_name'] }}@if($default_poller_group['is_default_poller']) {{ $default_poller_marker }}@endif{{ $default_poller_group['devices']->count() }}{{ $default_poller_group['descr'] }} +
{{ $group['id'] }}{{ $group['group_name'] }}@if($group['is_default_poller']) {{ $default_poller_marker }}@endif{{ $group['devices']->count() }}{{ $group['descr'] }} + @if($group['id']) + + + @endif +
+
+ +@if(auth()->user()->isAdmin())