I have one other idea. There is a script included with EXOS: cli2json.py.
This script runs any EXOS command, captures the XML and converts it to JSON.
JSON may be easier to process since python has simple conversion routines that converts JSON to/from dictionaries/lists.
From the app environment, spawn an EXOS shell to run the cli2json.py script with the desired CLI command and collect the data in JSON. An example python snippet is below.
You can run cli2json.py from the cli prompt to see what kind of information a show command will give you before including it in a script. My recommendation is to run it from a telnet session instead of the console since it can display a lot of data and console speeds are slow.
Be sure to use the -d when running it from a CLI prompt so the output is human readable.
It is important not to use the 'auto refresh' capabilities of some of the EXOS commands. E.g. show ports will display a list of ports and refresh it on the screen. If it is called from cli2json.py, the script will never return.
The cli2json.py JSON output also has a variable CLIoutput which contains what the actual CLI display would have been for the command. This way you get the formatted output as well as the data structures that were used to create the display
The non-refreshing format of that command would look like: show ports no-refresh
From a CLI prompt: run script cli2json.py -d
E.g.
run script cli2json.py -d show port 1-2 statistics no-refresh
[
{
"CLIoutput": "Port Link Tx Pkt Tx Byte Rx Pkt Rx Byte Rx Pkt Rx Pkt Tx Pkt Tx Pkt\n State Count Count Count Count Bcast Mcast Bcast Mcast\n========= ===== =========== =========== =========== =========== =========== =========== =========== ===========\n1 A 128 22980 128 22599 0 65 0 63\n2 R 0 0 0 0 0 0 0 0\n========= ===== =========== =========== =========== =========== =========== =========== =========== ===========\n > in Port indicates Port Display Name truncated past 8 characters\n > in Count indicates value exceeds column width. Use 'wide' option or '0' to clear.\n Link State: A-Active, R-Ready, NP-Port Not Present, L-Loopback\n"
},
{
"show_ports_stats": {
"dot1dTpPortInDiscards": 0,
"dot1dTpPortInFrames": 128,
"dot1dTpPortMaxInfo": 1500,
"dot1dTpPortOutFrames": 128,
"linkState": 1,
"port": 1,
"portList": "1-2",
"portNoSnmp": 1,
"rxBcast": 0,
"rxByteCnt": 22599,
"rxMcast": 65,
"rxPktCnt": 128,
"txBcast": 0,
"txByteCnt": 22980,
"txMcast": 63,
"txPktCnt": 128
},
"status": "MORE"
},
{
"show_ports_stats": {
"dot1dTpPortInDiscards": 0,
"dot1dTpPortInFrames": 0,
"dot1dTpPortMaxInfo": 1500,
"dot1dTpPortOutFrames": 0,
"linkState": 0,
"port": 2,
"portList": "1-2",
"portNoSnmp": 2,
"rxBcast": 0,
"rxByteCnt": 0,
"rxMcast": 0,
"rxPktCnt": 0,
"txBcast": 0,
"txByteCnt": 0,
"txMcast": 0,
"txPktCnt": 0
},
"status": "SUCCESS"
}
]
Now for the scripting part.
Spawning an EXOS shell from inside the app environment enables the app to run the cli2json.py script and collect the JSON formatted result.
import subprocess
import json
def exos2json(cmd):
JSONERROR = 'error'
shellCmd = '/exos/bin/exsh -n 0 -b -c "run script cli2json.py {0}"'.format(cmd)
p = subprocess.Popen([shellCmd], shell=True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
(stdoutdata, stderrdata) = p.communicate()
try:
jsonData = json.loads(stdoutdata)
except:
jsonData = {JSONERROR:'error processing command {0}'.format(cmd)}
return jsonData
#example calling an EXOS show command
jsonData = exos2json('show ports 1 statistics no-refresh')
print json.dumps(jsonData, sort_keys=True, indent=2)
[
{
"CLIoutput": "Port Link Tx Pkt Tx Byte Rx Pkt Rx Byte Rx Pkt Rx Pkt Tx Pkt Tx Pkt\n State Count Count Count Count Bcast Mcast Bcast Mcast\n========= ===== =========== =========== =========== =========== =========== =========== =========== ===========\n1 A 147 26426 147 26036 0 74 0 72\n========= ===== =========== =========== =========== =========== =========== =========== =========== ===========\n > in Port indicates Port Display Name truncated past 8 characters\n > in Count indicates value exceeds column width. Use 'wide' option or '0' to clear.\n Link State: A-Active, R-Ready, NP-Port Not Present, L-Loopback\n"
},
{
"show_ports_stats": {
"dot1dTpPortInDiscards": 0,
"dot1dTpPortInFrames": 147,
"dot1dTpPortMaxInfo": 1500,
"dot1dTpPortOutFrames": 147,
"linkState": 1,
"port": 1,
"portList": 1,
"portNoSnmp": 1,
"rxBcast": 0,
"rxByteCnt": 26036,
"rxMcast": 74,
"rxPktCnt": 147,
"txBcast": 0,
"txByteCnt": 26426,
"txMcast": 72,
"txPktCnt": 147
},
"status": "SUCCESS"
}
]