LAG support.
Also, archive disappeared nodes from device after macsuck. Squashed commit of the following: commit6d16cddaabMerge:37d9bda3fdf780Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 19 15:48:41 2014 +0000 Merge branch 'master' of ssh://git.code.sf.net/p/netdisco/netdisco-ng into og-agg commit37d9bda2bbAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 18:50:22 2014 +0000 release 2.021000_004 commit3939a2a51cMerge:cf23636571d57dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 18:45:14 2014 +0000 Merge branch 'og-agg' of ssh://olly_g@git.code.sf.net/p/netdisco/netdisco-ng into og-agg commitcf23636ddfAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 18:43:59 2014 +0000 archive disappeared nodes from device - really important! commit571d57dcc7Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 18:20:51 2014 +0000 release 2.021000_003 commit444bc1e81dAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 17:51:54 2014 +0000 protect sprintf from undefined remote_type commit5b875c4641Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 17:49:40 2014 +0000 tidy connected device+node layout commitc09dddb7d1Merge:4f5501c95fc6b1Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 17:46:39 2014 +0000 Merge branch 'og-agg' of ssh://olly_g@git.code.sf.net/p/netdisco/netdisco-ng into og-agg commit4f5501c613Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 17:46:23 2014 +0000 allow sanity checks on lag member before moving node commit95fc6b18dcAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 14:02:19 2014 +0000 release 2.021000_002 commit8b809c445fMerge:04d486efe3e8e3Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 13:58:31 2014 +0000 Merge branch 'og-agg' of ssh://git.code.sf.net/p/netdisco/netdisco-ng into og-agg commitfe3e8e3ef2Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 13:57:31 2014 +0000 do not set master neigh if master is a slave commit04d486e433Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 13:38:45 2014 +0000 display remote ip if only remote ip commit14f9eb01adAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 13:35:54 2014 +0000 show all members of lag when searching for lag master commit5b2a0a0a4bAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 13:35:16 2014 +0000 fix copy of remote master to local master remote_port commit86a9854f39Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 10:00:13 2014 +0000 show both link and device type icons commit88510552e5Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 09:57:29 2014 +0000 hide neighbor device ID and add sidebar option to show commit29da3097cbMerge:8bca30d9fe92fbAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 09:04:15 2014 +0000 Merge branch 'og-agg' of ssh://git.code.sf.net/p/netdisco/netdisco-ng into og-agg commit9fe92fb5e8Merge:6620a035557811Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 09:03:02 2014 +0000 Merge branch 'og-agg' of ssh://olly_g@git.code.sf.net/p/netdisco/netdisco-ng into og-agg commit6620a03686Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 08:56:13 2014 +0000 also store master neighbor port commit8bca30d085Author: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 00:41:46 2014 +0000 release 2.021000_001 commit5557811aebAuthor: Oliver Gorwits <oliver@cpan.org> Date: Mon Jan 13 00:38:18 2014 +0000 fix icon placement in editable device port cells commit25292e1ce8Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 22:20:08 2014 +0000 fix name of class commit99ce56d794Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 22:13:53 2014 +0000 remove brackets from lag name commit27aa80ed93Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 22:12:06 2014 +0000 rename link agg legend commit84ed4c5008Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 22:11:15 2014 +0000 move lag member icon into port icon column commit67c9c783ecAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 21:58:11 2014 +0000 fix Cisco stack port ignore commit4531c61246Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 21:51:41 2014 +0000 move nodes to lag master port commitffc6b9c315Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 20:45:58 2014 +0000 use group icon for slave and master commit68fd345e37Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 20:34:01 2014 +0000 indicate aggregate master commit79c69f5a0fAuthor: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 19:14:48 2014 +0000 show aggreate parent in device ports commit3a4beed2f1Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 18:46:25 2014 +0000 store aggregate port into db commitfd7bb0cd62Author: Oliver Gorwits <oliver@cpan.org> Date: Sun Jan 12 17:49:39 2014 +0000 add device_port cols for aggregate links data
This commit is contained in:
@@ -72,8 +72,6 @@ lib/App/Netdisco/DB/Result/Virtual/ActiveNodeWithAge.pm
|
|||||||
lib/App/Netdisco/DB/Result/Virtual/ApRadioChannelPower.pm
|
lib/App/Netdisco/DB/Result/Virtual/ApRadioChannelPower.pm
|
||||||
lib/App/Netdisco/DB/Result/Virtual/CidrIps.pm
|
lib/App/Netdisco/DB/Result/Virtual/CidrIps.pm
|
||||||
lib/App/Netdisco/DB/Result/Virtual/DeviceLinks.pm
|
lib/App/Netdisco/DB/Result/Virtual/DeviceLinks.pm
|
||||||
lib/App/Netdisco/DB/Result/Virtual/DevicePortVlanNative.pm
|
|
||||||
lib/App/Netdisco/DB/Result/Virtual/DevicePortVlanTagged.pm
|
|
||||||
lib/App/Netdisco/DB/Result/Virtual/DuplexMismatch.pm
|
lib/App/Netdisco/DB/Result/Virtual/DuplexMismatch.pm
|
||||||
lib/App/Netdisco/DB/Result/Virtual/NodeWithAge.pm
|
lib/App/Netdisco/DB/Result/Virtual/NodeWithAge.pm
|
||||||
lib/App/Netdisco/DB/Result/Virtual/PhonesDiscovered.pm
|
lib/App/Netdisco/DB/Result/Virtual/PhonesDiscovered.pm
|
||||||
@@ -119,6 +117,9 @@ lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-28-29-PostgreSQL.sql
|
|||||||
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-29-30-PostgreSQL.sql
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-29-30-PostgreSQL.sql
|
||||||
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-3-4-PostgreSQL.sql
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-3-4-PostgreSQL.sql
|
||||||
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-30-31-PostgreSQL.sql
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-30-31-PostgreSQL.sql
|
||||||
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-31-32-PostgreSQL.sql
|
||||||
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-32-33-PostgreSQL.sql
|
||||||
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-33-34-PostgreSQL.sql
|
||||||
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-4-5-PostgreSQL.sql
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-4-5-PostgreSQL.sql
|
||||||
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-5-6-PostgreSQL.sql
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-5-6-PostgreSQL.sql
|
||||||
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-6-7-PostgreSQL.sql
|
lib/App/Netdisco/DB/schema_versions/App-Netdisco-DB-6-7-PostgreSQL.sql
|
||||||
|
|||||||
@@ -71,4 +71,4 @@ resources:
|
|||||||
homepage: http://netdisco.org/
|
homepage: http://netdisco.org/
|
||||||
license: http://opensource.org/licenses/bsd-license.php
|
license: http://opensource.org/licenses/bsd-license.php
|
||||||
repository: git://git.code.sf.net/p/netdisco/netdisco-ng
|
repository: git://git.code.sf.net/p/netdisco/netdisco-ng
|
||||||
version: 2.021000
|
version: 2.021000_004
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use 5.010_000;
|
|||||||
use File::ShareDir 'dist_dir';
|
use File::ShareDir 'dist_dir';
|
||||||
use Path::Class;
|
use Path::Class;
|
||||||
|
|
||||||
our $VERSION = '2.021000';
|
our $VERSION = '2.021000_004';
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
if (not ($ENV{DANCER_APPDIR} || '')
|
if (not ($ENV{DANCER_APPDIR} || '')
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ sub store_interfaces {
|
|||||||
my $i_stp_state = $snmp->i_stp_state;
|
my $i_stp_state = $snmp->i_stp_state;
|
||||||
my $i_vlan = $snmp->i_vlan;
|
my $i_vlan = $snmp->i_vlan;
|
||||||
my $i_lastchange = $snmp->i_lastchange;
|
my $i_lastchange = $snmp->i_lastchange;
|
||||||
|
my $agg_ports = $snmp->agg_ports;
|
||||||
|
|
||||||
# clear the cached uptime and get a new one
|
# clear the cached uptime and get a new one
|
||||||
my $dev_uptime = $snmp->load_uptime;
|
my $dev_uptime = $snmp->load_uptime;
|
||||||
@@ -278,10 +279,22 @@ sub store_interfaces {
|
|||||||
type => $i_type->{$entry},
|
type => $i_type->{$entry},
|
||||||
vlan => $i_vlan->{$entry},
|
vlan => $i_vlan->{$entry},
|
||||||
pvid => $i_vlan->{$entry},
|
pvid => $i_vlan->{$entry},
|
||||||
|
is_master => 'false',
|
||||||
|
slave_of => undef,
|
||||||
lastchange => $lc,
|
lastchange => $lc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# must do this after building %interfaces so that we can set is_master
|
||||||
|
foreach my $sidx (keys %$agg_ports) {
|
||||||
|
my $slave = $interfaces->{$sidx} or next;
|
||||||
|
my $master = $interfaces->{ $agg_ports->{$sidx} } or next;
|
||||||
|
next unless exists $interfaces{$slave} and exists $interfaces{$master};
|
||||||
|
|
||||||
|
$interfaces{$slave}->{slave_of} = $master;
|
||||||
|
$interfaces{$master}->{is_master} = 'true';
|
||||||
|
}
|
||||||
|
|
||||||
schema('netdisco')->resultset('DevicePort')->txn_do_locked(sub {
|
schema('netdisco')->resultset('DevicePort')->txn_do_locked(sub {
|
||||||
my $gone = $device->ports->delete({keep_nodes => 1});
|
my $gone = $device->ports->delete({keep_nodes => 1});
|
||||||
debug sprintf ' [%s] interfaces - removed %d interfaces',
|
debug sprintf ' [%s] interfaces - removed %d interfaces',
|
||||||
@@ -695,18 +708,19 @@ sub store_neighbors {
|
|||||||
|
|
||||||
# IP Phone and WAP detection type fixup
|
# IP Phone and WAP detection type fixup
|
||||||
if (defined $remote_type) {
|
if (defined $remote_type) {
|
||||||
my $phone_flag = grep {/phone/i} @$remote_cap;
|
my $phone_flag = grep {/phone/i} @$remote_cap;
|
||||||
my $ap_flag = grep {/wlanAccessPoint/} @$remote_cap;
|
my $ap_flag = grep {/wlanAccessPoint/} @$remote_cap;
|
||||||
if ($phone_flag or $remote_type =~ m/(mitel.5\d{3})/i) {
|
|
||||||
$remote_type = 'IP Phone: '. $remote_type
|
if ($phone_flag or $remote_type =~ m/(mitel.5\d{3})/i) {
|
||||||
if $remote_type !~ /ip phone/i;
|
$remote_type = 'IP Phone: '. $remote_type
|
||||||
}
|
if $remote_type !~ /ip phone/i;
|
||||||
elsif ($ap_flag) {
|
}
|
||||||
$remote_type = 'AP: '. $remote_type;
|
elsif ($ap_flag) {
|
||||||
}
|
$remote_type = 'AP: '. $remote_type;
|
||||||
else {
|
}
|
||||||
$remote_type ||= '';
|
else {
|
||||||
}
|
$remote_type ||= '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# hack for devices seeing multiple neighbors on the port
|
# hack for devices seeing multiple neighbors on the port
|
||||||
@@ -719,7 +733,7 @@ sub store_neighbors {
|
|||||||
foreach my $n (@$remote_ip) {
|
foreach my $n (@$remote_ip) {
|
||||||
debug sprintf
|
debug sprintf
|
||||||
' [%s] neigh - adding neighbor %s, type [%s], on %s to discovery queue',
|
' [%s] neigh - adding neighbor %s, type [%s], on %s to discovery queue',
|
||||||
$device->ip, $n, $remote_type, $port;
|
$device->ip, $n, ($remote_type || ''), $port;
|
||||||
push @to_discover, [$n, $remote_type];
|
push @to_discover, [$n, $remote_type];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -733,7 +747,7 @@ sub store_neighbors {
|
|||||||
if (wantarray) {
|
if (wantarray) {
|
||||||
debug sprintf
|
debug sprintf
|
||||||
' [%s] neigh - adding neighbor %s, type [%s], on %s to discovery queue',
|
' [%s] neigh - adding neighbor %s, type [%s], on %s to discovery queue',
|
||||||
$device->ip, $remote_ip, $remote_type, $port;
|
$device->ip, $remote_ip, ($remote_type || ''), $port;
|
||||||
push @to_discover, [$remote_ip, $remote_type];
|
push @to_discover, [$remote_ip, $remote_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,6 +787,26 @@ sub store_neighbors {
|
|||||||
is_uplink => \"true",
|
is_uplink => \"true",
|
||||||
manual_topo => \"false",
|
manual_topo => \"false",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (defined $portrow->slave_of and
|
||||||
|
my $master = schema('netdisco')->resultset('DevicePort')
|
||||||
|
->single({ip => $device->ip, port => $portrow->slave_of})) {
|
||||||
|
|
||||||
|
if (not ($portrow->is_master or defined $master->slave_of)) {
|
||||||
|
# TODO needs refactoring - this is quite expensive
|
||||||
|
my $peer = schema('netdisco')->resultset('DevicePort')->find({
|
||||||
|
ip => $portrow->neighbor->ip,
|
||||||
|
port => $portrow->remote_port,
|
||||||
|
}) if $portrow->neighbor;
|
||||||
|
|
||||||
|
$master->update({
|
||||||
|
remote_ip => ($peer ? $peer->ip : $remote_ip),
|
||||||
|
remote_port => ($peer ? $peer->slave_of : undef ),
|
||||||
|
is_uplink => \"true",
|
||||||
|
manual_topo => \"false",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return @to_discover;
|
return @to_discover;
|
||||||
@@ -860,7 +894,7 @@ sub discover_new_neighbors {
|
|||||||
if (not is_discoverable($device, $remote_type)) {
|
if (not is_discoverable($device, $remote_type)) {
|
||||||
debug sprintf
|
debug sprintf
|
||||||
' queue - %s, type [%s] excluded by discover_* config',
|
' queue - %s, type [%s] excluded by discover_* config',
|
||||||
$ip, $remote_type;
|
$ip, ($remote_type || '');
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ sub do_macsuck {
|
|||||||
my $ip = $device->ip;
|
my $ip = $device->ip;
|
||||||
|
|
||||||
# would be possible just to use now() on updated records, but by using this
|
# would be possible just to use now() on updated records, but by using this
|
||||||
# same value for them all, we _can_ if we want add a job at the end to
|
# same value for them all, we can if we want add a job at the end to
|
||||||
# select and do something with the updated set (no reason to yet, though)
|
# select and do something with the updated set (see set archive, below)
|
||||||
my $now = 'to_timestamp('. (join '.', gettimeofday) .')';
|
my $now = 'to_timestamp('. (join '.', gettimeofday) .')';
|
||||||
my $total_nodes = 0;
|
my $total_nodes = 0;
|
||||||
|
|
||||||
@@ -98,8 +98,10 @@ sub do_macsuck {
|
|||||||
debug sprintf ' [%s] macsuck - port %s vlan %s : %s nodes',
|
debug sprintf ' [%s] macsuck - port %s vlan %s : %s nodes',
|
||||||
$ip, $port, $vlan, scalar keys %{ $fwtable->{$vlan}->{$port} };
|
$ip, $port, $vlan, scalar keys %{ $fwtable->{$vlan}->{$port} };
|
||||||
|
|
||||||
# make sure this port is UP in netdisco
|
# make sure this port is UP in netdisco (unless it's a lag master,
|
||||||
$device_ports->{$port}->update({up_admin => 'up', up => 'up'});
|
# because we can still see nodes without a functioning aggregate)
|
||||||
|
$device_ports->{$port}->update({up_admin => 'up', up => 'up'})
|
||||||
|
if not $device_ports->{$port}->is_master;
|
||||||
|
|
||||||
foreach my $mac (keys %{ $fwtable->{$vlan}->{$port} }) {
|
foreach my $mac (keys %{ $fwtable->{$vlan}->{$port} }) {
|
||||||
|
|
||||||
@@ -113,8 +115,18 @@ sub do_macsuck {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug sprintf ' [%s] macsuck - %s forwarding table entries',
|
debug sprintf ' [%s] macsuck - %s updated forwarding table entries',
|
||||||
$ip, $total_nodes;
|
$ip, $total_nodes;
|
||||||
|
|
||||||
|
# a use for $now ... need to archive dissapeared nodes
|
||||||
|
my $archived = schema('netdisco')->resultset('Node')->search({
|
||||||
|
switch => $ip,
|
||||||
|
time_last => { '<' => \$now },
|
||||||
|
})->update({ active => \'false' });
|
||||||
|
|
||||||
|
debug sprintf ' [%s] macsuck - removed %s fwd table entries to archive',
|
||||||
|
$ip, $archived;
|
||||||
|
|
||||||
$device->update({last_macsuck => \$now});
|
$device->update({last_macsuck => \$now});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,14 +336,6 @@ sub _walk_fwtable {
|
|||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: add proper port channel support!
|
|
||||||
if ($port =~ m/port.channel/i) {
|
|
||||||
debug sprintf
|
|
||||||
' [%s] macsuck %s - port %s is LAG member - skipping.',
|
|
||||||
$device->ip, $mac, $port;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# this uses the cached $ports resultset to limit hits on the db
|
# this uses the cached $ports resultset to limit hits on the db
|
||||||
my $device_port = $device_ports->{$port};
|
my $device_port = $device_ports->{$port};
|
||||||
|
|
||||||
@@ -389,8 +393,14 @@ sub _walk_fwtable {
|
|||||||
next unless setting('macsuck_bleed');
|
next unless setting('macsuck_bleed');
|
||||||
}
|
}
|
||||||
|
|
||||||
my $vlan = $fw_vlan->{$idx} || $comm_vlan || '0';
|
# possibly move node to lag master
|
||||||
|
if (defined $device_port->slave_of
|
||||||
|
and exists $device_ports->{$device_port->slave_of}) {
|
||||||
|
$port = $device_port->slave_of;
|
||||||
|
$device_ports->{$port}->update({is_uplink => \'true'});
|
||||||
|
}
|
||||||
|
|
||||||
|
my $vlan = $fw_vlan->{$idx} || $comm_vlan || '0';
|
||||||
++$cache->{$vlan}->{$port}->{$mac};
|
++$cache->{$vlan}->{$port}->{$mac};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ __PACKAGE__->load_namespaces(
|
|||||||
default_resultset_class => 'ResultSet',
|
default_resultset_class => 'ResultSet',
|
||||||
);
|
);
|
||||||
|
|
||||||
our $VERSION = 33; # schema version used for upgrades, keep as integer
|
our $VERSION = 34; # schema version used for upgrades, keep as integer
|
||||||
|
|
||||||
use Path::Class;
|
use Path::Class;
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ __PACKAGE__->add_columns(
|
|||||||
{ data_type => "text", is_nullable => 1 },
|
{ data_type => "text", is_nullable => 1 },
|
||||||
"remote_id",
|
"remote_id",
|
||||||
{ data_type => "text", is_nullable => 1 },
|
{ data_type => "text", is_nullable => 1 },
|
||||||
|
"is_master",
|
||||||
|
{ data_type => "bool", is_nullable => 0, default_value => \"false" },
|
||||||
|
"slave_of",
|
||||||
|
{ data_type => "text", is_nullable => 1 },
|
||||||
"manual_topo",
|
"manual_topo",
|
||||||
{ data_type => "bool", is_nullable => 0, default_value => \"false" },
|
{ data_type => "bool", is_nullable => 0, default_value => \"false" },
|
||||||
"is_uplink",
|
"is_uplink",
|
||||||
@@ -179,6 +183,22 @@ __PACKAGE__->might_have(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
=head2 agg_master
|
||||||
|
|
||||||
|
Returns another row from the C<device_port> table if this port is slave
|
||||||
|
to another in a link aggregate.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
__PACKAGE__->belongs_to(
|
||||||
|
agg_master => 'App::Netdisco::DB::Result::DevicePort', {
|
||||||
|
'foreign.ip' => 'self.ip',
|
||||||
|
'foreign.port' => 'self.slave_of',
|
||||||
|
}, {
|
||||||
|
join_type => 'LEFT',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
=head2 neighbor_alias
|
=head2 neighbor_alias
|
||||||
|
|
||||||
When a device port has an attached neighbor device, this relationship will
|
When a device port has an attached neighbor device, this relationship will
|
||||||
@@ -231,7 +251,7 @@ __PACKAGE__->belongs_to( oui => 'App::Netdisco::DB::Result::Oui',
|
|||||||
|
|
||||||
=head1 ADDITIONAL METHODS
|
=head1 ADDITIONAL METHODS
|
||||||
|
|
||||||
=head2
|
=head2 neighbor
|
||||||
|
|
||||||
Returns the Device entry for the neighbour Device on the given port.
|
Returns the Device entry for the neighbour Device on the given port.
|
||||||
|
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ sub with_is_free {
|
|||||||
->search({},
|
->search({},
|
||||||
{
|
{
|
||||||
'+columns' => { is_free =>
|
'+columns' => { is_free =>
|
||||||
\["up != 'up' and "
|
\["me.up != 'up' and "
|
||||||
."age(now(), to_timestamp(extract(epoch from device.last_discover) "
|
."age(now(), to_timestamp(extract(epoch from device.last_discover) "
|
||||||
."- (device.uptime - lastchange)/100)) "
|
."- (device.uptime - me.lastchange)/100)) "
|
||||||
."> ?::interval",
|
."> ?::interval",
|
||||||
[{} => $interval]] },
|
[{} => $interval]] },
|
||||||
join => 'device',
|
join => 'device',
|
||||||
@@ -93,11 +93,11 @@ sub only_free_ports {
|
|||||||
->search_rs($cond, $attrs)
|
->search_rs($cond, $attrs)
|
||||||
->search(
|
->search(
|
||||||
{
|
{
|
||||||
'up' => { '!=' => 'up' },
|
'me.up' => { '!=' => 'up' },
|
||||||
},{
|
},{
|
||||||
where =>
|
where =>
|
||||||
\["age(now(), to_timestamp(extract(epoch from device.last_discover) "
|
\["age(now(), to_timestamp(extract(epoch from device.last_discover) "
|
||||||
."- (device.uptime - lastchange)/100)) "
|
."- (device.uptime - me.lastchange)/100)) "
|
||||||
."> ?::interval",
|
."> ?::interval",
|
||||||
[{} => $interval]],
|
[{} => $interval]],
|
||||||
join => 'device' },
|
join => 'device' },
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE device_port DROP COLUMN is_uplink_admin;
|
||||||
|
ALTER TABLE device_port ADD COLUMN "slave_of" text;
|
||||||
|
ALTER TABLE device_port ADD COLUMN "is_master" bool DEFAULT false NOT NULL;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -63,7 +63,12 @@ get '/ajax/content/device/ports' => require_login sub {
|
|||||||
if (($prefer eq 'port') or not $prefer and
|
if (($prefer eq 'port') or not $prefer and
|
||||||
$set->search({'me.port' => $f})->count) {
|
$set->search({'me.port' => $f})->count) {
|
||||||
|
|
||||||
$set = $set->search({'me.port' => $f});
|
$set = $set->search({
|
||||||
|
-or => [
|
||||||
|
'me.port' => $f,
|
||||||
|
'me.slave_of' => $f,
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$set = $set->search({'me.name' => $f});
|
$set = $set->search({'me.name' => $f});
|
||||||
@@ -108,6 +113,13 @@ get '/ajax/content/device/ports' => require_login sub {
|
|||||||
$set = $set->search({-or => \@combi});
|
$set = $set->search({-or => \@combi});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# get aggregate master status
|
||||||
|
$set = $set->search({}, {
|
||||||
|
'join' => 'agg_master',
|
||||||
|
'+select' => [qw/agg_master.up_admin agg_master.up/],
|
||||||
|
'+as' => [qw/agg_master_up_admin agg_master_up/],
|
||||||
|
});
|
||||||
|
|
||||||
# make sure query asks for formatted timestamps when needed
|
# make sure query asks for formatted timestamps when needed
|
||||||
$set = $set->with_times if param('c_lastchange');
|
$set = $set->with_times if param('c_lastchange');
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ logger_format: '[%P] %L @%D> %m'
|
|||||||
# WEB FRONTEND
|
# WEB FRONTEND
|
||||||
# ------------
|
# ------------
|
||||||
|
|
||||||
domain_suffix: ''
|
domain_suffix: ""
|
||||||
no_auth: false
|
no_auth: false
|
||||||
suggest_guest: false
|
suggest_guest: false
|
||||||
trust_remote_user: false
|
trust_remote_user: false
|
||||||
@@ -24,9 +24,9 @@ trust_x_remote_user: false
|
|||||||
#ldap:
|
#ldap:
|
||||||
# servers: []
|
# servers: []
|
||||||
# user_string: 'MYDOMAIN\%USER%'
|
# user_string: 'MYDOMAIN\%USER%'
|
||||||
# base: ''
|
# base: ""
|
||||||
# proxy_user: ''
|
# proxy_user: ""
|
||||||
# proxy_pass: ''
|
# proxy_pass: ""
|
||||||
# opts:
|
# opts:
|
||||||
# debug: 3
|
# debug: 3
|
||||||
# tls_opts: {}
|
# tls_opts: {}
|
||||||
@@ -80,7 +80,7 @@ extra_web_plugins: []
|
|||||||
community: ['public']
|
community: ['public']
|
||||||
community_rw: ['private']
|
community_rw: ['private']
|
||||||
snmp_auth: []
|
snmp_auth: []
|
||||||
get_community: ''
|
get_community: ""
|
||||||
bulkwalk_off: false
|
bulkwalk_off: false
|
||||||
bulkwalk_no: []
|
bulkwalk_no: []
|
||||||
bulkwalk_repeaters: 20
|
bulkwalk_repeaters: 20
|
||||||
@@ -117,7 +117,8 @@ ignore_interfaces:
|
|||||||
- 'StackPort'
|
- 'StackPort'
|
||||||
- 'Control Plane Interface'
|
- 'Control Plane Interface'
|
||||||
- 'SPAN (S|R)P Interface'
|
- 'SPAN (S|R)P Interface'
|
||||||
- 'StackSub'
|
- 'StackSub-.*'
|
||||||
|
- 'StackPort\d+'
|
||||||
- 'netflow'
|
- 'netflow'
|
||||||
- 'Vlan\d+-mpls layer'
|
- 'Vlan\d+-mpls layer'
|
||||||
- 'BRI\S+-Bearer Channel'
|
- 'BRI\S+-Bearer Channel'
|
||||||
|
|||||||
@@ -158,9 +158,14 @@ div.content > div.tab-content table.nd_floatinghead thead {
|
|||||||
/* nudge cell content to the right when port_control controls are enabled */
|
/* nudge cell content to the right when port_control controls are enabled */
|
||||||
.nd_editable-cell > .nd_this-port-only {
|
.nd_editable-cell > .nd_this-port-only {
|
||||||
margin-left: 18px;
|
margin-left: 18px;
|
||||||
|
margin-right: 18px;
|
||||||
}
|
}
|
||||||
|
.nd_editable-cell > .nd_port-only-first {
|
||||||
|
margin-left: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
.nd_editable-cell > .nd_editable-cell-content {
|
.nd_editable-cell > .nd_editable-cell-content {
|
||||||
margin-left: 18px;
|
margin-right: 18px;
|
||||||
}
|
}
|
||||||
.table .nd_nudge-for-icon {
|
.table .nd_nudge-for-icon {
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
@@ -177,6 +182,10 @@ div.content > div.tab-content table.nd_floatinghead thead {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.nd_devport-icon i {
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
/* undo nd_center-cell when in a modial dialog (which lives in table cell) */
|
/* undo nd_center-cell when in a modial dialog (which lives in table cell) */
|
||||||
.table .nd_center-cell .modal-body {
|
.table .nd_center-cell .modal-body {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -261,7 +270,7 @@ td > form.nd_inline-form {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: black;
|
color: black;
|
||||||
float: left;
|
float: left;
|
||||||
display: none;
|
visibility: hidden;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
.nd_log-icon:hover, .nd_log-icon:focus {
|
.nd_log-icon:hover, .nd_log-icon:focus {
|
||||||
|
|||||||
@@ -92,14 +92,16 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
// toggle visibility of port up/down and edit controls
|
// toggle visibility of port up/down and edit controls
|
||||||
$('.tab-content').on('mouseenter', '.nd_editable-cell', function() {
|
$('.tab-content').on('mouseenter', '.nd_editable-cell', function() {
|
||||||
$(this).children('.nd_hand-icon,.nd_log-icon').show();
|
$(this).children('.nd_hand-icon').show();
|
||||||
|
$(this).children('.nd_log-icon').css('visibility', 'visible');
|
||||||
if (! $(this).is(':focus')) {
|
if (! $(this).is(':focus')) {
|
||||||
$(this).children('.nd_edit-icon').show(); // ports
|
$(this).children('.nd_edit-icon').show(); // ports
|
||||||
$(this).siblings('td').find('.nd_device-details-edit').show(); // details
|
$(this).siblings('td').find('.nd_device-details-edit').show(); // details
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('.tab-content').on('mouseleave', '.nd_editable-cell', function() {
|
$('.tab-content').on('mouseleave', '.nd_editable-cell', function() {
|
||||||
$(this).children('.nd_hand-icon,.nd_log-icon').hide();
|
$(this).children('.nd_hand-icon').hide();
|
||||||
|
$(this).children('.nd_log-icon').css('visibility', 'hidden');
|
||||||
if (! $(this).is(':focus')) {
|
if (! $(this).is(':focus')) {
|
||||||
$(this).children('.nd_edit-icon').hide(); // ports
|
$(this).children('.nd_edit-icon').hide(); // ports
|
||||||
$(this).siblings('td').find('.nd_device-details-edit').hide(); // details
|
$(this).siblings('td').find('.nd_device-details-edit').hide(); // details
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
[% FOREACH row IN results %]
|
[% FOREACH row IN results %]
|
||||||
<tr>
|
<tr>
|
||||||
<td class="nd_center-cell">
|
<td class="nd_center-cell nd_devport-icon">
|
||||||
[% IF row.up_admin != 'up' %]
|
[% IF row.up_admin != 'up' %]
|
||||||
<i class="icon-remove"></i>
|
<i class="icon-remove"></i>
|
||||||
[% ELSIF row.stp == 'blocking' %]
|
[% ELSIF row.stp == 'blocking' %]
|
||||||
@@ -29,6 +29,15 @@
|
|||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<i class="icon-angle-up text-success"></i>
|
<i class="icon-angle-up text-success"></i>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
[% IF row.slave_of %]<br/>
|
||||||
|
[% IF row.get_column('agg_master_up_admin') != 'up' %]
|
||||||
|
<small><i class="icon-group muted"></i></small>
|
||||||
|
[% ELSIF row.get_column('agg_master_up') == 'up' %]
|
||||||
|
<small><i class="icon-group text-success"></i></small>
|
||||||
|
[% ELSE %]
|
||||||
|
<small><i class="icon-group text-error"></i></small>
|
||||||
|
[% END %]
|
||||||
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
[% FOREACH config IN settings._extra_device_port_cols %]
|
[% FOREACH config IN settings._extra_device_port_cols %]
|
||||||
@@ -66,10 +75,18 @@
|
|||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<td nowrap>
|
<td nowrap>
|
||||||
[% END %]
|
[% END %]
|
||||||
<a class="nd_linkcell nd_this-port-only" href="[% uri_for('/device',
|
<a class="nd_this-port-only nd_port-only-first" href="[% uri_for('/device',
|
||||||
self_options) %]&q=[% params.q | uri %]&f=[% row.port | uri %]&prefer=port">
|
self_options) %]&q=[% params.q | uri %]&f=[% row.port | uri %]&prefer=port">
|
||||||
[% row.port | html_entity %]
|
[% IF row.is_master %]
|
||||||
</a></td>
|
<small><i class="icon-group muted"></i></small>
|
||||||
|
[% END %]
|
||||||
|
[% row.port | html_entity %]</a>
|
||||||
|
[% IF row.slave_of %]<br/>
|
||||||
|
<a class="nd_this-port-only" href="[% uri_for('/device',
|
||||||
|
self_options) %]&q=[% params.q | uri %]&f=[% row.slave_of | uri %]&prefer=port">
|
||||||
|
[% row.slave_of | html_entity %]</a>
|
||||||
|
[% END %]
|
||||||
|
</td>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% FOREACH config IN settings._extra_device_port_cols %]
|
[% FOREACH config IN settings._extra_device_port_cols %]
|
||||||
@@ -216,27 +233,36 @@
|
|||||||
<td>
|
<td>
|
||||||
[% IF params.c_neighbors AND (row.remote_ip OR row.is_uplink) %]
|
[% IF params.c_neighbors AND (row.remote_ip OR row.is_uplink) %]
|
||||||
[% IF row.neighbor %]
|
[% IF row.neighbor %]
|
||||||
<i class="icon-link[% ' text-warning' IF row.manual_topo %]"></i>
|
<i class="icon-link[% ' text-warning' IF row.manual_topo %]"></i>
|
||||||
<a href="[% uri_for('/device',
|
|
||||||
self_options) %]&q=[% row.neighbor.dns || row.neighbor.ip | uri %]&f=[% row.remote_port | uri %]">
|
|
||||||
[% row.neighbor.dns.remove(settings.domain_suffix) || row.neighbor.ip | html_entity %]
|
|
||||||
([% row.remote_port | html_entity %]
|
|
||||||
[% ' id: '_ row.remote_id IF row.remote_id %]
|
|
||||||
[% ' type: '_ row.remote_type IF row.remote_type %])</a>
|
|
||||||
[% ELSIF row.remote_ip AND row.remote_port %]
|
|
||||||
[% IF row.remote_type AND row.remote_type.match('(?i)ip.phone') %]
|
[% IF row.remote_type AND row.remote_type.match('(?i)ip.phone') %]
|
||||||
<i class="icon-phone"></i>
|
<i class="icon-phone"></i>
|
||||||
[% ELSIF row.remote_type AND row.remote_type.match('(cisco\s+AIR-[L|C]?AP|-K9W8-|^AP:\s)') %]
|
[% ELSIF row.remote_type AND row.remote_type.match('(cisco\s+AIR-[L|C]?AP|-K9W8-|^AP:\s)') %]
|
||||||
<i class="icon-signal"></i>
|
<i class="icon-signal"></i>
|
||||||
[% ELSE %]
|
|
||||||
<i class="icon-unlink text-error"></i>
|
|
||||||
[% END %]
|
[% END %]
|
||||||
<a href="[% search_node %]&q=[% row.remote_ip | uri %]">
|
<a href="[% uri_for('/device',
|
||||||
[% row.remote_ip | html_entity %] (port: [% row.remote_port | html_entity %]
|
self_options) %]&q=[% row.neighbor.dns || row.neighbor.ip | uri %]&f=[% row.remote_port | uri %]">
|
||||||
[% ' id: '_ row.remote_id IF row.remote_id %]
|
[% row.neighbor.dns.remove(settings.domain_suffix) || row.neighbor.ip | html_entity %]
|
||||||
[% ' type: '_ row.remote_type IF row.remote_type %])</a>
|
[% ' - ' IF row.remote_port %][% row.remote_port | html_entity %]</a><br/>
|
||||||
|
[% IF params.neigh_id and (row.remote_id or row.remote_type) %]
|
||||||
|
([% 'id: '_ row.remote_id IF row.remote_id %]
|
||||||
|
[% ' type: '_ row.remote_type IF row.remote_type %])<br/>
|
||||||
|
[% END %]
|
||||||
|
[% ELSIF row.remote_ip %]
|
||||||
|
<i class="icon-unlink text-error"></i>
|
||||||
|
[% IF row.remote_type AND row.remote_type.match('(?i)ip.phone') %]
|
||||||
|
<i class="icon-phone"></i>
|
||||||
|
[% ELSIF row.remote_type AND row.remote_type.match('(cisco\s+AIR-[L|C]?AP|-K9W8-|^AP:\s)') %]
|
||||||
|
<i class="icon-signal"></i>
|
||||||
|
[% END %]
|
||||||
|
<a href="[% search_node %]&q=[% row.remote_ip | uri %]">
|
||||||
|
[% row.remote_ip | html_entity %]
|
||||||
|
[% ' - ' IF row.remote_port %][% row.remote_port | html_entity %]</a><br/>
|
||||||
|
[% IF params.neigh_id and (row.remote_id or row.remote_type) %]
|
||||||
|
([% 'id: '_ row.remote_id IF row.remote_id %]
|
||||||
|
[% ' type: '_ row.remote_type IF row.remote_type %])<br/>
|
||||||
|
[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<i class="icon-unlink text-error"></i> (possible uplink)
|
<i class="icon-unlink text-error"></i> (possible uplink)
|
||||||
[% END %]
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
[% IF params.c_nodes %]
|
[% IF params.c_nodes %]
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<li><i class="icon-li icon-phone"></i> IP Phone</li>
|
<li><i class="icon-li icon-phone"></i> IP Phone</li>
|
||||||
<li><i class="icon-li icon-signal"></i> Wireless Client</li>
|
<li><i class="icon-li icon-signal"></i> Wireless Client</li>
|
||||||
<li><i class="icon-li icon-book"></i> Archived Data</li>
|
<li><i class="icon-li icon-book"></i> Archived Data</li>
|
||||||
|
<li><i class="icon-li icon-group"></i> Link Aggregate</li>
|
||||||
[% IF user_has_role('port_control') %]
|
[% IF user_has_role('port_control') %]
|
||||||
<li><i class="icon-li icon-refresh icon-spin"></i> Click "Update View"</li>
|
<li><i class="icon-li icon-refresh icon-spin"></i> Click "Update View"</li>
|
||||||
[% END %]
|
[% END %]
|
||||||
@@ -104,6 +105,13 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" id="neigh_id"
|
||||||
|
name="neigh_id"[% ' checked="checked"' IF params.neigh_id %] />
|
||||||
|
Connected Device ID
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user