Changing the Configurations of Many Routers at Once

Problem

You want to make a configuration change to a large number of routers.

Solution

The Expect script in Example 1-2 makes the same configuration changes to a list of routers by using Telnet. When it finishes running, the script produces a status report to identify which devices, if any, failed to update properly. No arguments are required or expected.

Example 1-2. rtrchg.exp

#!/usr/local/bin/expect
#
#    rtrcfg.exp -- a script to perform mass configuration changes to  
#                  a list of routers using telnet and Expect       
#
#
# Set Behavior
set tftp "172.25.1.1"
set workingdir /home/cisco/rtr
#
puts stdout "Enter user name:"
gets stdin userid
system stty -echo
puts stdout "Enter login password:"
gets stdin vtypasswd
puts stdout "\nEnter enable password:"
gets stdin enablepwd
system stty echo
system "cp $workingdir/NEWCONFIG /tftpboot/NEWCONFIG"
set RTR [open "$workingdir/RTR_LIST" r]
set LOG [open "$workingdir/RESULT" w]
while {[gets $RTR router] != -1} {
   if {[ string range $router 0 0 ] != "#"} {
     set timeout 10
     spawn telnet; expect "telnet>"; send "open $router\n"
     expect {
              {Username}   { send "$userid\r"
                             expect {
                                       {*Password*} { send "$vtypasswd\r" }
                                    }
                           }
              {Password}   { send "$vtypasswd\r" }
              timeout      { puts $LOG "$router - telnet failed"
                             close; wait; continue
                           }
            }

     expect {
              {Password}   { puts $LOG "$router - vty login failed"
                             close; wait; continue
                           }
              {Username}   { puts $LOG "$router - vty login failed"
                             close; wait; continue
                           }
              {>}          { puts $LOG "$router - vty login ok" }

              timeout      { puts $LOG "$router - vty login failed"
                             close; wait; continue
                           }
            }

      send "enable\r"
      expect "Password"
      send "$enablepwd\r"
      #
      expect {
               {*#}        { puts $LOG "$router - enable login ok" }

               {*>}        { puts $LOG "$router - enable login failed"
                             close; wait; continue
                           }

              timeout      { puts $LOG "$router - enable login failed"
                             close; wait; continue
                           }
             }
     # CMDs
     set timeout 30
     send "copy tftp://$tftp/NEWCONFIG running-config\r"
     expect "running-config"
     send "\r"
     expect  {
               {OK}        { puts $LOG "$router - TFTP successful"}
               timeout     { puts $LOG "$router - TFTP failed"
                             close; wait; continue }
             }
     send "copy running-config startup-config\r\r\r"
     expect  {
               {OK}        { puts $LOG "$router - config saved"}
               timeout     { puts $LOG "$router - config failed"
                             close; wait; continue }
             }
     #CMDs
     send "exit\r"; close; wait
    }
}
close $RTR; close $LOG
system "rm /tftpboot/NEWCONFIG"

Discussion

This script uses the Expect language to emulate how a performing human router engineer would do a series of configuration updates via TFTP. The script logs into each router in a list and uses TFTP to download a set of configuration changes into the router’s running configuration. It then saves the new configuration file to NVRAM to make sure that it will survive any power failures, and moves on to the next router in the list. Automating a routine but time-consuming procedure with a script like this saves time and decreases the chances of fatigue-induced errors.

The script is designed to work with either normal router passwords or AAA-enabled username and password combinations, which we describe in Chapter 3. The script begins by asking you to supply a username. If one or more of your routers aren’t configured to use AAA or local authentication, the script will simply ignore this username and insert the password instead.

After asking for the username, the script will prompt you to enter a login password that will either be your VTY password or AAA password. Then the script will ask for the enable password, and it will then begin to perform its task.

Warning

The script is designed to work with IOS Versions 12.0 and greater. Unfortunately, Cisco changed the command sequence prior to 12.0, meaning the script will not work correctly with old IOS versions.

You must change two variables in this script for it to work in your network. The first variable is called tftp. You must set this value to your TFTP server’s IP address. The second variable you need to change is workingdir, which must contain the name of the directory that holds the list of routers, the file of configuration changes, and the location where the script will put its report.

The script is written in the Expect language and requires Expect to be loaded on your server and available in the /usr/local/bin directory. For more information on the Expect language, please see Appendix A or Exploring Expect by Don Libes (O’Reilly).

The script expects to find two special files in the working directory. The first is called RTR_LIST, and contains a list of router names, with one name on each line. The second file is called NEWCONFIG, which contains all required configuration changes. We also recommend you put the configuration command end on that the last line of the NEWCONFIG file to avoid the error messages that we mentioned in Recipe 1.1.

Here is a typical example of the sort of things you might put in the configuration file:

Freebsd% cat NEWCONFIG 
enable secret cisco
end

Using this file, the script will log into all routers and change the enable secret password. You could put any number of commands in this configuration file, but naturally the script will download the exact same set of configuration commands into every router, so you should never change anything that is unique to a particular router, such as an IP address, this way. This method is perfect for changing things like passwords, SNMP community strings, and access-lists, which can be the same on all routers.

The script will copy the NEWCONFIG file into the /tftpboot directory so it can then use TFTP to transfer it to each of the routers. It is a good idea to ensure that your server’s TFTP is working correctly before launching the script.

When the script finishes, it will create a status file called RESULT in the working directory. This status file will contain detailed status reports of what happened on each router. The easiest way to see a list of the routers that the script failed to change is to use the Unix grep command to search for the keyword “fail”, as follows:

Freebsd% grep fail RESULT
toronto - enable login failed
boston  - telnet failed
test    - enable login failed
frame   - enable login failed

See Also

Recipe 1.1; Appendix A; Exploring Expect by Don Libes (O’Reilly)

Get Cisco IOS Cookbook, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.