If you are in the planning stages for a migration from Exchange 2010 to Exchange 2016, then you have probably seen this TechNet article.
At first, it may seem daunting.
So many scripts. So many PowerShell commands.
If you are not comfortable with PowerShell it may seem a bit overwhelming.
Plus, it is vastly different than any previous migration process.
Why the change?
Architecture
Beginning with Exchange 2013–and continued with 2016–public folders underwent a major architectural change.
This new architecture is referred to as Modern Public Folders. The old architecture is now known as Legacy Public Folders. But its much more than a name change. Gone is the Public Folder database. And hello are the new Public Folder Mailboxes.
The benefit?
No more Public Folder Replication. Boy, did that used to be a pain!
With Public Folders stored as a mailbox, that mailbox can now be part of a Database Availability Group (DAG). And with that, all the benefits of Windows Failover Clustering.
This makes the migration process vastly different.
On a high level, it is the process of moving all data out of a database and into a special mailbox. That is where the scripts come in. I’ll explain along the way.
Let’s get started!
Works with 2013: This process also works with migrations to Exchange 2013 (from 2007 SP3 RU15 or 2010 SP3 RU8). It requires Exchange 2013 be on Cumulative Update 7 or later. If not, you will need to perform the older serial migration method documented here.
Step 1: The Prerequisites
Caution: Before you get started with any migration process it’s always good to do a backup. For Exchange, it is imperative to use a solution that is Exchange-aware. Whichever solution you use, be sure to have a good working backup of your Public Folder Database.
Before we get started we need to download the migration scripts. These can be downloaded from here. Save these to your old server. Be sure to get all six files.
Save them to an easily accessible directory. Such as C:\PFScripts. The end result should look like this.
Next, we need to make sure our source servers are fully patched. At a minimum, we need to be at the following levels.
Exchange Server 2010 SP3 and SP3 RU8.
Of course, these are only the minimum patch levels. It’s always best practice to get the latest update available. At the time of writing Exchange 2010 SP3 RU12 is the latest release.
In addition, be sure to patch your Exchange 2016 server as well. At the time of writing, there is no cumulative update for Exchange 2016.
Tip: It is important to migrate public folders after you migrate all users to 2016. Users on legacy versions of Exchange will not be able to access the modern public folders of Exchange 2016.
Step 2: Running the scripts
The first script we need to run is the Export-PublicFolderStatistics.ps1 script.
To do this open the Exchange Management Shell on your 2010 server. Change to your scripts directory. Run the .\Export-PublicFolderStatistics.ps1 script. Be sure to include the period and backslash.
You may be prompted to allow the script to run. Pick [R] to run once, or, [A] to always run.
You will then be prompted to enter an output file name. I called this PublicFolderStats.csv.
You are then prompted for a source server that contains your Public Folder database. In my lab, the 2010 server is called EX10.
C:\PFScripts>.\Export-PublicFolderStatistics.ps1 cmdlet Export-PublicFolderStatistics.ps1 at command pipeline position 1 Supply values for the following parameters: (Type !? for Help.) ExportFile: PublicFolderStats.csv PublicFolderServer: EX10 [3/8/2016 11:23:21 AM] Enumerating folders under NON_IPM_SUBTREE... [3/8/2016 11:23:23 AM] Enumerating folders under NON_IPM_SUBTREE completed...6 folders found. [3/8/2016 11:23:25 AM] Retrieving statistics from server EX10 [3/8/2016 11:23:25 AM] Retrieving statistics from server EX10 complete...7 folders found. [3/8/2016 11:23:25 AM] Total unique folders found : 7. [3/8/2016 11:23:25 AM] Exporting statistics for 7 folders [3/8/2016 11:23:25 AM] Exporting folders to a CSV file [PS] C:\PFScripts>
This will create the file called PublicFolderStats.csv in the scripts folder. If we open the file, we can see all the folders it discovered and their sizes in bytes. In my lab, I only have six folders. All of which are empty. The size column is measured in bytes.
Next, we need to run the PublicFolderToMailboxMapGenerator.ps1 script. To do this run the .\PublicFolderToMailboxMapGenerator.ps1 script. Be sure to include the period and backslash.
This script will input the PublicFolderStats.csv file we just created. It will then determine how many Public Folder Mailboxes need to be created.
The script will prompt for the desired size of each Public Folder Mailbox. Remember, this is entered as bytes.
For a 20GB mailbox, this would be 21474836480 bytes. There are a lot of calculators out there. I recommend this one from whatsabyte.com.
We are then asked for the file we created with the previous script. We had called this PublicFolderStats.csv.
Next enter the name of the map file we want to create. I made this FolderToMailbox.csv.
C:\PFScripts>.\PublicFolderToMailboxMapGenerator.ps1 cmdlet PublicFolderToMailboxMapGenerator.ps1 at command pipeline position 1 Supply values for the following parameters: (Type !? for Help.) MailboxSize: 21474836480 ImportFile: PublicFolderStats.csv ExportFile: FolderToMailbox.csv [3/8/2016 11:31:57 AM] Reading public folder list... [3/8/2016 11:31:57 AM] Loading folder hierarchy... [3/8/2016 11:31:57 AM] Allocating folders to mailboxes... [3/8/2016 11:31:57 AM] Trying to accomodate folders with their parent... [3/8/2016 11:31:57 AM] Exporting folder mapping... [PS] C:\PFScripts>
As you are sizing the Public Folder mailboxes, keep in mind any quotas you have in place in 2016. Like user mailboxes, public folder mailboxes follow the same quota scheme. That said, if you have a massive public folder deployment, you may want to create a dedicated database that only contains your public folder mailboxes.
This recommendation may seem contradictory to the architecture changes mentioned earlier as the public folders would be once again in a dedicated database. But keep in mind that the database is using Windows Failover Clustering as its shipping mechanism and not public folder replication (Yay!).
Let’s open the FolderToMailbox.csv file and see what it recommends.
In my case, the script determines I only need one Public Folder Mailbox. In my lab, I have very little data. Your result could be quite different. And will vary based on the size you specified when running the mapping script. The map generator script may determine you need several public folder mailboxes.
The map generator names these public folder mailboxes generic names of Mailbox1, Mailbox2 and so on. If you want to utilize a different naming convention then change the name here and save the file.
In my case, I will change this to “Public Folder Mailbox 1” and save the file. If I had a requirement for a second mailbox I would call it “Public Folder Mailbox 2” and so on.
Now we need to switch gears and log onto our Exchange 2016 server. Once logged on, copy the entire contents of the C:\PFScripts folder from the old Exchange server to the same location on the 2016 server.
Open PowerShell and change to the C:\PFScripts directory. Run the .\Create-PublicFolderMailboxesForMigration.ps1 script. Be sure to include the preceding period and backslash.
You may be prompted to allow the script to run. Pick [R] to run once, or, [A] to always run.
You will then be prompted to enter the name of our mapping file we created on the old server. This should have come across when you copied the PFScripts folder. We had called this FolderToMailbox.csv.
You will then be asked for an estimate of your concurrent users who access public folders. Microsoft states this is less than your actual user count. Microsoft’s recommended limit for concurrent connections to a single public folder mailbox is 2,000. So, for an environment with less than 2,000 users, it really doesn’t matter what you enter here. For a large environment with more than 2,000 users, you want to make sure that you have one public folder mailbox for every 2,000 concurrent connections. You may wish to correct your map file, if you have too few mailboxes, before proceeding.
The script will validate the contents of the CSV map file and ask if you wish to proceed. Hit enter to accept the default of [Y] Yes.
C:\PFScripts>.\Create-PublicFolderMailboxesForMigration.ps1 Do you want to run software from this untrusted publisher? File C:\PFScripts\Create-PublicFolderMailboxesForMigration.ps1 is published by CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers. [V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"): a cmdlet Create-PublicFolderMailboxesForMigration.ps1 at command pipeline position 1 Supply values for the following parameters: (Type !? for Help.) FolderMappingCsv: FolderToMailbox.csv EstimatedNumberOfConcurrentUsers: 100 Public Folder mailbox updates. Creating 1 Public Folder mailbox(es) and updating 0. Total mailboxes to serve hierarchy will be 1. Would you like to proceed? [Y] Yes [N] No [?] Help (default is "Y"): Total mailboxes created: 1. Total mailboxes updated: 0. Total serving hierarchy: 1. Here is a list of Public Folder mailboxes created: Name IsServingHierarchy IsMigrationTarget ---- ------------------ ----------------- Public Folder Mailbox 1 True True [PS] C:\PFScripts>
The script then lists all the public folder mailboxes it created. It should be every mailbox you had in your map file. In our case, it was just the one which we had renamed Public Folder Mailbox 1.
In part one of public folder migration, we prepared our environment. Then we ran all the necessary scripts to size and create the new public folder mailbox hierarchy.
In this second and final part of our series, we will copy the data from the legacy public folder databases into our newly created modern public folders. We will also finalize the migration process.
Step 3: Data Migration
Let’s start moving our data. First, let’s create the migration batch. From the Exchange 2016 server issue the following command.
C:\> New-MigrationBatch -Name PFMigration -SourcePublicFolderDatabase (Get-PublicFolderDatabase -Server EX10) -CSVData (Get-Content C:\PFScripts\FolderToMailbox.csv -Encoding Byte) -NotificationEmails [email protected]
In our example:
-Name specifies a display name to help identify the batch.
-SourcePublicFolderDatabase (-Server) specifies the 2010 server hosting the public folder database. In my lab, this is called EX10.
-CSVData specifies the path to our map file we created in part one of our series. We had called this FolderToMailbox.csv and saved it to C:\PFScripts.
-NotificationEmails specifies where to email the batch migration report. This is optional.
C:\> New-MigrationBatch -Name PFMigration -SourcePublicFolderDatabase (Get-PublicFolderDatabase -Server EX10) -CSVData (Get-Content C:\PFScripts\FolderToMailbox.csv -Encoding Byte) -NotificationEmails [email protected] Identity Status Type TotalCount -------- ------ ---- ---------- PFMigration Created PublicFolder 1 [PS] C:\>
This only creates the job. To start the actual data copy run the following command. If you named your job anything other than PFMigration you will need to change that here.
C:\> Start-MigrationBatch PFMigration
We can check the progress of the batch by logging into the Exchange Admin Center. Once logged in, navigate to Recipients >> Migration tab.
From here we will see our PFMigration job and its current status. Before issuing the previous command it would have shown a status of “Created”. Once we started the batch it switches to “Syncing”.
Selecting the batch and clicking the View Details link, will give us a deeper insight into what is happening with the batch.
From here we can see greater detail into the progress of our PFMigration batch. We can see that 5 items have synced, nothing has been skipped and, so far no errors are reported. The real magic is the Download the report for this user link. This link is a detailed play by play of everything the migration is doing. Including any additional information on errors. It’s great for troubleshooting purposes.
If you are interested in what my detailed migration report looked like check this link.
You can also see the same report in PowerShell by issuing the following command. You will need to replace PFMigration with the name of your batch if different.
C:\> Get-MigrationUser -Batch PFMigration | Get-MigrationUserStatistics -IncludeReport | fl
Eventually, your migration will show a status of Synced. In addition, the report will list a percentage of 95 and indicate it was automatically suspended. This means the initial seed of data has been completed. However, your new public folder mailbox it is not yet live. If you take no action the migration job will perform an incremental copy every 24 hours until you complete the batch. Keep in mind completing the batch will force downtime for your public folders. It may be best to perform these next tasks under a maintenance window.
Step 4: Completing the Migration
Now that the data is seeded its time to flip the switch.
Warning: This will take your public folders offline. You may wish to schedule this during a maintenance window.
Okay, let’s switch back to the 2010 server.
From the Exchange Management Shell run this command. Users will be blocked from accessing Public Folders.
C:\> Set-OrganizationConfig –PublicFoldersLockedForMigration:$true
Warning: It can take some time for this lock command to propagate through your network. It’s not uncommon for this change to take several hours for a large network. The next two commands will fail until the change is replicated through the network.
Let’s switch back to the 2016 server again.
From the Exchange Management Shell run the following.
C:\> Set-OrganizationConfig -PublicFoldersEnabled Remote
Now let’s complete the batch. Be sure to rename PFMigration to the name of your batch, if different. Hit enter to accept the default action of Yes.
C:\> Complete-MigrationBatch PFMigration Confirm Are you sure you want to perform this action? Complete migration batch "PFMigration"? [Y] Yes [A] Yes to All [N] No [L] No to All [?] Help (default is "Y"):
The batch status will switch to Completing. During this time a final incremental sync is performed. Once finished the status column will display Completed. How long this takes depends on how many changes have been made in public folders since the initial seed, or, last incremental sync. Cleanup and replication are also performed in the environment.
If you are curious about what the final report contains check out this link.
You should also see your folder structure appear under the Public Folders > Public Folders tab. You may need to hit the refresh () button. This is where you manage public folders going forward.
Now we need to test. Issue this command against one of your test users. In this command, I am assigning the public folder mailbox that contains the new hierarchy to user Rory Williams.
Tip: I recommend using a non-administrative user for this next test. I’ve seen strange errors when using administrative accounts for testing purposes.
C:\> Set-Mailbox -Identity rwilliams -DefaultPublicFolderMailbox "Public Folder Mailbox 1"
You can access Public Folders with either Outlook 2010 or greater or Outlook Web App. From either of these programs check the hierarchy, check content, check permissions and check mail settings. If it doesn’t look right Microsoft recommends using their rollback method documented here.
If everything looks great then run the following command on 2016 to deploy to all other users.
C:\> Get-Mailbox -PublicFolder | Set-Mailbox -PublicFolder -IsExcludedFromServingHierarchy $false
Now, switch gears back to 2010 and run this command.
C:\> Set-OrganizationConfig -PublicFolderMigrationComplete:$true
And finally one last command back on the 2016 server.
C:\> Set-OrganizationConfig -PublicFoldersEnabled Local
All good?
You are done!