Using Python with Templates to Build Consistent Device Configs

It has been a long-held and accurate notion that configuration consistency is key to running a secure and reliable network. There are many commercial and complex tools on the market that help achieve this goal. However, it isn’t always necessary to absorb the burden or cost of tools that are unnecessarily flexible or complex. In many cases, we can quickly build a solution that addresses this challenge.

For example, an organization may be deploying 200 branch routers. After looking at several configurations, the administrator realizes that there are very few differences between devices deployed at each branch location. Specifically, each host has a unique name and some unique IP information. Each router is responsible for a voice and data network. Fortunately the third octet is the same for the voice and data networks and it corresponds with the fourth octet of the network used to connect to the WAN.

There are many ways to take a base configuration and change it from branch to branch. One method might simply be using the find and replace function in a text editor. This article takes a slightly different approach and uses a very simple python script to parse a template. Although this is a simplified example, it can easily be customized to a given deployment scenario. Additionally, it is much simpler than one would expect.

The file below is a partial router configuration. The areas of the file that will be replaced by the script are represented as a variable similar to $var_name.

Router Configuration Template (rtrtemplate.cfg)

version 12.4
service timestamps debug datetime msec
service timestamps log datetime msec localtime show-timezone
service password-encryption
!
hostname $hostname
!
boot-start-marker
boot-end-marker
!
logging buffered 4096 notifications
!
clock timezone EST -5
ip cef
!
!
ip dhcp excluded-address 192.168.$subnet.1 192.168.$subnet.18
ip dhcp excluded-address 10.200.$subnet.1 192.168.$subnet.18
!
ip dhcp pool VoicePool
   network 10.200.$subnet.0 255.255.255.0
   default-router 10.200.$subnet.1
!
ip dhcp pool DataPool
   network 192.168.$subnet.0 255.255.255.0
   dns-server 8.8.8.8
   default-router 192.168.$subnet.1
!
interface FastEthernet0/0
   description to LAN
!   
interface FastEthernet0/0.10
   encapsulation dot1q 10
   description to Voice VLAN
   ip address 10.200.$subnet.1 255.255.255.0
   no shut
!
interface FastEthernet0/0.192
   encapsulation dot1q 192
   description to Data VLAN
   ip address 192.168.$subnet.1 255.255.255.0
   no shut
!
interface FastEthernet0/1
   description to WAN
   ip address 172.16.0.$subnet 255.255.255.0
   no shut
!
router eigrp 1
   passive-interface default
   no auto-summary
   network 192.168.$subnet.0
   network 10.200.$subnet.0 0.0.0.255
   network 172.16.0.$subnet 0.0.0.255

 

To parse the template and replace $subnet and $hostname, a simple Python script can be used. The script, shown below, can be easily customized to work with additional variables or different methods of input.

The Python Script (rtrtemplate.py)

import string
import sys

#Open and Read the Template File
filein = open( 'rtrtemplate.cfg' )
src = string.Template( filein.read() )

#Ask the administrator about the stuff that
#is different on a device by device basis
hostname = raw_input("Enter the hostname: ")
subnet = raw_input("Enter the third octet: ")

#note--some versions use "input" instead of "raw_input"

#Substitute and store in the variable "result"
d={ 'hostname':hostname, 'subnet':subnet }
result = src.substitute(d)

#Uncomment to output to screen
#print result

#Create an output file based on provided hostname
fileout = open( hostname + '.cfg', 'w' )
fileout.write(result)

Executing the script is simple and will ask the administrator the appropriate questions. At the conclusion, a unique output file will be produced.

Running the Script

MyHost$ python rtrtemplate.py
Enter the hostname: ManchesterRTR
Enter the third octet: 33

The script completes instantaneously and produces an output file for use as a router configuration.

Router Configuration File

version 12.4
service timestamps debug datetime msec
service timestamps log datetime msec localtime show-timezone
service password-encryption
!
hostname ManchesterRTR
!
boot-start-marker
boot-end-marker
!
logging buffered 4096 notifications
!
clock timezone EST -5
ip cef
!
!
ip dhcp excluded-address 192.168.33.1 192.168.33.18
ip dhcp excluded-address 10.200.33.1 192.168.33.18
!
ip dhcp pool VoicePool
   network 10.200.33.0 255.255.255.0
   default-router 10.200.33.1
!
ip dhcp pool DataPool
   network 192.168.33.0 255.255.255.0
   dns-server 8.8.8.8
   default-router 192.168.33.1
!
interface FastEthernet0/0
   description to LAN
!   
interface FastEthernet0/0.10
   encapsulation dot1q 10
   description to Voice VLAN
   ip address 10.200.33.1 255.255.255.0
   no shut
!
interface FastEthernet0/0.192
   encapsulation dot1q 192
   description to Data VLAN
   ip address 192.168.33.1 255.255.255.0
   no shut
!
interface FastEthernet0/1
   description to WAN
   ip address 172.16.0.33 255.255.255.0
   no shut
!   
router eigrp 1
   passive-interface default
   no auto-summary
   network 192.168.33.0
   network 10.200.33.0 0.0.0.255
   network 172.16.0.33 0.0.0.255

Conclusion

Consistency in device configuration is important from an operational and security standpoint. A good way to achieve this is by building the configuration from a common template. In many cases only a few parameters need to be changed between similar devices deployed in similar roles. This article looked at how a very simple python script could parse a template file and build individual configuration files. Only a few changes would be required to the script to accept input from the command line or a file. These methods can be used as a starting point to build out a processes that will improve configuration consistency for network devices in any organization.

No related content found.

About Paul Stewart, CCIE 26009 (Security)

Paul is a Network and Security Engineer, Trainer and Blogger who enjoys understanding how things really work. With over 15 years of experience in the technology industry, Paul has helped many organizations build, maintain and secure their networks and systems.
This entry was posted in How-To. Bookmark the permalink.

8 Responses to Using Python with Templates to Build Consistent Device Configs

  1. dave_tucker says:

    Nice work! To get around the “raw_input” and “input” (Python 2 vs. Python 3) issue you can use the following…

    # Fix Python 2.x.
    try: input = raw_input
    except NameError: pass

    … and replace your “raw_input” with “input”. This should then run on any version of Python 🙂

  2. carlniger says:

    Very cool!

    I’m working on getting some Ansible templates for different platforms with variables for everything (banner, hostname, vty configs, vty acl, timezone, spt (where applicable), basic port config, 1st/2nd/3rd/4th octets) so for each new customer I go to I can just make a new variable file and automagically populate those generic/boring fields.

    I suppose all of that could be done entirely in Python too, however I imagine that the script would get fairly big fairly quickly, and wouldn’t have (without more work) the built in differentiation of roles per device.

    What are your thoughts on something like this, or kind of an old school excel doc w/ variables, etc vs Ansible?

  3. cpcshub says:

    .cfg is getting generated but it’s empty. any suggestion?

  4. Hi,
    How shall I do if I want to ask the user to start with a new configurationfile and start over again?

  5. simon says:

    Please make a correction in line 5
    instead of filein = open( ‘rtrtemplate.cfg’ )
    change it to
    filein = open( ‘rtrtemplate.py’ )

    Now it is working
    Thanks a lot paul

  6. praveen says:

    I tried this with .py but againg empty output. Any suggession.

  7. Amir says:

    worked fine with me, but i have a question.
    How to make it really interactive, like according to your example above , if we don’t have VoIP in specific location we shall remove the DHCP config of the VoIP pool; how to achieve this based on user input

Comments are closed.