cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
32911
Views
26
Helpful
61
Replies

python client for AXL

jseynaev
Cisco Employee
Cisco Employee

Hello,

I have a nice working toolset that is interacting very well with AXL interface using PHP.

However, we are looking to switch to python (it does look like this would be a lot easier to process data coming in). Unfortunately, i can't find any working example to connect to the AXL interface.

suds seems to be the way to go, but that's not working on python3. I'm happy doing this in python2, but still, i don't get suds to get the works done ... any working example is welcome! (i'll give you a working PHP example in return ;p )

Jan.

61 Replies 61

jocreed
Cisco Employee
Cisco Employee

Jan,

Below I have provided some sample code to use with AXL.  I use the "Requests" libraries to process HTTP so if you use the below code exactly you will need to download the Requests library for python.  Also, and I am sure you know this, but please change your keep your AXL version consistent with the CUCM you are using.  The below code is using AXL 8.5.  Let me know if you have any questions.

Thank You,

Jock

import requests

import xml.etree.ElementTree as ET

soaprequest = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/8.5"><soapenv:Header /><soapenv:Body><ns:listPhone><searchCriteria><name>SEP%</name></searchCriteria><returnedTags><name></name></returnedTags></ns:listPhone></soapenv:Body></soapenv:Envelope>'

soapheaders = {'Content-type':'text/xml', 'SOAPAction':'CUCM:DB ver=8.5 listPhone'}

AXLRequest = requests.post('https://CMServer:8443/axl/', data = soaprequest, headers = soapheaders, verify = False, auth=('username','password'))

root = ET.fromstring(AXLRequest.text)

DeviceNames = []

for phone in root.iter('phone'):

    DeviceNames.append(phone.find('name').text)

    #print phone.find('name').text

print DeviceNames

Thx Kristopher, that's indeed working and a good first step ;-)

Kind of complicated, though. I do use quite a few methods and with the php SoapClient, i can just load the connection with the  xdml file and give the parameters in a nice array / list ... and get the stuff back in sort of a nice way.

So if anyone can give a working example using SUDS, that would be perfect.

I did find something that's working in Python2 for the RIS interface:

Parky's Place: Using Python to call Cisco Communications Manager Serviceability SOAP API

Havent' been able to port that to work with AXL though ...

For what it's worth, I've tried AXL with Python Suds and pysimplesoap.  Suds seems to create XML that AXL doesn't like, and I get this error when I try to use an API:

AttributeError: 'NoneType' object has no attribute 'promotePrefixes'

I get a little farther with Pysimplesoap, but in the end I haven't figured out how to call an API.  Here's code to get you started, though, if you're interested (substitute your own username, password, and server, and point to the place where you have the WSDL and XSDs):

from pysimplesoap.client import SoapClient

import base64

wsdl="http://localhost/AXLAPI.wsdl"

location="https://server:8443/axl"

action="https://server:8443/axl"

ns='http://schemas.cisco.com/ast/soap/'

username="username"

password="password"

toencode=username + ':' + password

encoded=base64.b64encode(bytes(toencode,"utf-8"))

client = SoapClient(wsdl=wsdl, location=location, action=action, ns=ns, http_headers={'Authorization': 'Basic %s' % encoded})

print(client.help('listPhone'))

jocreed
Cisco Employee
Cisco Employee

try this Python SUDS code.  I am running this on Python 2.7.8 on Windows 7

from suds.client import Client

cmserver = '10.10.10.10'

cmport = '8443'

wsdl = 'file:///your/system/path/schema/current/AXLAPI.wsdl'

location = 'https://' + cmserver + ':' + cmport + '/axl/'

username = 'username'

password = 'password'

client = Client(wsdl,location=location, username=username, password=password)

result = client.service.listPhone({'name':'SEP%'},{'name':'','model':''})

for node in result['return']['phone']:

    print str(node['name']), str(node['model'])

I am getting below error when i am running given code:

result = client.service.listPhone({'name':'SEPEXXXXD958F06'},{'name':'','model':''})

print(result)

for node in result['return']['phone']:

    print str(node['name']), str(node['model'])

************

(200, (reply){

   return =

      (return){

         phone[] =

            (LPhone){

               _uuid = "{51D5AC0A-E3F9-C05B-B446-4F1ACD6D0472}"

               name = "SEPEXXXXD958F06"

               model = "Cisco 7945"

            },

      }

})

Traceback (most recent call last):

  File "C:\Python27\Scripts\Listphone1.py", line 58, in <module>

    for node in result['return']['phone']:

TypeError: tuple indices must be integers, not str

Any help will be appreciated.

jseynaev
Cisco Employee
Cisco Employee

Waw, i think i have figured it out ... but it's a  bit a painful one. Got it working for get* methods too now, list is working also (as it always did), still have to try add* stuff.

So, here's how it goes:

  • Windows7 (shouldn't matter that much) and Python3.4.2
  • install suds-jurko with pip
  • PATCH the file (not kidding) C:\Python34\Lib\site-packages\suds\bindings\document.py
    you just need to comment out line 141:
                   if not child.isattr():
    (there's only one line like this, so you can't miss)
  • TADAA, all is working. if i understand it correct, suds does not pull in 'optional' stuff from wsdl and with the above patch it should do that now

As I don't know suds at all, here's a very rudimentary example for a get* request (pretty much based on the answers above ;p)

wsdl = 'file:///C:/path/to/your/matching/AXLAPI.wsdl'

from suds.client import Client

client = Client(wsdl,location='https://yourserverhere:8443/axl/',username='yourusername',password='yourpassword')

phone = client.service.getPhone(name='test')

print(phone)

(reply){

   return =

      (return){

         phone =

            (RPhone){

               _uuid = "{50BCA715-C781-C8B0-CC90-E0B95CB2F1AD}"

               _ctiid = 9

               name = "jseynaev-test"

               description = "jseynaev-test"

               product = "Cisco IP Communicator"

< ... very long list of params ... >

Let me know if this works for you too!

Jan.

I did a pip install suds-jurko with Python34, and it didn't install C:\Python34\Lib\site-packages\suds\bindings\document.py.  I believe everything necessary is packed in the egg file, and I didn't extract it or edit document.py there. 

However, the following code still worked fine for me:

from suds.client import Client

from suds.transport.https import HttpAuthenticated

cmserver = 'server'

cmport = '8443'

wsdl = 'PATH/TO/AXLAPI.wsdl'

location = 'https://' + cmserver + ':' + cmport + '/axl/'

username = 'username'

password = 'password'

client = Client(wsdl,location=location, transport = HttpAuthenticated(username=username, password=password))

result = client.service.listPhone({'name':'SEP%'},{'name':'','model':''})

for node in result['return']['phone']:

    print (str(node['name']), str(node['model']))

Yes, the list* calls seem to work fine 'out of the box', however, things like getPhone or getRegion (try e.g. region = client.service.getRegion(name='Default')) throw an error of some non-defined property ...

Not sure how the whole pip install works, but for me that's where the file was, maybe it installed it somewhere in your home directory? (i choose to install 'for everyone on this pc')

This works for me in the above example in place of listPhone:

result = client.service.getPhone(name='SEP010101010101')

print(result)

I tried various ways of specifying returnedTags, but nothing I tried worked.  Suds is not extremely well documented when it comes to using a WSDL like AXLAPI.    By the way, I'm using the 10.5 WSDL against a 10.5 CUCM. 

I agree with Nick.  There is not a lot of documentation for using AXL with suds or any other python soap handlerfor that matter, even pysimplesoap.  His assessment is also correct with usage of tags.  Trying to find out exactly what works with suds was a little difficult.  when I posted my code in my last post the only way I was able to figure it out for the listPhone was through a little trial and error with the tags.  Also, I was able to get it to work without patching the file you mentioned

I think depending on the call you are using you might have to adjust how you write the tags, so you might have a little trial and error on that one.  which would be a benefit in the future maintaining your code.  That being said you could always use the old fashioned way like my very first post on this thread, depends on your preference and how simple or complex you want to make it considering your trade offs of time and how mush maintenance you are willing to do to your code.

Below is the final code sample I have combining Nick's testing and my own.  Let us know if that works for you or if you are having trouble with any other calls in AXL.

from suds.client import Client

cmserver = '10.10.10.10'

cmport = '8443'

wsdl = 'file:///your/file/location/schema/current/AXLAPI.wsdl'

location = 'https://' + cmserver + ':' + cmport + '/axl/'

username = 'user'

password = 'pass'

client = Client(wsdl,location=location, username=username, password=password)

result = client.service.getPhone(name = 'IPCMRAEU5UCM5X7')

print result

I forgot to mention that in my last post the code is utilizing the 9.1 version of AXL. 

Hi Jan & everyone,

I know I am a very late entrant to this but I am stuck at the same point which is being discussed in this forum. I've tried multiple combinations of the script but the error keeps popping up. Following is one of the script examples that I tried after importing URLLIB2 since URLLIB doesn't work with Python 2.7 . Any kind of help or direction will be greatly appreciated. I've hit a dead end on my own.

***************************************************

import ssl

import urllib

import urllib2

from suds.client import Client

from suds.transport.https import HttpAuthenticated

from suds.xsd.doctor import Import

import logging

from suds.xsd.doctor import ImportDoctor

t = HttpAuthenticated(username='ccmadmin', password='pswd')

t.handler = urllib2.HTTPBasicAuthHandler(t.pm)

ssl_def_context = ssl.create_default_context()

ssl_def_context.check_hostname = False

ssl_def_context.verify_mode = ssl.CERT_NONE

t1=urllib2.HTTPSHandler(ssl_def_context)

t.urlopener = urllib2.build_opener(t.handler,t1)

wsdl = 'file:///C:/actual path/axlsqltoolkit/schema/current/AXLAPI.wsdl'

location = 'https://10.1.2.5:8443/axl/'

username = 'ccmadmin'

password = 'pswd'

client = Client(wsdl,location=location, transport=t)

resp = client.service.listDevicePool({'name':'%'},{'name':''})

print resp

**********************************************************************

The error that keeps popping up is following

Traceback (most recent call last):

  File "C:\Users\Simran\Desktop\PythonScripts\CUCMDetails.py", line 36, in <module>

    resp = client.service.listDevicePool({'name':'%'},{'name':''})

  File "C:\Python27\lib\site-packages\suds\client.py", line 542, in __call__

    return client.invoke(args, kwargs)

  File "C:\Python27\lib\site-packages\suds\client.py", line 602, in invoke

    result = self.send(soapenv)

  File "C:\Python27\lib\site-packages\suds\client.py", line 637, in send

    reply = transport.send(request)

  File "C:\Python27\lib\site-packages\suds\transport\https.py", line 64, in send

    return  HttpTransport.send(self, request)

  File "C:\Python27\lib\site-packages\suds\transport\http.py", line 77, in send

    fp = self.u2open(u2request)

  File "C:\Python27\lib\site-packages\suds\transport\http.py", line 118, in u2open

    return url.open(u2request, timeout=tm)

  File "C:\Python27\lib\urllib2.py", line 429, in open

    response = self._open(req, data)

  File "C:\Python27\lib\urllib2.py", line 447, in _open

    '_open', req)

  File "C:\Python27\lib\urllib2.py", line 407, in _call_chain

    result = func(*args)

  File "C:\Python27\lib\urllib2.py", line 1241, in https_open

    context=self._context)

  File "C:\Python27\lib\urllib2.py", line 1198, in do_open

    raise URLError(err)

URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)>

>>>

It looks like the attempt to disable certificate checking for the SSL connection is not working in your code.  It appears that suds does not include a simple way to disable cert checking.

Here is a similar example that has some info on actually using cert checking (which should be best practice anyway:)

Re: Python CUCM 10.5 AXL updateLine

Yes.. you are right...I've made some more modifications in the script & now I get an error about DH keys being too small. One way or the other, it never gets past certificate authentication point.

But I don't see anyone here facing such issues... they all seem to run the same script & get the desired results which makes me wonder if I am skipping something basic and why is it behaving this way in my case. Any help in that regards will be very useful because I am at a dead end & don't know what to follow now.

I'll try the cert checking method given in the link & see if it results in something different. Thanks very much for that.