napalm-automation-community / napalm-panos

NAPALM driver for PAN-OS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`get_facts` raises exception when there is only one physical interface

gjim83 opened this issue · comments

Description of Issue/Question

When a device only has one physical interface active, the current get_facts will raise an exception because xmltodict will parse the entry key as a dictionary, instead of list of dictionaries, but the current function expects the latter.

Did you follow the steps from https://github.com/napalm-automation/napalm#faq

  • Yes
  • No

Setup

napalm-panos version

(Paste verbatim output from pip freeze | grep napalm-panos between quotes below)

$ pip freeze | grep napalm-panos
napalm-panos==0.4.0

PanOS version

(Paste verbatim output from show system info between quotes below)

sw-version: 7.0.10

Steps to Reproduce the Issue

Try to run get_facts from a PanOS devices with only one physical interface. In my case, the API returns the following for <show><interface>all</interface></show>:

<response status="success"><result>
  <ifnet>
    <entry>
      <name>ethernet1/1</name>
      <zone/>
      <fwd>N/A</fwd>
      <vsys>1</vsys>
      <dyn-addr/>
      <addr6/>
      <tag>0</tag>
      <ip>N/A</ip>
      <id>16</id>
      <addr/>
    </entry>
    <entry>
      <name>ethernet1/1.135</name>
      <zone>Untrust</zone>
      <fwd>vr:default</fwd>
      <vsys>1</vsys>
      <dyn-addr/>
      <addr6/>
      <tag>135</tag>
      <ip>10.20.30.40/29</ip>
      <id>256</id>
      <addr/>
    </entry>
  </ifnet>
  <hw>
    <entry>
      <name>ethernet1/1</name>
      <duplex>full</duplex>
      <type>0</type>
      <state>up</state>
      <st>10000/full/up</st>
      <mac>00:ca:fe:be:ef:00</mac>
      <mode>(autoneg)</mode>
      <speed>10000</speed>
      <id>16</id>
    </entry>
  </hw>
</result></response>

Error Traceback

(Paste the complete traceback of the exception between quotes below)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/neteng/guido-venv/nsm-base/nsm_base/bin/base.py", line 164, in __init__
    self.get_device_facts()
  File "/home/neteng/guido-venv/nsm-base/nsm_base/bin/base.py", line 196, in get_device_facts
    facts = dev.get_facts()
  File "/home/neteng/guido-venv/lib/python3.5/site-packages/napalm_base/base.py", line 60, in __exit__
    self.__raise_clean_exception(exc_type, exc_value, exc_traceback)
  File "/home/neteng/guido-venv/lib/python3.5/site-packages/napalm_base/base.py", line 95, in __raise_clean_exception
    raise exc_value
  File "/home/neteng/guido-venv/nsm-base/nsm_base/bin/base.py", line 196, in get_device_facts
    facts = dev.get_facts()
  File "/home/neteng/guido-venv/lib/python3.5/site-packages/napalm_panos/panos.py", line 377, in get_facts
    if intf['name'] not in facts['interface_list']:
TypeError: string indices must be integers

I fixed it locally by changing the for loop here https://github.com/napalm-automation/napalm-panos/blob/develop/napalm_panos/panos.py#L373 to:

for element in interfaces:
    for entry in interfaces[element]:
        if isinstance(interfaces[element][entry], list):
            for intf in interfaces[element][entry]:
                if intf['name'] not in facts['interface_list']:
                    facts['interface_list'].append(intf['name'])
        else:
            if interfaces[element][entry]['name'] not in facts['interface_list']:
                facts['interface_list'].append(interfaces[element][entry]['name'])

I added some tests to my branch as well, I can post the PR if it makes sense.

Hey @gjim83 , sorry for the very long delay in coming back to you.

What you have looks good to me, would you mind opening a PR?

done! thanks @GGabriele

Thank you!