Site icon David Ramsden

Automating Cisco Switch Swap Outs

So you can’t automate the entire process unfortunately. You’re still going to need to pull a late night and get your hands dirty…

Recently I was tasked with swapping out 4 old Cisco 10/100Mb switches with new 10/100/1000Mb switches. The old switches were a combination of Cisco 3560, 2950 and 3548 series. The old switches also had some old configurations that needed to be updated and the interface configurations weren’t consistent. The interfaces also had different VLAN configurations and this was my main concern. What if I made a mistake? It’s not very realistic to chase 192 ports and make sure every single one was working as expected.

Going back to a previous blog, should network engineers be programmers, writing a script to speed up the configuration process and eliminate any mistakes was the answer.

The process would be:

  1. Get the existing IOS configuration.
  2. Find the interfaces.
  3. Convert the old 10/100 (“FastEthernet”) interfaces to 10/100/100 (“GigabitEthernet”) interfaces.
  4. Extract the important parts of the interface configuration (description, speed/duplex if set, VLAN configuration, trunk configuration etc).
  5. Pump out the converted interfaces.
  6. Copy/paste in to a template after manually making sure it looks good.
  7. Upload the configuration to the startup-config of the new switch.
  8. Swap the switch out.

First of all, the existing IOS configurations are stored in SVN. They get here via RANCID. So I had the old configurations easily to hand. Also if anything did happen to go wrong on the night, this served as a good reference point.

My weapon of choice for this scripting task was Perl. The script I wrote took in an existing IOS configuration and extracted the physical interfaces and SVIs, converted them from FastEthernet to GigabitEthernet and grabbed all of the important stuff such as description, speed/duplex, VLAN configuration, trunk configuration, IP configuration it’s an SVI etc.

Here it is:

#!/usr/bin/perl -w
#

use strict;

# Switch IP address is the first arguement of the script.
my $switch = $ARGV[0];
my $int_is_vlan = 0;

# Open existing configuration.
open FP, "./$switch" or die "Unable to open switch config: $!\n";
        my @config = <FP>;
close FP;

# Remove line termination.
chomp @config;

# Loop through each line of the existing configuration.
my $i = 0;
while($i <= $#config) {
        # We found an interface...
        if ($config[$i] =~ m/^interface .*/) {
                print "!\n";

                # This interface is an SVI.
                if ($config[$i] =~ m/^interface Vlan(\d+)$/i) {
                        $int_is_vlan = 1;
                }

                # Gi0/1-4 will become Gi0/49-52 on the new switch.
                $config[$i] =~ s/GigabitEthernet0\/1$/GigabitEthernet0\/49/;
                $config[$i] =~ s/GigabitEthernet0\/2$/GigabitEthernet0\/50/;
                $config[$i] =~ s/GigabitEthernet0\/3$/GigabitEthernet0\/51/;
                $config[$i] =~ s/GigabitEthernet0\/4$/GigabitEthernet0\/52/;
                # Convert old FastEthernet interfaces.
                $config[$i] =~ s/FastEthernet/GigabitEthernet/;

                # Print interface.
                print $config[$i] . "\n";

                # Move to the next line of the old configuration.
                $i++;

                # Loop through interface configuration...
                while($i <= $#config) {
                        # If the line starts with an upper/lowercase character or a !
                        # we're done with the interface.
                        if ($config[$i] =~ m/^[A-Za-z!]/) {
                                $int_is_vlan = 0;

                                # Go back one line and move on.
                                $i--;
                                last;
                        }

                        # Stuff we want from the interface.
                        if ($config[$i] =~ m/^ switchport access .*/) {
                                print $config[$i] . "\n";
                                # Unconditional access port.
                                print " switchport mode access\n";
                        } elsif ($config[$i] =~ m/^ switchport voice .*/) {
                                print $config[$i] . "\n";
                        } elsif ($config[$i] =~ m/^ speed .*|^ duplex .*/) {
                                print $config[$i] . "\n";
                        } elsif ($config[$i] =~ m/^ shutdown/) {
                                print $config[$i] . "\n";
                        } elsif ($int_is_vlan && $config[$i] =~ m/^ no ip address/) {
                                print $config[$i] . "\n";
                        } elsif ($config[$i] =~ m/^ ip address .*/) {
                                print $config[$i] . "\n";
                        } elsif ($config[$i] =~ m/^ description .*/) {
                                print $config[$i] . "\n";
                        }

                        # Interface is a trunk.
                        # Set the port to unconditional trunk and explicitly disable portfast.
                        if ($config[$i] =~ m/^ switchport trunk .*/) {
                                print $config[$i] . "\n";
                                print " switchport mode trunk\n";
                                print " spanning-tree portfast disable\n";
                        }

                        $i++;
                }
        }

        $i++;
}

I ran this against each of the 4 existing switch IOS configurations, checked the output quickly and then copied/pasted the interfaces in to my switch template that has everything else set such as Spanning Tree configuration, errdisable recovery, NTP, AAA, SNMP, syslog etc etc. VTP would take care of the VLAN database once the switch was connected to the core.

I connected each of the new switches to my laptop and configured the Vlan1 SVI with a temporary IP, then TFTP’d the switch template to the startup-config along with the IOS version required. Turn the switch off and on again to make sure it looks good and job done on the configuration front. Each switch took a very small amount of time to configure and I could be safe in the knowledge that all the interfaces were correct.

The 4 switches were swapped out in the dead of night. It took 4 hours from start to finish, including testing and monitoring. Out of roughly 192 ports there was only one device which didn’t work the next morning and that was due to an auto-negotiation issue.In my book it was a very successful, painless and efficient change. One which I wasn’t particularly looking forward to but thanks to a bit of scripting ended up being easy.