Recently I started to receive more and more complaints from my users that my Cisco video codecs are not working. The problem was that these same users had unplugged ethernet cords from the codecs so they lost registration with CUCM. So I decided to create some tool to monitor registration status of video endpoints and possibly 7937 conference phones (they’ve got unplugged too).
I decided that CUCM Serviceability API (https://developer.cisco.com/site/collaboration/management/uc-manager-serviceability/overview/) would do.
1) Let’s install suds module (and we will need python 2.7.9 with ssl module too)
cd ~/Downloads
sudo wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
sudo python -m pip install suds
cd ~/
vi srv_xml_api.py
2) Inside srv_xml_api.py let’s import only necessary parts:
import sslimport urllib2from suds.xsd.doctor
import Importfrom suds.xsd.doctor
import ImportDoctorfrom suds.client
import Clientfrom suds.transport.https
import HttpAuthenticatedfrom datetime
import datetime, timedelta
3) Let’s also define global variable MODELS – a dictionary with device’s model id as it appears in CUCM database and its description:
MODELS={'626':'Cisco TelePresence SX20',
'682': 'Cisco TelePresence SX10',
'608': 'Cisco TelePresence Codec C40'}
4) We will also need path to CUCM Serviceability API, and application user credentials to access it.
SRV_CMSERVER='192.168.0.1' #IP of CUCM
SRV_axl_port='8443'
SRV_user='srv_api_user'
SRV_passwd='****'
SRV_wsdl='https://'+SRV_CMSERVER+':'+SRV_axl_port+'/realtimeservice/services/RisPort?wsdl'
SRV_location='https://'+SRV_CMSERVER+':'+SRV_axl_port+'/realtimeservice/services/RisPort'
Note that srv_api_user should be a part of AXLUsers, Standard CCM Admin Users and Standart CCM Super Users groups.
4) Here comes the one and only class cmdevices. It will have cur_layout and prev_layout vars – lists of dictionaries where we will store device name (as it appears in CUCM), directory number, description, IP, registration status, and model. When initializing in stance of the class I’m going to run update_current_states() method to populate cur_layout (we’ll come to this method later), and add Stat_change_at and Stat_change_reason keys to layouts to indicate when registration status has changed and what what the reason for that.
class cmdevices(object):
cur_layout=[]
prev_layout=[]
def __init__(self):
self.update_current_states()
self.prev_layout=self.cur_layout
for i in range(len(self.prev_layout)):
self.prev_layout[i]['Stat_change_at']=datetime.now()
self.prev_layout[i]['Stat_change_reason']= '1strun'
5) Main method of the class would be update_current_states. It’s going to communicate with CUCM, and query it for device states.
def update_current_states(self):
layout=[]
layout_reduce=[]
for model in MODELS:
t = HttpAuthenticated(username=SRV_user, password=SRV_passwd)
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(context=ssl_def_context)
t.urlopener = urllib2.build_opener(t.handler,t1)
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(SRV_wsdl,location=SRV_location,plugins=[ImportDoctor(imp)],transport=t)
result = client.service.SelectCmDevice('',{'SelectBy':'Name', 'Class':'Phone', 'Model':model})
for node in result['SelectCmDeviceResult']['CmNodes']:
for device in node['CmDevices']
layout.append({ 'Name':str(device['Name']),
'DN':str(device['DirNumber'])[:4],
'Description':str(device['Description']),
'IP': str(device['IpAddress']),
'Status':str(device['Status']),
'Model':str(MODELS[device['Model']])})
return True
First part is obvious – we are connecting to CUCM using default ssl context with Basic Auth and mend our schema with Doctor from suds. But I noticed that of one of the devices lost registration with it’s first CUCM from CM_Group and register with the second Serviceability API will list this device as unregistered with 1st node and registered with the second. Let’s call this status split and assume that in that case device is registered. So you have to parse returne layout to sort this out.
6) Last method of the class you have to implement will fetch for current states from CUCM and analyze changes comparing cur_layout and prev_layout
7) That’s it – in the main part of the script you should create an instance of the class and call update_changes periodically (I personally use apscheduler python module for that) display information you are interested in from cur_layout of the instance. You can go beyond with it as I did and use Flask framework to launch web-server and show device registration status on a web page with automatic refresh.