Using python to create uniform network configurations

One of the first things that I’d like to highlight that has helped me in my role as a network engineer is utilizing python to create uniform network configurations for branch sites. Essentially I just use a “cookie cutter” device template that I’ve replaced the site specific details with variables. Then I use a python script that goes through and automatically builds out the configuration for the device. From here the programming could easily be configured to build the configuration for the routers, populate the network monitoring system with the new devices, and even push the configuration out to the devices automatically. I wanted to keep this post bite size and show that python doesn’t need to be connected to the devices directly to be highly useful.

There’s a few things to note here before we get started:

  • These examples are created for Juniper EX4300 switches, though can easily be repurposed for any other model or vendor of network equipment.
  • The python script was made using python3.7 and doesn’t work on earlier versions.
  • The device template is assuming an IP scheme using /16 subnets to differentiate between locations.

The first step is to build out a device template configuration and then replace the site specific information with variables.

In this example you can see how I’ve created the variables at the top for location, host name, and site specific IP information. I then also added comments in the configuration that I use as a variable only when more than two switches are required for the site (if not used they are simply ignored as comments).

#Switch Template
#
#Replace following variables with site specific info: 
#
#Description of Item 		- [variable name]
#hostname 			- [hostname]
#Branch number 			- [xx]
#City Name 			- [name]
#City-State 			- [location]
#Switch 01 Serial Number 	- [serial_1]
#Switch 02 Serial Number 	- [serial_2]
#Port configuration if more than 2 switches 	         - /*additional_swch_ports*/
#Virtual Chassis configuration if more than two switches - /*additional_swch_vr_chas*/
#
# Load the following configuration on the switch core
set system host-name [hostname]
set system services dhcp-local-server group server1 interface irb.1
set system services dhcp-local-server group server2 interface irb.2
set system commit synchronize
set chassis redundancy graceful-switchover
set chassis alarm management-ethernet link-down ignore
set interfaces interface-range access_ports member-range ge-0/0/1 to ge-0/0/47
set interfaces interface-range access_ports member-range ge-1/0/0 to ge-1/0/47
/*additional_swch_ports*/
set interfaces interface-range access_ports unit 0 family ethernet-switching interface-mode access
set interfaces interface-range access_ports unit 0 family ethernet-switching vlan members vlan1
set interfaces ge-0/0/0 description "Uplink to RTR01"
set interfaces ge-0/0/0 unit 0 family inet address 10.[xx].3.1/24
set interfaces irb unit 1 description "Data Network"
set interfaces irb unit 1 family inet address 10.[xx].1.1/24
set interfaces irb unit 2 description "Voice Network"
set interfaces irb unit 2 family inet address 10.[xx].2.1/24
set interfaces lo0 unit 0 family inet address 10.[xx].255.3/32
set snmp location "[location]"
set routing-options nonstop-routing
set protocols ospf area 0.0.0.0 interface ge-0/0/0.0
set protocols ospf area 0.0.0.0 interface lo0.0 passive
set protocols ospf area 0.0.0.0 interface irb.1 passive
set protocols ospf area 0.0.0.0 interface irb.2 passive
set access address-assignment pool pool1 family inet network 10.[xx].1.0/24
set access address-assignment pool pool1 family inet range range1 low 10.[xx].1.20
set access address-assignment pool pool1 family inet range range1 high 10.[xx].1.200
set access address-assignment pool pool2 family inet network 10.[xx].2.0/24
set access address-assignment pool pool2 family inet range range1 low 10.[xx].2.20
set access address-assignment pool pool2 family inet range range1 high 10.[xx].2.200
set switch-options voip interface access_ports vlan vlan2
set switch-options voip interface access_ports forwarding-class expedited-forwarding
set virtual-chassis preprovisioned
set virtual-chassis member 0 role routing-engine
set virtual-chassis member 0 serial-number [serial_1]
set virtual-chassis member 1 role routing-engine
set virtual-chassis member 1 serial-number [serial_2]
/*additional_swch_vr_chas*/
set vlans vlan1 description "Data Vlan"
set vlans vlan1 vlan-id 1
set vlans vlan1 l3-interface irb.1
set vlans vlan2 description "Voice Vlan"
set vlans vlan2 vlan-id 2
set vlans vlan2 l3-interface irb.2

The second step is to build out a python script to match and replace the variables in the switch template.

Import switch_template file

t = open(r"switch_template.txt", "r")
tempstr = t.read()
t.close()

Ask user for site information

print('What is the hostname of the device?')
hostname = input()

print('What is the branch IP number? Example: type 28 for 10.28.10.1')
ipxx = input()

print('What City is the branch in? Example: Paris')
city = input()

print('What State or Country is the branch in? Example: France')
state = input()

print('How many switches will the branch have?')
switch_number = int(input())

switch_dict = {}
for i in range(switch_number):
    switchnumber = i
    print("What is the serial number of switch ",i,"?")
    switch_dict.update( {switchnumber: input()})

If more than two switches, create additional lines of configuration for port and virtual chassis

add_sw_ports = ""
add_sw_vr_chass = ""

for k, v in switch_dict.items():
    if k > 1:
        k = str(k)
        add_sw_ports += ("set interfaces interface-range access_ports member-range ge-"+k+"/0/1 to ge-"+k+"/0/47\n")
        add_sw_vr_chass += ("set virtual-chassis member "+k+" serial-number "+v+" role line-card\n")

Create dictionary that references variables in switch_template and above newly created variables

device_values = {
    '[hostname]': hostname,
    '[xx]': ipxx,
    '[name]': city,
    '[location]': city_state,
    '[serial_1]': switch_dict[0],
    '[serial_2]': switch_dict[1],
    '/*additional_swch_ports*/': add_sw_ports, 
    '/*additional_swch_vr_chas*/': add_sw_vr_chass,
    }

Finally, replace the variables in switch_template with newly created variables and then print this out

for key,val in device_values.items():
    tempstr = tempstr.replace(key,val)

print(tempstr)

You can find the example switch template and python script on my GitHub account: 


https://github.com/timjbaron/switch-template-python.git