diff --git a/Netdisco/Changes b/Netdisco/Changes index 117ba8f9..f88e712a 100644 --- a/Netdisco/Changes +++ b/Netdisco/Changes @@ -1,3 +1,26 @@ +2.028014 + + [ENHANCEMENTS] + + * [#108] Port Bounce port control feature (down and up in succession) + + [BUG FIXES] + + * Missing action to netdisco-do should not throw Perl error + * Sort CDP/LLDP data to be more consistent when multiple neighbors on a port + * Add "AP" as a hint for WAP support + +2.028013 - 2014-07-31 + + [ENHANCEMENTS] + + * [#122] CDP/LLDP discovery for some HP switches (M. Kosmach) + + [BUG FIXES] + + * Fix when Interactives number set to zero + * [#121] Daemon crash when restarting with in-progress jobs and many workers + 2.028012 - 2014-07-22 [BUG FIXES] diff --git a/Netdisco/META.yml b/Netdisco/META.yml index fe65e38b..6d596879 100644 --- a/Netdisco/META.yml +++ b/Netdisco/META.yml @@ -81,4 +81,4 @@ resources: homepage: http://netdisco.org/ license: http://opensource.org/licenses/bsd-license.php repository: git://git.code.sf.net/p/netdisco/netdisco-ng -version: 2.028012 +version: 2.028013 diff --git a/Netdisco/bin/netdisco-daemon-fg b/Netdisco/bin/netdisco-daemon-fg index 6e2cbe49..69a73c39 100755 --- a/Netdisco/bin/netdisco-daemon-fg +++ b/Netdisco/bin/netdisco-daemon-fg @@ -41,7 +41,7 @@ my $mce = MCE->new( job_delay => 1.15, tmp_dir => $tmp_dir, user_func => sub { $_[0]->worker_body }, - on_post_exit => \&restart_worker, + on_post_exit => \&restart_this_worker, user_tasks => build_tasks_list(), )->run(); @@ -100,7 +100,7 @@ sub worker_factory { }; } -sub restart_worker { +sub restart_this_worker { my ($self, $e) = @_; reset_jobs($e->{wid}); diff --git a/Netdisco/bin/netdisco-do b/Netdisco/bin/netdisco-do index 58bd329b..7d6457b9 100755 --- a/Netdisco/bin/netdisco-do +++ b/Netdisco/bin/netdisco-do @@ -65,7 +65,7 @@ schema('daemon')->deploy; # get requested action my $action = shift @ARGV; -if (!length $action) { +unless ($action) { error 'error: missing action!'; exit (1); } diff --git a/Netdisco/lib/App/Netdisco.pm b/Netdisco/lib/App/Netdisco.pm index ad363d37..305353d3 100644 --- a/Netdisco/lib/App/Netdisco.pm +++ b/Netdisco/lib/App/Netdisco.pm @@ -4,7 +4,7 @@ use strict; use warnings; use 5.010_000; -our $VERSION = '2.028012'; +our $VERSION = '2.028013'; use App::Netdisco::Configuration; use Module::Find (); diff --git a/Netdisco/lib/App/Netdisco/Configuration.pm b/Netdisco/lib/App/Netdisco/Configuration.pm index 2dc444bc..91bec56c 100644 --- a/Netdisco/lib/App/Netdisco/Configuration.pm +++ b/Netdisco/lib/App/Netdisco/Configuration.pm @@ -43,7 +43,8 @@ setting('plugins')->{DBIC}->{daemon} = { # defaults for workers setting('workers')->{queue} ||= 'PostgreSQL'; -setting('workers')->{interactives} ||= 1; +setting('workers')->{interactives} = 1 + if setting('workers') and not exists setting('workers')->{interactives}; # force skipped DNS resolution, if unset setting('dns')->{hosts_file} ||= '/etc/hosts'; diff --git a/Netdisco/lib/App/Netdisco/Core/Discover.pm b/Netdisco/lib/App/Netdisco/Core/Discover.pm index dbacbbdd..779b92a2 100644 --- a/Netdisco/lib/App/Netdisco/Core/Discover.pm +++ b/Netdisco/lib/App/Netdisco/Core/Discover.pm @@ -666,7 +666,7 @@ sub store_neighbors { my $c_platform = $snmp->c_platform; my $c_cap = $snmp->c_cap; - foreach my $entry (List::MoreUtils::uniq( (keys %$c_ip), (keys %$c_cap) )) { + foreach my $entry (sort (List::MoreUtils::uniq( (keys %$c_ip), (keys %$c_cap) ))) { if (!defined $c_if->{$entry} or !defined $interfaces->{ $c_if->{$entry} }) { debug sprintf ' [%s] neigh - port for IID:%s not resolved, skipping', $device->ip, $entry; @@ -695,11 +695,11 @@ sub store_neighbors { my $phone_flag = grep {/phone/i} @$remote_cap; my $ap_flag = grep {/wlanAccessPoint/} @$remote_cap; - if ($phone_flag or $remote_type =~ m/(mitel.5\d{3})/i) { + if ($phone_flag or $remote_type =~ m/mitel.5\d{3}/i) { $remote_type = 'IP Phone: '. $remote_type if $remote_type !~ /ip phone/i; } - elsif ($ap_flag) { + elsif ($ap_flag or $remote_type =~ m/\bw?ap\b/i) { $remote_type = 'AP: '. $remote_type; } @@ -730,7 +730,22 @@ sub store_neighbors { if (!defined $neigh) { my $mac = Net::MAC->new(mac => $remote_id, 'die' => 0, verbose => 0); if (not $mac->get_error) { - $neigh = $devices->single({mac => $remote_id}); + $neigh = $devices->single({mac => $mac->as_IEEE()}); + } + } + + # some HP switches send 127.0.0.1 as remote_ip if no ip address + # on default vlan for HP switches remote_ip looks like + # "myswitchname(012345-012345)" + if (!defined $neigh) { + (my $tmpid = $remote_id) =~ s/.([0-9a-f]{6})-([0-9a-f]{6})./$1$2/; + my $mac = Net::MAC->new(mac => $tmpid, 'die' => 0, verbose => 0); + + if (not $mac->get_error) { + info sprintf + '[%s] neigh - found neighbor %s by MAC %s', + $device->ip, $remote_id, $mac->as_IEEE(); + $neigh = $devices->single({mac => $mac->as_IEEE()}); } } diff --git a/Netdisco/lib/App/Netdisco/Daemon/LocalQueue.pm b/Netdisco/lib/App/Netdisco/Daemon/LocalQueue.pm index 13834a3f..b3dbcb9a 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/LocalQueue.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/LocalQueue.pm @@ -5,7 +5,7 @@ use Dancer::Plugin::DBIC 'schema'; use base 'Exporter'; our @EXPORT = (); -our @EXPORT_OK = qw/ add_jobs capacity_for take_jobs reset_jobs/; +our @EXPORT_OK = qw/ add_jobs capacity_for take_jobs reset_jobs release_jobs /; our %EXPORT_TAGS = ( all => \@EXPORT_OK ); schema('daemon')->deploy; @@ -59,4 +59,11 @@ sub reset_jobs { ->update({wid => 0}); } +# not used by workers, only the daemon when reinitializing a worker +sub release_jobs { + my ($jid) = @_; + debug "releasing local job ID $jid"; + $queue->search({job => $jid})->delete; +} + 1; diff --git a/Netdisco/lib/App/Netdisco/Daemon/Worker/Interactive/PortActions.pm b/Netdisco/lib/App/Netdisco/Daemon/Worker/Interactive/PortActions.pm index 917851a1..7adf941c 100644 --- a/Netdisco/lib/App/Netdisco/Daemon/Worker/Interactive/PortActions.pm +++ b/Netdisco/lib/App/Netdisco/Daemon/Worker/Interactive/PortActions.pm @@ -27,7 +27,16 @@ sub set_portcontrol { (my $sa = $job->subaction) =~ s/-\w+//; $job->subaction($sa); - return _set_port_generic($job, 'up_admin'); + if ($sa eq 'bounce') { + $job->subaction('down'); + my @stat = _set_port_generic($job, 'up_admin'); + return @stat if $stat[0] ne 'done'; + $job->subaction('up'); + return _set_port_generic($job, 'up_admin'); + } + else { + return _set_port_generic($job, 'up_admin'); + } } sub set_vlan { diff --git a/Netdisco/lib/App/Netdisco/JobQueue/PostgreSQL.pm b/Netdisco/lib/App/Netdisco/JobQueue/PostgreSQL.pm index ffd89ef7..dc66f6af 100644 --- a/Netdisco/lib/App/Netdisco/JobQueue/PostgreSQL.pm +++ b/Netdisco/lib/App/Netdisco/JobQueue/PostgreSQL.pm @@ -143,12 +143,19 @@ sub jq_lock { return $happy; } +# PostgreSQL engine depends on LocalQueue, which is accessed synchronously via +# the main daemon process. This is only used by daemon workers which can use +# MCE ->do() method. sub jq_defer { my $job = shift; my $happy = false; - # lock db row and update to show job is available try { + # other local workers are polling the central queue, so + # to prevent a race, first delete the job in our local queue + MCE->do('release_jobs', $job->id); + + # lock db row and update to show job is available schema('netdisco')->txn_do(sub { schema('netdisco')->resultset('Admin') ->find($job->id, {for => 'update'}) diff --git a/Netdisco/share/public/javascripts/netdisco_portcontrol.js b/Netdisco/share/public/javascripts/netdisco_portcontrol.js index add009c8..8d210caf 100644 --- a/Netdisco/share/public/javascripts/netdisco_portcontrol.js +++ b/Netdisco/share/public/javascripts/netdisco_portcontrol.js @@ -22,7 +22,7 @@ function port_control (e) { device: td.data('for-device') ,port: td.data('for-port') ,field: td.data('field') - ,action: td.data('action') + ,action: ($(e).data('action') || td.data('action')) ,value: td.text().trim() ,reason: reason ,log: logmessage @@ -30,31 +30,35 @@ function port_control (e) { ,success: function() { toastr.info('Submitted change request'); - // update all the screen furniture for port up/down control - if ($.trim(td.data('action')) == 'down') { - td.prev('td').html(''); - $(e).toggleClass('icon-hand-down'); - $(e).toggleClass('icon-hand-up'); - $(e).data('tooltip').options.title = 'Click to Enable'; - td.data('action', 'up'); - } - else if ($.trim(td.data('action')) == 'up') { - td.prev('td').html(''); - $(e).toggleClass('icon-hand-up'); - $(e).toggleClass('icon-hand-down'); - $(e).data('tooltip').options.title = 'Click to Disable'; - td.data('action', 'down'); - } - else if ($.trim(td.data('action')) == 'false') { - $(e).next('span').text(''); - $(e).toggleClass('nd_power-on'); - $(e).data('tooltip').options.title = 'Click to Enable'; - td.data('action', 'true'); - } - else if ($.trim(td.data('action')) == 'true') { - $(e).toggleClass('nd_power-on'); - $(e).data('tooltip').options.title = 'Click to Disable'; - td.data('action', 'false'); + // update all the screen furniture unless bouncing + if (! $(e).hasClass('icon-bullseye')) { + if ($.trim(td.data('action')) == 'down') { + td.prev('td').html(''); + $(e).toggleClass('icon-hand-down'); + $(e).toggleClass('icon-hand-up'); + $(e).siblings('.icon-bullseye').hide(); + $(e).data('tooltip').options.title = 'Enable Port'; + td.data('action', 'up'); + } + else if ($.trim(td.data('action')) == 'up') { + td.prev('td').html(''); + $(e).toggleClass('icon-hand-up'); + $(e).toggleClass('icon-hand-down'); + $(e).siblings('.icon-bullseye').show(); + $(e).data('tooltip').options.title = 'Disable Port'; + td.data('action', 'down'); + } + else if ($.trim(td.data('action')) == 'false') { + $(e).next('span').text(''); + $(e).toggleClass('nd_power-on'); + $(e).data('tooltip').options.title = 'Enable Power'; + td.data('action', 'true'); + } + else if ($.trim(td.data('action')) == 'true') { + $(e).toggleClass('nd_power-on'); + $(e).data('tooltip').options.title = 'Disable Power'; + td.data('action', 'false'); + } } } ,error: function() { @@ -118,7 +122,7 @@ $(document).ready(function() { }); // activity for port up/down control, power enable/disable control - $('#ports_pane').on('click', '.icon-hand-up,.icon-hand-down,.nd_pointer-icon', function() { + $('#ports_pane').on('click', '.icon-hand-up,.icon-hand-down,.nd_pointer-icon,.icon-bullseye', function() { var clicked = this; // create a closure $('#nd_portlog').one('hidden', function() { port_control(clicked); // save diff --git a/Netdisco/share/views/ajax/device/ports.tt b/Netdisco/share/views/ajax/device/ports.tt index d321ac1a..b57c2d48 100644 --- a/Netdisco/share/views/ajax/device/ports.tt +++ b/Netdisco/share/views/ajax/device/ports.tt @@ -62,16 +62,26 @@