CUCM Python scripting

Today I’d like to share with you simple python script which can be used to automate and speed-up some time consuming activities in CUCM.

Goal of the script is to establish SSH connection to multiple CUCMs (using threads), issue required commands, wait for the output and save it to separate files on your PC.

In bellow examples we will check CUCM status and database replication, but you can play with it and implement whatever logic you want. This can be also used against IOS devices.

So here is the script:

#!/usr/bin/python
# PSFL license


import paramiko
from paramiko_expect import SSHClientInteraction
import threading


# Specify connection info for each node in square brackets: ["IP ADDRESS", "USERNAME", "PASSWORD"]
connection = [["10.10.10.10", "admin", "password10"],
              ["11.11.11.11", "admin", "password11"]
              ]

# Define function which is responsible for opening SSH connection and running specified commands
def session(ip, username, password):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    ssh.connect(ip, username=username, password=password)
    interact = SSHClientInteraction(ssh, timeout=60, display=True)  # "display=True" is just to show you what script does in real time. While in production you can set it to False

    interact.expect('admin:')   # program will wait till session is established and CUCM returns admin prompt
    interact.send('show status')    # program runs show status command
    interact.expect('admin:')   # program waits for show status command to finish (this happen when CUCM returns admin prompt)
    output = interact.current_output_clean  # program saves output of show status command to the "output" variable
    ssh.close()

# This part of function will save output of your commands into file. The 'replace' part is just to use IP address of server as a file name while replacing dots "." with underscore "_". So the file name with output from first server will be "10_10_10_10.txt"
    ip_file_name = ip.replace('.', '_')
    output_file = '{}.txt'.format(ip_file_name)
    with open(output_file, 'w') as out:
        out.write(output)
    

# Run loop which will open separate thread for each node specified in the connection list. This targets "session" function defined at the beginning 
for i in connection:
    t = threading.Thread(target = session, args = (i[0], i[1], i[2]))   # as an example, on the first iteration "i[0]" equals to "connection[0][0]" which equals to IP address 10.10.10.10
    t.daemon = True
    t.start()

Main logic of the script is based on “expect” command. Paramiko-Expect is really useful extension to Paramiko library, which provides easy way to build a program based on known and predefined responses from the server. For example, if I know that after logging into CUCM I need to wait for the admin prompt to proceed, I can just say:

expect('admin:')

When script gets to above line it will not proceed until it sees CUCM admin prompt “admin:”. Once prompt is there and ONLY once it’s there, script will proceed with next line of code.

This is cool but doesn’t handle errors well, so if you want to use it in the production you should probably think about some error handling mechanism (like IF loop with various options).

Still, this is very useful for your day to day internal tasks. When you’re running some CLI checks on tens of CUCMs, this can really speed up the process.

Bellow you have another example. Same base, but session function has different logic – now we want to check dbreplication status in our clusters. To better understand dbreplication check process take a look at my previous post

#!/usr/bin/python
# PSFL license

import paramiko
from paramiko_expect import SSHClientInteraction
import threading
import re
import time

connection = [["10.10.10.10", "admin", "password10"],
              ["11.11.11.11", "admin", "password11"]
              ]

def session(ip, username, password):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    ssh.connect(ip, username=username, password=password)
    interact = SSHClientInteraction(ssh, timeout=60, display=True)

    result1 = 0
    result2 = 1

    interact.expect('admin:')
    interact.send('utils dbreplication status')
    interact.expect('admin:')

    while not result1 == result2:
    
        interact.send('utils dbreplication runtimestate')
        interact.expect('admin:')
        output = interact.current_output_clean
        regex = re.search('COMPLETED ([0-9]+) tables checked out of ([0-9]+)', output)
        result1 = regex.group(1)
        result2 = regex.group(2)
        time.sleep(30)
        

    ip_file_name = ip.replace('.', '_')
    output_file = '{}.txt'.format(ip_file_name)
    with open(output_file, 'w') as out:
        out.write(output)

for i in connection:
    t = threading.Thread(target = session, args = (i[0], i[1], i[2]))
    t.daemon = True
    t.start()

Just short explanation of how does it work.

  1. When we hit while loop for the first time, result1 = 0 and result2 = 1, which triggers while loop.
  2. Script runs utils dbrpelication runtimestate for the first time. After first round it will check some tables, but not all of them, let’s say 60 tables out of 681. These numbers will be saved to result1 and result2 variables respectively, based on rexeg search. Then script waits for 30 seconds.
  3. Script hits while loop for the second time. Now result1 = 60 and result2 = 681, so while loop condition is again true and we again run the runtimestate command.
  4. Step 3 will be repeated couple times depending of your database size and overal process speed.
  5. At some point, CUCM will check all 681 tables, so result1 will be equal to result2. After that while loop condition will be false and we will end our loop, with output saved to “output” variable.

Imagine you have to check database replication on 10 different clusters. Instead of logging into each of them and waiting for whole process to complete, you just specify connection settings (IP address, username, password), run script, and after ~5 minutes you have output in separate files from all 10 clusters. Saves time, trust me.

 

Thanks!

2 thoughts on “CUCM Python scripting

  1. jayantanand

    Hello,

    This is certainly a very powerful and useful article for doing health checks on UC environment. Kudos for developing this script , i would definitely try in my lab.

    Thanks
    Jayant

    Like

    Reply
  2. Michael

    Thanks for sharing this. This is exactly what we’re looking for… One question though.. I ran the show status script but it did not echo the response nor did it create a file with the ip ending in .txt?

    Like

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s