Preparing to Rebuild an Entire Exchange 2010 Organization

With the release of Exchange 2010 there has been some great advancement with high availability and site resiliency.  The traditional methods of disaster recovery are fading away.  Modern day high availability capabilities are introducing backup-less strategies.  Does that mean we don’t need to know how to get our messaging systems up and running in the event of a large scale major disaster….I think not?!

This thought process all got started when I was working to a recent effort to bring up a lab environment.  We didn’t have a lab in any way, but some systems were hosted on VMware’s hypervisor.  This included a couple Domain Controllers, but not any Exchange servers (mix of E2K7 & E2K10).  Creating a lab that mirrored production from scratch would be quite the undertaking, I mean, we were talking about some 14+ Exchange servers….not fun.  Well, to me, that scenario felt a lot like a disaster recovery situation and it got my wheels turning.  The use of Exchange’s recovery feature (setup.exe /m:RecoverServer) would allow me to leverage the directory (AD) that could be quickly cloned (thank you virtualization) to the lab.  After all, most Exchange configuration information is stored in Active Directory.  After building a few virtual machines for Exchange and I should be up and running.  I should mention that in this case, I don’t really care about the data, so the only material I really need is a Domain Controller and the Exchange installation media.

Well when I started digging into it all the work prepare for the unattended recovery I started thinking about what needed to be accomplished along the way.  That’s still a bit of tedious work cleaning up all the database copies in Active Directory before I even get to start the Exchange installation…blah blah blah.  Forget that, if I can throw together a quick PowerShell script I can not only save myself a lot of time, but also add another tool to the toolbox.

So, let’s take a quick review of the steps needed to recover and entire Exchange organization.  First, the single server approach is covered in Recover an Exchange Server: Exchange 2010 SP1 Help.  Also, there are some special considerations to be made when dealing with a DAG member; it’s covered in Recover a Database Availability Group Member Server: Exchange 2010 SP1 Help.  So in this case I will be recovering all Exchange server, but I’ll need one server installed in the lab that had the Exchange PowerShell modules.  So the first thing I did was recover one of the CAS servers.

Now for the fun part…the script.  The major prep work is around resetting computer accounts and cleaning up mailbox database copies.  The requirements of the script were as follows:

  • Gather all Exchange Server from AD and reset their computer account.
  • Gather all DAGs from AD and reset the CNO (Cluster Network Object).
  • Get a list of all mailbox database copies, but exclude the copy that was last active, and remove the copies.
  • Remove all Mailbox servers from any DAGs.

I also wanted something that was easy to run and gave the user some feedback about the progress of the script.  After all, were would be changing Exchange attributes in AD when no actual servers were online, this won’t process very quickly because of all the timeouts with attempts to contact offline servers.

The resulting script had one pitfall that wasn’t mentioned in any of the reference material.  If a database had circular logging enabled the database copy would not delete properly.  As a result, before executing the script make sure to enable circular logging on all database copies.  Easy enough:

Get-MailboxDatabase | where {$_.CircularLoggingEnabled -eq $True} | Set-MailboxDatabase -CircularLoggingEnabled $false

The final result is the following script.  Please keep in mind that this is a very invasive script and should not be run anywhere near a healthy production environment.  For one, once executed in about 10 seconds all your Exchange server will be kicked out of the domain…..not good for production. You’ll notice that the beginning of the script includes a warning, which is only cosmetic. I felt it prudent to include that to remind users of the impact the script is capable of causing.

}

##############################################
## Clean Up Database Copies and DAG Members ##
##############################################

Write-Host "`nGathering Database Availability Group(s):" -ForegroundColor Green
Get-DatabaseAvailabilityGroup | Tee-Object -Variable DAGs
Write-Host "Resetting Exchange Server Computer Accounts and DAG CNO" -ForegroundColor DarkBlue -BackgroundColor Yellow
IF (!$DAGs) {
	Write-Host "No DAGs detected." -ForegroundColor DarkBlue -BackgroundColor Yellow
} Else {
	#Reset DAG(s) CNO & Exchange Server computer accounts
	Foreach ($DAG in $DAGs) {dsquery computer -name $DAG.Name | dsmod computer -reset}

	#Get all Database Copies (This excludes databases on servers that currently "own" the DB)
	$DBCopies = Foreach ($DB in Get-MailboxDatabase) {
		$Server = $DB.Server.ToString()
		$DB.DatabaseCopies | Where {$_.HostServerName -notlike $Server} |% {$_.Identity.ToString()}
		}

	#Remove database copies
	$P = 0; $T = $DBCopies.Count #For progress bar
	IF ($T) { #Make sure there are copies.
		Foreach ($DB in $DBCopies) {
			Write-Progress -ID 1 -Activity "Removing Database Copies" -CurrentOperation $DB -PercentComplete ($P/$T*100) -Status "Please Wait..."
			Write-Host "Removing Database Copy" $DB "`tWarnings can be ignored if server is offline" -ForegroundColor DarkBlue -BackgroundColor Yellow
			Remove-MailboxDatabaseCopy -Identity $DB -Confirm:$false -DomainController $StaticDC
			$P++
			}
		Write-Progress -ID 1 -Activity "Removing Database Copies" -CurrentOperation $DB -PercentComplete ($P/$T*100) -Status "Database copy removal complete." -Completed
	} Else { Write-Host "No Database Copies Found." -ForegroundColor DarkBlue -BackgroundColor Yellow }

	#Remove Servers from DAG
	$P = 0; $T = ($DAGs |% {$_.Servers}).count #For progress bar
	IF ($T) { #Make sure there are servers to remove.
		Foreach ($DAG in $DAGs) {
			Write-Host "Removing Servers from DAG: $DAG" -ForegroundColor DarkBlue -BackgroundColor Yellow
			Foreach ($Server in $DAG.Servers) {
				Write-Progress -Id 2 -Activity "Removing server from Dag: $DAG" -CurrentOperation $Server -PercentComplete ($P/$T*100) -Status "Please Wait..."
				Write-Host "Removing Server: $Server" -ForegroundColor Yellow
				Remove-DatabaseAvailabilityGroupServer -Identity $DAG -MailboxServer $Server -ConfigurationOnly -Confirm:$false
				$P++
			}
		}
		Write-Progress -Id 2 -Activity "Removing server from Dag: $DAG" -CurrentOperation $Server -PercentComplete ($P/$T*100) -Status "Complete." -Completed
	} Else { Write-Host "No DAG Member servers found." -ForegroundColor DarkBlue -BackgroundColor Yellow }
}

You can download the .PS1 HERE.

Cheers!

Posted in Disaster Recovery, Exchange 2010, PowerShell

Leave a Reply