Article 5 - Restoring Saved Device Ownership Data
This article covers restoring device ownership information using data stored in a CSV generated by the Python script in the previous article.
To do this we will use a Python script to submit SQL update queries to the CUCM API using device and owner information read from the CSV file.
- Article 1 - Introduction and CUCM Licensing Overview.
- Article 2 - Basic SQL Commands to Monitor and Update Licensing.
- Article 3 - Using the CUCM AXL API.
- Article 4 - Saving Existing Device Ownership Data.
- Article 5 - Restoring Saved Device Ownership Data
- Article 6 - Clearing Device Ownership Data
- Article 7 - Setting Device Ownership by Primary Extension
SQL Query Used to Restore Device Ownership Data
The SQL query we will use to restore the device owner data is shown below.
run sql update device set fkenduser = 'value_of_fkenduser_read_from_csv_file' where pkid = 'value_of_pkid_read_from_csv_file'
This query will be run for each row in the CSV file (excluding the header row) using the pkid and fkenduser values from that row.
The Python Script
The Python script shown below will retrieve the data listed above and save it to a CSV file. The name of the CSV file includes date and time information so that new output files can be created without overwriting existing files.
The script comprises the following high level steps:
- Load information needed to connect to the target CUCM server from an ini file.
- Ask the user to enter the name of the CSV file that contains the device ownership data to be restored.
- Connect to the CUCM AXL API using the settings from the ini file to retrieve and store cookies data.
- Open the input CSV file and loop through data.
- For each line try to update the device owner using an AXL SQL Update query the fkenduser and devicepkid values for that line.
- The result of each SQL Update query is written to a CSV log file along with the device and owner details.
import sys
import requests
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
from configparser import ConfigParser
import datetime
import pprint
import csv
from csv import DictReader
disable_warnings(InsecureRequestWarning)
########################################################################################################################
def axlgetcookies(serveraddress, version, axluser, axlpassword):
try:
# Make AXL query using Requests module
axlgetcookiessoapresponse = requests.get(f'https://{ipaddr}:8443/axl/', headers=soapheaders, verify=False,\
auth=(axluser, axlpassword), timeout=3)
print(axlgetcookiessoapresponse)
getaxlcookiesresult = axlgetcookiessoapresponse.cookies
if '200' in str(axlgetcookiessoapresponse):
# request is successful
print('AXL Request Successful')
elif '401' in str(axlgetcookiessoapresponse):
# request fails due to invalid credentials
print('Response is 401 Unauthorised - please check credentials')
else:
# request fails due to other cause
print('Request failed! - HTTP Response Code is ' + axlgetcookiessoapresponse)
except requests.exceptions.Timeout:
axlgetcookiesresult = 'Error: IP address not found!'
except requests.exceptions.ConnectionError:
axlgetcookiesresult = 'Error: DNS lookup failed!'
return getaxlcookiesresult
########################################################################################################################
def axlupdatedeviceownerdata(cookies,devicepkid,fkenduser):
# Set SOAP request body
axlupdatedeviceownerdatasoaprequest = f'<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/{version}"><soapenv:Header/><soapenv:Body><ns:executeSQLUpdate><sql>UPDATE device SET fkenduser = "{fkenduser}" WHERE pkid = "{devicepkid}"</sql></ns:executeSQLUpdate></soapenv:Body></soapenv:Envelope>'
try:
# Make SOAP request
axlupdatedeviceownerdatasoapresponse = requests.post(f'https://{ipaddr}:8443/axl/', data=axlupdatedeviceownerdatasoaprequest, headers=soapheaders, verify=False, cookies=cookies, timeout=9)
if '200' in str(axlupdatedeviceownerdatasoapresponse):
# request is successful
device_update = 'Success'
else:
# request is unsuccessful
device_update = 'Failure'
return device_update
except requests.exceptions.Timeout:
print('IP address not found! ')
except requests.exceptions.ConnectionError:
print('DNS lookup failed! ')
########################################################################################################################
def main():
# Import values for the CUCM environment from ini file using ConfigParser
global ipaddr, version, axluser, axlpassword, soapheaders, cookies
parser = ConfigParser()
parser.read('cucm-settings.ini')
ipaddr = parser.get('CUCM', 'ipaddr')
version = parser.get('CUCM', 'version')
axluser = parser.get('CUCM', 'axluser')
axlpassword = parser.get('CUCM', 'axlpassword')
soapheaders = {'Content-type': 'text/xml', 'SOAPAction': 'CUCM:DB ver=' + version}
# Ask user for the name of the CSV file that contains the ownership data
print('*' * 120)
print()
print('Python 3.x Script to Restore CUCM User Ownership Data from CSV File')
print()
print('Written by James Hawkins, Axonex, July 2017')
print()
deviceownerdatainputfile = input('Enter the name of the file containing the device ownership data you wish to restore: ')
print(deviceownerdatainputfile)
# Get cookies for future AXL requests
axlgetcookiesresult = axlgetcookies(ipaddr, version, axluser, axlpassword)
print(axlgetcookiesresult)
if 'JSESSIONIDSSO' in str(axlgetcookiesresult):
print('Cookies Retrieved')
else:
sys.exit('Program has ended due to error!')
# Create filename for output file in format deviceownerdata-year-month-dom-hour-minute-second.csv
now = datetime.datetime.now()
outputfile = 'deviceownerupdatelog-' + now.strftime("%Y-%m-%d-%H-%M-%S") + '.csv'
# Open output log csv file
deviceownerdataoutputfile = open(outputfile, 'w', newline='')
deviceownerdataoutputwriter = csv.writer(deviceownerdataoutputfile)
deviceownerdataoutputwriter.writerow(['devicepkid', 'devicename', 'fkenduser', 'userid', 'Result'])
# Open input CSV file and read device pkid and fkenduser values
with open(deviceownerdatainputfile, mode='r') as csv_file:
csv_dict_reader = DictReader(csv_file)
for row in csv_dict_reader:
devicepkid = row['devicepkid']
devicename = row['devicename']
fkenduser = row['fkenduser']
userid = row['userid']
# Call update device owner function
update_status = axlupdatedeviceownerdata(axlgetcookiesresult,devicepkid,fkenduser)
deviceownerdataoutputwriter.writerow([devicepkid,devicename,fkenduser,userid,update_status])
if update_status == "Success":
print(f'Success! - User "{userid}" set as the owner of {devicename}')
else:
print(f'Failure! - User "{userid}" not set as the owner of {devicename}')
deviceownerdataoutputfile.close()
########################################################################################################################
if __name__ == "__main__":
main()
The Output Data
The csv file output should look similar to that shown below - thanks to Donat Studios for providing a tool to convert CSV data to Markdown.
| devicepkid | devicename | fkenduser | userid | Result |
|---|---|---|---|---|
| 6eb51642-2723-8ceb-0431-6d1f70437fb8 | CSFJHAWKINS | 8c758cf4-da8c-bd00-53be-a0902f1707e1 | jhawkins | Success |
| 5a5fbb7b-6b34-7a81-332f-e8bf39bb669d | TCTJHAWKINS | 8c758cf4-da8c-bd00-53be-a0902f1707e1 | jhawkins | Success |