12 Apr

Cisco Video Communication Server Alarm Notification

I thought I’d finally sit down and learn how to Python – I wanted to do something useful with my first Python script so I decided to create an alarm notifier for the Cisco VCS.  I’m aware Cisco TMS generates tickets on Cisco VCS alarms (don’t think you get email alerts?) but what if you don’t have Cisco TMS or your Cisco VCS appliance can’t be actively monitored by Cisco TMS due to your network setup?

I’ll walk you through the steps to get this working, it’s pretty simple to setup and you can just leave it to monitor your Cisco VCS appliances/VMs.

Step One: VCS

Login to your Cisco Video Communications Server and add a user account for your monitoring script, the account only needs Read-only API access as per the screenshot below

Cisco VCS alarms

STEP TWO: SCRIPT

As Python is cross-platform this script should work on either Linux or Windows (I haven’t tested it on Windows), you will need to install Python 3 which you can install on Linux from src or your favorite packing tool or on Windows by downloading the required files from http://www.python.org/getit/

You can download the script from http://pastebin.com/56LYkSrn or simply copy the code below. You can add as many Cisco VCS instances to the script as you want – instructions on how to add your Cisco VCS details are included but if you get stuck just shout.

#!/usr/bin/env python3
#update the above line to suit your env
'''
 VCS Configuration
 Create a read-only account on your VCS with API access
 NOTE: VCS must be running at least x7.2.1
 Format:
 vcs = (
     ['username', 'password', 'authentication_realm', 'base_uri', 'full uri to status.xml'],
 }
 
 To get the authentication_realm simply open the status.xml in your browser
 i.e. https://vcs.hostname.com/status.xml
 the authentication popup will include a string like
 "TANDBERG Video Communication Server xxxxxx" where x is the serial number
'''
vcs = (
    ['username', 'password', 'TANDBERG Video Communication Server XXXXXXXX', 'http://vcs1.hostname.com', 'http://vcs1.hostname.com/status.xml'],
    ['username', 'password', 'TANDBERG Video Communication Server XXXXXXXX', 'https://vcs2.hostname.com', 'https://vcs2.hostname.com/status.xml'],
)
# SMTP server configuration
smtpsrv = "my.smtphost.com"								# smtp host
destadd = "destination.email@address.com".split()		# email destination - don't remove the .split()
fromadd = "source.email@address.com"					# email source

import urllib.request, urllib.error, re, sys, smtplib, string
from xml.dom.minidom import parseString
def stream (username, password, vcsrealm, vcs_buri, vcs_furi):
    'connect to cisco video communication server'
    auth_handler = urllib.request.HTTPBasicAuthHandler()
    auth_handler.add_password(realm=vcsrealm,
                       uri=vcs_buri,
                       user=username,
                       passwd=password)
    opener =  urllib.request.build_opener(auth_handler)
    urllib.request.install_opener(opener)
    res = opener.open(vcs_furi)
    nodes = res.read()
    return nodes
def stripxml (xml):
    'strip XML tagging'
    regex = '<[^<]+>'
    r1 = (re.sub(regex, ':::', xml))
    r2 = (r1.split(':::'))
    r3 = [x for x in r2 if x != '']
    da = 3
    ad = ([])
    while da < len(r3):
        for i in range(0, len(r3), 3):
            ad.append (r3[i:i + 3])
        po = len(r3) / 2
        da *= int(po)
    return ad
def getalarmdetail (xml):
    'parse stripped xml'
    parseme = stripxml(xml)
    x = ''
    c = 0
    for i in enumerate(parseme):
        if i[1][2] == 'Acknowledged':
            continue
        if i[1][2] == 'Unacknowledged':
            c += 1
        elif i[1][2] == 'Raised':
            c += 1
        u = 'ID: ' + str(i[1][0])
        u = u + '\nDescription: ' + str(i[1][1])
        u = u + '\nState: ' + str(i[1][2])
        u = u + '\n'
        x = ("%s%s\n" % (x, u))
    if x == '':
        return str(x)
    x = x + '\nPlease login to ' + vcs_buri + ' to investigate'
    return (c, str(x))
for o in vcs:
    username = o[0]
    password = o[1]
    vcsrealm = o[2]
    vcs_buri = o[3]
    vcs_furi = o[4]
    try:
        dom = parseString(stream(username, password, vcsrealm, vcs_buri, vcs_furi))
        xmlTag = dom.getElementsByTagName('Warnings')[0].toxml()
        # send email
        body = getalarmdetail(xmlTag)
        if body == '':
             break
        body_d = body[1]
        alarm_c = body[0]
        if str(alarm_c) > "1":
            subject = '[WARNING] ' + str(alarm_c) + ' unacknowledged alarms detected on ' + o[3]
        else:
            subject = '[WARNING] ' + str(alarm_c) + ' unacknowledged alarm detected on ' + o[3]
        msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n"
               % (fromadd, ", ".join(destadd), subject))
        msg = msg + body_d
        server = smtplib.SMTP(smtpsrv)
        server.sendmail(fromadd, [destadd], msg)
        server.quit()
    except urllib.error.HTTPError as e:
        if e.code == 401:
            print ( "Error: Basic authentication failed %s, please check your username and password" % e.code )
        elif e.code == 404:
            print ( "Error: Page not found %s, please check your configuration" % e.code )
        elif e.code == 408:
            print ( "Error: Request timed out %s" % e.code )
        else:
            print ( "Error: %s" % e.code )
    except urllib.error.URLError as e:
        print ( "Error opening URL: %s, please check your configuration" % e )

When your ready to test the script if you have no VCS alarms you can generate one by enabling a diagnostic log – from your VCS menu ‘Maintenance> Diagnostics > Diagnostic logging > Start new log’ run it manually and if configured correctly you should get an email like below

Cisco VCS alarm

Cisco VCS alarm

STEP THREE: CRON

CRON is a task scheduler for Linux. I won’t be covering it in-depth here, but I’ll give you what you need to run your script every week. To add a task to the CRON scheduler, you simply add a line to the “crontab”. Edit this by typing:

crontab -e
or
env EDITOR=nano crontab -e

This will open up the CRON file in your text editor, if you’ve never added anything before, it’s also likely to be blank. No worries, add line 2 if you’ve made the Python script executable otherwise add line 4:
if executable
* * * * * /home/vcs_alarms/script.py
otherwise
* * * * * /path/to/python3 /home/vcs_alarms/script.py

The format this command follows is pretty simple:
*    *    *    *    *  command to be executed
_    _    _    _    _
|    |    |    |    |
|    |    |    |    |
|    |    |    |    ------ day of week (0 - 7) (0 or 7 are Sunday, or use names)
|    |    |    ----------- month (1 - 12)
|    |    ---------------- day of month (1 - 31)
|    --------------------- hour (0 - 23)
-------------------------- min (0 - 59)

A * in the pattern ignores that item. So in the example above, we are going to run our monitoring script every minute.

  • Anthony Thomson

    This is excellent. Is it possible to adapt this to retrieve the status of neighbor or traversal zones, looking for ones in a Failed state?

  • Chris Swinney

    Hey Another Techy,

    This may well be able to be modified for our own needs. One of the big issues I have with the monitoring in TMS (apart from the fact that it completely rubbish at this), is the fact that there is no alerts raised when a Traversal or Neighbour zone fails, or one of the peers fails. Whilst this is NOT raised as an alarm, the status of these zones are referenced in the status.xml file.

    Phython is one of those areas I need/want to look at, so I’m just wondering what the resultant XML file looks like after it has been stripped, as I will need to parse for different information.

  • darrengoulden

    TMS isn’t the best at monitoring this stuff I agree, I was surprised when I saw zone failure alarms in Prime Collaboration when they are not in TMS, Cisco obviously have no problem writing the code for it but to only put it in Prime is a crazy decision when the majority of VCS’s out there are monitored by TMS.

    I need to update the script, I’ve been a bit lazy on this front

    • Chris Swinney

      Lazy or overworked elsewhere ;)?

      Still, what are you using a Python IDE, if all all?

      • darrengoulden

        Just nano Chris 🙂 I’m planning to update the script within the next month (hopefully!)

  • Syed

    Error opening URl:, please check your configuration

    I get this error while I run this script. Can someone guide me here?

    • darrengoulden

      It seems that Python < 2.7.9 didn't validate certificates in the HTTPS client. Since the certificate returned is self-signed, Python now throws an SSL: CERTIFICATE_VERIFY_FAILED error.

      The urllib code will need updating

  • Lewis

    I got a tricky question for you …

    I used to, by the use of your script (which worked like a charm, thanx to you idea :-)) send emails from the data found in the xml file ….
    But, since the clean reboot of my device this morning, I can’t access the file to get my precious data 🙁

    any idea why ?