Become a Columnist Microsoft Exchange Site Microsoft Support SiteMSDN Exchange Site

   

Subscribe to OutlookExchange
Anderson Patricio
Ann Mc Donough
Bob Spurzem
Brian Veal
Catherine Creary
Cherry Beado
Colin Janssen
Collins Timothy Mutesaria
Drew Nicholson
Fred Volking
Glen Scales
Goran Husman
Guy Thomas
Henrik Walther
Jason Sherry
Jayme Bowers
John Young
Joyce Tang
Justin Braun
Konstantin Zheludev
Kristina Waters
Kuang Zhang
Mahmoud Magdy
Martin Tuip
Michael Dong
Michele Deo
Mitch Tulloch
Nicolas Blank
Pavel Nagaev
Ragnar Harper
Ricardo Silva
Richard Wakeman
Russ Iuliano
Santhosh Hanumanthappa
Steve Bryant
Steve Craig
Todd Walker
Tracey J. Rosenblath
 
   

Debunking the top 5 Myths of Cross -Forest Exchange Migrations

Page 1 | Page 2 | Page 3 | Page 4 | Page 5

Myth 1:

Migrating Exchange mailboxes from one org to another without 3rd Party tools is suicide

FALSE

In my last large cross-org migration project, we moved roughly 30,000 mailboxes using the standard Exchange 2007 "Move-Mailbox" PowerShell command. The syntax is described here: http://technet.microsoft.com/en-us/library/aa997599.aspx.

Having said that let me point out that you should augment that command with additional scripts that provide additional error-handling and account management. In the end, the Move-Mailbox command is the only tool I use to migrate terabytes of Exchange information from one organization to another.  I will show you the command in a moment, but first let's talk about how we use it:

A)     For bulk moves, we script the command against a text file that contains the names we wish to migrate. I prefer this better than using an AD group to list the migration candidates since it allows us to "lock" the group and easily manipulate the names if so desired.

B)      Perform your AD work ahead of schedule. Create Mail-enabled user objects in the target domain and instruct the user community in advance as to how to change passwords and logon. You should avoid using AD Contacts and focus on Mail-enabled users in order to maintain passwords, groups and other attributes before, during and after the moves. This part of the project is critical and deserves its own section as you must maintain all X500, SMTP attributes. Moreover, it is important to cross-pollinate the LegacyExchangeDN value in one directory as an X500 address in the opposite directory for each mailbox. This will dramatically reduce and possibly eliminate reply failures and meeting ownerships.  

C)      Use the Move-Migration script to Mailbox-enable the target object and move the mail but use an outside process to handle all account changes in the source domain. This will give you more control and reliability of the source objects.  The Move-Mailbox script can perform these functions but there is little in the way of error-handling so if the AD is not responsive or there is a connection failure during object modifications, the Move-Mailbox command does not always recover. It is super reliable as a mail migration tool and semi-reliable with its AD changes so focus on its benefits and shore-up its weaknesses.

D)     Execute a series of Post Scripts to perform any additional cleanup you may require for the accounts and mailboxes. There will be plenty. You will need a script to disconnect (do not delete in case you need to reconnect later) the mailbox on the source object and to turn it in to a Mail-enabled object with all the previous addresses and mail attributes. You will need another script to compare the object to make sure it is correct.

Just to make sure my point is perfectly clear, this is the exact code we use for every migration:

Param([string]$textfile,[string]$database)

$import = Get-Content $textfile

$SourceCredential = get-credential

$TargetCredential = get-credential

$targetGC = "DC2.targetcompany.com"

$sourceGC = "DC2.sourcecompany.com"

 

#move the migrated user's mailbox

$report = "g:\migrations\results\MailboxMove-$(Get-Date -format 'yyyy-MM-dd hh-mm-ss').xml"

Move-Mailbox -Identity $item -TargetDatabase $database -GlobalCatalog $targetGC -SourceForestGlobalCatalog $sourceGC -SourceForestCredential $SourceCredential -TargetForestCredential $TargetCredential -confirm:$False -RetryInterval 00:00:30 -BadItemLimit 50000 -IgnorePolicyMatch -AllowMerge -ReportFile $report

}

 

It is very, very simple. We create variables for the credentials and the Domain Controllers and allow the target database to be entered as a string so the execution of the migration looks something like this:

 

./migrationscript -textfile "C:\Group1.txt" -database "SERVERA\Storage Group 01\Database-01"

 

So let me explain a few of the details in this script. First, we force the retry interval to 30 seconds instead of the default 60. This is important since there is a delay between the time you write the object in AD and when the target Exchange server acknowledges the write. Also, there is a bug in the Move-Mailbox script that reports “Failed to set basic mailbox information, will retry in 60 seconds. ” I detailed the work-around here: http://www.outlookexchange.com/Articles/Stevebryant/bryant_c18.asp

 

In short, you are likely to see this message when performing cross-forest migrations:

 

"Failed to set basic mailbox information, will retry in 60 seconds"

 

Microsoft should rename this function to "Waiting" instead of "Failed" and you should just consider this 30 seconds part of the migration and move on!

 

Second, we set the BadIemLimit to a high number but we have NEVER seen a SINGLE item get dropped. Lastly, we added the IgnorePolicyMatch and -AllowMerge in order to meet our own goals.

 

TimeSaver-Make sure all of the target Exchange 2007 servers only have one Storage Group and one Mail Store. In bulk migrations, we found that roughly 5% of the migrations resulted in a (complete) disconnected mailbox in the designated target store and an empty connected mailbox in a completely different store. It seems that at some point during the end of a mailbox migration, the target server cannot enable the mailbox and Move-Mailbox creates a new empty mailbox on the same server on a different store. No error is flagged and the only way to detect this was to write a script:

 

get-mailboxserver | where {$_.name -like "SERVERNAME*"} |Get-mailboxStatistics | where {$_.DisconnectDate -notlike "" -and $_.Displayname -notlike "*test*"} | sort LastLogonTime | ft DisplayName, LastLogonTime, Database -wrap

 

This script is pretty simply as it is only looking to see if there are mailboxes that are in a disconnected state. This will be the case if the mailbox has been moved to another database or server or if the mailbox suffered the "split" problem as described.  However, by targeting a server with only a single database you eliminate this problem and have no need for my clever script.

Debunking the top 5 Myths of Cross -Forest Exchange Migrations

Page 1 | Page 2 | Page 3 | Page 4 | Page 5

Disclaimer: Your use of the information contained in these pages is at your sole risk. All information on these pages is provided "as is", without any warranty, whether express or implied, of its accuracy, completeness, fitness for a particular purpose, title or non-infringement, and none of the third-party products or information mentioned in the work are authored, recommended, supported or guaranteed by Stephen Bryant or Pro Exchange. OutlookExchange.Com, Stephen Bryant and Pro Exchange shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages.

Copyright Stephen Bryant 2008