Python Scripting Host for Connection

Contents

Overview. 2

Requirements/Special Notes. 3

Connecting to Unity Connection 7.x or Later 3

Task 1: Configure a User with the Remote Administrator role. 4

Task 2: Set the Database Proxy Service Shutdown Time. 4

Task 3: Activate the Remote Database Proxy Service. 4

Task 4: Login to the Remote Server 4

Troubleshooting Remote Login Issues. 5

Double Check Connection Server Settings. 5

Disable CSA and all Virus Scanning Applications. 5

Make sure the Informix .NET Driver is Installed and the PATH Points to it. 5

Using Python Scripting Host 6

Helpers Methods. 6

Stored Procedure Helpers. 6

StartNewCommand: 6

AddCommandParam.. 6

ExecutProc. 6

ExecutProc_NoRet 6

Database Fetch Helpers. 7

SetActiveDatabase. 7

CreateDataTable. 7

ExecuteQuery. 7

GetCount 7

GetSingleValue. 7

File Read/Create Helpers. 7

WriteToLog. 8

AppendToFile. 8

ReadCsvFileIntoDataTable. 8

SaveDataTableAsCsvFile. 8

Application Helpers. 8

Pause. 8

StartTimer 8

StopTimer 8

Media Helpers. 8

UploadWavFile. 8

DownloadWavFile. 9

Notification Helpers. 9

AddFileToEmailNotification. 9

Samples. 9

Output Alias of First 20 Users. 9

Export Alias and Extension To Csv. 10

Create Users From Csv. 10

Create Call Handlers in Bulk. 11

Set Alternate Greeting To Disabled For All Users in Partition. 12

Update Building For All Users in Class of Service. 13

Update Conversation Name For All Users in Class of Service. 14

Get Mailbox Size For All Users. 15

Get Unread Voicemail Count For All Users. 15

Scheduling Script Runs. 16

Emailing Results of Scheduled Runs Automatically. 17

Obtaining Updates. 19

Revision History. 19

Overview

The mission of the Python Scripting Host utility is simple: To allow users to quickly generate Python scripts for producing reports, bulk update utilities, provisioning applications, performance testing frameworks and similar applications leveraging Unity Connection’s database directly quickly and easily.

 

The service provides a “Helpers” shim that gives access to all the power, performance and flexibility of the full ODBC and HTTP interfaces into Unity Connection with very little overhead and a simplified API that is easy to use from within Python’s scripting environment.  It also includes file reading/creating methods for simplified CSV handling, full database query and update abilities and includes the ability to fetch and upload media files to and from Connection for greetings, voice names, interview questions etc…

Requirements/Special Notes

This version of Python Scripting Host runs on Windows XP/2000/2003/2008/2012, Vista, Windows 7 or Windows 8. 

You must install the 32 bit Informix Client SDK version 3.5 or later including the .NET drivers even if you are running on a 64 bit version of your operating system.  The Python Scripting Host tool is strictly 32 bit.  See the Informix Driver Download Page for details.

This version of Python Scripting Host only works with Unity Connection 7.0(1) or later.

You must enable the ODBC proxy service on the Unity Connection server and attach to the database using an account enabled for the remote database access role.  See the next section for details on this.

This tool uses Microsoft’s full .NET 4.0 library (the limited “client” version of .NET 4.0 is not sufficient).  The installation will check to see if you have that installed and if not will offer you the option to download and install it automatically.

Connecting to Unity Connection 7.x or Later

For installations of 7.0(1) and later you need to use the database proxy service for access to the database from off box for any DB tool including Python Scripting Host.

Task 1: Configure a User with the Remote Administrator role

1.     Go to the Cisco Unity Connection Administration web interface for your installation.

2.     You can leverage a user with or without a mailbox for off box data access purposes. 

3.     Be sure the web administration password for this user is not configured to require a change at first login on the “Password Policy” page for that user.

4.     If necessary, change the web administration password on the “Change Password” page.  Note that only the web application password comes into play for remote data access.

5.     Finally, on the “Role” page for the user, add the “Remote Administrator” role to the “Assigned Roles” list and save.  You can assign any or all other roles as well but for the purposes of remote access to the database and making updates to users those two are necessary.

Task 2: Set the Database Proxy Service Shutdown Time

NOTE: For Unity Connection 10.0 and later this step is not necessary as there is no longer a shut down timer.

Out of the box the database proxy service is not running and if you try to start the service it will shut down right away.  First you need to set the “Database Proxy: Service Shutdown Timer” value found in the System Settings -> Advanced -> Connection Administration section of the Cisco Unity Connection Administration page.  By default this is 0.  You can set it to as high as 999 days if you like.  After the number of days configured here the remote database proxy service will shut down.  This is useful if you want to do some migration work, for instance, and don’t want to forget to have the service disabled for security reasons.

NOTE: For versions of Connection prior to 10.0 if you restart the server, the remote database proxy service will remain shut off.  After a system restart you have to go in and manually turn on the service again (see step 3)

Task 3: Activate the Remote Database Proxy Service

1.     Out of the box the service that listens to remote database requests is not active, you must turn it on.  To do this, go to the “Cisco Unity Connection Serviceability” web admin page.

2.     On the Tools menu, select the “Service Management” page.

3.     The “Connection Database Proxy” item under the “Optional Services” section will be marked as “Deactivated” and stopped.  Press the “Activate” button and it will be activated and started automatically.

Once you’ve started the proxy service you can connect with any tool that needs off box database access using the user name, web administration password and port “20532”.

NOTE: For versions of Connection prior to 10.0 the service will automatically shut down after the number of days configured in step 2 above or if you restart the server.

Task 4: Login to the Remote Server

When you first start Python Scripting Host, you will see a login dialog box that will be empty except for port 20532 filled in as the default for the port.  You must provide the server name or IP address for the “Server” field and provide the login and password for the database connection account.  Use the alias and web administration password of the database user created above for the login and password fields.

 

Python Scripting Host will remember your entries including the password (which is stored in a secure hash).  Each time you run Python Scripting Host it will load the settings of the last connection you made.  Every server you’ve successfully connected to in the past will be listed in the drop down list in the order in which you connected to it last – most recent to least recent.

NOTE: The login and password information is stored along with the local Windows login name.  Only those servers that have been attached to successfully using the current Windows login will be listed.  If you are logging into the same Windows server with different users you will only see servers connected to with that particular Windows login.

NOTE: Providing the wrong password or login will fail quickly and give you a chance to try a different pair.  Providing an incorrect server or port, however, results in a 60 second timeout while UDD waits for the Informix driver to return.  Unfortunately this cannot be shorted.  Type carefully.

Troubleshooting Remote Login Issues

The error message issued by the application should have some details for you on the failure reason based on the error codes issued by the Informix driver to help narrow down your investigation.  Here are some general things to check that have been run across in the field for sites having trouble connecting to their remote Connection servers.

Double Check Connection Server Settings

Make sure the remote database proxy service is running.  This service does shut itself off after a period of time and does not start itself automatically on a server reboot.

Make sure the user you are logged in as has the remote administrator role assigned to their account, that their password is not set to reset at the next login and that their account is not currently locked. 

Make sure the server name or IP address you are using to connect with is reachable from your Windows client.  DNS issues often come up in connection failures.

Disable CSA and all Virus Scanning Applications

It’s a good idea to disable CSA and all virus scanning applications if you are having problems connecting to be sure the ODBC port (20532) is not being blocked.  Also check your firewall settings (assuming you are running one). 

Make sure the Informix .NET Driver is Installed and the PATH Points to it.

For 32 bit OS installs, the IBM Informix driver is installed in C:\Program Files\IBM\Informix\Client-SDK.  Make sure this path exists on your server and has not been removed or renamed.

The system PATH variable will also include a reference to the “\IBM\Informix\Client-SDK\bin” location where the driver is installed.  Make sure this path is referenced in the PATH.  Also, if the PATH is very long sometimes the Informix driver will not find it, try moving it to the beginning of the PATH statement.

If you had an older version of the IBM Informix Client SDK installed it's a good idea to uninstall all other versions and make sure you have a single instance of the SDK 3.5 or later.  Mixing versions of Informix drivers is not a good idea as only one can be active at a time.

Using Python Scripting Host

Helpers Methods

The Python Scripting Host provides a full Python environment to use however the reason you’d want to use it instead of a standalone Python interpreter is for the Helper methods it provides which grant you access to database functions, fetches, stored procedures, file processing methods and other useful items that will make your job much easier.

These can be accessed using the “Helpers” class from within the script – off the Helpers class the following method groups are available for your use:

Stored Procedure Helpers

StartNewCommand:

void StartNewCommand(string pStoredProc)

When starting the execution of a new stored procedure, start the process by calling the StartNewComand call with the stored procedure name such as “csp_SubscriberModify”.  Check the CUDLI data dictionary for a list of all the stored procedure names.

Once you execute StartNewCommand you will then add parameters using the AddCommandParam and then execute the procedure with either ExecutProc or ExecutProc_NoRet.

AddCommandParam

void AddCommandParam(string pParamName, ProcDataType pType, string pValue)
void AddCommandParam(string pParamName, ProcDataType pType, DateTime pValue)
void AddCommandParam(string pParamName, ProcDataType pType, int pValue)
void AddCommandParam(string pParamName, ProcDataType pType, long pValue)
void AddCommandParam(string pParamName, ProcDataType pType, bool pValue)

Allows you to add parameters to a stored procedure using several overloads for passing in strings, dates, integers etc… the parameter will be added formatted correctly based on the ProcDataType (int, bool, varchar etc…) used.  Again, use the CUDLI data dictionary information for determining which parameters and their types to include for any given stored procedure being called.

ExecutProc

string ExecutProc(string pColumnName="")

Execute a stored procedure that you’ve started and added parameters to.  Use this execute derivative when a return value is expected – all create stored procedures (such as csp_SubscriberCreate) will pass back an objectId string of the newly created object and requires you execute the procedure with this call.  In most cases providing the column name is not necessary as there’s only one value returned.  In rare cases some procedures will return multiple values and you need to provide the name of the column to return (i.e. “objectId”).

ExecutProc_NoRet

void ExecutProc_NoRet()

 

Execute a stored procedure that you’ve started and added parameters to.  Use this execute derivative when a return value is not expected – most procedures for delete and modify do not return a value.

Database Fetch Helpers

SetActiveDatabase

void SetActiveDatabase(string pDatabaseName)

By default you will be connected to “UnityDirDb” which is the main directory database for Unity Connection and is by far the most common database to run queries and procs against.  You can switch to the UnityRptDb or the UnityMbx1Db (or UnityMbx2Db through UnityMbx6Db) by using this method. 

CreateDataTable

DataTable CreateDataTable(string strSqparams object[] pParams)

Creates a DataTable from an query and passes it back.  The query string can contain question marks that will be replaced with values from the pParams list you can pass in.  This is the preferred method for providing parameters as opposed to adding them directly into the query string for both safety and performance.  For instance:

dtUsers = Helpers.CreateDataTable(“Select * from vw_subscriber where alias=?”,”jlindborg”)

is preferred over:

dtUsers = Helpers.CreateDataTable(“Select * from vw_subscriber where alias=’jlindborg’”)

although both will work.

ExecuteQuery

void ExecuteQuery(string strSqparams object[] pParams)

Executes a generic query – it returns nothing (no table or count).  This is for rare cases where you need to run an update query in SQL – as a rule it’s always better to make changes to data via stored procedures (detailed above) however in some instances you can only update some properties directly on tables and this method is provided for those cases.

GetCount

int GetCount(string pCountQueryStringparams object[] pParams)

Executes a scalar query and returns the value as an integer.  For instance:

Helpers.GetCount(“Select Count(*) from vw_subscriber”)

Again, parameters should be passed using question marks and parameter values whenever possible.

GetSingleValue

string GetSingleValue(string pQueryString, params object[] pParams)

 

For a query that returns a single value from a single row this will return a string with that value.  Useful as a shorthand for fetching Ids for objects based on unique constraints.  For instance:

 

strObjectId=GetSingleValue(“Select ObjectId from vw_Subscriber where Alias=?”,”jlindborg”)

 

since Alias must be unique in the vw_subscriber view this will only ever return a single match (or zero matches).  No matches returns an empty string, this is not an error condition.

 

File Read/Create Helpers

 

WriteToLog

void WriteToLog(string pString)

Writes a string to the active Python Scripting Host diagnostic output log.

AppendToFile

void AppendToFile(string pPathToFilestring pString)

Will append a string to the file name provided.  If the file name provided has no path provided the file will appear in the “Logs” folder under the directory where the Python Scripting Host is installed.

ReadCsvFileIntoDataTable

DataTable ReadCsvFileIntoDataTable(string pPathToCsvFile)

Reads a CSV file that has a header row into a data table and passes it back.  If the file is not found or is not formatted properly with a header an exception is thrown.  If the file name provided does not include a path the file is looked for in the “CSV” folder under the directory where the Python Scripting Service is installed.

SaveDataTableAsCsvFile

void SaveDataTableAsCsvFile(DataTable pDataTable, string pTargetFileName)

Saves a dataset as a CSV file with a header row containing the column names.  If the file name provided does not include a path the file is saves to the “CSV” folder under the directory where the Python Scripting Service is installed.

Application Helpers

Pause

void Pause(string pMessage = "")
 
Stops the execution of the script and pops a message box with the message string you pass (if any) and gives you the option to press “ok” to continue execution or “cancel” to stop the script at that point.  Can be useful for testing conditions out in a loop prior to applying the changes you are attempting for a very large number of objects for instance.

StartTimer

void StartTimer()
 
Starts a timer in the background that will be stopped when the StopTimer method is called.

 

StopTimer

long StopTimer()
 
Returns the milliseconds that have transpired since the StartTimer was called.  If the StopTimer method is called without having first called StartTimer(), an exception is thrown.

 

Media Helpers

UploadWavFile

string UploadWavFile (string pLocalWavFilePathbool pConvertToPcmFirst)

Uploads a local WAV file as s stream to the Connection server – the string returned is the unique id of that stream which can be used as a call handler or user greeting, voice name or interview handler question.  If the string returned is blank then the upload failed and you’ll need to check the log file output for errors.

The option to convert to PCM first will have the Python Scripting Host first convert whatever wav file is found into linear PCM mono before uploading to Connection.  This can be a good idea as the media file format for Connection can be fussy and this will ensure the format is acceptable.  If you pass this as false then the wav file is uploaded “as is”.

DownloadWavFile

bool DownloadWavFile (string pLocalWavFilePathstring pConnectionFileName)

Downloads a media stream file from Connection to the local file system.  Stream files hold user or call handler greetings, voice names for any objects or interview handler questions.  The ConnectionFileName property must come from the database, of course.  For greetings you would pull this from the vw_GreetingStreamFile view.  For voice names the file name is pulled from the “VoiceName” column of the object itself (subscriber, call handler, interviewer etc…).

For instance if you want to download the greeting wav file for a call handler you would get the call handler’s ObjectId and use the greeting type (standard, alternate, off hours, busy, internal, holiday, error) and the language code you want (English is 1033) you can pull the value from the “streamfile” column of the vw_greetingstreamfile view.  Remember each greeting for a handler or user can be recorded in multiple languages – this adds a significant amount of flexibility but also involves a bit more complexity for tasks like this.

Notification Helpers

AddFileToEmailNotification

void DAddFileToEmailNotification (string pLocalFilePath)

If you are running a script on a schedule and have email notification enabled this command will add an additional file to the email sent out.  The email will always include the execution results and script output text in the body of the message and the log file attached as a ZIP file.  This command will add additional file(s) to that ZIP file – there is no restriction on how many files you can add to the ZIP.

Samples

Output Alias of First 20 Users

import clr

clr.AddReference('System.Data')

from System.Data import DataTable

 

Helpers.SetActiveDatabase("UnityDirDb")

 

query = 'SELECT FIRST 20 Alias FROM vw_subscriber'

dtAlias = Helpers.CreateDataTable(query)

 

assert dtAlias.Rows.Count>0,"No users found!"

print("Processing user count="+ str(dtAlias.Rows.Count))

 

for row in dtAlias.Rows:

    print("user="+row['alias'])

 

print("Finished")

Export Alias and Extension To Csv

import clr

clr.AddReference('System.Data')

from System.Data import DataTable

Helpers.SetActiveDatabase("UnityDirDb")

 

#get all users that have an alias that starts with "o"

query = 'SELECT Alias, DTMFAccessID FROM vw_subscriber WHERE alias LIKE ?'

dtAlias = Helpers.CreateDataTable(query,'o%')

 

assert dtAlias.Rows.Count>0,"No users returned!"

 

#convert the dataset into a CSV on file.  If you just provide a file name

#and not a complete path string the file will appear in the CSV folder

#under the application install directory

Helpers.SaveDataTableAsCsvFile(dtAlias,'AliasExtensionOutput.csv')

print('Finished output, users exported='+str(dtAlias.Rows.Count))

Create Users From Csv

import clr

clr.AddReference('System.Data')

from System.Data import DataTable

clr.AddReference('Cisco.Unity.Connection.PythonScriptingHost')

from Cisco.Unity.Connection.PythonScriptingHost import ProcDataType

from datetime import datetime

 

Helpers.SetActiveDatabase("UnityDirDb")

 

#create simple function to print out to form and to write to log file

def myLog(str):

    print str

    Helpers.AppendToFile('CreateNewUsersDiag.log',datetime.now().strftime("[%Y-%m-%d %H:%M:%S]:") + str)

    return

 

myLog("** Starting import of users from CSV **")

myLog("Reading users from Csv")

dtUsers = Helpers.ReadCsvFileIntoDataTable('NewUsers.csv')

myLog("Users from Csv="+ str(dtUsers.Rows.Count))

 

for user in dtUsers.Rows:

    myLog(user['alias'])

    Helpers.StartNewCommand('csp_SubscriberCreate')

    Helpers.AddCommandParam('pTemplateAlias',ProcDataType.VarChar,'vmtemplate')

    Helpers.AddCommandParam('pAlias',ProcDataType.VarChar,user['alias'])

    Helpers.AddCommandParam('pFirstName',ProcDataType.VarChar,user['firstname'])

    Helpers.AddCommandParam('pLastName',ProcDataType.VarChar,user['lastname'])

    Helpers.AddCommandParam('pDtmfAccessId',ProcDataType.VarChar,user['Extension'])

    try:

        newObjectId = Helpers.ExecutProc()

    except Exception, e:

        myLog ('failed creating new user:%s' % e)

        continue

    myLog ('    New objectId ='+newObjectId)

Create Call Handlers in Bulk

import clr

clr.AddReference('System.Data')

from System.Data import DataTable

clr.AddReference('Cisco.Unity.Connection.PythonScriptingHost')

from Cisco.Unity.Connection.PythonScriptingHost import ProcDataType

 

Helpers.SetActiveDatabase("UnityDirDb")

 

#grab the first call handler template defined to create new handlers with

query="SELECT FIRST 1 ObjectID from vw_CallHandlerTemplate"

templateObjectId=Helpers.GetSingleValue(query)

 

assert len(templateObjectId)>0,"No template objectID found"

 

basename="LoadTestHandler"

 

#create 100 call handlers - keep in mind that display name uniqueness is not

#enforced for call handlers so this could create duplicates - hence the check for

#duplicates manually added here.

queryCount="SELECT COUNT(*) FROM vw_CallHandler WHERE displayname=?"

for x in range(1,100):

    print(basename+str(x))

    count = Helpers.GetCount(queryCount,basename+str(x))

    if (count>0):

        print("Duplicate name!")

        continue

    Helpers.StartNewCommand('csp_CallHandlerCreate')

    Helpers.AddCommandParam('pDisplayName',ProcDataType.VarChar,basename+str(x))

    Helpers.AddCommandParam('pTemplateObjectId',ProcDataType.VarChar,templateObjectId)

    try:

        newObjectId = Helpers.ExecutProc()

    except Exception, e:

        print ('failed creating new handler:%s' % e)

        continue

    print ('    New objectId ='+newObjectId)

print ('Done!')

 

Set Alternate Greeting To Disabled For All Users in Partition

import clr

clr.AddReference('System.Data')

clr.AddReference('Cisco.Unity.Connection.PythonScriptingHost')

from System.Data import DataTable

from System import DateTime

from Cisco.Unity.Connection.PythonScriptingHost import ProcDataType

 

Helpers.SetActiveDatabase("UnityDirDb")

 

query = 'SELECT vw_Subscriber.Alias, vw_Subscriber.CallHandlerObjectID FROM vw_Subscriber, vw_Partition WHERE vw_Subscriber.PartitionObjectId=vw_Partition.ObjectID AND fn_tolower(vw_Partition.Name)=?'

dtUsers = Helpers.CreateDataTable(query,"jeffs test partition")

 

assert dtUsers.Rows.Count>0,"No users found in partition!"

 

#use a date in the past for the timeexpires field to disable a greeting (or transfer rule)

#use a date in the future to make it active.

theDate = DateTime.Now.AddDays(-2)

 

for user in dtUsers.Rows:

    print ('updating:'+user['alias'])

    Helpers.StartNewCommand('csp_greetingmodify')

    Helpers.AddCommandParam('pCallHandlerObjectid',ProcDataType.Char,

        user['CallHandlerObjectId'])

    Helpers.AddCommandParam('pGreetingType',ProcDataType.VarChar,'Alternate')

    Helpers.AddCommandParam('ptimeexpires',ProcDataType.DateTime,"NULL")

    Helpers.ExecutProc_NoRet()

Update Building For All Users in Class of Service

import clr

clr.AddReference('System.Data')

clr.AddReference('Cisco.Unity.Connection.PythonScriptingHost')

from System.Data import DataTable

from System import DateTime

from Cisco.Unity.Connection.PythonScriptingHost import ProcDataType

 

Helpers.SetActiveDatabase("UnityDirDb")

 

#note the back slashes for the line continuation and the use of the fn_tolower

#function that ensures case for the display name wont be an issue

query = 'SELECT vw_Subscriber.ObjectId, vw_Subscriber.Alias FROM vw_Subscriber, \

        vw_COS WHERE vw_Subscriber.CosObjectId=vw_Cos.ObjectID \

        AND fn_tolower(vw_Cos.DisplayName)=?'

 

dtUsers = Helpers.CreateDataTable(query,"jeffs test cos")

 

assert dtUsers.Rows.Count>0,"No users found in COS!"

 

print('Users found in COS='+str(dtUsers.Rows.Count))

 

for user in dtUsers.Rows:

    print('Updating:'+user['alias'])

   

    Helpers.StartNewCommand('csp_subscribermodify')

    Helpers.AddCommandParam('pobjectid',ProcDataType.Char,user['objectid'])

    Helpers.AddCommandParam('pbuilding',ProcDataType.VarChar,'South Tower')

    Helpers.ExecutProc_NoRet()

   

Update Conversation Name For All Users in Class of Service

import clr

clr.AddReference('System.Data')

clr.AddReference('Cisco.Unity.Connection.PythonScriptingHost')

from System.Data import DataTable

from Cisco.Unity.Connection.PythonScriptingHost import ProcDataType

 

Helpers.SetActiveDatabase("UnityDirDb")

 

cosQuery="SELECT vw_subscriber.Alias, vw_subscriber.ObjectId FROM vw_subscriber, vw_cos WHERE vw_cos.ObjectId = vw_subscriber.CosObjectId AND fn_tolower(vw_cos.DisplayName)=?"

dtUsers = Helpers.CreateDataTable(cosQuery,"jeffs test cos")

 

assert dtUsers.Rows.Count>0,"No users found in that COS"

 

for user in dtUsers.Rows:

    print(user['alias'])

    Helpers.StartNewCommand("csp_SubscriberModify")

    Helpers.AddCommandParam("pObjectId",ProcDataType.Char,user['objectId'])

    Helpers.AddCommandParam("pConversationTui",ProcDataType.VarChar,"SubMenu_Alternate_Custom")

   

    try:

        Helpers.ExecutProc_NoRet()

    except(Exception, ex):

        print("Error editing user:"+str(ex))

        continue

    print("user updated!")

Get Mailbox Size For All Users

import clr

clr.AddReference('System.Data')

from System.Data import DataTable

 

Helpers.SetActiveDatabase("UnityDirDb")

 

userQuery = "SELECT vw_subscriber.Alias, vw_mailboxstoremap.MailDatabase FROM vw_Subscriber, vw_mailboxstoremap, vw_mailboxmap WHERE vw_subscriber.ObjectId = vw_mailboxmap.UserObjectId AND vw_mailboxmap.MailboxStoreObjectId = vw_mailboxstoremap.ObjectId"

dtUsers = Helpers.CreateDataTable(userQuery)

assert dtUsers.Rows.Count>0,"No users found!"

 

for user in dtUsers.Rows:

    mailboxQuery = "SELECT bytesize FROM %s:vw_mailbox WHERE description=?" % user['maildatabase']

    size = Helpers.GetSingleValue(mailboxQuery,user['alias'])

    if (len(size))==0:

        continue

    print(user['alias']+" mailbox size="+size)

 

print("done")

Get Unread Voicemail Count For All Users

import clr

clr.AddReference('System.Data')

from System.Data import DataTable

 

Helpers.SetActiveDatabase("UnityDirDb")

 

userQuery = "SELECT vw_subscriber.Alias, vw_mailboxstoremap.MailDatabase, vw_mailboxmap.MailboxId FROM vw_Subscriber, vw_mailboxstoremap, vw_mailboxmap WHERE vw_subscriber.ObjectId = vw_mailboxmap.UserObjectId AND vw_mailboxmap.MailboxStoreObjectId = vw_mailboxstoremap.ObjectId"

dtUsers = Helpers.CreateDataTable(userQuery)

assert dtUsers.Rows.Count>0,"No users found!"

 

for user in dtUsers.Rows:

    messagesQuery="SELECT count(*) FROM %s:vw_message WHERE type=2 AND seen=0 AND mailboxObjectId=?" % user['maildatabase']

    count = Helpers.GetCount(messagesQuery,user['MailboxId'])

    print (user['alias'] + " message count="+str(count))

 

print ("done")

Scheduling Script Runs

Starting in version 1.0.5 you can schedule the Python Scripting Host to run in the future either once or on a regular schedule.  This uses the Windows Scheduler to have the application launched with command line parameters identifying the server you wish to run the export against, the script you’d like to run and that you’d like it to run “silent” meaning no user input is required to complete the execution.

To configure this you need to do the following things:

1.     Attach to the Connection server you wish to schedule exports against.  The Python Scripting Host can handle multiple scheduled runs against different Connection servers with different scripts.

2.     Once you’ve selected the script you want and ensured that it runs properly, select the “Options” menu and choose to schedule a script run.

The schedule export interface launches the Windows scheduler task wizard – this will look a little different on Windows XP/2000/2003 than it will on Vista or Windows 7 or Windows 2008.  But the same basic options are available in all interfaces. You need to provide an account to run under (preferably the same one you are running the tool with currently if possible) and configure the schedule options (on the “Trigger” tab for the Windows 7 style schedule wizard below).

 

 

This gives you the option of scheduling it one time or to run daily, weekly, several times a week etc…

 

NOTE:  A common mistake for scheduling exports is to forget to check the “enabled (scheduled task runs as specified time)” box on the task tab on the old style interface or selecting the “Run whether user is logged on or not” option on the new style interface above.

NOTE: Some versions of Windows 2008 Server will not properly fill in the “Start In” path under Actions | Properties.  This needs to be the path that the tool is configured to run from.  Another Windows 2008 issue can be needing the “run with highest privileges” checkbox set on the General tab.

NOTE: Finally, if you need to schedule a run manually, all that’s necessary is to have the application executable called with a command line of “/Silent=[1.2.3.4] /Script=[c:\scriptname.py]”, where “1.2.3.4” is replaced with the IP address or server name of the target Connection server and the script path points to a working Python script.

Emailing Results of Scheduled Runs Automatically

With the Python Scripting Host you have the option of having the results of all scheduled runs sent as ZIP-ed up files via email to one or more addresses.  You configure this option by pressing the Options button and selecting “Scheduled Scripts to Run” and then “Configure Email Notifications”.  Selecting that will show the following dialog:

 

You will need to use an external SMTP server to send the mail out for you.  This will normally require you provide not just the server name/IP address but also a login and password to authenticate against that server.  It is possible that you have an “open” SMTP server that will blindly relay messages sent to it, but this is exceedingly rare in this age of SPAM we live in today.

It is highly recommended you send a test email using the “Send test e-mail” button.  This will simply send a text-only email to all addresses you have added to the list.  If the SMTP server attachment/login/send completes, it will indicate the message was sent.  Please verify the message(s) arrived at their destination before hitting “OK” and saving the data.

Python Scripting Host will send out emails with the log file output in a ZIP file after EVERY scheduled run.  The file name of the ZIP and the body of the email will have information about the time the script was run, which client it was run on, which Connection server it was run against and if there were any errors or warnings. 

NOTE: The subject line can contain the string “%Connection_Server%” – when the email is sent out this gets replaced by the actual server name of the Connection server the script was run against.  It’s not required to be in your subject line but it can be handy.

NOTE: While the “From e-mail” field is optional, some SMTP servers will not send mail off server unless a valid from address (in some cases a valid address that lives in its mail domain) is provided.  It’s best to provide this.

Obtaining Updates

To check for updates to this tool, visit http://www.CiscoUnityTools.com

Revision History

Version 1.0.9 – 3/19/2015

·         Updated Scintilla binaries

·         Updated SQLite binaries and switched to NuGet deployment path

·         Updated setup to support all modern versions of Windows

·         Fixed several scripts to replace “ExecutProc” with “ExecuteProc” instead.

Version 1.0.8 – 2/7/2015

·         Fixed spelling error in auto complete method for stored proc calls

·         Included script to add 2nd MWI device associated with a secondary phone system integration for users from a CSV file

Version 1.0.7 – 4/12/2014

·         Added AddFileToEmailNotification method to the Helpers class for email output on scheduled script runs

·         Added several new scripts to the Reports section of the install

Version 1.0.6 – 3/29/2014

·         Added UploadWavFile and DownloadWavFile options to the helper framework to make getting voice names and greetings on and off the server easy.

·         Added ExecuteQuery option to helper for generic SQL updates

·         Added logic for passing in full path to .PY script and have it load automatically if the file exists.  Otherwise the last file edited will be open.

·         Added simple report for voice mail status for all users in the samples section

Version 1.0.5 – 3/12/2014

·         Added option to run scheduled scripts

·         Added option to email script output/log file after each scheduled run

·         Added ability to check Connection version easily in Helper framework

Version 1.0.4 – 3/7/2014

·         Added more example scripts

·         Updated SQLIte library in setup

·         Updated IronPython library in setup

Version 1.0.3 – 12/10/2013

·         Changed logic to not include audio alias and component by default when starting a new stored proc call.

Version 1.0.2 – 8/4/2013

·         First beta release of the tool.

 

© 2015 Cisco Systems, Inc. -- Company Confidential