I’ve seen a lot more folks interested in working on UC automation and custom scripting against CUCM using AXL. This is great news. Unfortunately, Python, unlike other languages like Java, has no standard lib support for SOAP. This means that most samples online end up being one of:
- DIY with requests
- Suds (I’m not going to share a link)
Requests is excellent for REST, but as SOAP is a standard, re-inventing the wheel is just plain dumb. Copypasta of static xml strings is horrible as well. We want to automate stuff on CallManager – not screw around with xml tags! We need a library that does the heavy lifting for us.
Suds is not it. Everyone starts here because the only samples available online use suds. Suds has not been actively maintained for a number of years. It has been forked, and the most recent fork is also now not maintained. And it’s slow. Very, very slow.
Please use python-zeep. It is several orders of magnitude faster than suds. It is under active development. It abstracts away xml entirely and lets you work with native Python objects. It supports serialization. It’s a great piece of software.
So, since its the one thing that all UC engineers want when they get started… here is a Hello World for a simple add operation to CUCM. It was tested with Python 3.6.
# -*- coding: utf-8 -*- from zeep import Client from zeep.cache import SqliteCache from zeep.transports import Transport from zeep.exceptions import Fault from zeep.plugins import HistoryPlugin from requests import Session from requests.auth import HTTPBasicAuth from urllib3 import disable_warnings from urllib3.exceptions import InsecureRequestWarning from lxml import etree disable_warnings(InsecureRequestWarning) USERNAME = 'axl_magician' PASSWORD = '99problemsbutsudsaint1' FQDN = "192.168.99.99" WSDL = 'file://C://path//to//AXLAPI.wsdl' BINDING_NAME = "{http://www.cisco.com/AXLAPIService/}AXLAPIBinding" ADDRESS = "https://{fqdn}:8443/axl/".format(fqdn=FQDN) def main(): session = Session() session.verify = False session.auth = HTTPBasicAuth(USERNAME, PASSWORD) transport = Transport(cache=SqliteCache(), session=session, timeout=20) history = HistoryPlugin() client = Client(wsdl=WSDL, transport=transport, plugins=[history]) axl = client.create_service(BINDING_NAME, ADDRESS) kwargs = { "name": "Hello World AAR Group" } try: axl.addAarGroup(aarGroup=kwargs) except Fault: for hist in [history.last_sent, history.last_received]: print(etree.tostring(hist["envelope"], encoding="unicode", pretty_print=True)) if __name__ == '__main__': main()
I’ve included the xml dump on failures.
Happy coding, and pouring over the AXL API docs!
Hi,
First of all, thank you for sharing your knowledge.
I saw a script using suds, do you know what is the command in zeep similar to this one? I’ve tried, client.service.listphone using zeep but there is no “listphone” option.
result = client.service.listPhone({‘name’:’%SEP%’},{‘name’:”,’description’:”,’model’:”,’protocol’:”})
LikeLiked by 1 person
Don’t have a setup to run this against now… but in the case here with python-zeep, I’ve created the following service in a variable I call ‘axl’:
axl = client.create_service(BINDING_NAME, ADDRESS)
The call for listPhone would then be:
phone_kwargs = {
‘searchCriteria’: {
‘name’:’SEP%’,
},
‘returnedTags’: {
‘name’:”,
‘description’:”,
‘model’:”,
‘protocol’:”
}
}
result = axl.listPhone(**phone_kwargs)
The dict you supplied looks fine at face value. Let me know if you still have trouble and I’ll follow-up with a live api call check…
See this:
https://github.com/mvantellingen/python-zeep/issues/449
LikeLike