1#!/usr/bin/env perl 2 3use strict; 4use warnings; 5 6our $home; 7 8BEGIN { 9 use FindBin; 10 FindBin::again(); 11 12 $home = ($ENV{NETDISCO_HOME} || $ENV{HOME}); 13 14 # try to find a localenv if one isn't already in place. 15 if (!exists $ENV{PERL_LOCAL_LIB_ROOT}) { 16 use File::Spec; 17 my $localenv = File::Spec->catfile($FindBin::RealBin, 'localenv'); 18 exec($localenv, $0, @ARGV) if -f $localenv; 19 $localenv = File::Spec->catfile($home, 'perl5', 'bin', 'localenv'); 20 exec($localenv, $0, @ARGV) if -f $localenv; 21 22 die "Sorry, can't find libs required for App::Netdisco.\n" 23 if !exists $ENV{PERLBREW_PERL}; 24 } 25} 26 27BEGIN { 28 use Path::Class; 29 30 # stuff useful locations into @INC and $PATH 31 unshift @INC, 32 dir($FindBin::RealBin)->parent->subdir('lib')->stringify, 33 dir($FindBin::RealBin, 'lib')->stringify; 34 35 use Config; 36 $ENV{PATH} = $FindBin::RealBin . $Config{path_sep} . $ENV{PATH}; 37} 38 39use App::Netdisco; 40use Dancer ':script'; 41use Dancer::Plugin::DBIC 'schema'; 42 43use App::Netdisco::Util::Permission ':all'; 44 45# silent exit unless explicitly requested 46exit(0) unless setting('use_legacy_rancidexport'); 47 48my $settings = setting( 'rancid' ); 49my $domain_suffix = setting( 'domain_suffix' ); 50my $delimiter = $settings->{ 'delimiter' } || ':'; 51my $down_age = $settings->{ 'down_age' } || '1 day'; 52my $rancidhome = $settings->{ 'rancid_home' } || '/var/lib/rancid'; 53my $config_vendormap = $settings->{ 'vendormap' } || {}; 54 55my $by_ip = {}; 56foreach my $g (@{$settings->{ 'by_ip' }}) { 57 $by_ip->{$g} = 1; 58} 59 60my $by_hostname = {}; 61foreach my $g (@{$settings->{ 'by_hostname' }}) { 62 $by_hostname->{$g} = 1; 63} 64 65my @devices = schema('netdisco')->resultset('Device')->search({}, 66 { 67 '+columns' => { 68 old => \"age(now(), last_discover) > interval '$down_age'" 69 } 70 })->all; 71 72my $groups = $settings->{ 'groups' }; 73my $list = {}; 74 75foreach my $d (@devices) { 76 my $old = $d->get_column( 'old' ); 77 my $devgroup = 'other'; 78 foreach my $g (keys %$groups) { 79 if (check_acl_only( $d, $groups->{$g} )) { 80 $devgroup = $g; 81 last; 82 } 83 } 84 push(@{$list->{$devgroup}}, $d); 85} 86 87my %VENDORMAP = ( 88# If netdisco vendor name and rancid vendor name 89# do not map 1:1, map it here. 90# eg: 91# 'dell:2024' => 'dellnseries', 92# 'dell:3024' => 'dellnseries' 93); 94 95foreach my $group (keys %$list) { 96 open(ROUTER, ">${rancidhome}/${group}/router.db") || die "${rancidhome}/${group}/router.db: $!\n"; 97 foreach my $dev (sort {$a->ip cmp $b->ip} @{$list->{$group}}) { 98 my $vendor = $dev->vendor; 99 my $vendormodel = join(':',$dev->vendor,$dev->model); 100 my $name; 101 if ( $VENDORMAP{$vendor} or $VENDORMAP{$vendormodel} ) { 102 $vendor = $VENDORMAP{$vendormodel} || $VENDORMAP{$vendor}; 103 } 104 if ( $config_vendormap->{$vendor} or $config_vendormap->{$vendormodel} ) { 105 $vendor = $config_vendormap->{$vendormodel} || $config_vendormap->{$vendor}; 106 } 107 if ($by_ip->{$group}) { 108 $name = $dev->ip; 109 } else { 110 $name = ($dev->dns || $dev->name); 111 } 112 if ($by_hostname->{$group}) { 113 $name =~ s/$domain_suffix//; 114 } 115 printf ROUTER "%s$delimiter%s$delimiter%s\n", $name, $vendor, 116 $dev->get_column( 'old' ) ? "down" : "up"; 117 } 118 close(ROUTER); 119} 120 121=head1 NAME 122 123netdisco-rancid-export - DEPRECATED! 124 125=head1 DEPRECATED! 126 127Note! This script is now deprecated and no longer maintained. The replacement 128is built in to Netdisco core, so can be scheduled in the backend, and also has 129more powerful configuration. See 130L<App::Netdisco::Worker::Plugin::MakeRancidConf>. 131 132=head1 CONFIGURATION 133 134This script requires some configuration to be added to your Netdisco 135"C<~/environments/deployment.yml>" file, for example: 136 137 rancid: 138 rancid_home: /var/lib/rancid 139 down_age: '1 day' 140 delimiter: ':' 141 by_ip: [ other ] 142 by_hostname: [ other2 ] 143 groups: 144 switch: [ 'name:.*[Ss][Ww].*' ] 145 rtr: [ 'name:[rR]tr.*' ] 146 ap: [ 'name:[aA][pP].*' ] 147 vendormap: 148 "dell": force10 149 "dell:2024": dellnseries 150 151Note that C<netdisco-rancid-export> is not part of the automatic scheduler 152built in to Netdisco. You should run this script via C<cron> just after your 153periodic C<discoverall>. 154 155=head2 C<rancid_home> 156 157The location to write RANCID Group configuration files into. A subdirectory 158for each Group will be created. 159 160Default: "C</var/lib/rancid>". 161 162=head2 C<down_age> 163 164This should be the same or greater than the interval between regular discover 165jobs on your network. Devices which have not been discovered within this time 166will be marked as "C<down>" to RANCID. 167 168Default: "C<1 day>". 169 170=head2 C<delimiter> 171 172RANCID version 3 uses a semicolon as delimiter. Set this to the delimiter 173character if needed to be different from the default. 174 175Default: "C<:>". 176 177=head2 C<vendormap> 178 179If the device Vendor in Netdisco is not the same as the RANCID vendor script, 180configure a mapping here. The left hand side (key) should be the Netdisco 181vendor, the right hand side (value) should be the RANCID vendor script name. 182You can also set the Netdisco vendor to be "C<vendor:model>" for fine-grained 183control. See the synopsis for an example. 184 185=head2 C<groups> 186 187This dictionary maps RANCID Group names with configuration which will match 188devices in the Netdisco database. The configuration is the same as any of 189Netdisco's "C<*_only>" settings, and accepts IP, prefix, device property. 190 191=head2 C<by_ip> 192 193List of RANCID Groups which will have Device IPs written to the RANCID 194configuration file, instead of DNS or SNMP host names. 195 196=head2 C<by_hostname> 197 198List of RANCID Groups which will have Device Hostname written to the RANCID 199configuration file, instead of FQDN. This is done simply by stripping the 200C<domain_suffix> configuration item from the FQDN. 201 202=head1 SEE ALSO 203 204=over 4 205 206=item * 207 208L<App::Netdisco> 209 210=back 211 212=cut 213