complete the migration of connected device ID to connected inventory

This commit is contained in:
Oliver Gorwits
2018-03-02 12:42:36 +00:00
parent e1b9f2225e
commit 7b5f8c76f3
7 changed files with 146 additions and 57 deletions

View File

@@ -314,7 +314,44 @@ state, or else `undef` if the port is not in an error state.
=cut =cut
sub error_disable_cause { return (shift)->get_column('properties_error_disable_cause') } sub error_disable_cause { return (shift)->get_column('error_disable_cause') }
=head2 remote_is_wap
Returns true if the remote LLDP neighbor has reported Wireless Access Point
capability.
=cut
sub remote_is_wap { return (shift)->get_column('remote_is_wap') }
=head2 remote_is_phone
Returns true if the remote LLDP neighbor has reported Telephone capability.
=cut
sub remote_is_phone { return (shift)->get_column('remote_is_phone') }
=head2 remote_inventory
Returns a synthesized description of the remote LLDP device if inventory
information was given, including vendor, model, OS version, and serial number.
=cut
sub remote_inventory {
my $port = shift;
my $os_ver = ($port->get_column('remote_os_ver')
? ('running '. $port->get_column('remote_os_ver')) : '');
my $serial = ($port->get_column('remote_serial')
? ('('. $port->get_column('remote_serial') .')') : '');
my $retval = join ' ', ($port->get_column('remote_vendor') || ''),
($port->get_column('remote_model') || ''), $serial, $os_ver;
return (($retval =~ m/[[:alnum:]]/) ? $retval : '');
}
=head2 vlan_count =head2 vlan_count

View File

@@ -19,10 +19,10 @@ __PACKAGE__->add_columns(
{ data_type => "boolean", is_nullable => 1 }, { data_type => "boolean", is_nullable => 1 },
"remote_vendor", "remote_vendor",
{ data_type => "text", is_nullable => 1 }, { data_type => "text", is_nullable => 1 },
"remote_os_ver",
{ data_type => "text", is_nullable => 1 },
"remote_model", "remote_model",
{ data_type => "text", is_nullable => 1 }, { data_type => "text", is_nullable => 1 },
"remote_os_ver",
{ data_type => "text", is_nullable => 1 },
"remote_serial", "remote_serial",
{ data_type => "text", is_nullable => 1 }, { data_type => "text", is_nullable => 1 },
); );

View File

@@ -113,6 +113,10 @@ will add the following additional synthesized columns to the result set:
=item error_disable_cause =item error_disable_cause
=item remote_is_wap (boolean)
=item remote_is_phone (boolean)
=back =back
=cut =cut
@@ -124,8 +128,54 @@ sub with_properties {
->search_rs($cond, $attrs) ->search_rs($cond, $attrs)
->search({}, ->search({},
{ {
'+select' => ['properties.error_disable_cause'], '+select' => [qw/
'+as' => ['properties_error_disable_cause'], properties.error_disable_cause
properties.remote_is_wap
properties.remote_is_phone
/],
'+as' => [qw/
error_disable_cause
remote_is_wap remote_is_phone
/],
join => 'properties',
});
}
=head2 with_remote_inventory
This is a modifier for any C<search()> which
will add the following additional synthesized columns to the result set:
=over 4
=item remote_vendor
=item remote_model
=item remote_os_ver
=item remote_serial
=back
=cut
sub with_remote_inventory {
my ($rs, $cond, $attrs) = @_;
return $rs
->search_rs($cond, $attrs)
->search({},
{
'+select' => [qw/
properties.remote_vendor
properties.remote_model
properties.remote_os_ver
properties.remote_serial
/],
'+as' => [qw/
remote_vendor remote_model remote_os_ver remote_serial
/],
join => 'properties', join => 'properties',
}); });
} }

View File

@@ -190,6 +190,9 @@ get '/ajax/content/device/ports' => require_login sub {
'+as' => ['neighbor_ip', 'neighbor_dns'], '+as' => ['neighbor_ip', 'neighbor_dns'],
}) if param('c_neighbors'); }) if param('c_neighbors');
# also get remote LLDP inventory if asked for
$set = $set->with_remote_inventory if param('n_inventory');
# sort ports (empty set would be a 'no records' msg) # sort ports (empty set would be a 'no records' msg)
my $results = [ sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } $set->all ]; my $results = [ sort { &App::Netdisco::Util::Web::sort_port($a->port, $b->port) } $set->all ];
return unless scalar @$results; return unless scalar @$results;

View File

@@ -122,17 +122,18 @@ sidebar_defaults:
c_neighbors: { label: 'Connected Devices', default: checked, idx: 17 } c_neighbors: { label: 'Connected Devices', default: checked, idx: 17 }
c_stp: { label: 'Spanning Tree', default: null, idx: 18 } c_stp: { label: 'Spanning Tree', default: null, idx: 18 }
c_up: { label: 'Status', default: null, idx: 19 } c_up: { label: 'Status', default: null, idx: 19 }
n_age: { label: 'Age Stamp', default: null, idx: 0 } mac_format: { default: IEEE }
n_ip4: { label: 'IPv4 Addresses', default: checked, idx: 1 } n_inventory: { label: 'Inventory Data', default: checked, idx: 0 }
n_ip6: { label: 'IPv6 Addresses', default: checked, idx: 2 } n_detailed_inventory: { label: 'Detailed Inventory', default: null, idx: 1 }
n_netbios: { label: 'NetBIOS Name', default: checked, idx: 3 } n_age: { label: 'Age Stamp', default: null, idx: 2 }
n_ssid: { label: 'SSID', default: checked, idx: 4 } n_ip4: { label: 'IPv4 Addresses', default: checked, idx: 3 }
n_vendor: { label: 'Vendor', default: null, idx: 5 } n_ip6: { label: 'IPv6 Addresses', default: checked, idx: 4 }
n_archived: { label: 'Archived Data', default: null, idx: 6 } n_netbios: { label: 'NetBIOS Name', default: checked, idx: 5 }
n_ssid: { label: 'SSID', default: checked, idx: 6 }
n_vendor: { label: 'Vendor', default: null, idx: 7 }
n_archived: { label: 'Archived Data', default: null, idx: 8 }
age_num: { default: 3 } age_num: { default: 3 }
age_unit: { default: months } age_unit: { default: months }
mac_format: { default: IEEE }
neigh_id: { default: null }
device_netmap: device_netmap:
showips: { default: null } showips: { default: null }
showspeed: { default: null } showspeed: { default: null }

View File

@@ -267,9 +267,9 @@
[% 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.get_column('neighbor_ip') %] [% IF row.get_column('neighbor_ip') %]
<i class="icon-link[% ' text-warning' IF row.manual_topo %]"></i> <i class="icon-link[% ' text-warning' IF row.manual_topo %]"></i>
[% IF row.remote_type AND row.remote_type.match('(?i)ip.phone') %] [% IF row.remote_is_phone %]
<i class="icon-phone"></i>&nbsp; <i class="icon-phone"></i>&nbsp;
[% ELSIF row.remote_type AND row.remote_type.match('^AP:\s') %] [% ELSIF row.remote_is_wap %]
<i class="icon-signal"></i>&nbsp; <i class="icon-signal"></i>&nbsp;
[% END %] [% END %]
<a href="[% device_ports %]&q=[% row.get_column('neighbor_ip') | uri %]"> <a href="[% device_ports %]&q=[% row.get_column('neighbor_ip') | uri %]">
@@ -280,21 +280,27 @@
[% row.remote_port | html_entity %]</a> [% row.remote_port | html_entity %]</a>
[% END %] [% END %]
<br/> <br/>
[% IF params.neigh_id and (row.remote_id or row.remote_type) %] [% IF params.n_inventory and row.remote_inventory %]
[% row.remote_inventory %]<br/>
[% END %]
[% IF params.n_detailed_inventory and (row.remote_id or row.remote_type) %]
([% 'id: '_ row.remote_id IF row.remote_id %] ([% 'id: '_ row.remote_id IF row.remote_id %]
[% ' type: '_ row.remote_type IF row.remote_type %])<br/> [% ' type: '_ row.remote_type IF row.remote_type %])<br/>
[% END %] [% END %]
[% ELSIF row.remote_ip %] [% ELSIF row.remote_ip %]
<i class="icon-unlink text-error"></i>&nbsp; <i class="icon-unlink text-error"></i>&nbsp;
[% IF row.remote_type AND row.remote_type.match('(?i)ip.phone') %] [% IF row.remote_is_phone %]
<i class="icon-phone"></i>&nbsp; <i class="icon-phone"></i>&nbsp;
[% ELSIF row.remote_type AND row.remote_type.match('^AP:\s') %] [% ELSIF row.remote_is_wap %]
<i class="icon-signal"></i>&nbsp; <i class="icon-signal"></i>&nbsp;
[% END %] [% END %]
<a href="[% search_node %]&q=[% row.remote_ip | uri %]"> <a href="[% search_node %]&q=[% row.remote_ip | uri %]">
[% row.remote_ip | html_entity %] [% row.remote_ip | html_entity %]
[% ' - ' IF row.remote_port %][% row.remote_port | html_entity %]</a><br/> [% ' - ' IF row.remote_port %][% row.remote_port | html_entity %]</a><br/>
[% IF params.neigh_id and (row.remote_id or row.remote_type) %] [% IF params.n_inventory and row.remote_inventory %]
[% row.remote_inventory %]<br/>
[% END %]
[% IF params.n_detailed_inventory and (row.remote_id or row.remote_type) %]
([% 'id: '_ row.remote_id IF row.remote_id %] ([% 'id: '_ row.remote_id IF row.remote_id %]
[% ' type: '_ row.remote_type IF row.remote_type %])<br/> [% ' type: '_ row.remote_type IF row.remote_type %])<br/>
[% END %] [% END %]
@@ -306,10 +312,9 @@
[% FOREACH node IN row.$nodes %] [% FOREACH node IN row.$nodes %]
[% '<br/>' IF (row.remote_ip OR row.is_uplink) OR NOT loop.first %] [% '<br/>' IF (row.remote_ip OR row.is_uplink) OR NOT loop.first %]
[% '<i class="icon-book"></i>&nbsp; ' IF NOT node.active %] [% '<i class="icon-book"></i>&nbsp; ' IF NOT node.active %]
[% IF row.remote_type AND row.remote_type.match('(?i)ip.phone') %] [% IF row.remote_is_phone %]
<i class="icon-phone"></i>&nbsp; <i class="icon-phone"></i>&nbsp;
[% ELSIF node.wireless.defined [% ELSIF node.wireless.defined OR row.remote_is_wap %]
OR (row.remote_type AND row.remote_type.match('^AP:\s')) %]
<i class="icon-signal"></i>&nbsp; <i class="icon-signal"></i>&nbsp;
[% END %] [% END %]
<a href="[% search_node %]&q=[% node.net_mac.$mac_format_call | uri %]"> <a href="[% search_node %]&q=[% node.net_mac.$mac_format_call | uri %]">

View File

@@ -75,6 +75,33 @@
</ul> </ul>
</div> </div>
</div> </div>
<div class="clearfix">
<span data-toggle="collapse" data-target="#nd_nodeprops">
<label class="nd_collapser">Node Properties
<i class="nd_arrow-up-down-right icon-chevron-up icon-large"></i>
</label></span>
<div id="nd_nodeprops" class="collapse">
<ul class="nd_inputs-list unstyled">
<li>
<em class="muted">MAC address format:</em><br/>
<select id="nd_mac-format" name="mac_format">
[% FOREACH format IN [ 'IEEE', 'Cisco', 'Microsoft', 'Sun' ] %]
<option[% ' selected="selected"' IF vars.sidebar_defaults.device_ports.mac_format == format %]>[% format %]</option>
[% END %]
</select>
</li>
[% FOREACH item IN settings.connected_properties %]
<li>
<label class="checkbox">
<input type="checkbox" id="[% item.name | html_entity %]"
name="[% item.name | html_entity %]"[% ' checked="checked"' IF vars.sidebar_defaults.device_ports.${item.name} %] />
[% item.label | html_entity %]
</label>
</li>
[% END %]
</ul>
</div>
</div>
<div class="clearfix"> <div class="clearfix">
<span data-toggle="collapse" data-target="#nd_portprops"> <span data-toggle="collapse" data-target="#nd_portprops">
<label class="nd_collapser">Port Properties <label class="nd_collapser">Port Properties
@@ -106,40 +133,6 @@
</select> </select>
</div> </div>
</li> </li>
<li>
<label class="checkbox">
<input type="checkbox" id="neigh_id"
name="neigh_id"[% ' checked="checked"' IF vars.sidebar_defaults.device_ports.neigh_id %] />
Connected Device ID
</label>
</li>
</ul>
</div>
</div>
<div class="clearfix">
<span data-toggle="collapse" data-target="#nd_nodeprops">
<label class="nd_collapser">Node Properties
<i class="nd_arrow-up-down-right icon-chevron-up icon-large"></i>
</label></span>
<div id="nd_nodeprops" class="collapse">
<ul class="nd_inputs-list unstyled">
<li>
<em class="muted">MAC address format:</em><br/>
<select id="nd_mac-format" name="mac_format">
[% FOREACH format IN [ 'IEEE', 'Cisco', 'Microsoft', 'Sun' ] %]
<option[% ' selected="selected"' IF vars.sidebar_defaults.device_ports.mac_format == format %]>[% format %]</option>
[% END %]
</select>
</li>
[% FOREACH item IN settings.connected_properties %]
<li>
<label class="checkbox">
<input type="checkbox" id="[% item.name | html_entity %]"
name="[% item.name | html_entity %]"[% ' checked="checked"' IF vars.sidebar_defaults.device_ports.${item.name} %] />
[% item.label | html_entity %]
</label>
</li>
[% END %]
</ul> </ul>
</div> </div>
</div> </div>