Migrating OCS conference directories to Lync the hard way

A few evenings ago I ran into a scenario where moving a conference directory from OCS to Lync failed, and the conference directory ended up in this limbo state where it wasn't on Lync, I couldn't move it back to OCS, and the conferencing attendant wouldn't recognize any PSTNs IDs which were part of the directory. Not a great scenario.

After running Move-CsConferenceDirectory I could verify the move was in progress, but it never completed. The status would show it was trying to move, and OCS eventually started throwing errors that it no longer had a conference directory, but it never fully made it to Lync. The TargetServerIfMoving parameter stayed populated:

Get-CsConferenceDirectory -Identity 5
Identity: 5
ServiceId: UserServer:OCSPOOL.ptown.local
TargetServerIfMoving: UserServer:LYNCPOOL.ptown.local

Trying to run Move-CsConferenceDirectory again would consistently fail with the following errors:

WARNING: Move operation failed for conference directory with ID "5". Cannot perform a rollback because data migration might have already started. Retry the operation.
WARNING: Before using the -Force parameter, ensure that you have exported the conference directory data using DBImpExp.exe and imported the data on the target pool. Refer to the DBImpExp-Readme.htm file for more information.
Exception from HRESULT: 0xC3EE7950, Microsoft.Rtc.Management.ConferenceDirectoryCmdlets.MoveConferenceDirectoryCmdlet

In the end I needed to export the data from the OCS directory via DbImpExp, force the directory to move, and then import the data. Not the cleanest route, but it works. The order is important, so be patient.

On the OCS pool and database export the conference directory data:

DbImpExp.exe /hrxmlfile:C:\Temp\OCSDirectory5.xml /SQLServer:OCS-SQL.ptown.local /restype:confdir

Only once you're positive you have a good export (Read: opened the file and checked!), and made a copy of it you can force the Move-CsConferenceDirectory operation:

Move-CsConferenceDirectory 5 -TargetPool LYNCPOOL.ptown.local -Force

Congrats. You've moved the directory to Lync, but it's empty. Copy the .xml export file to a FE in the Lync pool. On the Lync pool and database import the directory data while specifying the conference directory ID to recover the old data:

DbImpExp.exe /import /hrxmlfile:C:\Temp\OCSDirectory5.xml /SQLServer:LYNC-SQL.ptown.local /restype:confdir /dirid:5

At this point I could see the directory was no longer moving because TargetServerIfMoving was empty, and the conference attendant was now recognizing PSTN IDs which had been created against this directory.

Get-CsConferenceDirectory -Identity 5
Identity: 5
ServiceId: UserServer:LYNCPOOL.ptown.local
TargetServerIfMoving: 

Again, this is a good reason to always do a DbImpExp.exe dump before moving directories or databases around. Those .XML files can save your skin!

Monitoring OCS and Lync Peak Call Capacity

Recently I had a customer interested in checking how many concurrent calls a particular OCS Mediation Server was handling. The challenge with this is that separate perfmon counters exist for inbound calls and for outbound calls, but there is not a built-in counter which measures both. So while we could monitor the peak capacity of each we had no guarantee that these peak values were occurring at the same time.

In order to track this usage I've come up with a Powershell script which grabs these two counters, parses their values, adds them together, and dumps the output into a CSV file. At the end of the monitoring period you can take this CSV into Excel and easily find the peak total call count.

Here are some notes on the behavior:

  • The CSV output is date and time, inbound calls, outbound calls, and total calls.
  • Data is output to the console and to CSV for real-time monitoring.
  • The default values track usage for a week, polling the counters every 15 seconds. You can change the total number of loops in the script to your liking if you need a longer track record.
  • If you run the script again it will detect if previous data exists and rename the old file so you don't lose anything.
  • I've run this as a logged in user account, but I imagine you could set it up as a scheduled task to run in the background.
  • In order to run the script you should first run Set-ExecutionPolicy Unrestricted

The caveat with the Lync version is now that a Mediation server can use multiple gateways we can't see which gateway is being used for each inbound or outbound call. But this still gives an idea of concurrent call capacity flowing through each Mediation role.

I hope to improve this in the future, but wanted to make it available for everyone sooner than later.

OCS Create Pool Wizard Error: Invalid database parameter

Recently I had a project where we were moving the OCS databases to a new clustered SQL 2008 (R1) with SP2 Back-End and ran into a lovely new error I'd never seen before - also not seen before anywhere on Google!

For starters, we followed the steps outlined on Technet. After we had successfully detached and attached all databases and ran the LCSCMD.exe step, we launched the Create Pool wizard and attempted to plug in the info for the new SQL cluster. We got this error back:

An error occurred during the pool backend detection:

Pool backend discovery failed.

Invalid database parameter.

I double-checked the server name, instance, and FQDN and all looked well. We verified the SQL server was accessible via TCP 1433 and no firewall rules were preventing access, so the error didn't make a lot of sense. Obviously there was some kind of parameter that the wizard GUI was not cool with. I thought maybe this was the SQL allow updates issue, but that solution had no effect on this error. There was definitely some validation check the UI was failing on against our new DB.

Since I couldn't locate anyone else with this issue I figured my options were to call PSS and extend this process by a few hours, or pull out the ol' LCSCMD.exe again and try this operation via command line. The Create Pool wizard really is just collecting a bunch of information and then using it to execute the LCSCMD.exe commands in the background so while doing it manually is not fun, it works just as well.

The entire syntax for LCSCMD.exe can be found on Techet, but here is the command we ended up running. Please note, conferencing archiving was not implemented so that paramter is not present.

LCSCMD.exe /Forest /Action:CreatePool /PoolName:MyOCSPool /PoolBE:MySQLServer.ptown.local\OCSInstance /PoolFQDN:MyOCSPool.ptown.local /InternalWebFQDN:MyOCSPool.ptown.local /ExternalWebFQDN:PublicOCSWebComponents.confusedamused.com /RefDomain:ptown.local /ABOutputlocation:\\\\MyFileServer\AddressBook /MeetingContentPath:\\\\MyFileServer\MeetingContent /MeetingMetaPath:\\\\MyFileServer\MeetingMetadata /AppDataLocation:\\\\MyFileServer\AppData /ClientUpdateLocation:\\\\MyFilerServer\ClientUpdates /DBDataPath:"D:\Databases" /DBLogPath:"L:\Logs" /DynDataPath:"D:\Databases" /DynLogPath:"L:\Logs" /ABSDataPath:"D:\Databases" /ABSLogPath:"L:\Logs" /ACDDataPath:"D:\Databases" /ACDLogPath:"L:\Logs"

After running the command manually it succeeded with absolutely no issues. The new cluster has been running for over a week now without any issues so I think this is an problem specific to the UI. I'm not sure exactly what causes it, but our environment was running SQL 2008 with SP2 on top of a 2008 R2 SP1 operating system.

As a sidenote, this process seems to undo any changes made by the OCS2009-DBUpgrade.msi patches. You'll need to re-run the patch version which lines up with your FE patch levels before the FE services will be able to start.