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:
		| @@ -206,6 +206,7 @@ sub store_interfaces { | ||||
|   my $i_stp_state    = $snmp->i_stp_state; | ||||
|   my $i_vlan         = $snmp->i_vlan; | ||||
|   my $i_lastchange   = $snmp->i_lastchange; | ||||
|   my $agg_ports      = $snmp->agg_ports; | ||||
|  | ||||
|   # clear the cached uptime and get a new one | ||||
|   my $dev_uptime = $snmp->load_uptime; | ||||
| @@ -278,10 +279,22 @@ sub store_interfaces { | ||||
|           type         => $i_type->{$entry}, | ||||
|           vlan         => $i_vlan->{$entry}, | ||||
|           pvid         => $i_vlan->{$entry}, | ||||
|           is_master    => 'false', | ||||
|           slave_of     => undef, | ||||
|           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 { | ||||
|     my $gone = $device->ports->delete({keep_nodes => 1}); | ||||
|     debug sprintf ' [%s] interfaces - removed %d interfaces', | ||||
| @@ -695,18 +708,19 @@ sub store_neighbors { | ||||
|  | ||||
|       # IP Phone and WAP detection type fixup | ||||
|       if (defined $remote_type) { | ||||
|         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) { | ||||
|           $remote_type = 'IP Phone: '. $remote_type | ||||
|             if $remote_type !~ /ip phone/i; | ||||
|         } | ||||
|         elsif ($ap_flag) { | ||||
|           $remote_type = 'AP: '. $remote_type;           | ||||
|         } | ||||
|         else { | ||||
|           $remote_type ||= ''; | ||||
|         } | ||||
|           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) { | ||||
|               $remote_type = 'IP Phone: '. $remote_type | ||||
|               if $remote_type !~ /ip phone/i; | ||||
|           } | ||||
|           elsif ($ap_flag) { | ||||
|               $remote_type = 'AP: '. $remote_type; | ||||
|           } | ||||
|           else { | ||||
|               $remote_type ||= ''; | ||||
|           } | ||||
|       } | ||||
|  | ||||
|       # hack for devices seeing multiple neighbors on the port | ||||
| @@ -719,7 +733,7 @@ sub store_neighbors { | ||||
|               foreach my $n (@$remote_ip) { | ||||
|                   debug sprintf | ||||
|                     ' [%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]; | ||||
|               } | ||||
|           } | ||||
| @@ -733,7 +747,7 @@ sub store_neighbors { | ||||
|           if (wantarray) { | ||||
|               debug sprintf | ||||
|                 ' [%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]; | ||||
|           } | ||||
|  | ||||
| @@ -773,6 +787,26 @@ sub store_neighbors { | ||||
|           is_uplink   => \"true", | ||||
|           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; | ||||
| @@ -860,7 +894,7 @@ sub discover_new_neighbors { | ||||
|       if (not is_discoverable($device, $remote_type)) { | ||||
|           debug sprintf | ||||
|             ' queue - %s, type [%s] excluded by discover_* config', | ||||
|             $ip, $remote_type; | ||||
|             $ip, ($remote_type || ''); | ||||
|           next; | ||||
|       } | ||||
|  | ||||
|   | ||||
| @@ -57,8 +57,8 @@ sub do_macsuck { | ||||
|   my $ip = $device->ip; | ||||
|  | ||||
|   # 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 | ||||
|   # select and do something with the updated set (no reason to yet, though) | ||||
|   # 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 (see set archive, below) | ||||
|   my $now = 'to_timestamp('. (join '.', gettimeofday) .')'; | ||||
|   my $total_nodes = 0; | ||||
|  | ||||
| @@ -98,8 +98,10 @@ sub do_macsuck { | ||||
|           debug sprintf ' [%s] macsuck - port %s vlan %s : %s nodes', | ||||
|             $ip, $port, $vlan, scalar keys %{ $fwtable->{$vlan}->{$port} }; | ||||
|  | ||||
|           # make sure this port is UP in netdisco | ||||
|           $device_ports->{$port}->update({up_admin => 'up', up => 'up'}); | ||||
|           # make sure this port is UP in netdisco (unless it's a lag master, | ||||
|           # 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} }) { | ||||
|  | ||||
| @@ -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; | ||||
|  | ||||
|   # 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}); | ||||
| } | ||||
|  | ||||
| @@ -324,14 +336,6 @@ sub _walk_fwtable { | ||||
|           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 | ||||
|       my $device_port = $device_ports->{$port}; | ||||
|  | ||||
| @@ -389,8 +393,14 @@ sub _walk_fwtable { | ||||
|           next unless setting('macsuck_bleed'); | ||||
|       } | ||||
|  | ||||
|       # 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}; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ __PACKAGE__->load_namespaces( | ||||
|     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 File::Basename; | ||||
|   | ||||
| @@ -53,6 +53,10 @@ __PACKAGE__->add_columns( | ||||
|   { data_type => "text", is_nullable => 1 }, | ||||
|   "remote_id", | ||||
|   { 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", | ||||
|   { data_type => "bool", is_nullable => 0, default_value => \"false" }, | ||||
|   "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 | ||||
|  | ||||
| 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 | ||||
|  | ||||
| =head2 | ||||
| =head2 neighbor | ||||
|  | ||||
| Returns the Device entry for the neighbour Device on the given port. | ||||
|  | ||||
|   | ||||
| @@ -64,9 +64,9 @@ sub with_is_free { | ||||
|     ->search({}, | ||||
|       { | ||||
|         '+columns' => { is_free => | ||||
|           \["up != 'up' and " | ||||
|           \["me.up != 'up' and " | ||||
|               ."age(now(), to_timestamp(extract(epoch from device.last_discover) " | ||||
|                 ."- (device.uptime - lastchange)/100)) " | ||||
|                 ."- (device.uptime - me.lastchange)/100)) " | ||||
|               ."> ?::interval", | ||||
|             [{} => $interval]] }, | ||||
|         join => 'device', | ||||
| @@ -93,11 +93,11 @@ sub only_free_ports { | ||||
|     ->search_rs($cond, $attrs) | ||||
|     ->search( | ||||
|       { | ||||
|         'up' => { '!=' => 'up' }, | ||||
|         'me.up' => { '!=' => 'up' }, | ||||
|       },{ | ||||
|         where => | ||||
|           \["age(now(), to_timestamp(extract(epoch from device.last_discover) " | ||||
|                 ."- (device.uptime - lastchange)/100)) " | ||||
|                 ."- (device.uptime - me.lastchange)/100)) " | ||||
|               ."> ?::interval", | ||||
|             [{} => $interval]], | ||||
|       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 | ||||
|                 $set->search({'me.port' => $f})->count) { | ||||
|  | ||||
|                 $set = $set->search({'me.port' => $f}); | ||||
|                 $set = $set->search({ | ||||
|                   -or => [ | ||||
|                     'me.port' => $f, | ||||
|                     'me.slave_of' => $f, | ||||
|                   ], | ||||
|                 }); | ||||
|             } | ||||
|             else { | ||||
|                 $set = $set->search({'me.name' => $f}); | ||||
| @@ -108,6 +113,13 @@ get '/ajax/content/device/ports' => require_login sub { | ||||
|         $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 | ||||
|     $set = $set->with_times if param('c_lastchange'); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user