4

New to stack exchange and Python. Hopefully this is allowed to be asked.

I am taking a class on Python and finally starting to dip my toe into the water.

I have a ton to learn but I already have a use case that I personally would find helpful and practical.

I have an upcoming project that will require me to login and touch every device, finding all instances of "ip-helper" configured and altering the current IP addresses stored.

Since the ip-helper exists under any number of SVIs, not only would you have to be able to do a show run and find all instances of ip-helper being configured but you'd also have to be able to identify what SVI its configured under to then generate the new config that would have to be applied.

Would anyone have a working example of a script that would do this that I can learn from and use?

I would think something like this could be applied to many things when it comes to Cisco device configuration? Finding any number of strings, checking to make sure if it is a sub configuration and what the parent would be prior to generating and applying new replacement config?

1
  • 1
    You could look up some resources on the Internet. Product and resource recommendations are explicitly off-topic here, as are questions about programming which should be asked on Stack Overflow, where there are many network-savvy programmers, but they will expect you to show your work and where you think you may have gone wrong. – Ron Maupin Jan 28 '16 at 23:02
2

Welcome to SE!

As a network engineer I too have recently started programming in Python to better support my own internal automation efforts. In the interest of avoiding a lot of manual work handling the low-level ssh processing that comes with working with CLI, I have focused exclusively on the scripting interface that comes with the SecureCRT application. If you have SecureCRT you can review its scripting capabilities and its documentation will show you how you can use Python scripts like the one below with it. Even if you do not have SecureCRT, you can use the following code as a general outline of how you can put such a script together using native ssh daemons, provided you handle all of the low-level SSH/CLI work separately. Please note that this code was created under the assumption that you are only working with modern Cisco wired network devices with relatively recent versions of IOS.

I MAKE NO WARRANTY OF ANY KIND ON THIS CODE IN ITS CURRENT STATE. THIS IS BASIC TESTING CODE AND NOT INTENDED FOR PRODUCTION. IT MAY BREAK YOUR NETWORK!

You have been warned :)

# $language = "python"
# $interface = "1.0"
import sys
import re

# Your hosts file should just be a list of IP's, each on its own line
HOSTSFILE = '\path_to\your_hosts_file.txt'
USER = 'username'
PASS = 'password'
ENABLEP = 'enablepassword'
NEW_HELPER_CMD = 'ip helper-address x.x.x.x'

def Wait():
    # Wait for a prompt
    while True:
        if not crt.Screen.WaitForCursor(1):
            break
def Get_prompt():
    row = crt.Screen.CurrentRow
    prompt = crt.Screen.Get(row, 0, row, crt.Screen.CurrentColumn - 1).strip()
    return prompt
def Get_list_from_file(file_path):
    f = open(file_path, 'r')
    hostlist = f.readlines()
    f.close()
    return hostlist
def Log_in(host):
    login_command = '/SSH2 /L {0} /PASSWORD {1} {2}'.format(USER, PASS, host)
    try:
        crt.Session.Connect(login_command)
        crt.Session.Synchronous = True
        Wait()
        return True
    except:
        # More specific except clauses needed
        # For specific error conditions, add corresponding error messages
        return False
def Exec_mode():
    prompt = Get_prompt()
    tries = 0
    # Enter priveleged exec mode if not already there
    while tries > 4:
        if re.search(r'#$', prompt):
            break
        elif re.search(r'[>]$', prompt):
            crt.Screen.Send('enable\n')
            Wait()
            prompt = Get_prompt()
            if re.search(r'Password:', prompt):
                crt.Screen.Send('{0}\n'.format(ENABLEP))
                Wait()
        elif re.search(r'\)$', prompt):
            crt.Screen.Send('end\n')
            Wait()
        tries += 1
    if tries >= 4:
        # Add an error code stating that exec_mode failed
        return False
    else:
        return True
def Config_mode():
    prompt = Get_prompt()
    if re.search(r'#$', prompt):
        crt.Screen.Send('config t\n')
        Wait()
    else:
        b = Exec_mode()
        if b:
            crt.Screen.Send('config t\n')
            Wait()
    prompt = Get_prompt()
    if re.search(r'\)$', prompt):
        return True
    else:
        return False
def Pull_and_parse_config():
    Wait()
    crt.Screen.Send('term len 0\n')
    Wait()
    prompt = Get_prompt()
    # Output the runnning config
    crt.Screen.Send(r'sh running-config\n')
    crt.Screen.WaitForString(r'\n')
    # Capture config output to string var 'config'
    # Note: If there is any duplicate of the 'prompt' string in the config, it will stop the
    # capture prematurely
    config = crt.Screen.ReadString(prompt)
    Wait()
    # Split the captured config into a list, containing the interface string, old ip helper string, and
    # remaining config. Will capture each interface on the device that currently has an ip helper command
    # Note: this only captures the first ip helper command on each interface
    configlist = re.split(r'(interface [^\n]+?)\n[^!]*?(ip helper-address .+?)\n', config, flags=re.DOTALL)
    if len(configlist) > 1:
        configlist.pop(0)
        return configlist
    else:
        # add message stating no interfaces matched
        return False
def Update_config(configlist):
    # For each interface with an ip helper command, remove old command and add new helper command
    while len(configlist) > 2:
        int_id = configlist.pop(0)
        old_helper_cmd = configlist.pop(0)
        if re.search(r'interface .+', int_id) and re.search(r'ip helper-address .+', old_helper_cmd):
            Enter_config_mode()
            # Here is where you actually update the config
            # If you don't want to remove old helper command, remove "no {1}\n" from the following string
            crt.Screen.Send('{0}\n no {1}\n {2}\n'.format(int_id, old_helper_cmd, NEW_HELPER_CMD))
            Wait()
            return True
        elif not re.search(r'interface .+', int_id):
            # add error message stating invalid interface id
            return False
        else:
            # add error message stating invalid ip helper command
            return False
def Main():
    hostfile = Get_list_from_file(HOSTSFLIE)
    for host in hostfile:
        ok = Log_in(host)
        if not ok:
            # add error message stating login failed
            continue
        ok = Exec_mode()
        if not ok:
            # add error message here
            continue
        configlist = Pull_and_parse_config()
        if not configlist:
            # add error message stating config capture failed
        ok = Update_config(configlist)
        if not ok:
            # add error message stating config update failed
        else:
            # add success message stating config on host successfully updated

Main()

You will see that this involves a fair amount of code for something that seems like it should be simple, and this performs only one specific task! If you are still new to the scripting/programming world I highly recommend you consult with a more experienced programmer before attempting to implement any scripts in your production network, particularly anything like this that involves modifying configs. Although I adapted this code from some previous work I have done, I have not tested this and I cannot guarantee that any of this will work. Nevertheless, this should provide you with a good starting point. Good luck!

2
  • I just wanted to say thanks for taking the time to share this. It is quite a bit and I am new to Python. I do use SecureCRT so this is extra interesting to me. The code itself looks well detailed (in the opinion of this rookie anyway) and I am excited to dissect it and learn from it as well as see how I can make it work for my needs. I plan to start testing in lab and go from there. Thank you for all the insight I feel this code will provide me in learning. – ddevalco Apr 7 '16 at 6:31
  • @user22424 glad to help! FWIW, I have recently switched from securecrt scripts to a native python library called netmiko. If you are looking for network CLI scripting in Python, netmiko is a solid resource to use. It is developed and is actively maintained by a developer who also happens to be a long-time CCIE. – halfmetaljacket Apr 9 '16 at 1:31
0

You could use PrettyGoodTerminal to run the below Python script to get the helper addresses and relevant SVI names and build your update config as you need:

import re

# report status back to PGT if you need    
ActionResult = "ip helper not found"

result = Terminal.ExecCommand("sh ip int brief","#")
commandResult = result[0]
timedout = result[1]
if not timedout:
  for thisLine in commandResult.splitlines():
    ifList = filter(None, thisLine.split(" "))
    if ifList[4] == "up" and ifList[5] == "up":
      ifName = ifList[0]
      result = Terminal.ExecCommand("sh run int {0}".format(ifName), "#")
      ifconfig = result[0]
      timedout = result[1]
      if not timedout:
        helperAddresses = re.findall(r'ip helper-address.*',ifconfig)
        if len(helperAddresses) > 0:
          # report status back to PGT if you need
          ActionResult = "ip helper found"
          # Here you have the SVI name in ifName and the helperAddresses list containing the defined ip helper-addresses

Alternatively you can also build a nice Visual Script with the above Python code added to a Command element, then add another Command element to execute the constructed update script. Like this: Visual Script to update ip helper-address

Just let me know if you need help with PGT ;-)

5
  • Product and rexource recommendations are explicitly off-topic here. – Ron Maupin Apr 6 '16 at 14:25
  • Is the same applies to SecureCRT, PyCharm, Visual Studio and Python.exe, too as all are products ? Or what makes the difference when I post a code which can be a solution for the question and can be helpful for solving a problem ? I did not make a promotion but rather just suggested a code... – user24335 Apr 6 '16 at 15:20
  • You should use more generic terms, e.g. terminal applications, but don't specifically recommend any product. Almost no SE sites allow product recommendations since it can lead to flame wars (e.g., mine is bigger than yours). – Ron Maupin Apr 6 '16 at 15:29
  • Understood, will try to be less specific on products in the future – user24335 Apr 6 '16 at 17:00
  • Appreciate the info and will definitely look into this code to see what I can learn from it. Thank you! – ddevalco Apr 7 '16 at 6:29
0

You can use a library called ciscoconfparse, it understands and can parse cisco ios as parent and child items using the indents. I Have done exactly this in a production environment, I updated the ip helpers on 600 routers, a quick google search should land you in the documentation for the ciscoconfparse library

1
  • 1
    You should post an example – user36472 Mar 26 '18 at 19:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.