cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
33057
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

Don't have a Suds example, but if it helps attaching a (rather inelegant) Python script I put together to bulk-create a bunch of users/lines/phones - it just uses XML templates and .format() manipulations to handle the variables.

Thanks for the example will have a look at see what I can get together, it seems like I may end up using suds and requests to get what I want done.

Thanks

Glen

Thanks Brad! You have been a great help! That worked for me!

Not sure what's up with the update issue. You mentioned using the suds doctor? Did that work for you with CUCM 10.5? Is there anything special you used to get it working?

Sorry Travis, moderation is so slow here, might be better to move the question over the stackoverflow

frank.darrigo
Level 1
Level 1

Wow.  Thank you everyone for your detailed examples.  It's reassuring to know I am not in the Python AXL boat all alone.  This has been a frustrating few weeks as I tip toe through the the API.  I have had some of the same frustations as you, but there is one in particular that's driving me crazy.

I want to change the routing for a route list.  Basically, I have a route list for a site (Site A) with 3 route list members (Site A, Site B, Site C - in that order) and I want to change it Site B, Site C, Site A.

I thought I could do it with the AXL api but I can't find a way to list them route list members.

Any ideas?

Frank

I should have mentioned it, but I am running CUCM 9.1

Hey Franck,

Give this a try, I just tested it and it updates route list in v8.6, I don't have 9.1 to test, but it should be similar if different.

Just change the selection order to the order that you want the route groups in the list.

For example, originally I had ABC_RG in position 1 and TSTING_RG in position 3, when I ran this code, ABC_RG was in position 3 and TSTING_RG was in position 1

client.service.updateRouteList(

    name='TST_RL',

    members={'member': [{

                'selectionOrder' : 1,

                'routeGroupName': 'TSTING_RG'

                }, {

                'selectionOrder' : 2,

                'routeGroupName': 'BRI_RG'

                }, {

                'selectionOrder' : 3,

                'routeGroupName': 'ABC_RG'

                }]

            })

Cheers,

Brad

Hey Brad-

Thanks for the code, but unfortunately, it didn't work.  I'm getting the following errors:

Server raised fault: no uuid or name element found

No handlers could be found for logger "suds.client"

I ran into this problem when trying to list the route members and I thought the problem had to due with a lack of searchCriteria in the WSDL.

The complete code looks like this:

cmserver = myserver'

cmport = '8443'

wsdl = 'file:///c:/axlapi/schema/9.1/AXLAPI.wsdl'

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

username="username"

password="password"

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

client.service.updateRouteList(

name=my_RL',

members={'member': [{

'selectionOrder' : 1,

'routeGroupName': apple_RG'

}, {

'selectionOrder' : 2,

'routeGroupName': blueberry_RG'

}, {

'selectionOrder' : 3,

'routeGroupName': cherry_RG'

}]

})

After some more digging - and looking at other posts on this thread, I adopted an alternate approach

def updateRouteList (device):

   SOAP = '<SOAP-ENV:Envelope xmlns:ns0="http://www.cisco.com/AXL/API/9.1" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">'

   SOAP += '<SOAP-ENV:Header/>'

   SOAP += '<ns1:Body>'

   SOAP += '<ns0:updateRouteList>'

   SOAP += '<name>' + device + '</name>'

   SOAP += '<description>my description</description>'

   SOAP += '<addMembers><member><selectionOrder>4</selectionOrder><routeGroupName>XYZ-PSTN_RG</routeGroupName></member></addMembers>'

   SOAP += '<removeMembers><member><selectionOrder>3</selectionOrder><routeGroupName>BCD-PSTN_RG</routeGroupName></member></removeMembers>'

   SOAP += '</ns0:updateRouteList>'

   SOAP += '</ns1:Body>'

   SOAP += '</SOAP-ENV:Envelope>'

   return SOAP

This changes the routeList description, adds a new routeGroup (XYZ-PSTN_RG) and deletes another RG (BCD-PSTN_RG).

I suppose one way of reordering the list is to remove all the member routeGroups and then add them to RL in their new order.

Unless someone else has a better idea....

Hello All,

first of all thanks all for the examples and the code you are providing. I'm not a programmer at all and tried to get a Little script running, just to get a phone from CUCM. That I would then use as a start for further Needs.

But I get all the time an error for that I cannot find a solution.

CUCM 10.5

Windows Server (where python is installed)

Here is my code:

from suds.xsd.doctor import Import
from suds.xsd.doctor import ImportDoctor
from suds.client import Client
import logging

logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)

cmserver = 'server'
cmport = '8443'
wsdl = 'file:///C:/Python27/CUCM/schema/current/AXLAPI.wsdl'
location = 'https://' + cmserver + ':' + cmport + '/axl'
username = 'username'
password = 'password'

# Define Authentication header to be appended to SOAP Requests to avoid 401 Unauthorized Response from CUCM
base64string = base64.encodestring('{}:{}'.format(username, password)).replace('\n', '')
authentication_header = {
    "SOAPAction" : "ActionName",
    "Authorization": "Basic {}".format(base64string)
}

tns = 'http://schemas.cisco.com/ast/soap/'
imp = Import('http://schemas.xmlsoap.org/soap/encoding/', 'http://schemas.xmlsoap.org/soap/encoding/')
imp.filter.add(tns)

client = Client(wsdl,location=location,faults=False,plugins=[ImportDoctor(imp)],
                headers=authentication_header)


result = client.service.getPhone(name='SEP00B0E15FD2D7', returnedTags={'name'})

print result

Here the Result incl. error message I get:

>>> DEBUG:suds.client:sending to (https://ccmserver:8443/axl)
message:
<suds.sax.document.Document instance at 0x0000000025293BC8>
DEBUG:suds.client:headers = {'SOAPAction': 'ActionName', 'Content-Type': 'text/xml; charset=utf-8', 'Authorization': 'Basic TWF0dGhpYXM6Q2lzY28xMjMhIQ=='}
DEBUG:suds.client:HTTP succeeded:
<html><head><title>Cisco CallManager: AXL Web Service</title></head><body>
<h1>Cisco CallManager: AXL Web Service</h1>
<p>The AXL Web Service is working and accepting requests.
Use HTTP POST to send a request.</p></body></html>

ERROR:suds.client:<suds.sax.document.Document instance at 0x0000000025293BC8>
Traceback (most recent call last):
  File "C:\Python27\Lib\site-packages\Pythonwin\pywin\framework\scriptutils.py", line 326, in RunScript
    exec codeObject in __main__.__dict__
  File "E:\Matthias Files\Scripts\CUCM_get_lines_test2.py", line 31, in <module>
    result = client.service.getPhone(name='SEP00B0E15FD2D7', returnedTags={'name'})
  File "C:\Python27\lib\site-packages\suds\client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "C:\Python27\lib\site-packages\suds\client.py", line 581, in invoke
    result = self.send(soapenv)
  File "C:\Python27\lib\site-packages\suds\client.py", line 621, in send
    original_soapenv=original_soapenv)
  File "C:\Python27\lib\site-packages\suds\client.py", line 685, in process_reply
    self.method, replyroot)
  File "C:\Python27\lib\site-packages\suds\bindings\binding.py", line 134, in get_reply
    soapenv.promotePrefixes()
AttributeError: 'NoneType' object has no attribute 'promotePrefixes'

I see, that the Connection and authentication to CUCM is working, but I get the AttributeError and don't know how to solve that.

Can you help?

Thanks a lot!

Kind regards

DrM

Hello all,

Nice to see this one popping up every now and then

For what it's worth, I have abandoned using SUDs or any other framework, just too much work to get it running. Zeep was working well after the author tweaked it a bit, but it still takes like 10secs to load the wsdl ... which might be ok for a script, but running it for a webpage, that's just too long.

I have written a quick mockup class which will create the SOAP XML content itself, based on the given function name and an argument dict. It's using quick and dirty dicttoxml and xmltodict to do the magic ...

Of course, there's no stubs are anything similar, so you need to figure out the arguments (and their behaviour) from the wsdl yourself (or use the AXL Schema reference), but I find once you get the hand of it, they are all very similar

BUT it is superfast as it doesn't need to load the huge wsdl and totally independant of any heavy weight soap framework ... and only a couple lines of code !

Have a look at:https://github.com/jseynaev-cisco/ucmaxlapi

there's a couple of 'test' cases in the __main__ that you can run safely. I tested these in both Python2 and Python3 ... so that's another plus

Leave some comments/suggestions if you like, it's called 'Raw' for a reason, but I'll probably add some functions to wrap some of the calls I use most commonly (like the executeSQLQuery, which is a bit of an odd one out anyways) or add some helpers to get the output in a list or csv string ...

Kind regards,

Jan.

Hello Jan,

thanks a lot for your effort and the Script.

I just wanted to test it, but I get an Error Message:

>>> Traceback (most recent call last):

  File "C:\Python27\Lib\site-packages\Pythonwin\pywin\framework\scriptutils.py", line 326, in RunScript

    exec codeObject in __main__.__dict__

  File "E:\Matthias Files\Scripts\New_Script_Test.py", line 94, in <module>

    axl = RawAxl(*sys.argv[1:])

TypeError: __init__() takes at least 3 arguments (1 given)

As I said, I'm not really a programmer. So I do not know what arguments it is meaning. Because there are three test cases in the script.

Thanks!

Greetings

M

right, it needs username, pwd and server. Like this:

$ python ucmaxlapi.py <username> <password> <server>

username and password being a user that has AXL rights, might need to put the password in brackets " " to catch the special characters

server being the one that is running AXL (all servers in the cluster by default)

Cheers,

Jan.

Hi again,

ah. Ok. That was my mistake. I wanted to add the URL, username and Password directly in the script. And that did not work.

Thanks!

Kind regards,

M

Here is a small sample using the Jurko variant of SUDS that I got working awhile back, hope it helps:

# Installing a root/CA Certificate

# (Tested on Ubuntu 16.10)

# Retrieve certificate from CUCM

#    - openssl s_client -showcerts -connect cucm-node.example.com:443 </dev/null 2>/dev/null|openssl x509 >cucm-node.example.com.crt

# Store certificate on the client

#    - Create a directory for extra CA certificates in /usr/share/ca-certificates:

#        sudo mkdir /usr/share/ca-certificates/extra

#    - Copy the CA .crt file to this directory:

#        sudo cp foo.crt /usr/share/ca-certificates/extra/foo.crt

#    - Append the certificate path (relative to /usr/share/ca-certificates) to /etc/ca-certificates.conf

#        sudo dpkg-reconfigure ca-certificates

# In case of a .pem file, it must first be converted to a .crt file:

#    openssl x509 -in foo.pem -inform PEM -out foo.crt

from suds.client import Client

# import logging

# logging.basicConfig(level=logging.INFO)

# logging.getLogger("suds.transport").setLevel(logging.DEBUG)

client = Client("file:///home/dstaudt/Documents/AXL/v10.5(1)/axlsqltoolkit/schema/10.5/AXLAPI.wsdl",

    location="https://ds-ucm105.cisco.com/axl/",

    username="Administrator",

    password="ciscopsdt")

newLine = {

        "pattern" : "5555",

        "routePartitionName": ""

}

result = client.service.addLine(newLine)

ean = {

    "numMask": "8XXXX",

    "isUrgent": True,

    "addLocalRoutePartition": True,

    "routePartition": "testPartition"

}

result = client.service.updateLine(

    pattern = "5555",

    routePartitionName = "",

    description = "test description",

    useEnterpriseAltNum = True,

    enterpriseAltNum = ean

)