1

Network guy that's new to Python and programming and found this ciscoconfparse library that looks to have some pretty useful features. I'm running into an issue that I'm sure is something basic, but haven't figured it out. I'm trying to pull snmp config from a router to create a config set to remove v2 configs. Using netmiko to grab output of "show run | in snmp" then parse it. The config that comes back shows as one line. When using ciscoconfparse statements to delete some lines, it deletes everything (assuming because it is only one line) so I have nothing left to build.

in all examples online, sample config looks like this and the functions work as it is multiple lines.

conf=[
        'access-list dmz_inbound extended deny udp object training-network any4 eq snmp',
        'snmp-server host inside 10.10.10.10 poll community ***** version 2c',
        'snmp-server host inside 10.20.20.20 poll community ***** version 2c',
        'no snmp-server location',
        'no snmp-server contact',
        'snmp-server community *****',
        '!'
        ]

when I actually pull config from a router, it looks like this with newline characters but gets parsed as 1 line:

'access-list testNada extended permit udp host 10.10.10.10 eq snmp host 10.20.10.10 eq snmp \nsnmp-server host inside 10.11.11.11 community ***** version 2c\nsnmp-server host inside 10.5.5.5 poll community ***** version 2c\nno snmp-server location\nno snmp-server contact\nsnmp-server community *****\n']

snippet of code I'm running. the delete line statements delete the whole config snip rather than just the line matching the arg.


    conf = [ssh.send_command("show run | include snmp")]
    parse = CiscoConfParse(conf)
    parse.delete_lines('no snmp-server')
    parse.delete_lines('access-list')
    newConf = (parse.replace_lines('snmp', 'no snmp',excludespec='v3'))

    ssh.send_config_set(newConf)

how do I get the config pulled directly from the router to show as multi-line so I can use the ciscoconfparse functions?

1
  • Use ciscoconfparse2 version 0.7.73 or later and it will read the configuration directly from netmiko... otherwise use CiscoConfParse(conf.splitlines()) as shown in my answer Commented Jul 6 at 18:10

3 Answers 3

0

You are passing a string to CiscoConfParse instead of a list.

Try the below:

conf = [ssh.send_command("show run | include snmp")]

# this will change your string into a list
formatted_output = conf.splitlines() 

parse = CiscoConfParse(formatted_output)
parse.delete_lines('no snmp-server')
parse.delete_lines('access-list')
newConf = (parse.replace_lines('snmp', 'no snmp',excludespec='v3'))

Explanation: Netmiko will return a string (/n means a new line, but it's still a string). When you use splitlines - it will transfer your string into a list (each line will be a new element)

1
  • tried that, but seems it does come back as a list, then I get an error. Here's code and error that generates now. conf=[ssh.send_command("show run | in snmp")] tConf=type(conf) print(tConf) output=conf.splitines() parse = CiscoConfParse(output) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <class 'list'> Traceback (most recent call last): File "/Users/xxxx/parseNX1.py", line 25, in <module> output=conf.splitines AttributeError: 'list' object has no attribute 'splitines'
    – spurious1
    Commented Jun 14, 2020 at 22:23
0

was able to get it to work by iterating over the list returned by netmiko, which returned a 'list in a list'. basically it was a list that had one index that happened to be the list containing the config.

newConf=[]
for i in conf:
    newConf.append(i.split("\n"))

which returned [['access-list testNada extended permit udp host 10.10.3.10 eq snmp host 10.10.10.10 eq snmp ', 'snmp-server host inside 10.4.233.8 community ***** version 2c', ....]]

then ran it through the parser for index 0.

parse = CiscoConfParse(newConf[0])

which resulted in multiple lines and I could use the delete_lines and replace_lines functions to produce the negated config I want to send back to my devices: ['no snmp-server host inside 10.4.233.8 community ***** version 2c', 'no snmp-server host inside 10.3.25.17 poll community ***** version 2c',...]]

0

Use ciscoconfparse2 instead of the now frozen ciscoconfparse (full disclosure: I am the author of ciscoconfparse2).

FYI, delete_lines() and replace_lines() is now deprecated. You should use BaseCfgLine().delete() and BaseCfgLine().re_sub()...

Also, use splitlines() to read the configuration directly from netmiko...

from ciscoconfparse2 import CiscoConfParse

conf = [ssh.send_command("show run | include snmp")]
parse = CiscoConfParse(conf.splitlines())

obj = parse.find_objects('no snmp-server')[0]
obj.delete()
# A manual commit is required in original ciscoconfparse
parse.commit()

obj = parse.find_objects('access-list')[0]
obj.delete()
# A manual commit is required in original ciscoconfparse
parse.commit()

for obj in parse.find_objects('^snmp-server'):
    if 'v3' in obj.text:
        continue
    obj.re_sub('snmp', 'no snmp')
    # A manual commit is required in original ciscoconfparse
    parse.commit()

# Use the new `get_text()` function in ciscoconfparse2
ssh.send_config_set(os.linesep.join(parse.get_text()))

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