I’ve been helping a friend at work with automating a report… Unfortunately this involves working with outdated Cisco API’s using SOAP and WSDL. This was my first time encountering this issue so figured I’d share some code to help anyone else who needs to tackle this problem in the future. First off the RisPort API only returns a maximum device list of 1000 (it used to be only 200). So this caused me to rewrite all of my code to pull from AXL and then loop through RisPort to pull all of the devices.
So here is how I pulled everything with AXL:
def get_axl(ip, xml_data):
"""
Connect to sql soap webservice
to get device pool per device
"""
uri = 'https://' + ip + '/axl/'
header = {
'Content-type': 'text/xml',
'SOAPAction': 'CUCM:DB ver=8.5',
}
r = requests.post(uri, headers=header, data=xml_data, verify=False, auth=(credentials['username'], credentials['password']))
if not r.status_code == 404:
axl_data.append(r.text)
xml_data = ("""
select a.name as device, b.name as pool from device as a left join devicepool as b on a.fkdevicepool = b.pkid
""")
axl_data = []
get_axl('1.2.3.4', xml_data)
Now this leaves us with a giant XML dump ( if you’re wondering why I was using an array, I am looping over multiple clusters of devices ) that we need to parse. The easiest way to do this was with the lxml module as shown below:
Parsing the XML
def parse_from_unicode(unicode_str):
"""
convert unicode to string
"""
s = unicode_str.encode('utf-8')
return objectify.fromstring(s, parser=utf8_parser)
data = {}
xml_string = axl_data[0]
utf8_parser = etree.XMLParser(encoding='utf-8')
root = parse_from_unicode(xml_string)
ret = objectify.SubElement(root, "return")
for i in root.iter('row'):
count = 0
device = None
pool = None
for x in i.iterchildren():
if count == 0:
device = x.text
else:
pool = x.text
data[device] = pool
count = count + 1
Above, we were able to create a dictionary with every device and each devices pool to be used later in pulling from RisPort. Moving forward we need to pull a set of 1000 devices from the RisPort web service. At the time of this writing I haven’t yet actually finished this project but here is what I am doing so far with RisPort:
def get_data(ip):
"""
Connect to soap webservice
Append device name and status
To data list
"""
uri = 'https://' + ip + ':8443/realtimeservice/services/RisPort?wsdl'
imp = Import('http://schemas.xmlsoap.org/soap/encoding/')
doctor = ImportDoctor(imp)
client = Client(url=uri, transport=t, doctor=doctor)
retval = client.service.SelectCmDevice("", {'SelectBy':'Name', 'Status':'Any', 'Class':'Any', 'Model':'255'})
for node in retval['SelectCmDeviceResult'].CmNodes:
for dev in node.CmDevices:
name = dev.Name
status = dev.Status
ris_data.append([name,status])
So above we append to the ris_data list an list containing the device name and its registration status. Since I have yet to finish this moving forward I know when calling client.service.SelectCmDevice I will need to pass a list of 1000 devices as an array and then iterate over every 1000 devices in the dictionary and perform the same call.
Anyways I hope this helps anyone working with any API as there really is little information on using Python with the Cisco API’s.