HP Procurve to Cisco switchport migration with Python and Netmiko

Summertime usually means a busy period for Network Engineers, customers are on holidays and we have the opportunity to performs all the changes that impact network connectivity.

For me this usually means core switch replacement.

Today I was moving a configuration from an HP8200 to a Cisco 4500, taking care of all the details of ports, trunks, vlans.

From this:

to this:

When a task is manual, boring, repetitive and error-prone my automation skills came to help.

The process

I prefer to write as little CLI commands as possible, so I start to work with and Excel spreadsheet with all the migration notes and what I call a switchmap.

In the switchmap, along with other information, I map the ports on the old switch to the ports on the new switch, something like

a1  g1/1
a2  g1/2

and so on for all the ports and modules.

This mapping will be used as input for the actual script.

Reading VLAN information from HP

From the HP switch it is possible to read detailed VLAN information and description for each port with this command:

sh vlans ports c1 detail 

The output for a trunk port is something like this:

Status and Counters - VLAN Information - for ports C1

 VLAN ID Name                 | Status     Voice Jumbo Mode    
 ------- -------------------- + ---------- ----- ----- --------
 100     Server               | Port-based No    No    Tagged  
 101     Clients              | Port-based No    No    Tagged  
 102     WiFi                 | Port-based No    No    Tagged  
 103     GuestWiFi            | Port-based No    No    Tagged  
 104     CCTV                 | Port-based No    No    Tagged  
 105     MGMT                 | Port-based No    No    Untagged
 106     IOT                  | Port-based No    No    Tagged  
 107     DMZ                  | Port-based No    No    Tagged  

An access port would be like this:

Status and Counters - VLAN Information - for ports C2

 VLAN ID Name                 | Status     Voice Jumbo Mode    
 ------- -------------------- + ---------- ----- ----- --------
 101     Clients              | Port-based No    No    Untagged  

The script

The script I created connects via SSH to the HP switch using NETMIKO. It uses the switchmap to read the list of switch ports, for each port it gets all the VLAN details.

With this information a for loop creates a file with all the commands translated to Cisco syntax. Notice that it’s not an elegant implementation, it adds each single vlan to the trunk instead of creating ranges, but it works fine.

from netmiko import ConnectHandler
import getpass
swip = raw_input('IP ADDRESS: ')
swun = raw_input('SWITCH USERNAME: ')
swpass = getpass.getpass()
connection = ConnectHandler(ip=swip, device_type='hp_procurve', username=swun, password=swpass)
cisco_output = open("cisco_output.txt", 'w')
portlist = open("portlist.total.txt", 'r')
for port in portlist:
    porthp = port.strip().split()[0]
    portcisco = port.strip().split()[1]
    print ("MAPPING HP PORT "+porthp+" TO CISCO PORT "+portcisco)
    command="sh vlans ports "+porthp+" detail"
    result = connection.send_command(command)
    cisco_output.write("interface "+portcisco+"\n") 
    trunk = 0
    if "Tagged" in result:
        trunk = 1
        cisco_output.write("switchport mode trunk\n")
        cisco_output.write("switchport trunk allowed vlan 1\n")
        if "Untagged" not in result:
            cisco_output.write("switchport trunk native vlan 1\n")            
        cisco_output.write("switchport mode access\n")
    for line in result.splitlines():     
        if "Tagged" in line and trunk:
            fields = line.strip().split()
            cisco_output.write("switchport trunk allowed vlan add "+fields[0]+"\n")
        elif "Untagged" in line:
            fields = line.strip().split()
            if trunk: cisco_output.write("switchport trunk allowed vlan add "+fields[0]+"\n"+"switchport trunk native vlan "+fields[0]+"\n")
            else: cisco_output.write("switchport access vlan "+fields[0]+"\n")
        elif "Port name" in line:
            fields = line.strip().split(":")
            cisco_output.write("description "+fields[1]+"\n")

This script is licensed under CC BY-SA.

Link on github

Final considerations

This script successfully migrated over 90 access and trunk ports. I consider this a success!

Robots will steal our job one day?

I think I’ll leave to the robot who wants to replace me just the boring tasks and I’ll keep the most creative ones.

Welcome to my fellow robot, we’ll be great friends!

comments powered by Disqus