#1009 neighbour map depth and/or until end of lldp chains
* sidebar and style changes * switch server code to new params and values * working algo for cloud and neighbor depth * store map positions for lldp cloud with depth * color the root node uniquely * restrict all devices, depth, cloud map to < 1000 devices
This commit is contained in:
@@ -11,7 +11,7 @@ __PACKAGE__->load_namespaces(
|
|||||||
);
|
);
|
||||||
|
|
||||||
our # try to hide from kwalitee
|
our # try to hide from kwalitee
|
||||||
$VERSION = 83; # schema version used for upgrades, keep as integer
|
$VERSION = 84; # schema version used for upgrades, keep as integer
|
||||||
|
|
||||||
use Path::Class;
|
use Path::Class;
|
||||||
use File::ShareDir 'dist_dir';
|
use File::ShareDir 'dist_dir';
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ __PACKAGE__->add_columns(
|
|||||||
{ data_type => "text[]", is_nullable => 0 },
|
{ data_type => "text[]", is_nullable => 0 },
|
||||||
"vlan",
|
"vlan",
|
||||||
{ data_type => "integer", is_nullable => 0, default => 0 },
|
{ data_type => "integer", is_nullable => 0, default => 0 },
|
||||||
|
"depth",
|
||||||
|
{ data_type => "integer", is_nullable => 0, default => 0 },
|
||||||
"positions",
|
"positions",
|
||||||
{ data_type => "text", is_nullable => 0 },
|
{ data_type => "text", is_nullable => 0 },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ get '/device' => require_login sub {
|
|||||||
template 'device', {
|
template 'device', {
|
||||||
netdisco_device => $first,
|
netdisco_device => $first,
|
||||||
display_name => ($others ? $first->ip : ($first->dns || $first->ip)),
|
display_name => ($others ? $first->ip : ($first->dns || $first->ip)),
|
||||||
|
device_count => schema(vars->{'tenant'})->resultset('Device')->count(),
|
||||||
lgroup_list => [ schema(vars->{'tenant'})->resultset('Device')->get_distinct_col('location') ],
|
lgroup_list => [ schema(vars->{'tenant'})->resultset('Device')->get_distinct_col('location') ],
|
||||||
hgroup_list => setting('host_group_displaynames'),
|
hgroup_list => setting('host_group_displaynames'),
|
||||||
device => params->{'tab'},
|
device => params->{'tab'},
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ ajax '/ajax/data/device/netmappositions' => require_login sub {
|
|||||||
undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/);
|
undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/);
|
||||||
|
|
||||||
my $mapshow = param('mapshow');
|
my $mapshow = param('mapshow');
|
||||||
return if !defined $mapshow or $mapshow !~ m/^(?:all|neighbors)$/;
|
return if !defined $mapshow or $mapshow !~ m/^(?:all|cloud|depth)$/;
|
||||||
|
my $depth = param('depth') || 1;
|
||||||
|
return if $depth !~ m/^\d+$/;
|
||||||
|
|
||||||
# list of groups selected by user and passed in param
|
# list of groups selected by user and passed in param
|
||||||
my $hgroup = (ref [] eq ref param('hgroup') ? param('hgroup') : [param('hgroup')]);
|
my $hgroup = (ref [] eq ref param('hgroup') ? param('hgroup') : [param('hgroup')]);
|
||||||
@@ -56,7 +58,8 @@ ajax '/ajax/data/device/netmappositions' => require_login sub {
|
|||||||
return unless scalar keys %clean;
|
return unless scalar keys %clean;
|
||||||
|
|
||||||
my $posrow = schema(vars->{'tenant'})->resultset('NetmapPositions')->find({
|
my $posrow = schema(vars->{'tenant'})->resultset('NetmapPositions')->find({
|
||||||
device => (($mapshow eq 'neighbors') ? $qdev->ip : undef),
|
device => ($mapshow ne 'all' ? $qdev->ip : undef),
|
||||||
|
depth => ($mapshow eq 'depth' ? $depth : 0),
|
||||||
host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ],
|
host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ],
|
||||||
locations => \[ '= ?', [locations => [sort @lgrplist]] ],
|
locations => \[ '= ?', [locations => [sort @lgrplist]] ],
|
||||||
vlan => ($vlan || 0),
|
vlan => ($vlan || 0),
|
||||||
@@ -67,7 +70,8 @@ ajax '/ajax/data/device/netmappositions' => require_login sub {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
schema(vars->{'tenant'})->resultset('NetmapPositions')->create({
|
schema(vars->{'tenant'})->resultset('NetmapPositions')->create({
|
||||||
device => (($mapshow eq 'neighbors') ? $qdev->ip : undef),
|
device => ($mapshow ne 'all' ? $qdev->ip : undef),
|
||||||
|
depth => ($mapshow eq 'depth' ? $depth : 0),
|
||||||
host_groups => [sort @hgrplist],
|
host_groups => [sort @hgrplist],
|
||||||
locations => [sort @lgrplist],
|
locations => [sort @lgrplist],
|
||||||
vlan => ($vlan || 0),
|
vlan => ($vlan || 0),
|
||||||
@@ -143,8 +147,9 @@ ajax '/ajax/data/device/netmap' => require_login sub {
|
|||||||
undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/);
|
undef $vlan if (defined $vlan and $vlan !~ m/^\d+$/);
|
||||||
|
|
||||||
my $colorby = (param('colorby') || 'speed');
|
my $colorby = (param('colorby') || 'speed');
|
||||||
my $mapshow = (param('mapshow') || 'neighbors');
|
my $mapshow = (param('mapshow') || 'depth');
|
||||||
$mapshow = 'neighbors' if $mapshow !~ m/^(?:all|neighbors)$/;
|
my $depth = (param('depth') || 1);
|
||||||
|
$mapshow = 'depth' if $mapshow !~ m/^(?:all|cloud|depth)$/;
|
||||||
$mapshow = 'all' unless $qdev->in_storage;
|
$mapshow = 'all' unless $qdev->in_storage;
|
||||||
|
|
||||||
# list of groups selected by user and passed in param
|
# list of groups selected by user and passed in param
|
||||||
@@ -169,7 +174,7 @@ ajax '/ajax/data/device/netmap' => require_login sub {
|
|||||||
|
|
||||||
my %seen_link = ();
|
my %seen_link = ();
|
||||||
my $links = schema(vars->{'tenant'})->resultset('Virtual::DeviceLinks')->search({
|
my $links = schema(vars->{'tenant'})->resultset('Virtual::DeviceLinks')->search({
|
||||||
($mapshow eq 'neighbors' ? ( -or => [
|
(($mapshow eq 'depth' and $depth == 1) ? ( -or => [
|
||||||
{ left_ip => $qdev->ip },
|
{ left_ip => $qdev->ip },
|
||||||
{ right_ip => $qdev->ip },
|
{ right_ip => $qdev->ip },
|
||||||
]) : ())
|
]) : ())
|
||||||
@@ -193,10 +198,41 @@ ajax '/ajax/data/device/netmap' => require_login sub {
|
|||||||
++$seen_link{$link->{left_ip} ."\0". $link->{right_ip}};
|
++$seen_link{$link->{left_ip} ."\0". $link->{right_ip}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# filter by lldp cloud or depth
|
||||||
|
# this is O(N^2) or worse
|
||||||
|
|
||||||
|
my %cloud = ($qdev->ip => 1);
|
||||||
|
my $seen_cloud = scalar keys %cloud;
|
||||||
|
my $passes = ($mapshow eq 'cloud' ? 999 : $depth);
|
||||||
|
|
||||||
|
if ($mapshow eq 'cloud' or ($mapshow eq 'depth' and $depth > 1)) {
|
||||||
|
while ($seen_cloud > 0 and $passes > 0) {
|
||||||
|
--$passes;
|
||||||
|
$seen_cloud = 0;
|
||||||
|
|
||||||
|
foreach my $cip (keys %cloud) {
|
||||||
|
foreach my $okip (keys %ok_dev) {
|
||||||
|
next if exists $cloud{$okip};
|
||||||
|
|
||||||
|
if (exists $seen_link{$cip ."\0". $okip}
|
||||||
|
or exists $seen_link{$okip ."\0". $cip}) {
|
||||||
|
|
||||||
|
++$cloud{$okip};
|
||||||
|
++$seen_cloud;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($mapshow eq 'depth' and $depth == 1) {
|
||||||
|
%cloud = %ok_dev;
|
||||||
|
}
|
||||||
|
|
||||||
# DEVICES (NODES)
|
# DEVICES (NODES)
|
||||||
|
|
||||||
my $posrow = schema(vars->{'tenant'})->resultset('NetmapPositions')->find({
|
my $posrow = schema(vars->{'tenant'})->resultset('NetmapPositions')->find({
|
||||||
device => (($mapshow eq 'neighbors') ? $qdev->ip : undef),
|
device => ($mapshow ne 'all' ? $qdev->ip : undef),
|
||||||
|
depth => ($mapshow eq 'depth' ? $depth : 0),
|
||||||
host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ],
|
host_groups => \[ '= ?', [host_groups => [sort @hgrplist]] ],
|
||||||
locations => \[ '= ?', [locations => [sort @lgrplist]] ],
|
locations => \[ '= ?', [locations => [sort @lgrplist]] ],
|
||||||
vlan => ($vlan || 0),
|
vlan => ($vlan || 0),
|
||||||
@@ -219,8 +255,8 @@ ajax '/ajax/data/device/netmap' => require_login sub {
|
|||||||
DEVICE: while (my $device = $devices->next) {
|
DEVICE: while (my $device = $devices->next) {
|
||||||
# if in neighbors mode then use %ok_dev to filter
|
# if in neighbors mode then use %ok_dev to filter
|
||||||
next DEVICE if ($device->ip ne $qdev->ip)
|
next DEVICE if ($device->ip ne $qdev->ip)
|
||||||
and ($mapshow eq 'neighbors')
|
and ($mapshow ne 'all')
|
||||||
and (not $ok_dev{$device->ip}); # showing only neighbors but no link
|
and (not $cloud{$device->ip}); # showing only neighbors but no link
|
||||||
|
|
||||||
# if location picked then filter
|
# if location picked then filter
|
||||||
next DEVICE if ((scalar @lgrplist) and ((!defined $device->location)
|
next DEVICE if ((scalar @lgrplist) and ((!defined $device->location)
|
||||||
@@ -249,6 +285,7 @@ ajax '/ajax/data/device/netmap' => require_login sub {
|
|||||||
ID => $device->ip,
|
ID => $device->ip,
|
||||||
SIZEVALUE => (param('dynamicsize') ? $color_lkp{speed} : 3000),
|
SIZEVALUE => (param('dynamicsize') ? $color_lkp{speed} : 3000),
|
||||||
((exists $color_lkp{$colorby}) ? (COLORVALUE => $color_lkp{$colorby}) : ()),
|
((exists $color_lkp{$colorby}) ? (COLORVALUE => $color_lkp{$colorby}) : ()),
|
||||||
|
(($device->ip eq $qdev->ip) ? (COLORVALUE => 'ROOTNODE') : ()),
|
||||||
LABEL => (param('showips') ? ($device->ip .' '. $name) : $name),
|
LABEL => (param('showips') ? ($device->ip .' '. $name) : $name),
|
||||||
ORIG_LABEL => $name,
|
ORIG_LABEL => $name,
|
||||||
INFOSTRING => make_node_infostring($device),
|
INFOSTRING => make_node_infostring($device),
|
||||||
|
|||||||
@@ -159,7 +159,9 @@ sidebar_defaults:
|
|||||||
device_netmap:
|
device_netmap:
|
||||||
showips: { default: null }
|
showips: { default: null }
|
||||||
showspeed: { default: null }
|
showspeed: { default: null }
|
||||||
mapshow: { default: neighbors }
|
mapshow: { default: depth }
|
||||||
|
depth: { default: 1 }
|
||||||
|
too_many_devices: { default: 1000 }
|
||||||
colorby: { default: speed }
|
colorby: { default: speed }
|
||||||
dynamicsize: { default: checked }
|
dynamicsize: { default: checked }
|
||||||
report_moduleinventory:
|
report_moduleinventory:
|
||||||
|
|||||||
@@ -494,8 +494,13 @@ td > form.nd_inline-form {
|
|||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
}
|
}
|
||||||
#nd_vlan-entry {
|
#nd_vlan-entry {
|
||||||
|
margin-top: 7px;
|
||||||
width: 45px;
|
width: 45px;
|
||||||
}
|
}
|
||||||
|
#nd_mapshow-hops {
|
||||||
|
width: 30px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
/* netmap maximise icon */
|
/* netmap maximise icon */
|
||||||
#nd2_netmap-fullscreen {
|
#nd2_netmap-fullscreen {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE netmap_positions ADD COLUMN "depth" integer DEFAULT 0 NOT NULL;
|
||||||
|
|
||||||
|
UPDATE netmap_positions SET depth = 0 WHERE device IS NOT NULL;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -216,7 +216,7 @@ function saveMapPositions() {
|
|||||||
graph.inspect().main.nodes.each(function(n) { n.fixed = true });
|
graph.inspect().main.nodes.each(function(n) { n.fixed = true });
|
||||||
$.post(
|
$.post(
|
||||||
'[% uri_for('/ajax/data/device/netmappositions') | none %]'
|
'[% uri_for('/ajax/data/device/netmappositions') | none %]'
|
||||||
,$("#nd_vlan-entry, #nd_hgroup-select, #nd_lgroup-select, #nq, input[name='mapshow']").serialize()
|
,$("#nd_vlan-entry, #nd_mapshow-hops, #nd_hgroup-select, #nd_lgroup-select, #nq, input[name='mapshow']").serialize()
|
||||||
+ '&positions=' + JSON.stringify(graph.positions())
|
+ '&positions=' + JSON.stringify(graph.positions())
|
||||||
);
|
);
|
||||||
// toastr.success('Saved map positions.');
|
// toastr.success('Saved map positions.');
|
||||||
|
|||||||
@@ -60,26 +60,37 @@
|
|||||||
|
|
||||||
<hr class="nd_sidebar-hr"/>
|
<hr class="nd_sidebar-hr"/>
|
||||||
|
|
||||||
|
[% IF device_count < (vars.sidebar_defaults.device_netmap.too_many_devices || 1000) %]
|
||||||
<div class="radio radio-success">
|
<div class="radio radio-success">
|
||||||
<input type="radio" name="mapshow" id="nd_mapshow-all"
|
<input type="radio" name="mapshow" id="nd_mapshow-all"
|
||||||
[% 'checked' IF vars.sidebar_defaults.device_netmap.mapshow == 'all' %] value="all">
|
[% 'checked' IF vars.sidebar_defaults.device_netmap.mapshow == 'all' %] value="all">
|
||||||
<label for="nd_mapshow-all">All Devices</label>
|
<label for="nd_mapshow-all">All Devices</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="radio radio-success">
|
<div class="radio radio-success">
|
||||||
<input type="radio" name="mapshow" id="nd_mapshow-neighbors"
|
<input type="radio" name="mapshow" id="nd_mapshow-cloud"
|
||||||
[% 'checked' IF vars.sidebar_defaults.device_netmap.mapshow == 'neighbors' %] value="neighbors">
|
[% 'checked' IF vars.sidebar_defaults.device_netmap.mapshow == 'cloud' %] value="cloud">
|
||||||
<label for="nd_mapshow-neighbors">Only Neighbors</label>
|
<label for="nd_mapshow-cloud">Neighbor Cloud</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="radio radio-success">
|
||||||
|
<input type="radio" name="mapshow" id="nd_mapshow-depth"
|
||||||
|
[% 'checked' IF vars.sidebar_defaults.device_netmap.mapshow == 'depth' %] value="depth">
|
||||||
|
<label for="nd_mapshow-depth">Neighbor Hops:
|
||||||
|
<input name="depth" id="nd_mapshow-hops" class="input-mini" type="number" placeholder="1"
|
||||||
|
value="[% params.depth || vars.sidebar_defaults.device_netmap.hops || 1 | html_entity %]"/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
[% END %]
|
||||||
|
|
||||||
<label><span id="nd_vlan-label-text">Carrying VLAN: </span>
|
<label><span id="nd_vlan-label-text">Carrying VLAN: </span>
|
||||||
<input name="vlan" id="nd_vlan-entry" class="input-mini" type="number" placeholder="ID"
|
<input name="vlan" id="nd_vlan-entry" class="input-mini" type="number" placeholder="ID"
|
||||||
value="[% params.vlan | html_entity %]" type="text"/>
|
value="[% params.vlan | html_entity %]"/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
[% IF hgroup_list.size %]
|
[% IF hgroup_list.size %]
|
||||||
|
<em class="muted">Device Groups:</em><br/>
|
||||||
<select class="nd_side-select" size="[% hgroup_list.size > 4 ? 4 : hgroup_list.size %]"
|
<select class="nd_side-select" size="[% hgroup_list.size > 4 ? 4 : hgroup_list.size %]"
|
||||||
multiple name="hgroup" id="nd_hgroup-select"
|
multiple name="hgroup" id="nd_hgroup-select"
|
||||||
rel="tooltip" data-placement="left" data-offset="5" data-title="Host Groups">
|
rel="tooltip" data-placement="left" data-offset="5" data-title="Device Groups">
|
||||||
[% FOREACH opt IN hgroup_list.pairs %]
|
[% FOREACH opt IN hgroup_list.pairs %]
|
||||||
<option[% ' selected="selected"' IF hgroup_lkp.exists(opt.key) %]
|
<option[% ' selected="selected"' IF hgroup_lkp.exists(opt.key) %]
|
||||||
value="[% opt.key | html_entity %]">[% opt.value | html_entity %]</option>
|
value="[% opt.key | html_entity %]">[% opt.value | html_entity %]</option>
|
||||||
@@ -87,6 +98,7 @@
|
|||||||
</select>
|
</select>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% IF lgroup_list.size %]
|
[% IF lgroup_list.size %]
|
||||||
|
<em class="muted">Device Locations:</em><br/>
|
||||||
<select class="nd_side-select" size="[% lgroup_list.size > 4 ? 4 : lgroup_list.size %]"
|
<select class="nd_side-select" size="[% lgroup_list.size > 4 ? 4 : lgroup_list.size %]"
|
||||||
multiple name="lgroup" id="nd_lgroup-select"
|
multiple name="lgroup" id="nd_lgroup-select"
|
||||||
rel="tooltip" data-placement="left" data-offset="5" data-title="Device Locations">
|
rel="tooltip" data-placement="left" data-offset="5" data-title="Device Locations">
|
||||||
|
|||||||
Reference in New Issue
Block a user