Using AXL/SOAP updateLine to Assist with CUCM Upgrades

William Bell
Vice President, Solutions and Products

Actually, that wasn’t my answer.  If it were, I am sure my customer would have went somewhere else for help.  Before we dive into my answer, let’s make sure we understand the question.

Let’s say you have 3,000 phones in your CM 4.1 cluster and you are also hosting Unity, UCCX, and various 3rd party applications.  You have been a Cisco voice customer for a while, and your servers are antiques.  You are ready to move to CUCM 7.1.  You are also migrating Unity, UCCX, and everything else.  You look at your upgrade options and you say to yourself: “Self, we are going to do a parrallel upgrade.”  You want to slowly introduce CUCM 7.1 to the environment, you have to buy new servers anyway, so why not stand up two production clusters and slowly migrate users?

Of the myriad of tasks you must contend with, figuring out how to redirect calls from the CM 4.1 to the CUCM 7.1 server for migrated phones is just one.  But, it is an important consideration.  If you had 3000 phones and you migrate 200, you have to make sure that the 2,800 phones on CM 4.1 can dial the 200 phones on CUCM 7.1.  For that matter, you have to make sure the reverse is also possible.

Clearly, you have to deal with ICT configurations and make sure you put in loop avoidance measures (overlapping dial plan and all).  In addition, you have to have a way to “tell” the CM 4.1 system that Elvis has the left the building and to send all calls to the new guy in Network Rack 41.

There are several approaches to this task and I happen to like using AXL/SOAP to accomplish what I need.  I think it is the most efficient way to reassign DNs in this scenario while also keeping most everything else in the phone record intact.  I’ve recently created a script that allows me to read in a list of phone MAC addresses, read in a rules file that identifies DN changes, and goes to town on the 4.x system to get things migrated.

Our objective is to move or hide 2000/Phone_PT  so that the route pattern 2xxx/Phone_PT can route the call to the Intercluster trunk that connect CM 4x to CUCM 7x.  You know, the whole longest match thing comes into play.

The Procedure

First, you’ll need a routine to read in the various text files.  One file should have the IP phone SEPxxxxxxxxxxxx names.  That is all you will need to start with.  Another file could be (but not required) something that helps your application/script identify what should change.  For example, “replace Phones_PT with HideMyPhone_PT”.

For each record, you will essentially do the following:

1. Find out the phone lines that are configured on the device.  I like to use a SQL query for this:

var phonesql = "select,d.description,n.pkid as dnpkid,n.dnorpattern,n.fkroutepartition,dmap.NumPlanIndex "
+ "from device as d inner join devicenumplanmap as dmap on dmap.fkdevice=d.pkid "
+ "inner join numplan as n on n.pkid=dmap.fknumplan "
+ " where = 'SUBSTITUTE' order by dmap.NumPlanIndex";

Note, you’ll swap the string SUBSTITUTE for the SEPxxxxxxxxxxxx ID for the phone.

2. You should wrap this query in a properly formatted SOAP request:

          <sql>..your sql query..</sql>

3. You’ll get back an SOAP response which you will need to parse.  I use Microsoft DOM objects:

var myxmldom = new ActiveXObject ("Microsoft.XMLDOM");
var chkdom = myxmldom.loadXML(axlResp);
if (!chkdom) some error handling...
var nodelist = myxmldom.getElementsByTagName("row");
if (nodelist.length==0) some error handling...
for(var row=0;row
{ //master row loop
var myrecord = {
var mydevnode = nodelist.item(row);
myrecord.devname = mydevnode.selectSingleNode("name").text;
myrecord.dnpkid = mydevnode.selectSingleNode("dnpkid").text;
myrecord.olddn = mydevnode.selectSingleNode("dnorpattern").text;
myrecord.oldpt = resolvename(mydevnode.selectSingleNode("fkroutepartition").text,myptnames);
myrecord.newdn = (mydnrules.length == 0) ? myrecord.olddn : resolveNewDN(myrecord.olddn,mydnrules);
myrecord.newpt = (myptrules.length == 0) ? myrecord.oldpt : resolveNewDN(myrecord.oldpt,myptrules);
dnarr.push(myrecord.devname + "::" + myrecord.dnpkid + "::" + myrecord.olddn + "::" + myrecord.oldpt + "::" + myrecord.newdn + "::" + myrecord.newpt);

Of course, my method is different because that’s just how these things work.  The resolvename() and resolveNewDN() functions are functions I wrote to resolve the GUID of the partition [resolvename()] to the “well known” name (i.e. resolve {87fg878ab…} to Phone_PT).  The resolveNewDN() uses my “rules file” to determine what (if anything) I should do this this particular line appearance.

Once you figure out how you want to modify the DN, maybe you have something like this:

  • DN: 2000
  • NewDN: 2000 /*for this app we don’t need to modify the DN*/
  • Old PT: Phone_PT
  • New PT: HideMyPhone_PT
  • NumPlanGUID: {xxxxxxxx…xxxxxx}  /*you’ll need this later*/

You’ll notice the SQL response could have more than one DN (phones have more than 1 button).  So, you’ll need to build your recordset into a variable you can pass around.  I like arrays for this.

4. Now you have the existing phone DN information and you have identified what you want to change it to.  Now, you will need to let the CM cluster know your intentions.  I do this by passing the record set I built in step 3 through a loop.  For each array element (which is one line appearance on the phone) I will first check to see if anything has changed.  I only process the line if there is a change.  When a line is to be processed, I use the AXL updateLine procedure.  The SOAP request for this will look something like the following:

          <uuid>..put the NumPlanGUID here..</uuid>
          <newPattern>..put NewDN here..</newPattern>
          <newRoutePartitionName>..put NewPT here..</newRoutePartitionName>

You will want to check for any fault messages in the response.  A successful response will have a return child node with the GUID. 

5. Now, there is a defect I have come across on CM 4.1(3) that you may have to contend with.  In my testing (and production use) I have found that even though the updateLine command works and the database is updated, the CM subscribers are still holding onto the old line configuration.  Something is stuck in the cached record for the line.  To “unstick” it I put together a workaround.  I basically use “newLine” SOAP function to put the “old” DN back into the database and then I use removeLine to remove it immediately.

To clarify.  Say that you had this:

  • OldDN: 2000
  • NewDN: 2000
  • OldPT: Phone_PT
  • NewPT: HideMyPhone_PT

In step 4, you use updateLine to change 2000/Phone_PT to 2000/HideMyPhone_PT.  That is our goal, so far, so good.  Now, you may (you can test if you want) find that the CM subscribers behave like 2000/Phone_PT still exists (even though the database shows the correct record).  What I do is re-create 2000/Phone_PT in the database (not associated to any devices BTW).  Then I delete it straight away.  Clunky, but it works.

Other Considerations and Notes

I noticed when I was trying to apply the same script on a CUCM 7x cluster that my updateLine call was failing.  I didn’t receive a fault message.  I just received a message with a return node equal to “true”.  I also noticed that the phone lines were not getting updated.  I looked at the AXL schema file for 7.1 and I didn’t see any changes in the schema that would affect what I am doing.  Then I looked at the raw XML and I noticed that in response to my sql query (executeSQLQuery), CUCM was sending a Num Plan guid that looked like this:


I checked this against the CM 4.1 response and I noticed that the response from CUCM 7.x was missing the braces like:


This isn’t really that big of a deal except that when I use updateLine to update the line I was passing the PKID without modifying (i.e. adding the braces).  Apparently, not adding the braces means that CUCM 7.1 (at least) will ignore your request.  Easy enough, check to see if the braces exist and if they don’t add them.  Then all is well with the world.

One response to “Using AXL/SOAP updateLine to Assist with CUCM Upgrades

  1. Hello William

    I am using updatePhone request to update the ownerusername of a phone. Resquest and response seems to be ok. However when I check CUCM, the value of the owneruser is the same. Ocassionally if I send the request a couple of times. it chages the CUCM. Any idea how to fix this problem?



Leave a Reply