Define Port Groups (#12402)
* Define Port Groups * . * . * . * API Calls * . * . * . * minor changes * . * update forms * remove link * . * change column settings * change migration * change update position * db migration fix * . * . * . * add missing doc reference * update test data * update test data * update test data * . * . * . * . * . * . * . * . * port group association in seperate table * . * . * show all found groups on port * select multiple Portgroups per Port * change on migration file * change query to eloquent * Code changes * move port group menu to ports main menu * port group update to eloquent * . * . * update to new setting way * add missing merge parameter * Use select2 and port some things to Laravel some fixes, hopefully no new added bugs * schema * don't use on update restrict unfortunately * remove unused import and revert changes Co-authored-by: Tony Murray <murraytony@gmail.com>
This commit is contained in:
parent
ecb87d9671
commit
4b9e480118
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
/*
|
||||
* PortController.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 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Port;
|
||||
|
||||
class PortController extends Controller
|
||||
{
|
||||
public function update(\Illuminate\Http\Request $request, Port $port)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'groups.*' => 'int',
|
||||
]);
|
||||
|
||||
$updated = false;
|
||||
$message = '';
|
||||
|
||||
if ($request->has('groups')) {
|
||||
$changes = $port->groups()->sync($request->get('groups'));
|
||||
$groups_updated = array_sum(array_map(function ($group_ids) {
|
||||
return count($group_ids);
|
||||
}, $changes));
|
||||
|
||||
if ($groups_updated > 0) {
|
||||
$message .= trans('port.groups.updated', ['port' => $port->getLabel()]);
|
||||
$updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $updated
|
||||
? response(['message' => $message])
|
||||
: response(['message' => trans('port.groups.none', ['port' => $port->getLabel()])], 400);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PortGroup;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Toastr;
|
||||
|
||||
class PortGroupController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('port-group.index', [
|
||||
'port_groups' => PortGroup::orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('port-group.create', [
|
||||
'port_group' => new PortGroup(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required|string|unique:port_groups',
|
||||
]);
|
||||
|
||||
$portGroup = PortGroup::make($request->only(['name', 'desc']));
|
||||
$portGroup->save();
|
||||
|
||||
Toastr::success(__('Port Group :name created', ['name' => $portGroup->name]));
|
||||
|
||||
return redirect()->route('port-groups.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\PortGroup $portGroup
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(PortGroup $portGroup)
|
||||
{
|
||||
return view('port-group.edit', [
|
||||
'port_group' => $portGroup,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\PortGroup $portGroup
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, PortGroup $portGroup)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:255',
|
||||
Rule::unique('port_groups', 'name')->where(function ($query) use ($portGroup) {
|
||||
$query->where('id', '!=', $portGroup->id);
|
||||
}),
|
||||
],
|
||||
'desc' => 'string|max:255',
|
||||
]);
|
||||
|
||||
$portGroup->fill($request->only(['name', 'desc']));
|
||||
|
||||
if ($portGroup->save()) {
|
||||
Toastr::success(__('Port Group :name updated', ['name' => $portGroup->name]));
|
||||
} else {
|
||||
Toastr::error(__('Failed to save'));
|
||||
|
||||
return redirect()->back()->withInput();
|
||||
}
|
||||
|
||||
return redirect()->route('port-groups.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\PortGroup $portGroup
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(PortGroup $portGroup)
|
||||
{
|
||||
$portGroup->delete();
|
||||
|
||||
$msg = __('Port Group :name deleted', ['name' => $portGroup->name]);
|
||||
|
||||
return response($msg, 200);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* PortGroupController.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/>.
|
||||
*
|
||||
* @link http://librenms.org
|
||||
* @copyright 2020 Thomas Berberich
|
||||
* @author Thomas Berberich <sourcehhdoctor@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Select;
|
||||
|
||||
use App\Models\PortGroup;
|
||||
|
||||
class PortGroupController extends SelectController
|
||||
{
|
||||
protected function searchFields($request)
|
||||
{
|
||||
return ['name'];
|
||||
}
|
||||
|
||||
protected function baseQuery($request)
|
||||
{
|
||||
return PortGroup::hasAccess($request->user())->select(['id', 'name']);
|
||||
}
|
||||
|
||||
public function formatItem($port_group)
|
||||
{
|
||||
return [
|
||||
'id' => $port_group->id,
|
||||
'text' => $port_group->name,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
/*
|
||||
* EditPortsController.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 2021 Tony Murray
|
||||
* @author Tony Murray <murraytony@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Table;
|
||||
|
||||
class EditPortsController extends TableController
|
||||
{
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'device_id' => 'required|int',
|
||||
'device_group' => 'nullable|int',
|
||||
'eventtype' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
|
||||
public function searchFields($request)
|
||||
{
|
||||
return ['ifName', 'ifAlias', 'ifDescr'];
|
||||
}
|
||||
|
||||
protected function sortFields($request)
|
||||
{
|
||||
return ['ifIndex', 'ifName', 'ifAdminStatus', 'ifOperStatus', 'ifSpeed', 'ifAlias'];
|
||||
}
|
||||
|
||||
protected function baseQuery($request)
|
||||
{
|
||||
return \App\Models\Port::where('device_id', $request->get('device_id'))
|
||||
->with('groups');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \App\Models\Port $port
|
||||
* @return array
|
||||
*/
|
||||
public function formatItem($port)
|
||||
{
|
||||
$is_port_bad = $port->ifAdminStatus != 'down' && $port->ifOperStatus != 'up';
|
||||
$do_we_care = ($port->ignore || $port->disabled) ? false : $is_port_bad;
|
||||
$out_of_sync = $do_we_care ? "class='red'" : '';
|
||||
$tune = $port->device->getAttrib('ifName_tune:' . $port->ifName) == 'true' ? 'checked' : '';
|
||||
|
||||
$port_group_options = '';
|
||||
foreach ($port->groups as $group) {
|
||||
/** @var \App\Models\PortGroup $group */
|
||||
$port_group_options .= '<option value="' . $group->id . '" selected>' . $group->name . '</option>';
|
||||
}
|
||||
|
||||
return [
|
||||
'ifIndex' => $port->ifIndex,
|
||||
'ifName' => $port->getLabel(),
|
||||
'ifAdminStatus' => $port->ifAdminStatus,
|
||||
'ifOperStatus' => '<span id="operstatus_' . $port->port_id . '" ' . $out_of_sync . '>' . $port->ifOperStatus . '</span>',
|
||||
'disabled' => '<input type="checkbox" class="disable-check" data-size="small" name="disabled_' . $port->port_id . '"' . ($port->disabled ? 'checked' : '') . '>
|
||||
<input type="hidden" name="olddis_' . $port->port_id . '" value="' . ($port->disabled ? 1 : 0) . '"">',
|
||||
'ignore' => '<input type="checkbox" class="ignore-check" data-size="small" name="ignore_' . $port->port_id . '"' . ($port->ignore ? 'checked' : '') . '>
|
||||
<input type="hidden" name="oldign_' . $port->port_id . '" value="' . ($port->ignore ? 1 : 0) . '"">',
|
||||
'port_tune' => '<input type="checkbox" name="override_config" data-attrib="ifName_tune:' . $port->ifName . '" data-device_id="' . $port->device_id . '" data-size="small" ' . $tune . '>',
|
||||
'ifAlias' => '<div class="form-group"><input class="form-control input-sm" name="if-alias" data-device_id="' . $port->device_id . '" data-port_id="' . $port->port_id . '" data-ifName="' . $port->ifName . '" value="' . $port->ifAlias . '"><span class="form-control-feedback"><i class="fa" aria-hidden="true"></i></span></div>',
|
||||
'ifSpeed' => '<div class="form-group has-feedback"><input type="text" pattern="[0-9]*" inputmode="numeric" class="form-control input-sm" name="if-speed" data-device_id="' . $port->device_id . '" data-port_id="' . $port->port_id . '" data-ifName="' . $port->ifName . '" value="' . $port->ifSpeed . '"><span class="form-control-feedback"><i class="fa" aria-hidden="true"></i></span></div>',
|
||||
'portGroup' => '<div class="form-group has-feedback"><select class="input-sm port_group_select" name="port_group_' . $port->port_id . '[]" data-port_id="' . $port->port_id . '" multiple>' . $port_group_options . '</select></div>',
|
||||
];
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ class TopInterfacesController extends WidgetController
|
|||
'time_interval' => 15,
|
||||
'interface_filter' => null,
|
||||
'device_group' => null,
|
||||
'port_group' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -60,6 +61,9 @@ class TopInterfacesController extends WidgetController
|
|||
}, function ($query) {
|
||||
$query->has('device');
|
||||
})
|
||||
->when($data['port_group'], function ($query) use ($data) {
|
||||
$query->inPortGroup($data['port_group']);
|
||||
})
|
||||
->orderByRaw('SUM(LEAST(ifInOctets_rate, 9223372036854775807) + LEAST(ifOutOctets_rate, 9223372036854775807)) DESC')
|
||||
->limit($data['interface_count']);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace App\Http\Controllers\Widgets;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DeviceGroup;
|
||||
use App\Models\PortGroup;
|
||||
use App\Models\UserWidget;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
@ -67,9 +68,22 @@ abstract class WidgetController extends Controller
|
|||
// This might be invoked in getSettingsView() in an extended class
|
||||
// So don't run it before since it's cached.
|
||||
$this->getSettings();
|
||||
}
|
||||
|
||||
if (! empty($this->settings['device_group'])) {
|
||||
$this->title .= ' (' . DeviceGroup::find($this->settings['device_group'])->name . ')';
|
||||
if (! $this->show_settings) {
|
||||
if (! empty($this->settings['device_group']) || ! empty($this->settings['port_group'])) {
|
||||
$this->title .= ' (';
|
||||
|
||||
$title_details = [];
|
||||
if (! empty($this->settings['device_group'])) {
|
||||
$title_details[] = DeviceGroup::find($this->settings['device_group'])->name;
|
||||
}
|
||||
if (! empty($this->settings['port_group'])) {
|
||||
$title_details[] = PortGroup::find($this->settings['port_group'])->name;
|
||||
}
|
||||
|
||||
$this->title .= implode(' ; ', $title_details);
|
||||
$this->title .= ')';
|
||||
}
|
||||
$view = $this->getView($request);
|
||||
}
|
||||
|
@ -101,6 +115,10 @@ abstract class WidgetController extends Controller
|
|||
if ($settingsView && isset($this->settings['device_group'])) {
|
||||
$this->settings['device_group'] = DeviceGroup::find($this->settings['device_group']);
|
||||
}
|
||||
|
||||
if ($settingsView && isset($this->settings['port_group'])) {
|
||||
$this->settings['port_group'] = PortGroup::find($this->settings['port_group']);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->settings;
|
||||
|
|
|
@ -255,6 +255,15 @@ class Port extends DeviceRelatedModel
|
|||
return $this->hasPortAccess($query, $user);
|
||||
}
|
||||
|
||||
public function scopeInPortGroup($query, $portGroup)
|
||||
{
|
||||
return $query->whereIn($query->qualifyColumn('port_id'), function ($query) use ($portGroup) {
|
||||
$query->select('port_id')
|
||||
->from('port_group_port')
|
||||
->where('port_group_id', $portGroup);
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Define Relationships ----
|
||||
|
||||
public function adsl(): HasMany
|
||||
|
@ -272,6 +281,11 @@ class Port extends DeviceRelatedModel
|
|||
return $this->hasMany(\App\Models\PortsFdb::class, 'port_id', 'port_id');
|
||||
}
|
||||
|
||||
public function groups(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(\App\Models\PortGroup::class, 'port_group_port', 'port_id', 'port_group_id');
|
||||
}
|
||||
|
||||
public function ipv4(): HasMany
|
||||
{
|
||||
return $this->hasMany(\App\Models\Ipv4Address::class, 'port_id');
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/**
|
||||
* PortGroup.php
|
||||
*
|
||||
* Groups of ports
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @link http://librenms.org
|
||||
* @copyright 2020 Thomas Berberich
|
||||
* @author Thomas Berberich <sourcehhdoctor@gmail.com>
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class PortGroup extends BaseModel
|
||||
{
|
||||
public $timestamps = false;
|
||||
protected $fillable = ['name', 'desc'];
|
||||
|
||||
public function scopeHasAccess($query, User $user)
|
||||
{
|
||||
if ($user->hasGlobalRead()) {
|
||||
return $query;
|
||||
}
|
||||
// maybe filtered in future
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function ports()
|
||||
{
|
||||
return $this->belongsToMany(\App\Models\Port::class, 'port_group_port', 'port_group_id', 'port_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreatePortGroupsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('port_groups', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->unique();
|
||||
$table->string('desc')->nullable();
|
||||
});
|
||||
Schema::create('port_group_port', function (Blueprint $table) {
|
||||
$table->unsignedInteger('port_group_id')->unsigned()->index();
|
||||
$table->unsignedInteger('port_id')->unsigned()->index();
|
||||
$table->primary(['port_group_id', 'port_id']);
|
||||
$table->foreign('port_group_id')->references('id')->on('port_groups')->onDelete('CASCADE');
|
||||
$table->foreign('port_id')->references('port_id')->on('ports')->onDelete('CASCADE');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('port_group_port');
|
||||
Schema::drop('port_groups');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
source: API/Port_Groups.md
|
||||
path: blob/master/doc/
|
||||
|
||||
### `get_portgroups`
|
||||
|
||||
List all port groups.
|
||||
|
||||
Route: `/api/v0/portgroups`
|
||||
|
||||
Input (JSON):
|
||||
|
||||
-
|
||||
|
||||
Examples:
|
||||
|
||||
```curl
|
||||
curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/portgroups
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"status": "ok",
|
||||
"message": "Found 1 port groups",
|
||||
"count": 1,
|
||||
"groups": [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Testing",
|
||||
"desc": "Testing"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### `add_portgroup`
|
||||
|
||||
Add a new port group. Upon success, the ID of the new port group is returned
|
||||
and the HTTP response code is `201`.
|
||||
|
||||
Route: `/api/v0/port_groups`
|
||||
|
||||
Input (JSON):
|
||||
|
||||
- `name`: *required* - The name of the port group
|
||||
- `desc`: *optional* - Description of the port group
|
||||
|
||||
Examples:
|
||||
|
||||
Dynamic Example:
|
||||
|
||||
```curl
|
||||
curl -H 'X-Auth-Token: YOURAPITOKENHERE' \
|
||||
-X POST \
|
||||
-d '{"name": "New Port Group", \
|
||||
"desc": "A very fancy port group"}' \
|
||||
https://librenms.org/api/v0/port_groups
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"id": 86,
|
||||
"message": "Port group New Port Group created"
|
||||
}
|
||||
```
|
|
@ -74,6 +74,7 @@ Output from the API currently is via two output types:
|
|||
- [Devices](Devices.md)
|
||||
- [DeviceGroups](DeviceGroups.md)
|
||||
- [Ports](Ports.md)
|
||||
- [Port_Groups](Port_Groups.md)
|
||||
- [PortGroups](PortGroups.md)
|
||||
- [Alerts](Alerts.md)
|
||||
- [Routing](Routing.md)
|
||||
|
|
|
@ -16,6 +16,7 @@ use App\Models\Availability;
|
|||
use App\Models\Device;
|
||||
use App\Models\DeviceGroup;
|
||||
use App\Models\DeviceOutage;
|
||||
use App\Models\PortGroup;
|
||||
use App\Models\PortsFdb;
|
||||
use App\Models\Sensor;
|
||||
use App\Models\ServiceTemplate;
|
||||
|
@ -1846,6 +1847,41 @@ function rename_device(Illuminate\Http\Request $request)
|
|||
}
|
||||
}
|
||||
|
||||
function add_port_group(Illuminate\Http\Request $request)
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
if (json_last_error() || ! is_array($data)) {
|
||||
return api_error(400, "We couldn't parse the provided json. " . json_last_error_msg());
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'name' => 'required|string|unique:port_groups',
|
||||
];
|
||||
|
||||
$v = Validator::make($data, $rules);
|
||||
if ($v->fails()) {
|
||||
return api_error(422, $v->messages());
|
||||
}
|
||||
|
||||
$portGroup = PortGroup::make(['name' => $data['name'], 'desc' => $data['desc']]);
|
||||
$portGroup->save();
|
||||
|
||||
return api_success($portGroup->id, 'id', 'Port group ' . $portGroup->name . ' created', 201);
|
||||
}
|
||||
|
||||
function get_port_groups(Illuminate\Http\Request $request)
|
||||
{
|
||||
$query = PortGroup::query();
|
||||
|
||||
$groups = $query->orderBy('name')->get();
|
||||
|
||||
if ($groups->isEmpty()) {
|
||||
return api_error(404, 'No port groups found');
|
||||
}
|
||||
|
||||
return api_success($groups->makeHidden('pivot')->toArray(), 'groups', 'Found ' . $groups->count() . ' port groups');
|
||||
}
|
||||
|
||||
function add_device_group(Illuminate\Http\Request $request)
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
|
|
@ -65,13 +65,13 @@ foreach ($_POST as $key => $val) {
|
|||
}//end foreach
|
||||
|
||||
if ($rows_updated > 0) {
|
||||
$message = $rows_updated . ' Device record updated.';
|
||||
$message = $rows_updated . ' Port record(s) updated.';
|
||||
$status = 'ok';
|
||||
} elseif ($rows_updated = '-1') {
|
||||
$message = 'Device record unchanged. No update necessary.';
|
||||
$message = 'Port records unchanged. No update necessary.';
|
||||
$status = 'ok';
|
||||
} else {
|
||||
$message = 'Device record update error.';
|
||||
$message = 'Port record update error.';
|
||||
}
|
||||
|
||||
$response = [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
</form>
|
||||
<h3> Port Settings </h3>
|
||||
<span id="message"><small><div class="alert alert-danger">n.b For the first time, please click any button twice.</div></small></span>
|
||||
<span id="message"></span>
|
||||
|
||||
<form id='ignoreport' name='ignoreport' method='post' action='' role='form' class='form-inline'>
|
||||
<?php echo csrf_field() ?>
|
||||
|
@ -14,10 +14,11 @@
|
|||
<th data-column-id='ifIndex'>Index</th>
|
||||
<th data-column-id='ifName'>Name</th>
|
||||
<th data-column-id='ifAdminStatus'>Admin</th>
|
||||
<th data-column-id='ifOperStatus'>Oper</th>
|
||||
<th data-column-id='ifOperStatus'>Operational</th>
|
||||
<th data-column-id='disabled' data-sortable='false'>Disable polling</th>
|
||||
<th data-column-id='ignore' data-sortable='false'>Ignore alert tag</th>
|
||||
<th data-column-id='ifSpeed'>ifSpeed (bits/s)</th>
|
||||
<th data-column-id='portGroup' data-sortable='false' data-searchable='false'>Port Group</th>
|
||||
<th data-column-id='port_tune' data-sortable='false' data-searchable='false'>RRD Tune</th>
|
||||
<th data-column-id='ifAlias'>Description</th>
|
||||
</tr>
|
||||
|
@ -111,106 +112,153 @@
|
|||
});
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$('form#ignoreport').submit(function (event) {
|
||||
$('#disable-toggle').click(function (event) {
|
||||
// invert selection on all disable buttons
|
||||
event.preventDefault();
|
||||
$('input[name^="disabled_"]').trigger('click');
|
||||
});
|
||||
$('#ignore-toggle').click(function (event) {
|
||||
// invert selection on all ignore buttons
|
||||
event.preventDefault();
|
||||
$('input[name^="ignore_"]').trigger('click');
|
||||
});
|
||||
$('#disable-select').click(function (event) {
|
||||
// select all disable buttons
|
||||
event.preventDefault();
|
||||
$('.disable-check').prop('checked', true);
|
||||
//TODO: find a better solution for 'select-all' button refresh
|
||||
$('.disable-check').trigger('click');
|
||||
$('.disable-check').trigger('click');
|
||||
});
|
||||
$('#ignore-select').click(function (event) {
|
||||
// select all ignore buttons
|
||||
event.preventDefault();
|
||||
$('.ignore-check').prop('checked', true);
|
||||
//TODO: find a better solution for 'select-all' button refresh
|
||||
$('.ignore-check').trigger('click');
|
||||
$('.ignore-check').trigger('click');
|
||||
});
|
||||
$('#down-select').click(function (event) {
|
||||
// select ignore buttons for all ports which are down
|
||||
event.preventDefault();
|
||||
$('[name^="operstatus_"]').each(function () {
|
||||
var name = $(this).attr('name');
|
||||
var text = $(this).text();
|
||||
if (name && text == 'down') {
|
||||
// get the interface number from the object name
|
||||
var port_id = name.split('_')[1];
|
||||
// find its corresponding checkbox and toggle it
|
||||
$('input[name="ignore_' + port_id + '"]').trigger('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#alerted-toggle').click(function (event) {
|
||||
// toggle ignore buttons for all ports which are in class red
|
||||
event.preventDefault();
|
||||
$('.red').each(function () {
|
||||
var name = $(this).attr('name');
|
||||
if (name) {
|
||||
// get the interface number from the object name
|
||||
var port_id = name.split('_')[1];
|
||||
// find its corresponding checkbox and toggle it
|
||||
$('input[name="ignore_' + port_id + '"]').trigger('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#form-reset').click(function (event) {
|
||||
// reset objects in the form to their previous values
|
||||
event.preventDefault();
|
||||
$('#ignoreport')[0].reset();
|
||||
});
|
||||
$('#save-form').click(function (event) {
|
||||
// reset objects in the form to their previous values
|
||||
event.preventDefault();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: $('form#ignoreport').serialize(),
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if (data.status == 'ok') {
|
||||
$("#message").html('<div class="alert alert-info">' + data.message + '</div>')
|
||||
} else {
|
||||
$("#message").html('<div class="alert alert-danger">' + data.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
$("#message").html('<div class="alert alert-danger">Error creating config item</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#disable-toggle').click(function (event) {
|
||||
// invert selection on all disable buttons
|
||||
event.preventDefault();
|
||||
$('input[name^="disabled_"]').trigger('click');
|
||||
});
|
||||
$('#ignore-toggle').click(function (event) {
|
||||
// invert selection on all ignore buttons
|
||||
event.preventDefault();
|
||||
$('input[name^="ignore_"]').trigger('click');
|
||||
});
|
||||
$('#disable-select').click(function (event) {
|
||||
// select all disable buttons
|
||||
event.preventDefault();
|
||||
$('.disable-check').prop('checked', true);
|
||||
//TODO: find a better solution for 'select-all' button refresh
|
||||
$('.disable-check').trigger('click');
|
||||
$('.disable-check').trigger('click');
|
||||
});
|
||||
$('#ignore-select').click(function (event) {
|
||||
// select all ignore buttons
|
||||
event.preventDefault();
|
||||
$('.ignore-check').prop('checked', true);
|
||||
//TODO: find a better solution for 'select-all' button refresh
|
||||
$('.ignore-check').trigger('click');
|
||||
$('.ignore-check').trigger('click');
|
||||
});
|
||||
$('#down-select').click(function (event) {
|
||||
// select ignore buttons for all ports which are down
|
||||
event.preventDefault();
|
||||
$('[id^="operstatus_"]').each(function () {
|
||||
var name = $(this).attr('name');
|
||||
var text = $(this).text();
|
||||
if (name && text == 'down') {
|
||||
// get the interface number from the object name
|
||||
var port_id = name.split('_')[1];
|
||||
// find its corresponding checkbox and toggle it
|
||||
$('input[name="ignore_' + port_id + '"]').trigger('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#alerted-toggle').click(function (event) {
|
||||
// toggle ignore buttons for all ports which are in class red
|
||||
event.preventDefault();
|
||||
$('.red').each(function () {
|
||||
var name = $(this).attr('name');
|
||||
if (name) {
|
||||
// get the interface number from the object name
|
||||
var port_id = name.split('_')[1];
|
||||
// find its corresponding checkbox and toggle it
|
||||
$('input[name="ignore_' + port_id + '"]').trigger('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
$('#form-reset').click(function (event) {
|
||||
// reset objects in the form to their previous values
|
||||
event.preventDefault();
|
||||
$('#ignoreport')[0].reset();
|
||||
});
|
||||
$('#save-form').click(function (event) {
|
||||
// reset objects in the form to their previous values
|
||||
event.preventDefault();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "ajax_form.php",
|
||||
data: $('form#ignoreport').serialize(),
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if (data.status == 'ok') {
|
||||
$("#message").html('<div class="alert alert-info">' + data.message + '</div>')
|
||||
} else {
|
||||
$("#message").html('<div class="alert alert-danger">' + data.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
$("#message").html('<div class="alert alert-danger">Error creating config item</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('form#ignoreport').submit(function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
var grid = $("#edit-ports").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
templates: {
|
||||
header: '<div id="{{ctx.id}}" class="{{css.header}}"><div class="row">\
|
||||
<div class="col-sm-8 actionBar header_actions">\
|
||||
<span class="pull-left">\
|
||||
<span class="action_group">Disable polling\
|
||||
<button type="submit" value="Toggle" class="btn btn-default btn-sm" id="disable-toggle" title="Toggle polling for all ports">Toggle</button>\
|
||||
<button type="submit" value="Select" class="btn btn-default btn-sm" id="disable-select" title="Disable polling on all ports">Disable All</button>\
|
||||
</span>\
|
||||
<span class="action_group">Ignore alerts\
|
||||
<button type="submit" value="Alerted" class="btn btn-default btn-sm" id="alerted-toggle" title="Toggle alerting on all currently-alerted ports">Alerted</button>\
|
||||
<button type="submit" value="Down" class="btn btn-default btn-sm" id="down-select" title="Disable alerting on all currently-down ports">Down</button>\
|
||||
<button type="submit" value="Toggle" class="btn btn-default btn-sm" id="ignore-toggle" title="Toggle alert tag for all ports">Toggle</button>\
|
||||
<button type="submit" value="Select" class="btn btn-default btn-sm" id="ignore-select" title="Disable alert tag on all ports">Ignore All</button></span>\
|
||||
</span>\
|
||||
<span class="action_group">\
|
||||
<button id="save-form" type="submit" value="Save" class="btn btn-success btn-sm" title="Save current port disable/ignore settings">Save Toggles</button>\
|
||||
<button type="submit" value="Reset" class="btn btn-danger btn-sm" id="form-reset" title="Reset form to previously-saved settings">Reset</button>\
|
||||
</span>\
|
||||
</span>\
|
||||
</div>\
|
||||
<div class="col-sm-4 actionBar"><p class="{{css.search}}"></p><p class="{{css.actions}}"></p></div>\
|
||||
</div></div>'
|
||||
},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
id: 'edit-ports',
|
||||
device_id: "<?php echo $device['device_id']; ?>"
|
||||
};
|
||||
},
|
||||
url: "ajax_table.php"
|
||||
url: "<?php echo url('/ajax/table/edit-ports/'); ?>"
|
||||
}).on("loaded.rs.jquery.bootgrid", function() {
|
||||
$("[type='checkbox']").bootstrapSwitch();
|
||||
$("[name='override_config']").bootstrapSwitch('offColor','danger');
|
||||
$('input[name="override_config"]').on('switchChange.bootstrapSwitch', function(event, state) {
|
||||
override_config(event,state,$(this));
|
||||
});
|
||||
|
||||
init_select2('.port_group_select', 'port-group', {}, null, 'No Group');
|
||||
$('.port_group_select').on('change', function (e) {
|
||||
var $target = $(e.target)
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url: "<?php echo url('port'); ?>/" + $target.data('port_id'),
|
||||
data: {"groups": $target.val()},
|
||||
success: function(data) {
|
||||
toastr.success(data.message)
|
||||
},
|
||||
error: function(data) {
|
||||
toastr.error(data.responseJSON.message)
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.header_actions {
|
||||
text-align: left !important;
|
||||
}
|
||||
.action_group {
|
||||
margin-right: 20px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -126,6 +126,7 @@ if ($vars['view'] == 'minigraphs') {
|
|||
<div style='margin: 0px;'><table class='table'>
|
||||
<tr>
|
||||
<th width="350"><A href="<?php echo \LibreNMS\Util\Url::generate($vars, ['sort' => 'port']); ?>">Port</a></th>
|
||||
<th width="100">Port Group</a></th>
|
||||
<th width="100"></th>
|
||||
<th width="120"><a href="<?php echo \LibreNMS\Util\Url::generate($vars, ['sort' => 'traffic']); ?>">Traffic</a></th>
|
||||
<th width="75">Speed</th>
|
||||
|
|
|
@ -5,6 +5,7 @@ $(function () {
|
|||
</script>
|
||||
<?php
|
||||
|
||||
use App\Models\Port;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\IP;
|
||||
use LibreNMS\Util\Number;
|
||||
|
@ -73,6 +74,10 @@ if ($port_details) {
|
|||
|
||||
echo '</span>';
|
||||
|
||||
$port_group_name_list = Port::find($port['port_id'])->groups->pluck('name')->toArray() ?: ['Default'];
|
||||
|
||||
echo '</td><td width=100>';
|
||||
echo implode('<br>', $port_group_name_list);
|
||||
echo "</td><td width=100 onclick=\"location.href='" . generate_port_url($port) . "'\" >";
|
||||
|
||||
if ($port_details) {
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
<?php
|
||||
|
||||
$row = 1;
|
||||
|
||||
$device_id = $vars['device_id'];
|
||||
|
||||
$sql = 'FROM `ports` WHERE `device_id` = ?';
|
||||
$param = [$device_id];
|
||||
|
||||
if (isset($searchPhrase) && ! empty($searchPhrase)) {
|
||||
$sql .= ' AND (`ifName` LIKE ? OR `ifAlias` LIKE ? OR `ifDescr` LIKE ?)';
|
||||
$param[] = "%$searchPhrase%";
|
||||
$param[] = "%$searchPhrase%";
|
||||
$param[] = "%$searchPhrase%";
|
||||
}
|
||||
|
||||
$count_sql = "SELECT COUNT(`port_id`) $sql";
|
||||
$total = dbFetchCell($count_sql, $param);
|
||||
if (empty($total)) {
|
||||
$total = 0;
|
||||
}
|
||||
|
||||
if (! isset($sort) || empty($sort)) {
|
||||
$sort = '`ifIndex` ASC';
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY $sort";
|
||||
|
||||
if (isset($current)) {
|
||||
$limit_low = (($current * $rowCount) - ($rowCount));
|
||||
$limit_high = $rowCount;
|
||||
}
|
||||
|
||||
if ($rowCount != -1) {
|
||||
$sql .= " LIMIT $limit_low,$limit_high";
|
||||
}
|
||||
|
||||
$sql = "SELECT * $sql";
|
||||
|
||||
$response[] = [
|
||||
'ifIndex' => "<button id='save-form' type='submit' value='Save' class='btn btn-success btn-sm' title='Save current port disable/ignore settings'>Save</button><button type='submit' value='Reset' class='btn btn-danger btn-sm' id='form-reset' title='Reset form to previously-saved settings'>Reset</button>",
|
||||
'label' => '',
|
||||
'ifAdminStatus' => '',
|
||||
'ifOperStatus' => "<button type='submit' value='Alerted' class='btn btn-default btn-sm' id='alerted-toggle' title='Toggle alerting on all currently-alerted ports'>Alerted</button><button type='submit' value='Down' class='btn btn-default btn-sm' id='down-select' title='Disable alerting on all currently-down ports'>Down</button>",
|
||||
'disabled' => "<button type='submit' value='Toggle' class='btn btn-default btn-sm' id='disable-toggle' title='Toggle polling for all ports'>Toggle</button><button type='submit' value='Select' class='btn btn-default btn-sm' id='disable-select' title='Disable polling on all ports'>Select All</button>",
|
||||
'ignore' => "<button type='submit' value='Toggle' class='btn btn-default btn-sm' id='ignore-toggle' title='Toggle alert tag for all ports'>Toggle</button><button type='submit' value='Select' class='btn btn-default btn-sm' id='ignore-select' title='Disable alert tag on all ports'>Select All</button>",
|
||||
'ifAlias' => '',
|
||||
];
|
||||
|
||||
foreach (dbFetchRows($sql, $param) as $port) {
|
||||
$port = cleanPort($port);
|
||||
|
||||
// Mark interfaces which are OperDown (but not AdminDown) yet not ignored or disabled, or up yet ignored or disabled
|
||||
// - as to draw the attention to a possible problem.
|
||||
|
||||
$isportbad = ($port['ifOperStatus'] != 'up' && $port['ifAdminStatus'] != 'down') ? 1 : 0;
|
||||
$dowecare = ($port['ignore'] == 0 && $port['disabled'] == 0) ? $isportbad : ! $isportbad;
|
||||
$outofsync = $dowecare ? " class='red'" : '';
|
||||
$checked = '';
|
||||
$device['device_id'] = $device_id;
|
||||
if (get_dev_attrib($device, 'ifName_tune:' . $port['ifName']) == 'true') {
|
||||
$checked = 'checked';
|
||||
}
|
||||
|
||||
$response[] = [
|
||||
'ifIndex' => $port['ifIndex'],
|
||||
'ifName' => $port['label'],
|
||||
'ifAdminStatus' => $port['ifAdminStatus'],
|
||||
'ifOperStatus' => '<span name="operstatus_' . $port['port_id'] . '"' . $outofsync . '>' . $port['ifOperStatus'] . '</span>',
|
||||
'disabled' => '<input type="checkbox" class="disable-check" data-size="small" name="disabled_' . $port['port_id'] . '"' . ($port['disabled'] ? 'checked' : '') . '>
|
||||
<input type="hidden" name="olddis_' . $port['port_id'] . '" value="' . ($port['disabled'] ? 1 : 0) . '"">',
|
||||
'ignore' => '<input type="checkbox" class="ignore-check" data-size="small" name="ignore_' . $port['port_id'] . '"' . ($port['ignore'] ? 'checked' : '') . '>
|
||||
<input type="hidden" name="oldign_' . $port['port_id'] . '" value="' . ($port['ignore'] ? 1 : 0) . '"">',
|
||||
'port_tune' => '<input type="checkbox" id="override_config" name="override_config" data-attrib="ifName_tune:' . $port['ifName'] . '" data-device_id="' . $port['device_id'] . '" data-size="small" ' . $checked . '>',
|
||||
'ifAlias' => '<div class="form-group"><input class="form-control input-sm" id="if-alias" name="if-alias" data-device_id="' . $port['device_id'] . '" data-port_id="' . $port['port_id'] . '" data-ifName="' . $port['ifName'] . '" value="' . $port['ifAlias'] . '"><span class="form-control-feedback"><i class="fa" aria-hidden="true"></i></span></div>',
|
||||
'ifSpeed' => '<div class="form-group has-feedback"><input type="text" pattern="[0-9]*" inputmode="numeric" class="form-control input-sm" id="if-speed" name="if-speed" data-device_id="' . $port['device_id'] . '" data-port_id="' . $port['port_id'] . '" data-ifName="' . $port['ifName'] . '" value="' . $port['ifSpeed'] . '"><span class="form-control-feedback"><i class="fa" aria-hidden="true"></i></span></div>',
|
||||
];
|
||||
}//end foreach
|
||||
|
||||
$output = [
|
||||
'current' => $current,
|
||||
'rowCount' => $rowCount,
|
||||
'rows' => $response,
|
||||
'total' => $total,
|
||||
];
|
||||
echo json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
@ -1461,6 +1461,25 @@ ports:
|
|||
PRIMARY: { Name: PRIMARY, Columns: [port_id], Unique: true, Type: BTREE }
|
||||
ports_device_id_ifindex_unique: { Name: ports_device_id_ifindex_unique, Columns: [device_id, ifIndex], Unique: true, Type: BTREE }
|
||||
ports_ifdescr_index: { Name: ports_ifdescr_index, Columns: [ifDescr], Unique: false, Type: BTREE }
|
||||
port_groups:
|
||||
Columns:
|
||||
- { Field: id, Type: 'int unsigned', 'Null': false, Extra: auto_increment }
|
||||
- { Field: name, Type: varchar(255), 'Null': false, Extra: ''}
|
||||
- { Field: desc, Type: varchar(255), 'Null': true, Extra: ''}
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
|
||||
port_groups_name_unique: { Name: port_groups_name_unique, Columns: [name], Unique: true, Type: BTREE }
|
||||
port_group_port:
|
||||
Columns:
|
||||
- { Field: port_group_id, Type: 'int unsigned', 'Null': false, Extra: '' }
|
||||
- { Field: port_id, Type: 'int unsigned', 'Null': false, Extra: '' }
|
||||
Indexes:
|
||||
PRIMARY: { Name: PRIMARY, Columns: [port_group_id, port_id], Unique: true, Type: BTREE }
|
||||
port_group_port_port_group_id_index: { Name: port_group_port_port_group_id_index, Columns: [port_group_id], Unique: false, Type: BTREE }
|
||||
port_group_port_port_id_index: { Name: port_group_port_port_id_index, Columns: [port_id], Unique: false, Type: BTREE }
|
||||
Constraints:
|
||||
port_group_port_port_group_id_foreign: { name: port_group_port_port_group_id_foreign, foreign_key: port_group_id, table: port_groups, key: id, extra: 'ON DELETE CASCADE' }
|
||||
port_group_port_port_id_foreign: { name: port_group_port_port_id_foreign, foreign_key: port_id, table: ports, key: port_id, extra: 'ON DELETE CASCADE' }
|
||||
ports_adsl:
|
||||
Columns:
|
||||
- { Field: port_id, Type: 'int unsigned', 'Null': false, Extra: '' }
|
||||
|
|
|
@ -121,6 +121,7 @@ nav:
|
|||
- DeviceGroups: API/DeviceGroups.md
|
||||
- Ports: API/Ports.md
|
||||
- PortGroups: API/PortGroups.md
|
||||
- Port_Groups: API/Port_Groups.md
|
||||
- Alerts: API/Alerts.md
|
||||
- Routing: API/Routing.md
|
||||
- Switching: API/Switching.md
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'groups' => [
|
||||
'updated' => ':port: groups updated',
|
||||
'none' => ':port no update requested',
|
||||
],
|
||||
];
|
|
@ -335,7 +335,11 @@
|
|||
@endif
|
||||
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li><a href="{{ url('port-groups') }}"><i class="fa fa-th fa-fw fa-lg"
|
||||
aria-hidden="true"></i> @lang('Manage Groups')
|
||||
</a></li>
|
||||
|
||||
<li role="presentation" class="divider"></li>
|
||||
@if($port_counts['alerted'])
|
||||
<li><a href="{{ url('ports/alerted=yes') }}"><i
|
||||
class="fa fa-exclamation-circle fa-fw fa-lg"
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
@extends('layouts.librenmsv1')
|
||||
|
||||
@section('title', __('Create Port Group'))
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<form action="{{ route('port-groups.store') }}" method="POST" role="form"
|
||||
class="form-horizontal device-group-form col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2 col-sm-12">
|
||||
<legend>@lang('Create Port Group')</legend>
|
||||
@csrf
|
||||
|
||||
@include('port-group.form')
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-sm-offset-2">
|
||||
<button type="submit" class="btn btn-primary">@lang('Save')</button>
|
||||
<a type="button" class="btn btn-danger"
|
||||
href="{{ route('port-groups.index') }}">@lang('Cancel')</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
@extends('layouts.librenmsv1')
|
||||
|
||||
@section('title', __('Edit Port Group'))
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<form action="{{ route('port-groups.update', $port_group->id) }}" method="POST" role="form"
|
||||
class="form-horizontal device-group-form col-md-10 col-md-offset-1 col-sm-12">
|
||||
<legend>@lang('Edit Port Group'): {{ $port_group->name }}</legend>
|
||||
{{ method_field('PUT') }}
|
||||
@csrf
|
||||
|
||||
@include('port-group.form')
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-sm-offset-2">
|
||||
<button type="submit" class="btn btn-primary">@lang('Save')</button>
|
||||
<a type="button" class="btn btn-danger"
|
||||
href="{{ route('port-groups.index') }}">@lang('Cancel')</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
|
@ -0,0 +1,15 @@
|
|||
<div class="form-group @if($errors->has('name')) has-error @endif">
|
||||
<label for="name" class="control-label col-sm-3 col-md-2 text-nowrap">@lang('Name')</label>
|
||||
<div class="col-sm-9 col-md-10">
|
||||
<input type="text" class="form-control" id="name" name="name" value="{{ old('name', $port_group->name) }}">
|
||||
<span class="help-block">{{ $errors->first('name') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group @if($errors->has('desc')) has-error @endif">
|
||||
<label for="desc" class="control-label col-sm-3 col-md-2 text-nowrap">@lang('Description')</label>
|
||||
<div class="col-sm-9 col-md-10">
|
||||
<input type="text" class="form-control" id="desc" name="desc" value="{{ old('desc', $port_group->desc) }}">
|
||||
<span class="help-block">{{ $errors->first('desc') }}</span>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,81 @@
|
|||
@extends('layouts.librenmsv1')
|
||||
|
||||
@section('title', __('Port Groups'))
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<x-panel id="manage-port-groups-panel">
|
||||
<x-slot name="title">
|
||||
<i class="fa fa-th fa-fw fa-lg" aria-hidden="true"></i> @lang('Port Groups')
|
||||
</x-slot>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<a type="button" class="btn btn-primary" href="{{ route('port-groups.create') }}">
|
||||
<i class="fa fa-plus"></i> @lang('New Port Group')
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table id="manage-port-groups-table" class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>@lang('Name')</th>
|
||||
<th>@lang('Description')</th>
|
||||
<th>@lang('Actions')</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($port_groups as $port_group)
|
||||
<tr id="row_{{ $port_group->id }}">
|
||||
<td>{{ $port_group->name }}</td>
|
||||
<td>{{ $port_group->desc }}</td>
|
||||
<td>
|
||||
<a type="button" title="@lang('edit Port Group')" class="btn btn-primary btn-sm" aria-label="@lang('Edit')"
|
||||
href="{{ route('port-groups.edit', $port_group->id) }}">
|
||||
<i class="fa fa-pencil" aria-hidden="true"></i></a>
|
||||
<button type="button" class="btn btn-danger btn-sm" title="@lang('delete Port Group')" aria-label="@lang('Delete')"
|
||||
onclick="delete_pg(this, '{{ $port_group->name }}', '{{ route('port-groups.destroy', $port_group->id) }}')">
|
||||
<i
|
||||
class="fa fa-trash" aria-hidden="true"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</x-panel>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
function delete_pg(button, name, url) {
|
||||
var index = button.parentNode.parentNode.rowIndex;
|
||||
|
||||
if (confirm('@lang('Are you sure you want to delete ')' + name + '?')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'DELETE',
|
||||
success: function (msg) {
|
||||
document.getElementById("manage-port-groups-table").deleteRow(index);
|
||||
toastr.success(msg);
|
||||
},
|
||||
error: function () {
|
||||
toastr.error('@lang('The port group could not be deleted')');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
||||
@section('css')
|
||||
<style>
|
||||
.table-responsive {
|
||||
padding-top: 16px
|
||||
}
|
||||
</style>
|
||||
@endsection
|
|
@ -25,11 +25,21 @@
|
|||
@endif
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="port_group-{{ $id }}" class="control-label">@lang('Port group')</label>
|
||||
<select class="form-control" name="port_group" id="port_group-{{ $id }}" data-placeholder="@lang('All Ports')">
|
||||
@if($port_group)
|
||||
<option value="{{ $port_group->id }}" selected>{{ $port_group->name }}</option>
|
||||
@endif
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('javascript')
|
||||
<script type="text/javascript">
|
||||
init_select2('#interface_filter-{{ $id }}', 'port-field', {limit: 100, field: 'ifType'}, '{{ $interface_filter ?: '' }}');
|
||||
init_select2('#device_group-{{ $id }}', 'device-group', {});
|
||||
init_select2('#port_group-{{ $id }}', 'port-group', {});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
@ -23,6 +23,7 @@ Route::group(['prefix' => 'v0', 'namespace' => '\App\Api\Controllers'], function
|
|||
Route::get('oxidized/{hostname?}', 'LegacyApiController@list_oxidized')->name('list_oxidized');
|
||||
Route::get('devicegroups/{name}', 'LegacyApiController@get_devices_by_group')->name('get_devices_by_group');
|
||||
Route::get('devicegroups', 'LegacyApiController@get_device_groups')->name('get_device_groups');
|
||||
Route::get('port_groups', 'LegacyApiController@get_port_groups')->name('get_port_groups');
|
||||
Route::get('portgroups/multiport/bits/{id}', 'LegacyApiController@get_graph_by_portgroup')->name('get_graph_by_portgroup_multiport_bits');
|
||||
Route::get('portgroups/{group}', 'LegacyApiController@get_graph_by_portgroup')->name('get_graph_by_portgroup');
|
||||
Route::get('alerts/{id}', 'LegacyApiController@list_alerts')->name('get_alert');
|
||||
|
@ -74,6 +75,7 @@ Route::group(['prefix' => 'v0', 'namespace' => '\App\Api\Controllers'], function
|
|||
Route::get('oxidized/config/search/{searchstring}', 'LegacyApiController@search_oxidized')->name('search_oxidized');
|
||||
Route::get('oxidized/config/{device_name}', 'LegacyApiController@get_oxidized_config')->name('get_oxidized_config');
|
||||
Route::post('devicegroups', 'LegacyApiController@add_device_group')->name('add_device_group');
|
||||
Route::post('port_groups', 'LegacyApiController@add_port_group')->name('add_port_group');
|
||||
Route::post('devices/{id}/parents', 'LegacyApiController@add_parents_to_host')->name('add_parents_to_host');
|
||||
Route::delete('/devices/{id}/parents', 'LegacyApiController@del_parents_from_host')->name('del_parents_from_host');
|
||||
Route::post('locations', 'LegacyApiController@add_location')->name('add_location');
|
||||
|
|
|
@ -19,6 +19,8 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
|
|||
|
||||
// pages
|
||||
Route::resource('device-groups', 'DeviceGroupController');
|
||||
Route::resource('port-groups', 'PortGroupController');
|
||||
Route::resource('port', 'PortController', ['only' => 'update']);
|
||||
Route::group(['prefix' => 'poller'], function () {
|
||||
Route::get('', 'PollerController@pollerTab')->name('poller.index');
|
||||
Route::get('log', 'PollerController@logTab')->name('poller.log');
|
||||
|
@ -107,6 +109,7 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
|
|||
Route::get('device', 'DeviceController');
|
||||
Route::get('device-field', 'DeviceFieldController');
|
||||
Route::get('device-group', 'DeviceGroupController');
|
||||
Route::get('port-group', 'PortGroupController');
|
||||
Route::get('eventlog', 'EventlogController');
|
||||
Route::get('graph', 'GraphController');
|
||||
Route::get('graph-aggregate', 'GraphAggregateController');
|
||||
|
@ -125,6 +128,7 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
|
|||
Route::post('alert-schedule', 'AlertScheduleController');
|
||||
Route::post('customers', 'CustomersController');
|
||||
Route::post('device', 'DeviceController');
|
||||
Route::post('edit-ports', 'EditPortsController');
|
||||
Route::post('eventlog', 'EventlogController');
|
||||
Route::post('fdb-tables', 'FdbTablesController');
|
||||
Route::post('graylog', 'GraylogController');
|
||||
|
|
Loading…
Reference in New Issue