cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
3393
Views
14
Helpful
5
Replies

CUCM Device Registration Status from RIS via zeep

derek.fraser
Level 1
Level 1

There a couple client choices for python to generate a soap request to access data from CUCM. Not trying to reinvent the wheel I used examples that were readily available online for another client that hasn't been updated/supported in a while.

At the recommendation of another engineer I wanted to challenge myself to migrate to a modern/actively maintained soap client for python, which leads us to zeep.  Some benefits of zeep is the project is actively maintained, python2/3 support, faster than other clients (definitely noticeable on larger UC clusters), good documentation and some nice helper features.

There are limited examples available with zeep (especially UC related) so I thought I'd share a RISPort70 request to CUCM 11.5 and some of the hurdles I had getting it working in hopes it might benefit others.

First off, read the docs.  Zeep has some good documentation and an active community.  Familiarize yourself with the wsdl you're working with, Cisco provides really nice docs in the DevNet API Developer Guide:

https://developer.cisco.com/site/sxml/documents/api-reference/risport/

Another tool that helped me out was using SoapUI to examine the wsdl, zeep also comes bundled with a wsdl inspector that helps view the client operations.

python -mzeep <wsdl>

I got tripped up on selectCmDevice as it has some nested complex data objects.  I tried passing the client straight kwargs for the selection criteria, which worked but did not honor the complex data "SelectItems" (at least with child dictionaries in the parent kwargs).  This led me to creating a factory with zeep that we can use to send the nested data to CUCM.  The zeep history plugin really helped me out, you can view your sent/received soap envelope to see if your constructing the xml the way the DevNet guide expects.

My use case is more focused towards all registered phones in the cluster, but included is a loop to iterate over a list of mac addresses in case individual devices are desired.

Hopefully the below can help, thanks again for the great community!

Python 3.5.2

Zeep 2.5.0

CUCM 11.5.1(SU4)

from zeep import Client

from zeep.cache import SqliteCache

from zeep.transports import Transport

from zeep.plugins import HistoryPlugin

from requests import Session

from requests.auth import HTTPBasicAuth

from lxml import etree

import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

username = 'username'

password = 'password'

wsdl = 'file:///path/to/RISService70.wsdl'

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])

factory = client.type_factory('ns0')

macs = ['SEP111122223333', 'SEP222233334444'] #'*' for all

item=[]

for mac in macs:

    item.append(factory.SelectItem(Item=mac))

Item = factory.ArrayOfSelectItem(item)

stateInfo = ''

criteria = factory.CmSelectionCriteria(

    MaxReturnedDevices = 1000,

    DeviceClass='Phone',

    Model=537,    #255 for all

    Status='Registered',

    NodeName='',

    SelectBy='Name',

    SelectItems=Item,

    Protocol='Any',

    DownloadStatus='Any'

)

result = client.service.selectCmDevice(stateInfo, criteria)

print(result)

#troubleshooting soap envelope

for hist in [history.last_sent, history.last_received]:

    print(etree.tostring(hist["envelope"], encoding="unicode", pretty_print=True))

5 Replies 5

Randall White
Level 3
Level 3

Thank you for posting the code. I have tried running it, but get an error:

ValueError: No visitor defined for '{http://www.w3.org/2001/XMLSchema}documentation'

Did you ever see this error? The only Google references are for the zeep project, it is listed as a closed bug on Github.

I am running zeep 2.5.0, python 3.6.0, CUCM 10.5(2)

Thanks, Randy

I was getting this error as well and it was because I was referencing the wrong RIS WSDL file.  I was referencing the RPC/Encoded WSDL file found at https://<ServerName>:8443/realtimeservice/services/RisPort70?wsdl and I needed to use the Doc/Literal version found at https://<ServerName>:8443/realtimeservice2/services/RISService70?wsdl.  Once I pointed to the correct WSDL file I was able to get the connection to work.

Hi

Thanks a lot, it helped me.

This is working perfectly with print(result)

However, I have added few lines to display output in table format, so that I can copy the output and open it in CSV.

Added few lines as below

result = client.service.selectCmDevice(stateInfo, criteria)
for node in (result['SelectCmDeviceResult']['CmNodes']):
for device in node['CmDevices']:
print (device['Name'], device['IpAddress'], device['DirNumber'], device['Description'])

 

If I just print (result) I am getting output as below output, I want to display output in proper way, onlt name, IP address, directory number and description
But while adding "for device in node" I am getting error on this line as below;
for device in node['CmDevices']:
error is:
Traceback (most recent call last):
File "phone2.py", line 40, in <module>
for device in node['CmDevices']:
TypeError: string indices must be integers

 

Pls. advice why TypeError: string indices must be integers

rajesh.kumar
Level 4
Level 4

Hi

This is working perfectly with print(result)

However, I have added few lines to display output in table format, so that I can copy the output and open it in CSV.

Added few lines as below

result = client.service.selectCmDevice(stateInfo, criteria)
for node in (result['SelectCmDeviceResult']['CmNodes']):
for device in node['CmDevices']:
print (device['Name'], device['IpAddress'], device['DirNumber'], device['Description'])

 

If I just print (result) I am getting output as below output, I want to display output in proper way, onlt name, IP address, directory number and description
But while adding "for device in node" I am getting error on this line as below;
for device in node['CmDevices']:
error is:
Traceback (most recent call last):
File "phone2.py", line 40, in <module>
for device in node['CmDevices']:
TypeError: string indices must be integers

 

Pls. advice why TypeError: string indices must be integers

 

I know it's an old thread but I didn't see anyone post a working example of navigating the response in zeep so here's what worked for me.

 

result = client.service.selectCmDevice(stateInfo, criteria)
for node in result.SelectCmDeviceResult.CmNodes.item:
  for device in node.CmDevices.item:
    print (device.Name)

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: