As a person who enjoys weekends and sleep, my favorite friday night cutover is one that lasts approximately 30 seconds. To do this, you need three things:

-Enough resources to temporarily have two of everything
-A portgroup configured with an isolated VLAN
-A staging PC for use as an NTP server (I recommend Meinberg NTP for that)

After building and testing your new environment, you’ll want to “flip the nics” to make the new system live:

Connect-viserver -User admin -Password pass

Get-Cluster “Old-UC-Cluster” | Get-VM | Get-NetworkAdapter | set-networkadapter -Connected:$false -Confirm:$false

Get-Cluster “New-UC-Cluster” | Get-VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup “VLAN 9” -Confirm:$false

This is in a sunny day scenario where everything in the whole cluster is disconnected while everything in another is connected. Sometimes you need to apply some logic to exclude some vms that happen to coexist within the same cluster:

Get-Cluster “New-UC-Cluster” | Get-VM | Get-NetworkAdapter | Where {$_.NetworkName -eq “VLAN 3” -and $_.Name -notlike “CUCMSUB2”} | Set-NetworkAdapter -Portgroup “VLAN 9” -Confirm:$false

UC applications aren’t only supported by Cisco on a virtual platform now, it’s the ONLY supported platform. As a “Collaboration Engineer” by title, I am usually focused on only a handful of applications, traditionally relying on the “Datacenter Guy” to provide the infrastructure and hope it works. But, it’s always good to see the whole picture.

In my opinion, virtualization is something everyone needs to know at least the basics of. You might not be the one adding a vlan to a switch anymore, but you still need to know networking.

Each VM contains two basic files: one .vmx (configuration) and one .vmdk (disc)
The .vmdk (disc) is considerably larger and contains all the bits a physical hard drive would. The .vmx (configuration) is a small, editable file containing all of the settings a physical bios chip would.

A few items you’ll find in a .vmx file:
numvcpus = “2”
memsize = “6144”
scsi0:0.fileName = “UCCX1.vmdk”
ethernet0.networkName = “Voice_VLAN”
guestOS = “rhel4”
sched.cpu.min = “1300”
sched.cpu.units = “mhz”
sched.cpu.shares = “normal”
sched.mem.minsize = “6144”
sched.mem.shares = “normal”
One task any Cisco UC Engineer will go through at least once is an upgrade from pre 8.6 to post 8.6 version. Two changes come about: an OS change from Redhat 4/5 to 6, and adapter change from flexible to vmxnet3.

One method is to edit the .vmx by finding it on the datastore, downloading the file, making the edits below, and import it back:
guestOS = “rhel6_64guest”
ethernet0.virtualDev = “vmxnet3”
An easier method if you are doing multiple servers/clusters at once is to use PowerCLI
Connect-VIServer -Server vcenter01 -User admin -Password pass
Set-ExecutionPolicy RemoteSigned
Set-VM -VM ‘UCCX Pub’ -GuestId “rhel6_64guest” -Confirm:$false
Get-VM ‘UCCX Pub’ | get-networkadapter | set-networkadapter -type vmxnet3

So for a g711 call with default payload carried over ethernet:

Total Packet Size: 40 + 18 + 160 = 218 bytes = 1744 bits

PPS = 64,000 (bitrate) / 1280 (payload size) = 50

Bandwidth = 1744 * 50 = 87,200 (or 87.2 kbps)

You could also use the Voice Bandwidth Calculator from TAC:

Sometimes working with a large amount of phones (10,000+) it can take a whole day to export into a csv, and makes more sense to view and manipulate data in the live database. Caution should be taken when handling the live database, so if you are not a programmer, you may want to stick to the canned scripts below as an overly broad query could lock up your server!

I was recently tasked with running firmware updates on a large amount of phones, various models for over 100 device pools. Anything that can help organize and divide workload and cut down on unnecessary bulk jobs is a huge help!

UC Guerilla has a good blog on this here
Cisco’s documentation you can find here, but a tough read for a non-programmer

Count the number of devices per type, total:

run sql select count( Device_count, Device_Type from Device inner join typemodel on device.tkmodel=typemodel.enum group by

Count the number of phones in each device pool, sorted by device pool name:

run sql select count(, as DevicePool, as DeviceType from Device as d inner join DevicePool as dp on d.fkDevicePool=dp.pkid inner join typeClass as tc on tc.enum=d.tkClass group by, order by

Count the number of each type of phone per device pool, sorted by device pool name:

run sql select count( Device_count, Device_Pool, Device_Type from Device inner join DevicePool on Device.fkDevicePool=DevicePool.pkid inner join typemodel on device.tkmodel=typemodel.enum group by, order by


ILS is a new feature service in CUCM 9.0 that allows for sharing of Directory-URIs between clusters.

A Directory URI is much like an email address, formatted like where jlevensailor is the user portion and is the host portion. The user portion is actually case sensitive, but only in the context of CUCM, and is actually an enterprise parameter that can be set to fix this.

The internet uses dns via _sip._udp/tcp or _sips._tls SRV records to route calls between Directory URIs much like email uses mx records. CUCM uses sip route patterns for Directory URIs much like they use standard route patterns for DNs. To tell CUCM that a particular Directory URI is on-net within a particular multi-cluster environment, ILS was introduced.

*It is recommended to first change the Cluster ID enterprise parameter in both clusters to something unique.

To get started, I’ll assume you have a sip trunk has been created already between the two clusters, directly or via SME. Go to Advanced Features and ILS Configuration.

You’ll change the role to “Hub Cluster” and enter the corresponding clusters domain name or ip-address in the popup. For authentication you can either use TLS certificates and exchange certs (default), or you can use a password. Note: The password does require a restart of the ILS service, in case you were already running this.

The advertised route string is what you will create a sip route pattern for on the other cluster, pointing to the ICT so calls can work. When you are done, you can go ahead and start the service if you haven’t already, wait until synchronization finishes and run a route plan report to confirm:

As you can see, any URI on the remote hub cluster will be discovered, not just those that happen to match the advertised route string, which by default is the cluster FQDN.

The call flow is: nbates@car.lab wants to call test@dur.lab. CUCM checks the CSS of nbates@car.lab and proceeds to search for the URI in the list of ordered partitions as usual. When it finds test@dur.lab, it sees that it is a “Learned URI” from sbcucm.dur.lab, and uses the target from the sip route pattern of “dur.lab” I created to call the remote user.

The benefit of this is that sip route patterns won’t have to be created for each remote domain, just one for each ILS partner cluster. I would imagine you’ll start seeing a blank sip route pattern pointed to VCS/Expressway-C for outside domains and a specific ILS route pattern for internal domains/on-net traffic.

Official Documentation HERE

Well oh well, I guess it’s been a while since I posted anything. I’ve been so busy lately, mostly working in large bat files or manipulating call manager databases.
Something that ticked me off was how you can’t put windows side by side because they are nested inside Excel. The following code makes all Excel files open in a new window!

*Note this is for .xls files, for .xlsx change the (Excel.Sheet.8 to Excel.Sheet.12), For .csv files, it’s Excel.CSV


@=””C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE” /e “%1″”




Adding to my post from monday, I had another issue with SRM not changing ip addresses on an Asterisk (CentOS) box, so I had to engineer a workaround..

For PRIMARY = and DR =

1. On the linux box, we’ll create two bash scripts, chmod these 755 and stick these in your $PATH.
ifconfig eth0 netmask up
route add default gw eth0
ifconfig eth0 netmask up
route add default gw eth0

2. On the vCenter, install WinSCP and run. Create 2 new sessions with saved credentials and name primary and dr. Connect to each session and accept the certificates!
3. Ensure the following is in the windows PATH, if not, add this directory: C:Program Files (x86)WinSCP
4. Create the batch file below to call winscp, start the session and run the relevant script from step 1.

@echo off
echo “Logging into host and running script”
If EXIST c:primary.txt (winscp primary /command “call”) ELSE (winscp dr /command “call”)
echo Exit Value %ERRORLEVEL%
TIMEOUT /t 5 /nobreak

In SRM run the bat file, no flags needed.

VMware advertises the ability to “perform fully automated orchestration of site failover and fallback with a single click.” While this technology is extremely easy to setup and use, it’s oftentimes the small things that cause the biggest headache. SRM uses dns to propogate ip changes from the primary to secondary virtual machines. With windows this is automatic: the servers simply register their new ip addresses in dns. For linux servers, however this is not so easy, especially in my case (an avaya phone system) which provides no access to the CLI. The fix is to create a script.

DNS Server –
Primary Site Avaya –
Failover Site Avaya-

First you’ll want to make sure you are running the SRM service as an account with domain admin rights (assuming you setup the database with windows authentication during setup).

Next you’ll need DNSCMD from the RSAT (remote server administration tools), which you can find here

Below is an example script:

@echo OFF
echo “Removing Records from DNS…”
dnscmd /recorddelete dom.local AVAYA-SRV-01 A /f
echo Exit Value:  %ERRORLEVEL%
TIMEOUT /t 3 /nobreak
dnscmd /recorddelete dom.local AVAYA-SRV-01 A /f
echo Exit Value:  %ERRORLEVEL%
TIMEOUT /t 3 /nobreak

@echo off
echo “Adding Records to DNS ..”
If EXIST c:primary.txt (dnscmd /recordadd dom.local AVAYA-SRV-01 A ELSE (dnscmd /recordadd dom.local AVAYA-SRV-01 A
echo Exit Value:  %ERRORLEVEL%
TIMEOUT /t 5 /nobreak

In SRM, you’ll call the script as:
C:windowssystem32cmd.exe /c c:srmscriptsdnschange.bat

Also, you may notice the “If EXIST c:primary.txt”
It was the most elegant way I could think of the check if the system was in a failover state. This file will exist only on the primary side. Credit to Derek Bickel on this one!

  1. NAT Exemption – don’t ever nat this
  2. Static Policy NAT – nat to something when this goes to that
  3. Static NAT – nat this to that
  4. Dynamic Policy NAT/PAT – nat to something when these go to that
  5. Identity NAT – don’t nat this when i’m talking
  6. Dynamic NAT – nat all these to this
  7. Dynamic PAT –  nat all these ports to this