diff options
Diffstat (limited to 'dlink-ng')
-rwxr-xr-x | dlink-ng/dlink-ng-config.pm.dist | 169 | ||||
-rwxr-xr-x | dlink-ng/dlink-ng.pl | 1242 | ||||
-rwxr-xr-x | dlink-ng/make-dlink-config.pl | 71 |
3 files changed, 0 insertions, 1482 deletions
diff --git a/dlink-ng/dlink-ng-config.pm.dist b/dlink-ng/dlink-ng-config.pm.dist deleted file mode 100755 index 82abbf6..0000000 --- a/dlink-ng/dlink-ng-config.pm.dist +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -no warnings 'closure'; # remove "Variable $foo will not stay shared" :-D -package dlinkng::config; - -# Common config -our $domain_name = ".net.party.bylan.net"; # DNS-name to append to hostnames (overriden later on for TG-mode) -our $dlink_def_user = "admin"; # Default user for a factory-default D-Link -our $dlink_def_ip = "10.90.90.90"; # IP for a factory-default D-Link -our $dlink_def_mask = "255.255.255.0"; # Mask for a factory-default D-Link -our $dlink_router_ip = "10.90.90.91"; # IP to use on the router/core -our $dlink_prefix = "30"; # Prefix to use when setting D-Link IP -our $dhcp4_proxyprofile = "DHCPv4Proxy"; # DHCPv4 proxy profile to use on IOS-XR -our $dhcp6_proxyprofile = "DHCPv6Proxy"; # DHCPv6 proxy profile to use on IOS-XR -our $vrf_prefix = "dlink"; # What to prefix the VRF-number (Thread ID) with -our $max_threads = 1; # Max threads to use -our $dlink_host_suffix = "_DGS-3100"; # Suffix for hostname on the D-Link switches (needed by NMS) -our $default_coreswos = "ios"; # Default OS on coresw -our $dlink_lacp_start = '45'; # First port for LACP-group on D-Links -our $dlink_lacp_end = '48'; # Last port for LACP-group on D-Links -our $configure_last_port = 0; # Configure last port differently than the rest -our $last_port_regex = '^e([1-8][1-9]|[2-8][0-9])-'; # Regex to use in combination with $configure_last_port -our $use_ssh_cisco = 0; # Use SSH towards Cisco-boxes -our $use_ssh_dlink = 0; # Use SSH towards D-Link switches -our $cdp_enable = 0; # Enable or disable CDP on each port -our $save_config = 1; # Save configuration to Cisco switch -our $access_vlan = '3602'; # VLAN to use for last port - -# Specific config -- just declare empty -our $cisco_user = ""; # Username used when logging into the swithces -our $cisco_pass = ""; # Password used when logging into the switches -our $dhcprelay4_pri = ""; # Primary ip helper-address / ip dhcp relay address -our $dhcprelay4_sec = ""; # Secondary ip helper-address / ip dhcp relay address -our $dhcprelay6_pri = ""; # Primary ipv6 dhcp relay -our $dhcprelay6_sec = ""; # Secondary ipv6 dhcp relay -our $log_dir = ""; # Path to logfiles - -# Placeholders, setting them after all config loaded -our ($po_config, $last_port_config, $os_regex, $os_info); - -# Set variables that relies on all config being loaded -sub set_variables{ - # Custom Portchannel-config - $po_config = { - ios => [ - "ip directed-broadcast 2699", - "ip pim sparse-mode", - "ip pim bsr-border", - "logging event link-status", - "ipv6 nd other-config-flag", - "ipv6 dhcp server sexdhcp", - ], - nx => [ - "", - ], - xr => [ - "logging events link-status", - "ipv4 directed-broadcast", - "ipv6 nd prefix default 300 300 no-autoconfig", - "ipv6 nd other-config-flag", - "ipv6 nd managed-config-flag", - ], - }; - - # Custom last port config - $last_port_config = { - ios => [ - "logging event link-status", - "switchport mode access", - "switchport access vlan $access_vlan", - "spanning-tree bpduguard enable", - ], - nx => [ - "", - ], - xr => [ - "", - ], - }; - - # Define what OS-version a coresw runs - # NX, XR, XE, etc - # The regex is matched against $coreswip - $os_regex = { - ios => 'iosbox', - nx => 'flexusnexus', - xr => 'c01', - }; - - # Configure settings for each OS - $os_info = { - ios => { - max_sessions => 10, - }, - nx => { - # define 64 sessions on nxos - # nx-os# conf t - # nx-os(config)# feature dhcp - # nx-os(config)# line vty - # nx-os(config-line)# session-limit 64 - max_sessions => 50, - }, - xr => { - # telnet vrf default ipv4 server max-servers 100 access-list MGNTv4 - # telnet vrf default ipv6 server max-servers 100 access-list MGNTv6 - max_sessions => 50, - }, - }; -} - -# Load ByLAN related configuration -sub load_bylan_config{ - # Define bylan-dir, and add it to %INC - my $bylan_dir; - BEGIN { - use FindBin; - $bylan_dir = "$FindBin::Bin"; # Assume working-folder is the path where this script resides - } - use lib $bylan_dir; - eval "use bylan"; - use Getopt::Long; - - # Load config - my $config_file = "$bylan_dir/bylan.conf"; - my $conf = Config::General->new( - -ConfigFile => $config_file, - -InterPolateVars => 1); - my %config = $conf->getall; - - # Options - $cisco_user = "$config{switches}->{user}"; # Username used when logging into the swithces - $cisco_pass = "$config{switches}->{pw}"; # Password used when logging into the switches - $dhcprelay4_pri = "$config{servers}->{dhcp1_ipv4}"; # Primary ip helper-address / ip dhcp relay address - $dhcprelay4_sec = "$config{servers}->{dhcp2_ipv4}"; # Secondary ip helper-address / ip dhcp relay address - $dhcprelay6_pri = "$config{servers}->{dhcp1_ipv6}"; # Primary ipv6 dhcp relay - $dhcprelay6_sec = "$config{servers}->{dhcp2_ipv6}"; # Secondary ipv6 dhcp relay - $log_dir = "$bylan_dir/logs/telnet"; # Path to logfiles -} - -# Load TG related configuration -sub load_tg_config{ - my $tg_dir; - BEGIN { - $tg_dir = '/root/tgmanage'; - require "$tg_dir/include/config.pm"; - eval { - require "$tg_dir/include/config.local.pm"; - }; - } - - # Options - $cisco_user = "$nms::config::ios_user"; # Username used when logging into the swithces - $cisco_pass = "$nms::config::ios_pass"; # Password used when logging into the switches - $domain_name = ".infra.$nms::config::tgname.gathering.org"; # DNS-name to append to hostnames - $dhcprelay4_pri = "$nms::config::dhcp_server1"; # Primary ip helper-address / ip dhcp relay address - $dhcprelay4_sec = "$nms::config::dhcp_server2"; # Secondary ip helper-address / ip dhcp relay address - $log_dir = "$tg_dir/dlink-ng/log"; # Path to logfiles -} - -# Uncomment the one you want -#load_bylan_config(); -#load_tg_config(); - -# Set last variables that depend on the config above being set -set_variables(); - - -1; diff --git a/dlink-ng/dlink-ng.pl b/dlink-ng/dlink-ng.pl deleted file mode 100755 index 5d9efa0..0000000 --- a/dlink-ng/dlink-ng.pl +++ /dev/null @@ -1,1242 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use Net::Telnet::Cisco; -use Net::Ping; -use Term::ANSIColor; -use threads; -use threads::shared; -use Thread::Queue; -use Getopt::Long; -use Net::IP; -use Net::OpenSSH; -BEGIN { - use File::Basename; - my $dlink_dir = dirname(__FILE__); - require "$dlink_dir/dlink-ng-config.pm"; -} - -# Make sure dlinkconfig.pm loads config (i.e. one config type has been uncommented) -die("No config type specified. Uncomment the wanted subroutine in the config file.\n") unless ($dlinkng::config::cisco_user); - -# Stuff -my $switchq = Thread::Queue->new(); # Queue to put switches in -my $switches : shared = 0; # Number of successful switches -my $failed_switches : shared = 0; # Number of failed switches -my $total_time : shared = 0; # Total time spent for all switches -my %telnet_sessions : shared; # Number of sessions currently in use -my $DLINK_TEMPLATE; # Filehandle used for reading D-Link template - -# Autoflush -$| = 1; - -# Get options -my ($cisco_config, $single_switch, $dlink_config, $last_port_config, $last_port_desc); -if (@ARGV > 0) { - GetOptions( - 'c|cisco|ciscoconfig' => \$cisco_config, # Configure on the Cisco-side only (Portchannel, interfaces, etc) - 's|switch=s' => \$single_switch, # Configure a single switch - 'd|dlink|dlinkconfig=s' => \$dlink_config, # Push D-Link-template-config to D-Link (not used @ TG) - 'lastport' => \$last_port_config, # Configure the last port only (Cisco-side) - 'lastportdesc' => \$last_port_desc, # Configure the description on the last port (Cisco-side) - ) -} - -# Exit if D-Link template file doesn't exist -if ($dlink_config){ - unless(-e $dlink_config){ - die("File '$dlink_config' does not exists. Aborting.\n"); - } -} - -# Exit if $cisco_config and $last_port_config or $last_port_desc is set -if ($cisco_config && ($last_port_config || $last_port_desc)){ - die("\$cisco_config and \$last_port_config (or \$last_port_desc) can't be used together.\n"); -} - -# If $last_port_desc, assume $last_port_config -if ($last_port_desc){ - $last_port_config = 1; -} - -# Exit if we give $last_port_config or $last_port_desc parameters, but $configure_last_port is not set -if ($last_port_config || $last_port_desc){ - unless($dlinkng::config::configure_last_port){ - die("\$configure_last_port not set, but expected due to either \$last_port_config or \$last_port_desc.\n"); - } -} - -# Print stuff -sub log_it{ - my ($logtype, $color, $switchname, $msg) = @_; - printf ("%-38s %s\n", colored("$logtype", "$color") . "/" . colored("$switchname", "bold") . ":", "$msg"); -} - -# INFO-logs -sub info{ - my ($switchname, $msg) = @_; - log_it("INFO", "blue", $switchname, $msg); - return 1; -} - -# ERROR-logs -sub error{ - my ($switchname, $msg) = @_; - printf ("%-38s %s\n", colored("ERROR", "red") . "/" . colored("$switchname", "bold") . ":", "$msg"); - return 0; -} - -# Debug from Net::Telnet::Cisco and similar -sub debug{ - my ($switchname, $errmsg) = @_; - - if ($errmsg){ - foreach my $line (split('\\n', $errmsg)){ - error($switchname, $line); - } - } -} - -# Abort -sub abort{ - my ($switchname, $t1, $t2) = @_; - - $t1->close if defined($t1); - $t2->close if defined($t2); - - return error($switchname, "Aborting."); -} - -# Set coreswos -sub set_coreswos{ - my $coreswip = shift; - - my $os = $dlinkng::config::default_coreswos; - - foreach my $swos ( sort keys %$dlinkng::config::os_regex ){ - $os = $swos if ($coreswip =~ m/$dlinkng::config::os_regex->{$swos}/); - } - - return $os; -} - -# Is normal IOS? -sub is_ios{ - my $coreswos = shift; - return 1 if ($coreswos =~ m/^ios$/i); - return 0; -} - -# Is NX-OS? -sub is_nx{ - my $coreswos = shift; - return 1 if ($coreswos =~ m/^nx$/i); - return 0; -} - -# Is IOS-XR? -sub is_xr{ - my $coreswos = shift; - return 1 if ($coreswos =~ m/^xr$/i); - return 0; -} - -# Cisco-ping -sub cisco_ping{ - my ($cisco, $ip, $timeout, $coreswos, $vrf) = @_; - my $cmd; - - if (is_nx($coreswos)){ - $cmd = "ping $ip count 1 timeout 1"; - $cmd .= " vrf ${dlinkng::config::vrf_prefix}${vrf}" if ($vrf && defined($vrf)); - - } elsif (is_xr($coreswos)){ - # IOS-XR - $cmd = "ping"; - $cmd .= " vrf ${dlinkng::config::vrf_prefix}${vrf}" if ($vrf && defined($vrf)); - $cmd .= " $ip count 1 timeout 1"; - - } else { - # IOS - $cmd = "ping"; - $cmd .= " vrf ${dlinkng::config::vrf_prefix}${vrf}" if ($vrf && defined($vrf)); - $cmd .= " $ip repeat 1 timeout 1"; - } - - my $pong = 0; - my $tries = 0; - while (($pong == 0) && ($tries < $timeout)){ - my @res = $cisco->cmd($cmd); - - # if blank, try again - # happens at least on ME3600X - next unless @res; - - # sleep if it complains about no valid source address - # % VRF does not have a usable source address - # this is caused by no link, or network not propagated - # observed on WS-C6506-E with sup720 running 122-33.SXJ5 - sleep 1 if ("@res" =~ m/VRF does not have a usable source address/); - - if (is_nx($coreswos)){ - $pong = 1 if ($res[1] =~ m/^64 bytes from $ip/i); - } else { - $pong = 1 if ($res[-1] =~ m/^\s*Success rate is 100 percent/i); - } - $tries++; - } - return $pong; -} - -# Net::Ping-ping -sub pong{ - my ($ip, $timeout) = @_; - my $pong = 0; - my $tries = 0; - - while(($pong == 0) && ($tries < $timeout)){ - my $p = Net::Ping->new(); - - if ($p->ping($ip, 5)) { - $pong = 1; - } - - $tries++; - } - return $pong; -} - -# Create login to D-Link -sub dlink_login{ - my ($switch, $ip, $vrf, $telnet_source) = @_; - - my $dlink = Net::Telnet::Cisco->new( - Host => $switch->{coreswip} . $dlinkng::config::domain_name, - Errmode => 'return', - output_log => "$dlinkng::config::log_dir/dlink-output-$switch->{coreswip}-$switch->{switchname}.log", - input_log => "$dlinkng::config::log_dir/dlink-input-$switch->{coreswip}-$switch->{switchname}.log", - Prompt => '/\S+[#>]/', - Timeout => 60 - ); - - unless (defined($dlink)) { - return error($switch->{switchname}, "Could not connect to '$switch->{coreswip}'."); - } - - info($switch->{switchname}, "Logging in to coreswitch '$switch->{coreswip}' to telnet to D-Link."); - - unless ($dlink->login($dlinkng::config::cisco_user, $dlinkng::config::cisco_pass)){ - $dlink->close; - return error($switch->{switchname}, "Can't log in to coreswitch '$switch->{coreswip}' (to telnet to D-Link)."); - } - - # Don't do enable on IOS-XR - unless(is_xr($switch->{coreswos})){ - $dlink->enable; - debug($switch->{switchname}, $dlink->errmsg); - } - - my $cmd; - if (is_nx($switch->{coreswos})){ - # NX-OS - $cmd = "telnet $ip"; - $cmd .= " vrf ${dlinkng::config::vrf_prefix}${vrf}" if ($vrf && defined($vrf)); - $cmd .= " source $telnet_source" if ($telnet_source && defined($telnet_source)); - - } elsif (is_xr($switch->{coreswos})){ - # IOS-XR - $cmd = "telnet "; - $cmd .= "vrf ${dlinkng::config::vrf_prefix}${vrf} " if ($vrf && defined($vrf)); - $cmd .= "$ip"; - $cmd .= " source-interface $telnet_source" if ($telnet_source && defined($telnet_source)); - - } else { - # IOS - $cmd = "telnet $ip"; - $cmd .= " /vrf ${dlinkng::config::vrf_prefix}${vrf}" if ($vrf && defined($vrf)); - $cmd .= " /source-interface $telnet_source" if ($telnet_source && defined($telnet_source)); - } - - info($switch->{switchname}, "Telneting to D-Link."); - $dlink->print($cmd); - - info($switch->{switchname}, "Waiting for login prompt."); - $dlink->waitfor('/User ?Name:/') - or return abort($switch->{switchname}, $dlink); - - info($switch->{switchname}, "Got login prompt, logging in."); - telnet_print($switch, $dlink, $dlinkng::config::dlink_def_user, 0) - or return abort($switch->{switchname}, $dlink); - - info($switch->{switchname}, "Waiting for prompt."); - $dlink->waitfor('/\S+\#/') - or return abort($switch->{switchname}, $dlink); - - # disable CLI paging - telnet_print($switch, $dlink, "disable clipaging") - or return abort($switch->{switchname}, $dlink); - - info($switch->{switchname}, "Logged in to D-Link"); - return $dlink; -} - -# Execute telnet-command -sub telnet_cmd{ - my ($switch, $telnet, $cmd) = @_; - - unless ($telnet->cmd($cmd)){ - error($switch->{switchname}, "Command '$cmd' failed"); - debug($switch->{switchname}, $telnet->errmsg); - - if($cmd =~ m/commit/){ - # If commit on IOS-XR failed, print the reason - if(is_xr($switch->{coreswos})){ - # Redundant check, but whatever - my @failed = $telnet->cmd("show configuration failed"); - - if(@failed){ - foreach my $line (@failed){ - chomp($line); - error($switch->{switchname}, $line); - } - } - } - } - - return 0; - } - - return 1; -} - -# Execute telnet-print -sub telnet_print{ - my ($switch, $telnet, $cmd, $waitfor) = @_; - - unless (defined($waitfor)){ - $waitfor = 1; - } - - unless ($telnet->print($cmd)){ - error($switch->{switchname}, "Command '$cmd' failed."); - debug($switch->{switchname}, $telnet->errmsg); - return 0; - } - - if ($waitfor){ - $telnet->waitfor('/\S+\#/') or return 0; - } - - return 1; -} - -# Make sure interface actually is shut -sub no_no_shut{ - my ($switch, $cisco, $port) = @_; - - info($switch->{switchname}, "Making sure interface $port /REALLY/ gets shut."); - - # There is a few reasons as to why we want to do this. - # On some boxes/OSes, default config for an interface is 'no shut'. - # On some boxes/OSes, the 'shut' command isn't applied right away after - # you do a 'shut'. - - my $return = 0; - if(is_xr($switch->{coreswos})){ - # don't need to do any checks on XR - telnet_cmd($switch, $cisco, "shut") - or return abort($switch->{switchname}, $cisco); - - $return = 1; - } else { - # on all other OS - my $tries = 0; - - while (1){ - if($tries >= 5){ - # max 5 tries - last; - } - - sleep 1; # wait a bit - - telnet_cmd($switch, $cisco, "shut") - or return abort($switch->{switchname}, $cisco); - - # now we need to check that the 'running config' actually reflects this - - my @shut_info = $cisco->cmd("do sh run int $port | i shutdown"); - - unless(@shut_info){ - $tries++; - next; - } - - my $shut = "@shut_info"; - chomp($shut); - - if ($shut =~ m/shutdown/i){ - $return = 1; - last; - } else { - $tries++; - next; - } - } - } - - return $return; -} - -# Reset all interfaces -sub reset_interfaces{ - my ($switch, $cisco) = @_; - - # Take down interface - info($switch->{switchname}, "Resetting interfaces."); - - telnet_cmd($switch, $cisco, "conf t") - or return abort($switch->{switchname}, $cisco); - - # Remove old config/return to defaults on interfaces - # We also shut them to avoid D-Link looping - foreach my $port (@{$switch->{ports}}){ - telnet_cmd($switch, $cisco, "default int $port") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "int $port") - or return abort($switch->{switchname}, $cisco); - no_no_shut($switch, $cisco, $port) - or return abort($switch->{switchname}, $cisco); - - unless(is_xr($switch->{coreswos})){ - # only do this if not IOS-XR - telnet_cmd($switch, $cisco, "no switchport") - or return abort($switch->{switchname}, $cisco); - } - } - - # Remove portchannel - if(is_ios($switch->{coreswos})){ - # IOS fails on the next command, if the portchannel doesn't exist - # Ignore error on this command - $cisco->cmd("no int Po$switch->{etherchannel}"); - - } elsif(is_xr($switch->{coreswos})){ - # Other syntax on XR, called Bundle-Ether - telnet_cmd($switch, $cisco, "no int Bundle-Ether$switch->{etherchannel}") - or return abort($switch->{switchname}, $cisco); - - } else { - # Other OS, that doesnt fail - telnet_cmd($switch, $cisco, "no int Po$switch->{etherchannel}") - or return abort($switch->{switchname}, $cisco); - - } - - # Commit on XR - if(is_xr($switch->{coreswos})){ - telnet_cmd($switch, $cisco, "commit") - or return abort($switch->{switchname}, $cisco); - } - - telnet_cmd($switch, $cisco, "end") - or return abort($switch->{switchname}, $cisco); - - return 1; -} - -# Set up single interface -sub configure_interface{ - my ($switch, $cisco, $port, $ip, $mask, $vrf) = @_; - - # Configure port - telnet_cmd($switch, $cisco, "int $port") - or return abort($switch->{switchname}, $cisco); - - unless(is_xr($switch->{coreswos})){ - # only do this if not IOS-XR - telnet_cmd($switch, $cisco, "no switchport") - or return abort($switch->{switchname}, $cisco); - } - - # Only do VRF-config if $vrf is defined - if($vrf && defined($vrf)){ - if(is_nx($switch->{coreswos})){ - # No error-check on the next command, as NX-OS - # spits out "% Deleted all L3 config on interface Ethernet1/45" - # making Net::Telnet::Cisco think it's an error - - $cisco->cmd("vrf member ${dlinkng::config::vrf_prefix}${vrf}"); - - } elsif(is_xr($switch->{coreswos})){ - # IOS-XR - telnet_cmd($switch, $cisco, "vrf ${dlinkng::config::vrf_prefix}${vrf}") - or return abort($switch->{switchname}, $cisco); - - } else { - # IOS - telnet_cmd($switch, $cisco, "ip vrf forwarding ${dlinkng::config::vrf_prefix}${vrf}") - or return abort($switch->{switchname}, $cisco); - } - } - - # Add IP - info($switch->{switchname}, "Adding IP-address to interface."); - - if(is_xr($switch->{coreswos})){ - # IOS-XR - telnet_cmd($switch, $cisco, "ipv4 address $ip $mask") - or return abort($switch->{switchname}, $cisco); - - } else { - # All other - telnet_cmd($switch, $cisco, "ip address $ip $mask") - or return abort($switch->{switchname}, $cisco); - } - - # 'no shut'-patrol reporting in! - telnet_cmd($switch, $cisco, "no shut") - or return abort($switch->{switchname}, $cisco); - - # Commit on XR - if(is_xr($switch->{coreswos})){ - telnet_cmd($switch, $cisco, "commit") - or return abort($switch->{switchname}, $cisco); - } - - telnet_cmd($switch, $cisco, "end") - or return abort($switch->{switchname}, $cisco); - - return 1; -} - -# Push D-Link template config to a D-Link -sub push_dlink_template_config{ - my $switch = shift; # switchinfo - - # No need to bounce via Cisco-box; login directly to D-Link - my $dlink = Net::Telnet::Cisco->new( - Host => $switch->{ipv4address}, - Errmode => 'return', - output_log => "$dlinkng::config::log_dir/dlink-output-$switch->{coreswip}-$switch->{switchname}.log", - input_log => "$dlinkng::config::log_dir/dlink-input-$switch->{coreswip}-$switch->{switchname}.log", - Prompt => '/\S+[#>]/', - Timeout => 60 - ); - - unless (defined($dlink)) { - return error($switch->{switchname}, "Could not connect to '$switch->{switchname}' ($switch->{ipv4})."); - } - - info($switch->{switchname}, "Logging in to D-Link '$switch->{switchname}' ($switch->{ipv4address})."); - $dlink->waitfor('/User ?Name:/') - or return abort($switch->{switchname}, $dlink); - - info($switch->{switchname}, "Got login prompt, logging in."); - telnet_print($switch, $dlink, $dlinkng::config::dlink_def_user, 0) - or return abort($switch->{switchname}, $dlink); - - info($switch->{switchname}, "Waiting for prompt."); - $dlink->waitfor('/\S+\#/') - or return abort($switch->{switchname}, $dlink); - - # disable CLI paging - telnet_print($switch, $dlink, "disable clipaging") - or return abort($switch->{switchname}, $dlink); - - info($switch->{switchname}, "Logged in to D-Link"); - - # Done logging in, let's configure stuff - info($switch->{switchname}, "Opening D-Link template file ($dlink_config)."); - open $DLINK_TEMPLATE, '<', $dlink_config or return error($switch->{switchname}, "Couldn't open D-Link template ($dlink_config): $!"); - - info($switch->{switchname}, "Applying config from D-Link template file ($dlink_config)."); - - while (my $line=<$DLINK_TEMPLATE>) { - chomp $line; - - next if ($line =~ m/^\s*(((#|\!).*)|$)/); # skip if comment, or blank line - - telnet_print($switch, $dlink, $line) - or return abort($switch->{switchname}, $dlink); - - sleep 1; # The D-Link's are a bit slow... - } - - close $DLINK_TEMPLATE or return error($switch->{switchname}, "Couldn't close D-Link template ($dlink_config): $!"); - - info($switch->{switchname}, "Done applying config from D-Link template file ($dlink_config). Saving..."); - - # Save config + logout - telnet_print($switch, $dlink, "save", 0) - or return abort($switch->{switchname}, $dlink); - telnet_print($switch, $dlink, "Y") - or return abort($switch->{switchname}, $dlink); - telnet_print($switch, $dlink, "logout") - or return abort($switch->{switchname}, $dlink); - - # Done - log_it("SUCCESS", "green", $switch->{switchname}, "Done pushing D-Link template config to switch $switch->{switchname} ($switch->{ipv4address}). \\o/"); - $dlink->close; - return 1; -} - -# Setup a switch -sub setup{ - my $switch = shift; # switchinfo - my $vrf = threads->tid(); # use thread ID as VRF-number - - # Remove last port if we're skipping it - my $last_port; - if ($dlinkng::config::configure_last_port){ - # assume we want to skip a port, so we check against regex - if($switch->{switchname} =~ m/$dlinkng::config::last_port_regex/){ - $last_port = pop(@{$switch->{ports}}); - } - } - - if($last_port_config){ - info($switch->{switchname}, "Configuring last port only."); - } - - if($cisco_config){ - info($switch->{switchname}, "Configuring things on the Cisco-side only."); - } - - unless($cisco_config || $last_port_config){ - info($switch->{switchname}, "Starting configuration of $switch->{switchname} ($switch->{ipv4address})."); - info($switch->{switchname}, "Trying to ping $switch->{ipv4address}."); - - if (pong($switch->{ipv4address}, 1)){ - # push template-config to D-Link if template-file is given as argument - if($dlink_config){ - log_it("INFO", "green", $switch->{switchname}, "Switch $switch->{switchname} ($switch->{ipv4address}) is already responding to ping! \\o/"); - info($switch->{switchname}, "Going to push D-Link template config to switch $switch->{switchname} ($switch->{ipv4address})"); - return push_dlink_template_config($switch); - } else { - # if not - log_it("INFO", "green", $switch->{switchname}, "Skipping $switch->{switchname} ($switch->{ipv4address}): is already responding to ping! \\o/"); - return 1; - } - } - - info($switch->{switchname}, "Not responding to ping, configuring device."); - } - - info($switch->{switchname}, "Connecting to coreswitch '$switch->{coreswip}'."); - - my $cisco; - if ($dlinkng::config::use_ssh_cisco){ - # Use SSH - my $ssh = Net::OpenSSH->new( $dlinkng::config::cisco_user . ':' . - $dlinkng::config::cisco_pass . '@' . - $switch->{coreswip} . $dlinkng::config::domain_name, - timeout => 60); - - if ($ssh->error){ - return debug($switch->{switchname}, $ssh->error); - } - - my ($pty, $pid) = $ssh->open2pty({stderr_to_stdout => 1}) - or return debug($switch->{switchname}, $ssh->error); - - $cisco = Net::Telnet::Cisco->new( - Fhopen => $pty, - Telnetmode => 0, - #Cmd_remove_mode => 1, - Errmode => 'return', - output_log => "$dlinkng::config::log_dir/cisco-output-$switch->{coreswip}-$switch->{switchname}.log", - input_log => "$dlinkng::config::log_dir/cisco-input-$switch->{coreswip}-$switch->{switchname}.log", - Prompt => '/\S+[#>]/', - #Prompt => '/(?m:^\\s?(?:[\\w.\/]+\:)?(?:[\\w.-]+\@)?[\\w.-]+\\s?(?:\(config[^\)]*\))?\\s?[\$#>]\\s?(?:\(enable\))?\\s*$)/', - ); - } else { - # Don't use SSH - $cisco = Net::Telnet::Cisco->new( - Host => $switch->{coreswip} . $dlinkng::config::domain_name, - Errmode => 'return', - output_log => "$dlinkng::config::log_dir/cisco-output-$switch->{coreswip}-$switch->{switchname}.log", - input_log => "$dlinkng::config::log_dir/cisco-input-$switch->{coreswip}-$switch->{switchname}.log", - Prompt => '/\S+[#>]/', - #Prompt => '/(?m:^\\s?(?:[\\w.\/]+\:)?(?:[\\w.-]+\@)?[\\w.-]+\\s?(?:\(config[^\)]*\))?\\s?[\$#>]\\s?(?:\(enable\))?\\s*$)/', - Timeout => 60 - ); - } - - unless (defined($cisco)){ - return error($switch->{switchname}, "Could not connect to '$switch->{coreswip}'."); - } - - unless ($dlinkng::config::use_ssh_cisco){ - info($switch->{switchname}, "Logging in to coreswitch '$switch->{coreswip}'."); - - unless ($cisco->login($dlinkng::config::cisco_user, $dlinkng::config::cisco_pass)){ - $cisco->close; - return error($switch->{switchname}, "Can't log in to '$switch->{coreswip}'."); - } - } - - # Don't do enable on IOS-XR - unless(is_xr($switch->{coreswos})){ - $cisco->enable; - debug($switch->{switchname}, $cisco->errmsg); - } - - # Disable paging - telnet_cmd($switch, $cisco, "terminal length 0") - or return abort($switch->{switchname}, $cisco); - - unless($cisco_config || $last_port_config){ - # Prepare ports - reset_interfaces($switch, $cisco) - or return abort($switch->{switchname}, $cisco); - - # Set up port 1 for D-Link telneting - telnet_cmd($switch, $cisco, "conf t") - or return abort($switch->{switchname}, $cisco); - - info($switch->{switchname}, "Enabling VRF (${dlinkng::config::vrf_prefix}${vrf}). Applying to interface."); - if(is_nx($switch->{coreswos})){ - # Remove previous VRF - # No error-check on the next command, as NX-OS - # spits out "% VRF dlink-X not found" - # making Net::Telnet::Cisco think it's an error - - # Extra overhead to delete, not used - #$cisco->cmd("no vrf context ${dlinkng::config::vrf_prefix}${vrf}"); - #sleep 10; # NX-OS seems to need some time to delete a VRF - - # Create VRF - telnet_cmd($switch, $cisco, "vrf context ${dlinkng::config::vrf_prefix}${vrf}") - or return abort($switch->{switchname}, $cisco); - - } elsif(is_xr($switch->{coreswos})){ - # IOS-XR - telnet_cmd($switch, $cisco, "vrf ${dlinkng::config::vrf_prefix}${vrf}") - or return abort($switch->{switchname}, $cisco); - - } else { - # Default OS - # IOS fails on the next command, if the vrf doesn't exist - # Ignore error on this command - - # Extra overhead to delete, not used - #$cisco->cmd("no ip vrf ${dlinkng::config::vrf_prefix}${vrf}"); - - # Create VRF - telnet_cmd($switch, $cisco, "ip vrf ${dlinkng::config::vrf_prefix}${vrf}") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "rd $vrf:$vrf") - or return abort($switch->{switchname}, $cisco); - } - - # Configure port #1 - configure_interface($switch, $cisco, @{$switch->{ports}}[0], $dlinkng::config::dlink_router_ip, $dlinkng::config::dlink_def_mask, $vrf) - or return abort($switch->{switchname}, $cisco); - - info($switch->{switchname}, "Waiting for D-Link to answer on $dlinkng::config::dlink_def_ip in VRF ${dlinkng::config::vrf_prefix}${vrf} on port #1 (" . @{$switch->{ports}}[0] . ")."); - - # Use port 1 if ping succeeds - my $p_count = 0; - my $dlink_port = @{$switch->{ports}}[$p_count]; - - until (cisco_ping($cisco, $dlinkng::config::dlink_def_ip, 30, $switch->{coreswos}, $vrf)) { - # Did not ping, let's try next port - # We do this because port#1 might be damaged/not patched - - # First we need to check if there are more ports to test - if ($p_count >= $#{$switch->{ports}}){ - # Current port is last port available - # Since it did not ping, we reset all interfaces - - reset_interfaces($switch, $cisco) - or return abort($switch->{switchname}, $cisco); - $cisco->close; - return error($switch->{switchname}, "No more ports on $switch->{switchname}. Aborting."); - } - - # Use next port - $p_count++; - - info($switch->{switchname}, "D-Link on port #" . ($p_count) . " ($dlink_port) did not respond. Trying next port (" . @{$switch->{ports}}[$p_count] . ")."); - - # Try next port, reset old port - telnet_cmd($switch, $cisco, "conf t") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "default int $dlink_port") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "int $dlink_port") - or return abort($switch->{switchname}, $cisco); - no_no_shut($switch, $cisco, $dlink_port) - or return abort($switch->{switchname}, $cisco); - - # Set new port - $dlink_port = @{$switch->{ports}}[$p_count]; - - # Configure new port - configure_interface($switch, $cisco, $dlink_port, $dlinkng::config::dlink_router_ip, $dlinkng::config::dlink_def_mask, $vrf) - or return abort($switch->{switchname}, $cisco); - - info($switch->{switchname}, "Waiting for D-Link to answer on $dlinkng::config::dlink_def_ip in VRF ${dlinkng::config::vrf_prefix}${vrf} on port #" . ($p_count+1) . " (" . @{$switch->{ports}}[$p_count] . ")."); - } - - # Telnet to D-Link - info($switch->{switchname}, "Starting D-Link config phase 1."); - my $dlink = dlink_login($switch, $dlinkng::config::dlink_def_ip, $vrf) - or return abort($switch->{switchname}, $cisco); - - info($switch->{switchname}, "Setting hostname to $switch->{switchname}${dlinkng::config::dlink_host_suffix}"); - telnet_print($switch, $dlink, "config snmp system_name $switch->{switchname}${dlinkng::config::dlink_host_suffix}") - or return abort($switch->{switchname}, $cisco, $dlink); - - info($switch->{switchname}, "Adding LACP. Enabling STP."); - telnet_print($switch, $dlink, "create link_aggregation group_id 1 type lacp") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "config link_aggregation group_id 1 ports 1:($dlinkng::config::dlink_lacp_start-$dlinkng::config::dlink_lacp_end)") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "enable stp") - or return abort($switch->{switchname}, $cisco, $dlink); - - info($switch->{switchname}, "STP enabled, logging in again."); - $dlink->close; - - unless (cisco_ping($cisco, $dlinkng::config::dlink_def_ip, 60, $switch->{coreswos}, $vrf)) { - reset_interfaces($switch, $cisco) - or return abort($switch->{switchname}, $cisco); - $cisco->close; - return error($switch->{switchname}, "Can't login to $switch->{switchname} on $dlinkng::config::dlink_def_ip, aborting."); - } - - $dlink = dlink_login($switch, $dlinkng::config::dlink_def_ip, $vrf) - or return abort($switch->{switchname}, $cisco); - - info($switch->{switchname}, "Running STP config."); - telnet_print($switch, $dlink, "config stp version mstp") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "config stp priority 61440 instance_id 0") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "config stp ports 1:(1-44) edge true") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "enable lldp") - or return abort($switch->{switchname}, $cisco, $dlink); - - info($switch->{switchname}, "Setting IP address."); - telnet_print($switch, $dlink, "config ipif System ipaddress $switch->{ipv4address}/$dlinkng::config::dlink_prefix vlan default") - or return abort($switch->{switchname}, $cisco, $dlink); - - info($switch->{switchname}, "Closing D-Link link."); - $dlink->close; - - info($switch->{switchname}, "Configuring IP on gateway."); - telnet_cmd($switch, $cisco, "conf t") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "default int $dlink_port") - or return abort($switch->{switchname}, $cisco); - configure_interface($switch, $cisco, $dlink_port, $switch->{ipv4gateway}, $switch->{netmask}) - or return abort($switch->{switchname}, $cisco); - - # Wait for network convergence - info($switch->{switchname}, "Waiting for network to converge."); - unless (cisco_ping($cisco, $switch->{ipv4address}, 60, $switch->{coreswos})) { - reset_interfaces($switch, $cisco) - or return abort($switch->{switchname}, $cisco); - $cisco->close; - return error($switch->{switchname}, "Can't ping $switch->{switchname} on $switch->{ipv4address}, aborting."); - } - - # Do it again! - info($switch->{switchname}, "D-Link config phase 2."); - $dlink = dlink_login($switch, $switch->{ipv4address}, '', $dlink_port) or return abort($switch->{switchname}, $cisco); - - info($switch->{switchname}, "Setting default route on switch. Saving config."); - telnet_print($switch, $dlink, "create iproute default $switch->{ipv4gateway}") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "save", 0) - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "Y") - or return abort($switch->{switchname}, $cisco, $dlink); - telnet_print($switch, $dlink, "logout") - or return abort($switch->{switchname}, $cisco, $dlink); - - info($switch->{switchname}, "Closing D-Link link."); - $dlink->close; - } - - unless($last_port_config){ - # Configure final IOS stuff - info($switch->{switchname}, "Final IOS config phase. Setting up all interfaces + Port-Channel."); - - # Reset interfaces - reset_interfaces($switch, $cisco) - or return abort($switch->{switchname}, $cisco); - - telnet_cmd($switch, $cisco, "conf t") - or return abort($switch->{switchname}, $cisco); - - # Portchannel needs to exist before we can assign interfaces to it - # This needs to be done on IOS-XE, but we do it on all - if(is_xr($switch->{coreswos})){ - # Other syntax on XR, called Bundle-Ether - telnet_cmd($switch, $cisco, "int Bundle-Ether$switch->{etherchannel}") - or return abort($switch->{switchname}, $cisco); - - } else { - telnet_cmd($switch, $cisco, "int Po$switch->{etherchannel}") - or return abort($switch->{switchname}, $cisco); - - } - - # Rest of the config - my $etherchan_desc; - foreach my $port (@{$switch->{ports}}){ - telnet_cmd($switch, $cisco, "int $port") - or return abort($switch->{switchname}, $cisco); - - unless(is_xr($switch->{coreswos})){ - # only do this if not IOS-XR - telnet_cmd($switch, $cisco, "no switchport") - or return abort($switch->{switchname}, $cisco); - } - - # 'no shut'-patrol reporting in! - telnet_cmd($switch, $cisco, "no shut") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "description D-Link $switch->{switchname}; RJ-45; 1G;") - or return abort($switch->{switchname}, $cisco); - - # disable CDP if specified - unless($dlinkng::config::cdp_enable){ - telnet_cmd($switch, $cisco, "no cdp enable") - or return abort($switch->{switchname}, $cisco); - } - - # Assign to Etherchannel - if(is_xr($switch->{coreswos})){ - # Other syntax on XR, called Bundle-Ether - telnet_cmd($switch, $cisco, "bundle id $switch->{etherchannel} mode passive") - or return abort($switch->{switchname}, $cisco); - - } else { - telnet_cmd($switch, $cisco, "channel-group $switch->{etherchannel} mode passive") - or return abort($switch->{switchname}, $cisco); - - } - - # add port to descr - $etherchan_desc .= "$port; "; - } - - if(is_xr($switch->{coreswos})){ - # Other syntax on XR, called Bundle-Ether - telnet_cmd($switch, $cisco, "int Bundle-Ether$switch->{etherchannel}") - or return abort($switch->{switchname}, $cisco); - - } else { - telnet_cmd($switch, $cisco, "int Po$switch->{etherchannel}") - or return abort($switch->{switchname}, $cisco); - - } - - telnet_cmd($switch, $cisco, "description D-Link $switch->{switchname}; $etherchan_desc") - or return abort($switch->{switchname}, $cisco); - - - if(is_xr($switch->{coreswos})){ - # IOS-XR - telnet_cmd($switch, $cisco, "ipv4 address $switch->{ipv4gateway} $switch->{netmask}") - or return abort($switch->{switchname}, $cisco); - - } else { - # All other - telnet_cmd($switch, $cisco, "ip address $switch->{ipv4gateway} $switch->{netmask}") - or return abort($switch->{switchname}, $cisco); - } - - # IPv6-stuff - unless (is_nx($switch->{coreswos})){ - # IOS + IOS-XR - telnet_cmd($switch, $cisco, "ipv6 enable") - or return abort($switch->{switchname}, $cisco); - } - - telnet_cmd($switch, $cisco, "ipv6 address $switch->{ipv6address}") - or return abort($switch->{switchname}, $cisco); - - # DHCP-relay/forwarding + MBD/Blazon-forwarding (broadcast) - if (is_nx($switch->{coreswos})){ - # NX-OS - telnet_cmd($switch, $cisco, "ip dhcp relay address $dlinkng::config::dhcprelay4_pri") - or return abort($switch->{switchname}, $cisco); - - # define secondary if present - if (defined($dlinkng::config::dhcprelay4_sec) && $dlinkng::config::dhcprelay4_sec){ - telnet_cmd($switch, $cisco, "ip dhcp relay address $dlinkng::config::dhcprelay4_sec") - or return abort($switch->{switchname}, $cisco); - } - } elsif (is_xr($switch->{coreswos})){ - # IOS-XR - telnet_cmd($switch, $cisco, "ipv4 helper-address vrf default $dlinkng::config::dhcprelay4_pri") - or return abort($switch->{switchname}, $cisco); - - # define secondary if present - if (defined($dlinkng::config::dhcprelay4_sec) && $dlinkng::config::dhcprelay4_sec){ - telnet_cmd($switch, $cisco, "ipv4 helper-address vrf default $dlinkng::config::dhcprelay4_sec") - or return abort($switch->{switchname}, $cisco); - } - } else { - # IOS - telnet_cmd($switch, $cisco, "ip helper-address $dlinkng::config::dhcprelay4_pri") - or return abort($switch->{switchname}, $cisco); - - # define secondary if present - if (defined($dlinkng::config::dhcprelay4_sec) && $dlinkng::config::dhcprelay4_sec){ - telnet_cmd($switch, $cisco, "ip helper-address $dlinkng::config::dhcprelay4_sec") - or return abort($switch->{switchname}, $cisco); - } - } - - # Custom Portchannel-config - # Dynamically applied depending on OS - foreach my $cmd (@{$dlinkng::config::po_config->{$switch->{coreswos}}}){ - telnet_cmd($switch, $cisco, $cmd) - or return abort($switch->{switchname}, $cisco); - } - - # 'no shut'-patrol reporting in! - telnet_cmd($switch, $cisco, "no shut") - or return abort($switch->{switchname}, $cisco); - - # Done with interface-config - # Apply DHCP-profiling if using IOS-XR - if (is_xr($switch->{coreswos})){ - telnet_cmd($switch, $cisco, "dhcp ipv4") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "interface Bundle-Ether$switch->{etherchannel} proxy profile $dlinkng::config::dhcp4_proxyprofile") - or return abort($switch->{switchname}, $cisco); - - if(defined($dlinkng::config::dhcp6_proxyprofile) && $dlinkng::config::dhcp6_proxyprofile){ - # Do DHCPv6 proxy as well - - telnet_cmd($switch, $cisco, "dhcp ipv6") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "interface Bundle-Ether$switch->{etherchannel} proxy profile $dlinkng::config::dhcp6_proxyprofile") - or return abort($switch->{switchname}, $cisco); - } - } - - # Commit on XR - if(is_xr($switch->{coreswos})){ - telnet_cmd($switch, $cisco, "commit") - or return abort($switch->{switchname}, $cisco); - } - - telnet_cmd($switch, $cisco, "end") - or return abort($switch->{switchname}, $cisco); - } - - # If we skipped last port at the start, we configure it now - if ($dlinkng::config::configure_last_port && $last_port){ - if ($last_port_desc){ - info($switch->{switchname}, "Configuring last port... (description only)"); - } else { - info($switch->{switchname}, "Configuring last port..."); - } - - telnet_cmd($switch, $cisco, "conf t") - or return abort($switch->{switchname}, $cisco); - unless ($last_port_desc){ - telnet_cmd($switch, $cisco, "default int $last_port") - or return abort($switch->{switchname}, $cisco); - } - - telnet_cmd($switch, $cisco, "int $last_port") - or return abort($switch->{switchname}, $cisco); - telnet_cmd($switch, $cisco, "description AP \@ D-Link $switch->{switchname}; RJ-45; 1G;") - or return abort($switch->{switchname}, $cisco); - - unless ($last_port_desc){ - foreach my $cmd (@{$dlinkng::config::last_port_config->{$switch->{coreswos}}}){ - telnet_cmd($switch, $cisco, $cmd) - or return abort($switch->{switchname}, $cisco); - } - # 'no shut'-patrol reporting in! - telnet_cmd($switch, $cisco, "no shut") - or return abort($switch->{switchname}, $cisco); - } - - # Commit on XR - if(is_xr($switch->{coreswos})){ - telnet_cmd($switch, $cisco, "commit") - or return abort($switch->{switchname}, $cisco); - } - - telnet_cmd($switch, $cisco, "end") - or return abort($switch->{switchname}, $cisco); - } - - # If only cisco-config - if($cisco_config){ - log_it("CONFIG", "green", $switch->{switchname}, "Cisco-config relevant to switch '$switch->{switchname}' ($switch->{ipv4address}) done! \\o/"); - } - - # Check if all is OK, but not if configuring skipped port only - my $return = 0; - if ($last_port_config){ - info($switch->{switchname}, "Done doing skipped port config. Not checking if anything is online."); - $return = 1; - } else { - if(pong($switch->{ipv4address}, 15)){ - # pingable, OK - log_it("SUCCESS", "green", $switch->{switchname}, "Switch $switch->{switchname} ($switch->{ipv4address}) set up! \\o/"); - - $return = 1; - - # push template-config to D-Link if template-file is given as argument - if($dlink_config){ - info($switch->{switchname}, "Going to push D-Link template config to switch $switch->{switchname} ($switch->{ipv4address})"); - $return = push_dlink_template_config($switch); - } - } else { - # Not pingable - if (cisco_ping($cisco, $switch->{ipv4address}, 60, $switch->{coreswos})) { - # we can reach from core, but not from other places, lets warn - log_it("ERROR", "red", $switch->{switchname}, "Switch $switch->{switchname} reachable only from core/distro."); - } else { - reset_interfaces($switch, $cisco) - or return abort($switch->{switchname}, $cisco); - $cisco->close; - return error($switch->{switchname}, "Can't ping $switch->{switchname} on $switch->{ipv4address}, aborting."); - } - } - } - - if($dlinkng::config::save_config && !is_xr($switch->{coreswos})){ - # save the cisco-config, but not if IOS-XR - info($switch->{switchname}, "Saving config on core-switch ($switch->{coreswip})."); - telnet_cmd($switch, $cisco, "write") - or return abort($switch->{switchname}, $cisco); - } - - $cisco->close; - return $return; -} - -# Process switches -sub process_switches { - while (my $switch = $switchq->dequeue()){ - last if ($switch eq 'DONE'); # all done - - my $time_start = time(); - - # Wait till there is sessions/VTYs available - while (1){ - $telnet_sessions{$switch->{coreswip}} = 0 unless $telnet_sessions{$switch->{coreswip}}; - $telnet_sessions{$switch->{coreswip}} += 2; - - if ($telnet_sessions{$switch->{coreswip}} <= $dlinkng::config::os_info->{$switch->{coreswos}}{max_sessions}){ - # lower or equal to max_sessions on current switch - # lets move on - last; - } else { - # we would exceed max_sessions on current switch - # we wait until there are free sessions - info($switch->{switchname}, "There are no more free sessions left on '$switch->{coreswip}' ($switch->{coreswos}). Waiting..."); - $telnet_sessions{$switch->{coreswip}} -= 2; - sleep (int(rand(10)) + 10); - } - } - - info($switch->{switchname}, "Number of sessions on switch '$switch->{coreswip}': $telnet_sessions{$switch->{coreswip}}."); - - if (setup($switch)) { - # Count number of switches - $switches++; - - } else { - log_it("FAILED", "red", $switch->{switchname}, "Configuring $switch->{switchname} failed."); - - # Count failed switches - $failed_switches++; - } - - # Remove session - $telnet_sessions{$switch->{coreswip}} -= 2; - - # Summarize total time spent, used to calculate average per switch - $total_time += time() - $time_start; - } - - # detach thread -- we're done - threads->detach; -} - -# Let's start -my $time_start = time(); -log_it("INFO", "yellow", "dlink-ng", "Starting dlink-ng with $dlinkng::config::max_threads threads..."); -log_it("INFO", "yellow", "dlink-ng", "Configured to skip last port on all switches.") if $dlinkng::config::configure_last_port; - -# Let's add all switches to the queue -while (<STDIN>){ - next if /^(.*#|\s+$)/; # skip if comment, or blank line - - my ($switchname, $coreswip, $etherchannel, $cidr, $ipv4address, $ipv4gateway, $ipv6address, @ports) = split; - - # skip if less than 1 port is provided - if (scalar(@ports) < 1){ - log_it("FAILED", "red", $switchname, "Switch '$switchname' had less than 1 port configured. Skipping."); - next; - } - - # define OS of the coresw - my $coreswos = set_coreswos($coreswip); - - # find netmask - my $netmask = Net::IP->new($cidr)->mask(); - - my %switch = ( - switchname => $switchname, - coreswip => $coreswip, - coreswos => $coreswos, - etherchannel => $etherchannel, - ipv4address => $ipv4address, - ipv4gateway => $ipv4gateway, - netmask => $netmask, - ipv6address => $ipv6address, - ports => \@ports, - ); - - # Only configure a single switch? - if (defined $single_switch){ - unless ($single_switch eq $switchname){ - next; - } - } - - # Add switch to queue - $switchq->enqueue(\%switch); -} - -# Let the threads know when they're done -$switchq->enqueue("DONE") for (1..$dlinkng::config::max_threads); - -# Start processing the queue -threads->create("process_switches") for (1..$dlinkng::config::max_threads); - -# Wait till all threads is done -sleep 5 while (threads->list(threads::running)); - -# If 0 switches -my $runtime = time() - $time_start; -my $total_switches = $switches + $failed_switches; -if($total_switches == 0){ - log_it("INFO", "yellow", "dlink-ng", "Finished!"); - log_it("INFO", "yellow", "dlink-ng", "Crunched 0 switches in $runtime seconds."); - exit 1; -} - -# Done -my $avg = sprintf("%.1f", $total_time / $total_switches); -log_it("INFO", "yellow", "dlink-ng", "Finished!"); -log_it("INFO", "yellow", "dlink-ng", "Crunched $total_switches switches in $runtime seconds."); -log_it("INFO", "yellow", "dlink-ng", "$switches of these were successful, while $failed_switches failed."); -log_it("INFO", "yellow", "dlink-ng", "Average of $avg seconds per switch."); diff --git a/dlink-ng/make-dlink-config.pl b/dlink-ng/make-dlink-config.pl deleted file mode 100755 index 7a20820..0000000 --- a/dlink-ng/make-dlink-config.pl +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/perl -I /root/tgmanage/ -use strict; -use warnings; -use lib '..'; -BEGIN { - require "include/config.pm"; - eval { - require "include/config.local.pm"; - }; -} - -unless (@ARGV > 0) { - print "No arguments. Need switches.txt and patchlist.txt.\n"; - exit 1; -} - -my $s = open(SWITCHES, "$ARGV[0]") or die ("Cannot open switches.txt"); -my $p = open(PATCH, "$ARGV[1]") or die ("Cannot open patchlist.txt"); - -my $portchannel_start = 10; -my %portchannels; -my $letter = "a"; - -my %switches; -while(<SWITCHES>) { - chomp; - my ($network, $netmask, $switchname, $mngmt_ip) = split; # $mngmt_ip is unused - $switches{$switchname} = { - network => $network, - netmask => $netmask, - }; -} -while (<PATCH>) { - chomp; - my ($switchname, $coregw, @ports) = split; - my $network = $switches{$switchname}{network}; - my $netmask = $switches{$switchname}{netmask}; - my ($o1, $o2, $o3, $o4) = split(/\./, $network); - - # portchannel per distro - if($coregw =~ m/distro0/){ - # TG14-fix for distro0 - $portchannels{$coregw} = 15 unless ($portchannels{$coregw} && defined($portchannels{$coregw})); - } else { - $portchannels{$coregw} = $portchannel_start unless ($portchannels{$coregw} && defined($portchannels{$coregw})); - } - - if ($o4 eq "0") { - $letter = "a"; - } elsif ($o4 eq "64") { - $letter = "b"; - } elsif ($o4 eq "128") { - $letter = "c"; - } elsif ($o4 eq "192") { - $letter = "d"; - } - - my $v6addr = $nms::config::base_ipv6net . $o3 . $letter ."::1/64"; - - $o4 += 1; - my $gateway_addr = "$o1.$o2.$o3.$o4"; - $o4 += 1; - my $switch_addr = "$o1.$o2.$o3.$o4"; - - print "$switchname $coregw $portchannels{$coregw} $network/$netmask $switch_addr $gateway_addr $v6addr " . join(' ', @ports) . "\n"; - - # increase portchannel - $portchannels{$coregw}++; - - die("NO MORE ETHERCHANNELS!") if($portchannels{$coregw} > 64); # IOS-XE 4500 only supports 64 portchannels -} |