Closed ak-empiak closed 2 years ago
:tada: Thanks for opening your first issue here! Welcome to the community!
op()
seems to be behaving properly:
In [1]: from panos.panorama import Panorama
In [2]: pano = Panorama(.......)
In [3]: pano.refresh_system_info()
Out[3]: SystemInfo(version='10.1.3-h1', platform='Panorama', serial='unknown')
In [4]: ans = pano.op('show system info')
In [5]: ans.attrib
Out[5]: {'status': 'success'}
In [6]: ans.text
In [7]: type(ans)
Out[7]: xml.etree.ElementTree.Element
In [8]: ans.tag
Out[8]: 'response'
So when you run op()
you get an xml.etree.ElementTree
back, you can get the tag of a given XML node, the attributes of a given node, and you can iterate over the children of the node by doing:
for subtag in ans:
print('tag:{0} attrib:{1}'.format(subtag.tag, subtag.attrib))
Hello, yes I'm sorry, I forgot to close this issue, you are right, ElementTree objects are still a bit a mystery to me : data are not visible through pycharm debugger, I had no idea how to get them. If it can help someone, here is a full working example for a "show devices summary" on a Panorama :
dict_summary = {}
session = Panorama(hostname=xxxxxxxxx, api_key=yyyyyyyyyyyyy)
command = f'show devices summary'
result = session.op(command)
xelement = result.find('result').find('device-summary')
dict_summary['connected'] = xelement.find('connected').text
dict_summary['dis-connected'] = xelement.find('dis-connected').text
dict_summary['sw-version'] = [{entry.attrib.get('name'): entry.find('count').text} for entry in
xelement.find('sw-version').findall('entry')]
dict_summary['app-version'] = [{entry.attrib.get('name'): entry.find('count').text} for entry in
xelement.find('app-version').findall('entry')]
dict_summary['dg-status'] = {'in-sync': xelement.find('dg-status').find('in-sync').text,
'out-sync': xelement.find('dg-status').find('out-sync').text}
dict_summary['tpl-status'] = {'in-sync': xelement.find('tpl-status').find('in-sync').text,
'out-sync': xelement.find('tpl-status').find('out-sync').text}
return dict_summary
And you have a beautiful dict.
Another option I use to navigate xml responses:
'''
find('./'element1/element2) = absolute path and must be specific to the xml tree from the root
find('.//'element1/element2) = goes to any depth in the tree to find the element
findall('.//devices/entry') = returns a list of all entries beneath devices
A trailing '/' in the find or findall string will find the child elements as opposed to the element last mentioned in the string
find('.//element1/element2') will find element2
find('.//element1/element2/' will find the child elements of element2
'''
from panos.panorama import Panorama
pano = (hn, un, pw)
result = pano.op('show devices connected')
# Search for a specific attribute such as a name:
hn = result.find('.//entry[@name="012345678901"]/hostname').text
# or using a variable
sn = '012345678901'
hn = result.find(f'.//entry[@name="{sn}"]/hostname').text
# Find the parent of an entry using a trailing '/..' which can be stacked out to go further up the tree '/../..'
sn = result.find('.//hostname/..').attrib['name']
# Find a specific text result from an element
sn = result.find('.//entry/[hostname="myHostname"]').attrib['name']
# or using a varialbe
hn = 'myHostname'
sn = result.find(f'.//entry/[hostname="{hn}"]').attrib['name']
# Search for child elements within the found element
ip = result.find(f'.//entry/[hostname="{hn}"].find('ip-address').text
st = result.find(f'.//entry/[hostname="{hn}"]/ha/state').text
# Getting fancy
for host in result.findall('.//ha/[state="active"]/../hostname'):
hn = host.text
It took a lot of research and help to pull these simple examples together and maybe it can help save someone else some time and effort.
Describe the bug
op method returns an successfull ElementTree without the content result.
Expected behavior
the text "attribute" of the xml.etree.ElementTree.Element result should contain the output of the command.
Current behavior
It is a NoneType type with None value (empty) Using the xml=True option works and returns the full output. It that normal that this last method returns a bytes object ? I tried to convert this bytes object into a ElementTree, but this new ElementTree has the exact same structure and content than the
Possible solution
i don't know.
Steps to reproduce
from panos.panorama import Panorama session = Panorama(hostname='192.168.103.10', api_key='**') result_et = session.op('show system info') ### successfull, but empty. result_xml = session.op('show system info', xml=True) ### successfull and returns output. import xml.etree.ElementTree as et result_xml_converted_to_et = et.fromstring(result_xml.decode()) ### result_xml is strictly identical as result_xml_converted_to_et
Screenshots
Context
I want to use the ElementTree object, which is simpler to get values, instead of the bytes object.
Your Environment
python 3.9.6 pan-python 0.16.0 panorama 10.1.3-h1