cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Announcements
Walkthrough Wednesdays
22637
Views
26
Helpful
61
Replies
jseynaev
Cisco Employee

python client for AXL

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

If you are using an old version of CUCM, it may not have received security updates for keeping up with modern SSL/TLS best practices - most browsers (and perhaps programming libraries?) will fail to connect to services with outdated SSL/TLS connection modes (like small Diffie-Helman keys).  You may be able to find a CUCM update that will fix-up the connection security (though you may need to re-generate keys, etc.) - if you suspect this problem, Cisco TAC will be your mains source of assistance in performing this kind of update.

You are right... I tried that with CUCM 11.5 & it worked.. It seems like OpenSSL libraries of Python have issues accepting DH keys =<2048.

I had to make further modifications in the SSL/Socket configuration & make Python use Windows default cert store... Eventually after all the frustrations & hair pulling, it all worked out..

DH key too small error while running axl api scripts.

Any way to solve this error.
dstaudt
Cisco Employee

I suspect the <returnedTags> element is required for those requests:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/10.5">

   <soapenv:Header/>

   <soapenv:Body>

      <ns:getPhone sequence="1">

         <name>IPCMRAEU5UCM5X7</name>

         <returnedTags>

            <name/>

         </returnedTags>

      </ns:getPhone>

   </soapenv:Body>

</soapenv:Envelope>

jocreed
Cisco Employee

Jan,

did you ever get the answer you were looking for?.

I hope you are having a good day.

Thank You,

Jock

Yes, as I stated in my earlier post, if I do that patch, all is working fine...

Pretty much agree on all of the above, it's a bit of trial and error, indeed.

bradleysearle
Beginner

Pretty good info here, looks like your still the man Jan . Thanks ALL for the use full tips! I managed to get python talking to AXL. I had some errors around SSL, so i used urllib for the authentication. Should be able to use the SSL cert for authentication with minimal modifications. Hopefully this can save someone else from bashing their head against a wall

#Environment

#Centos7/UCM8.5/Python3/suds-jurko

#Note no patching of the file was required, I used the suds-jurko(0.6) from pip install.

#http://smirnov-am.blogspot.com.au/2015/04/monitoring-device-registration-with.html

#got the SSL workaround from above blog

import ssl

import urllib

from suds.transport.https import HttpAuthenticated

from suds.client import Client

t = HttpAuthenticated(username='AXL_USER', password='axlPass')

t.handler=urllib.request.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=urllib.request.HTTPSHandler(context=ssl_def_context)

t.urlopener = urllib.request.build_opener(t.handler,t1)

wsdl = 'file:///path/to/your/axl/file/axlsqltoolkit/schema/8.5/AXLAPI.wsdl'

client=Client(wsdl, location='https://10.1.1.1:8443/axl/', transport=t)

#Usage

phone = client.service.getPhone(name='SMITH-TEST')

print(phone['return']['phone']['lines']['line'][0]['dirn']['pattern'])

86116094

phones = client.service.listPhone({'devicePoolName':'CNT_DP'},{'name':'','model':''})

for i in phone['return']['phone']:

    print(i['name'], i['model'])

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

for i in dp['return']['devicePool']:

    print(i['name'])

Will try out some add methods now and see how that goes.

Thank you Bradley for your contributions :-)

Hi Jock and all,

Have you had any luck adding phones or phone profiles with Python/Suds. If so is it possible to share the code please ?

For example to add a phone I have tried a number of combinations here is one;

ap = client.service.addPhone({

               "name" : "AAAABBBBCCCCDDDD",

               "product": "Cisco 7975",

               "class": "Phone",

               "protocol": "SCCP",

               "protocolSide": "User",

               "devicePoolName": "test_dp",

               "commonPhoneConfigName": "Standard Common Phone Profile",

               "locationName": "Hub_None",

               "securityProfileName": "Cisco 7975 - Standard SCCP Non-Secure Profile",

               })

Everything I have tried has failed. Any help would be appreciated.

Cheers,

Brad

I am attaching the code below that worked for me.  I needed to add a few elements to make it work.  A little trial and error, but you could always try to do a little pruning if you see any elements I have included that you think are not necessary.  I also included some debugging function which I have always found useful.  Just be careful what you turn on to be at the DEBUG level, you may get more than you bargain with if you set everything to DEBUG.

Let me know what you think.

from suds.xsd.doctor import Import

from suds.xsd.doctor import ImportDoctor

from suds.client import Client

from suds.transport.https import HttpAuthenticated

import logging

cmserver = 'your.cucm.com'

cmport = '8443'

wsdl = 'file:///Your/location/ofWSDL/axlsqltoolkit10(5)/schema/current/AXLAPI.wsdl'

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

username = <USERNAME>

password = <PASSWORD>

logging.basicConfig(level=logging.CRITICAL)

logging.getLogger('suds.client').setLevel(logging.DEBUG)

logging.getLogger('suds.transport').setLevel(logging.DEBUG)

logging.getLogger('suds.xsd.schema').setLevel(logging.CRITICAL)

logging.getLogger('suds.wsdl').setLevel(logging.CRITICAL)

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

#print client

result = client.service.addPhone({'name':'SEP018888675309','class':'Phone','product':'Cisco 7975','protocol':'SCCP',

                                  'protocolSide':'User','devicePoolName':'Default',

                                  'commonPhoneConfigName':'Standard Common Phone Profile',

                                  'locationName':'Hub_None','securityProfileName':'Cisco 7975 - Standard SCCP Non-Secure Profile',

                                  'useTrustedRelayPoint':'Default','presenceGroupName':'Standard Presence Group','phoneTemplateName':'Standard 7975 SCCP',

                                  })

print result

Thank you Jock ! that worked Looks like I wasn't using a valid mac add (slaps face)

I did a bit of experimenting and found this to be the least number of elements that can be used for 7975

#add Phone

ap = client.service.addPhone({

                            'name': 'SEPAAAABBBB2222',

                            'product': 'Cisco 7975',

                            'class': 'Phone',

                            'protocol': 'SCCP',

                            'devicePoolName': 'test_dp',

                            })

note that I am using ucm10.5 for my test server.

Thank you again, much appreciated.

Bradley, Awesome, I am glad that worked for you.  Thanks for finding out the least number elements required for adding a 7975 phone.  that will come in handy.  I am also running this against 10.5  I might give it a shot against the 9.1 and 10.0 servers in our lab just to make sure that works as well.  Probably will, but you never know.

Hi guys,

Your code really does the trick! I have been playing with it but for some reason when I try a getPhone the suds parser adds some extra tags to the SOAP request.

I am using python version 2.7 and suds .4 (don't know if you might be working with different versions)

For example if I try this:

result = client.service.getPhone({'name':'CSFDEMOJABBER'})

print result

suds generates something like this:

<SOAP-ENV:Envelope xmlns:ns0="http://www.cisco.com/AXL/API/10.5" 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-ENV:Header/>

   <ns1:Body>

      <ns0:getPhone>

        <returnedTags>

            <name>CSFDEMOJABBER</name>

         </returnedTags>

      </ns0:getPhone>

   </ns1:Body>

</SOAP-ENV:Envelope>

This fails cause returnTags shouldn't be there.

If you remove those returnedTags the SOAP request works without any problems

I have been looking around and seems that you can modify the SOAP request before sending it to CUCM but haven't had any luck yet.

python - Incorrect XML produced by SUDS - Stack Overflow

python - Suds generates empty elements; how to remove them? - Stack Overflow

Any thoughts?

Thanks!

UPDATE

Got it working!! I had to use the messageplugin in suds in order to modify the soap message before it is sent to CUCM

in the client request you have to add the plugin

client = Client(wsdl,location=location, transport=t, plugins=[MyPlugin()])

then I look for the child inside the body of the message and rename it to 'name'

class MyPlugin(MessagePlugin):

    def marshalled(self, context):

       body = context.envelope.getChild('Body').getChild('getPhone').getChild('returnedTags')

       body.rename('name')

maybe is not that "clean" but it works for me, hope it helps someone.

Thanks!

He Eder,

Not sure what you are trying to achieve, but if you want to get a single phone details, you can do it by

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

If you want to only get specific info, you can use listPhones and pass a dictionary with the returnedTags argument

client.service.listPhone({'name':'SEP111111111111'}, returnedTags={'callingSearchSpaceName':'', 'description':''})

Cheers

Brad

Hi all,

Thanks for the very helpful information!

I'm trying to do the same to add a CSS with partitions but I'm not sure of the syntax. Anyone have any input on this?

# Add CSS

css_result = client.service.addCss({'name':'CSS_TEST',

                                    'description':'CSS_TEST_DESC',

                                    'members'{'member'{'routePartitionName':'PT_TEST','index':'1'}}

                                  })

print css_result

Getting a syntax error.

SyntaxError: invalid syntax

    'members'{'member'{'routePartitionName':'PT_TEST','index':'1'}}
                    ^
SyntaxError: invalid syntax

Content for Community-Ad

This widget could not be displayed.