Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Created August 5, 2016 05:31
Show Gist options
  • Save JustinGrote/e7cebe41a2159bcef6591c3198c84646 to your computer and use it in GitHub Desktop.
Save JustinGrote/e7cebe41a2159bcef6591c3198c84646 to your computer and use it in GitHub Desktop.
Exchange Mailbox Batch Migration with Intelligent Mailbox Balancing
#requires -version 3.0
#requires -pssnapin Microsoft.Exchange.Management.PowerShell.E2010
<#
.SYNOPSIS
Generates a CSV that can be used with the BatchMigration process
.DESCRIPTION
This script generates a CSV from a list of mailboxes for local migrations. Its primary use is to allow for custom mailbox distribution methods, such as by least-full database or round-robin
This is primarily meant for greenfield migrations where all databases are of similar configuration, and not heterogeneous database environments.
.NOTES
Must be run on a computer with Exchange Management Shell installed due to serialization issues and byte conversion.
I could make it work remotely but it would require some ugly regex work on the serialized objects since default Exchange config doesn't allow scripts to be run remotely
.EXAMPLE
New-MailboxBatchMigrationCSV.ps1 -Identity (get-mailboxdatabase server1 | get-mailbox) -targetdatabase newdatabase* | export-csv "$home\desktop\mailboxdb.migrationbatch.csv"
Generate a batch migration CSV from an old mailbox database to databases newdatabase01, newdatabase02, newdatabase03, etc.
.EXAMPLE
$csvpath="C:\scripts\migrations\Group1.csv"
New-MailboxBatchMigrationCSV.ps1 -Identity (import-csv $csvpath).emailaddress -TargetDatabase Tinamail* -AutoMDBMethod leaststorageused -ShowDatabaseSizeDelta | export-csv "$csvpath.migrationbatch.csv"
Take a csv of email Addresses and generate a migrationbatch CSV based on leastStorageUsed algorithm
#>
#Uncomment this and trailing } to make into a command rather than a script
#function New-MailboxBatchMigrationCSV {
[CmdletBinding()]
param(
#Identity of the mailbox to migrate. May pass one or more email addresses,aliases,identity strings,or mailbox objects.
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]$Identity,
#Candidate Target Mailbox Databases. Leave blank to use all relevant databases.
[String[]]$TargetDatabase,
#Database Selection Method to use
#Default is LeastStorageUsed
#LeastStorageUsed: Select databases based on least storage used, resulting in even distribution by GB
[String]$AutoMDBMethod='LeastStorageUsed',
#Outputs the estimated final database sizes, in KB. This uses Write-Host so as not to interfere with the pipeline
[Switch]$ShowDatabaseSizeDelta
)
begin {
#If no databases were specified, get all databases
if (!($targetDatabase)) {
$targetDatabase = (Get-MailboxDatabase).Name
}
#TODO: Add ExcludeFromProvisioning Logic
#If we are doing 'leaststorageused', get the candidate mailbox sizes and set up the database size hashtable
if ($AutoMDBMethod -match 'leastStorageUsed') {
$mailDBSizeTable = @{}
foreach ($TargetDatabaseItem in $TargetDatabase) {
foreach ($mailDB in (Get-MailboxDatabase $TargetDatabaseItem -status | sort name)) {
#Generate a simple hashtable entry for each database for the total curent "used" size of the database
$mailDBSizeTable.Add($mailDB.Name,($mailDB.DatabaseSize.toKB() - $mailDB.AvailableNewMailboxSpace.toKB()))
}
}
}
#If ShowBeforeAfterSizes, take a snapshot of the DBSizeTable
if ($ShowDatabaseSizeDelta) {
$mailDBSizeTableBefore = $mailDBSizeTable.clone()
}
}
process {
$i = 1
foreach ($IdentityItem in $Identity) {
write-progress "Evaluating $IdentityItem mailbox placement" -PercentComplete (($i/$identity.count)*100)
$mbox = get-mailbox $IdentityItem
if ($mbox) {
$mboxStats = get-mailboxstatistics $IdentityItem
#First Determine the candidate mailbox database
$selectedDatabase = ($mailDBSizeTable.GetEnumerator() | sort Value | select -first 1).Name
[PSCustomObject]@{
EmailAddress = $mbox.PrimarySmtpAddress
TargetDatabase = $selectedDatabase
}
#Add the projected mail to be added to the database total, for use in the next evaluation
$mailDBSizeTable[$selectedDatabase] = $mailDBSizeTable[$selectedDatabase] + $mboxStats.TotalItemSize.Value.ToKB()
}
$i++
}
#Show the final database totals if requested
if ($ShowDatabaseSizeDelta) {
$strDBSizes = $mailDBSizeTable.GetEnumerator() | foreach {
[PSCustomObject]@{
Name = $_.Name
Before = $mailDBSizeTableBefore[$_.Name]
After = $_.Value
Growth = ($_.Value - $mailDBSizeTableBefore[$_.Name])
PercentGrowth = [Math]::Round((($_.Value / $mailDBSizeTableBefore[$_.Name])-1)*100)
}
} | sort name | format-table | out-string
write-host ""
write-host -ForegroundColor Green "===Estimated Database Sizes after Migration==="
write-host -ForegroundColor Green $strDBSizes
}
}
#} #Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment