Can't import api from exos


Hey everybody!

I'm working on a project with an Extreme Networks Summit X440-8p running firmware-version 16.1.1.4. I want to write a python script, but I'm stuck at the beginning.

The Python Scripting Guide (http://www.extremenetworks.com/wp-content/uploads/2015/02/Python_Getting_Started_Guide.pdf) tells me I have to import api from exos with the following line:

"from exos import api"

Unfortunately, every time I want to execute my script (which just has a print command at the moment), there's an error:

"* X440-8p.81 # run script print_test
Traceback (most recent call last):
File "/config/print_test.py", line 1, in
from exos import api
File "/exos/tools/lib/python2.7/site-packages/exos/api/__init__.py", line 21, in
File "/exos/tools/lib/python2.7/site-packages/exos/api/ems.py", line 10, in
ImportError: No module named _exos_ext_ems".

What am I doing wrong? It's exactly how the scripting guide tells me to import the api. This site tells me the same: http://documentation.extremenetworks.com/python/

Has anything changed since it looks like this site is for software-version 15.7.1 whereas I'm running 16.1.1.4?

Thanks in advance!
Mirco

22 replies

Userlevel 6
Marco,

I will look into the problem with loading the API, but you don't need to use the API to do simple python scripts. You can print "hello" by using the text below and run the python script.

print ("hello")[/code]
output:
Switch# run script test[/code]hello[/code]
Hello Stephen,

thanks for your reply and for looking into this issue!

I know that I can run simple scripts without loading the API but our aim isn't just printing something.

Actually, we want to read various parameters such as stream information (bandwidth etc.), and write them to a file, which we can read on a PC to display those data. We thought about using CLI-commands to achieve this. Therefore, we need the API.

Thanks again, hope you'll get back soon 🙂

Mirco
Userlevel 5
Hi Mirco,

EXOS has 2 python environments. one for writing scripts and the other for writing python apps.

Python that run with 'run script ' use the exsh library.

The python call you want is:

cliResult = exsh.clicmd(cmd, capture=True, xml=False)

If you wanted to capture the data in XML format instead of formatted CLI output:

xmlResult = exsh.clicmd(cmd, capture=False, xml=True)

Sometimes XML is easier to use to extract data instead of parsing the CLI output. CLI output format could change from release to release.

Here is a quick example with a pretty print script named xmlpp.py:

import xml.dom.minidom

xmlResult = exsh.clicmd('show ports statistics no-refresh', xml=True).replace('','\n')
for line in xmlResult.splitlines():
a = xml.dom.minidom.parseString(line)
print a.toprettyxml(indent=' ' * 4)

run script xmlpp.py



MORE


1
1
0
1869
1500
1868
1
1-34
0
608062
937
1869
0
334260
935
1868






MORE


2
2
0
0
1500
0
0
1-34
0
0
0
0
0
0
0
0






MORE


3
3
0
0
1500
0
0
1-34
0
0
0
0
0
0
0
0



etc ...

DaveH
Userlevel 6
I want to add to Dave's post. I created a script that will pull the ports, RX and TX bandwidth and display the data.

The function called cmd2data is used to make CLI output into a table of dictionaries.

Calling cmd2data function to run 'show port utilization bandwidth':
print cmd2data('show port utilization bandwidth')[/code]Output of the print command above is displayed below for one port only as an example:
{'show_ports_utilization': {'linkSpeed': 0, 'rxPeakBytesPerSec': 0, 'portNoSnmp': 0, 'txBytesPerSec': 0, 'portList': '1-54', 'rxPktsPerSec': 0, 'txPeakBytesPerSec': 0, 'txBwPeakPercent': '0.000000', 'rxBytesPerSec': 0, 'linkState': 0, 'rxBwPercent': '0.000000', 'samplingTime': 15, 'rxPeakPktsPerSec': 0, 'rxBwPeakPercent': '0.000000', 'txPeakPktsPerSec': 0, 'txBwPercent': '0.000000', 'txPktsPerSec': 0, 'port': 1}[/code]
The show_ports function grabs the data you want from the output that you want and prints it. You could add to the script to tftp the data to a tftp server. Hope this helps.

Python Script.
def cmd2data(clicmd):
import re
import xml.etree.cElementTree as ElementTree
re_reply = re.compile(r'.+?', re.DOTALL)
xmlout = exsh.clicmd(clicmd, capture=False, xml=True)
data = []
for reply in re.finditer(re_reply, xmlout):
if reply:
reply_xml = reply.group()
root = ElementTree.fromstring(reply_xml)
for message in root.iter('message'):
for element in message:
mdata = {}
edata = {}
for e in element:
text = int(e.text) if e.text is not None and e.text.isdigit() else e.text
edata[e.tag] = text
mdata[element.tag] = edata
data.append(mdata)
return data



def show_ports():
port_util = cmd2data('show port utilization bandwidth')
port_table = {}

for line in port_util:
port = line['show_ports_utilization']['port']
rx_bw = line['show_ports_utilization']['rxBwPercent']
tx_bw = line['show_ports_utilization']['txBwPercent']
print ("Port Number: %s --- RX BW: %s --- TX BW: %s") % (port,rx_bw,tx_bw)
print ("__________________________________________________________")
return port_table

show_ports()

Script output:

# run script portutil
Port Number: 1 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 2 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 3 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 4 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 5 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 6 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 7 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 8 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 9 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 10 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Userlevel 6
Stephen Williams wrote:

I want to add to Dave's post. I created a script that will pull the ports, RX and TX bandwidth and display the data.

The function called cmd2data is used to make CLI output into a table of dictionaries.

Calling cmd2data function to run 'show port utilization bandwidth':
print cmd2data('show port utilization bandwidth')[/code]Output of the print command above is displayed below for one port only as an example:
{'show_ports_utilization': {'linkSpeed': 0, 'rxPeakBytesPerSec': 0, 'portNoSnmp': 0, 'txBytesPerSec': 0, 'portList': '1-54', 'rxPktsPerSec': 0, 'txPeakBytesPerSec': 0, 'txBwPeakPercent': '0.000000', 'rxBytesPerSec': 0, 'linkState': 0, 'rxBwPercent': '0.000000', 'samplingTime': 15, 'rxPeakPktsPerSec': 0, 'rxBwPeakPercent': '0.000000', 'txPeakPktsPerSec': 0, 'txBwPercent': '0.000000', 'txPktsPerSec': 0, 'port': 1}[/code]
The show_ports function grabs the data you want from the output that you want and prints it. You could add to the script to tftp the data to a tftp server. Hope this helps.

Python Script.
def cmd2data(clicmd):
import re
import xml.etree.cElementTree as ElementTree
re_reply = re.compile(r'.+?', re.DOTALL)
xmlout = exsh.clicmd(clicmd, capture=False, xml=True)
data = []
for reply in re.finditer(re_reply, xmlout):
if reply:
reply_xml = reply.group()
root = ElementTree.fromstring(reply_xml)
for message in root.iter('message'):
for element in message:
mdata = {}
edata = {}
for e in element:
text = int(e.text) if e.text is not None and e.text.isdigit() else e.text
edata[e.tag] = text
mdata[element.tag] = edata
data.append(mdata)
return data



def show_ports():
port_util = cmd2data('show port utilization bandwidth')
port_table = {}

for line in port_util:
port = line['show_ports_utilization']['port']
rx_bw = line['show_ports_utilization']['rxBwPercent']
tx_bw = line['show_ports_utilization']['txBwPercent']
print ("Port Number: %s --- RX BW: %s --- TX BW: %s") % (port,rx_bw,tx_bw)
print ("__________________________________________________________")
return port_table

show_ports()

Script output:

# run script portutil
Port Number: 1 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 2 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 3 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 4 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 5 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 6 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 7 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 8 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 9 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________
Port Number: 10 --- RX BW: 0.000000 --- TX BW: 0.000000
_______________________________________________________________

This is impressive Stephen. Thanks.

Python in EXOS....very powerful together!
Hi Dave,thanks for your comment - the code works like a charm 🙂 Unfornutaley, we would like to run this script periodically without any user-interaction. Therefore, we would like to write a native python app which we yould start as a process.

We tried to do a print output to the console with the code-example in the python scripting guide (http://www.extremenetworks.com/wp-content/uploads/2015/02/Python_Getting_Started_Guide.pdf)

After we created the process with "create process test python-module test start on-demand" and started it with "start process test" it just says "Started test successfully". No print-output to the console at all... We even tried to run the example in the python scripting guide, but it just said "Buffer "MyBuffer" not found in MyFirstApp"

Can you give us any advice what we're doing wrong?

Thanks in advance!
Mirco
Ok, so i just figured out that the output won't be printed to the telnet-session-CLI but to the native CLI. Because that worked, I tried to execute a CLI command (show vlan), but it printed "command parse error" and "This command ("h") is not supported using execCLI XML API"

This is our code:

import sys
import logging
from exos import api

# Setup Logging
logger = logging.getLogger('xml_reader_process')
logger.setLevel(logging.DEBUG)
logHandler = api.TraceBufferHandler("MyBuffer", 5120)
logHandler.setLevel(logging.DEBUG)
logHandler.setFormatter(logging.Formatter("%(levelname)s:%(threadName)s:%(name)s:%(funcName)s.%(lineno)s:: %(message)s"))
logger.addHandler(logHandler)

try:

def main():
if not hasattr(sys, 'expy') or not sys.expy:
print "Must be run within expy"
return

print "Main started"
output = api.exec_cli("show vlan",5)
print output

main()

except BaseException, e:
logger.error("Exception on startup, {}".format(e), exc_info=True)


And this is the output:

Main started
Command parse error
This command ("h") is not supported using execCLI XML API.
Command parse error
Command parse error
Command parse error
Command parse error
Command parse error
Command parse error
Command parse error

I couldn't find a list of the supported commands, but I thought every CLI command would be supported - except those that has to be prompted?

It would be great if someone could have a look at our code and could explain what we're doing wrong!

Thanks so much 🙂
Mirco
Userlevel 7
Hi,

api.exec_cli() needs a dictionary as a first argument, not a string.

cmd = ['show vlan']
output = api.exec_cli(cmd,5)

should work.
Hi Stephane,

thanks a lot - it worked! I thought we would need a string because it's stated in the python scripting guide:

exos.api.exec_cli(cmds, timeout=0)

Send a list of commands to the CLI and return the output. This call will block until all commands have completed. This is a non-interactive, session-less version of the CLI. It doesn’t prompt or page, meaning some CLI commands are not valid in it (example: dis clipaging).

Parameters:
cmds (str): a list of commands.
timeout (int): timeout value, defaults to 0.

Returns:
A string of the CLI output (str).

So, we're now getting the formatted CLI output - is there a way to get it as XML like in the other python environment? As Dave stated, the CLI output could change from release to release, so it would be great to get XML instead of formatted CLI output.
Userlevel 5
Mirco wrote:

Hi Stephane,

thanks a lot - it worked! I thought we would need a string because it's stated in the python scripting guide:

exos.api.exec_cli(cmds, timeout=0)

Send a list of commands to the CLI and return the output. This call will block until all commands have completed. This is a non-interactive, session-less version of the CLI. It doesn’t prompt or page, meaning some CLI commands are not valid in it (example: dis clipaging).

Parameters:
cmds (str): a list of commands.
timeout (int): timeout value, defaults to 0.

Returns:
A string of the CLI output (str).

So, we're now getting the formatted CLI output - is there a way to get it as XML like in the other python environment? As Dave stated, the CLI output could change from release to release, so it would be great to get XML instead of formatted CLI output.

To run a periodic script using the 'run script' python environment, I would suggest using the EXOS UPM capability. This would allow capturing the XML information in the script. The script will be started by UPM and runs to completion each time. It also simplifies the script a bit by letting UPM determine when, and how often, the script should run. It would also be possible to enter 'run script

Scanning file for viruses.

Sorry, we're still checking this file's contents to make sure it's safe to download. Please try again in a few minutes.

OK

This file cannot be downloaded

Sorry, our virus scanner detected that this file isn't safe to download.

OK