icovada / netwalk

Python library to discover, parse, analyze and change Cisco switched networks
https://netwalk.readthedocs.io/en/latest/
GNU Affero General Public License v3.0
42 stars 8 forks source link

_parse_config() in `netwalk/device.py` is not parsing the running config correctly #12

Closed mpenning closed 2 years ago

mpenning commented 2 years ago

netwalk/device.py has a pretty bad bug as of git hash efd5b8d5affd877df4739a639b2d2762c4d94057... explicitly:

    def _parse_config(self):
        """Parse show run
        """
        if isinstance(self.config, str):
            running = StringIO()
            running.write(self.config)

            # Be kind rewind
            running.seek(0)

            # Get show run and interface access/trunk status
            parsed_conf = CiscoConfParse(running)

You are asking CiscoConfParse() to parse a configuration from a string. This is broken... you should be parsing a list, tuple or MutableSequence()... as such, this is one possible way to fix your call to CiscoConfParse():

icovada commented 2 years ago

This is because ciscoconfparse changed the type of data they accept I have pushed a fix for this just yesterday in branch dev

Can you check if you're having any issues with commit f27817e48accc3dd62c65b5858b33c14d200765f?

EDIT: I didn't notice you're the maintainer for that lib

mpenning commented 2 years ago

This is because ciscoconfparse changed the type of data they accept

No, I did not change the datatypes accepted. Before you ripped it out of your code, your running variable was a multi-line string, which is not a valid configuration input. CiscoConfParse() treats a string as a configuration filename.

You previously specified ciscoconfparse==1.5.30 in your requirements.txt

Notice what happens in 1.5.30 if you submit a multiline string... CiscoConfParse() throws an error because it sees that multi-line string as an invalid filename.

(py310_test) [mpenning@mudslide ~]$ pip freeze | grep cisco
ciscoconfparse==1.5.30
(py310_test) [mpenning@mudslide ~]$
(py310_test) [mpenning@mudslide ~]$ python gh_251.py
[FATAL] CiscoConfParse could not open '
!
!
end
'
Traceback (most recent call last):
  File "/opt/virtual_env/py310_test/lib/python3.10/site-packages/ciscoconfparse/ciscoconfparse.py", line 268, in __init__
    f = open(config, **self.openargs)
FileNotFoundError: [Errno 2] No such file or directory: '\n!\n!\nend\n'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/mpenning/gh_251.py", line 25, in <module>
    parse = CiscoConfParse(config)
  File "/opt/virtual_env/py310_test/lib/python3.10/site-packages/ciscoconfparse/ciscoconfparse.py", line 343, in __init__
    raise RuntimeError
RuntimeError
(py310_test) [mpenning@mudslide ~]$

However if you call CiscoConfParse("/home/mpenning/foo_config.conf"), and /home/mpenning/foo_config.conf is a real filename with a real config in it, the string is accepted with no problems. This has been the design since I first built it... consider this __init__() that I ripped out of version 0.8.2 (circa 2009)...

    def __init__(self, config):
        """Initialize the class, read the config, and spawn the parser"""
        if type(config) == type([ 'a', 'b' ]):
            # we already have a list object, simply call the parser
            ioscfg = config
            self.parse(ioscfg)
        elif type(config) == type("ab"):
            try:
                # string - assume a filename... open file, split and parse
                f = open(config)
                text = f.read()
                rgx = re.compile("\r*\n+")
                ioscfg = rgx.split(text)
                self.parse(ioscfg)
            except IOError:
                print "FATAL: CiscoConfParse could not open '%s'" % config
                raise RuntimeError
        else:
            raise RuntimeError("FATAL: CiscoConfParse() received an invalid argument\n")

Short story, I think we both fixed some things... I found some sketchy string comparisons in ciscoconfparse Issue #251 and I think you removed the multiline string issue in netwalk. If you find any other ciscoconfparse problems, please do not hesitate to let me know.

mpenning commented 2 years ago

My concern with netwalk/device.py was addressed... thank you!