Очередная бизнес задача: есть два леса с настроенным доверием, в каждом из них настроен Exchange. Необходимо произвести миграцию объектов из одного леса в другой.
Есть достаточно много статей, но в основном они описывают подготовку к миграции только почтовых ящиков, возможно я не прав и ищу не по тем параметрам, но всё же. Я постараюсь описать и некоторые другие моменты, с которыми я столкнулся при планировании , тестировании и проведении самой миграции.
Сама статья и алгоритм достаточно сырые, так как всё делалось в относительной спешке и из-за разделения обязанностей по миграции на большое число тестовых кейсов при миграции не приходилось рассчитывать.
План миграции будет таков:
- Добавление в целевом лесу internal relay почтовых доменов, настройка send коннекторов, смотрящих на исходный лес, настройка политик адресов.
- Произведение аналогичных настроек в исходном лесу.
- Удаление контактов в исходном и целевом лесах.
- Миграция пользователей\групп\компьютеров из исходного леса при помощи ADMT. В качестве бонуса после миграции компьютера Outlook перенастраивается сам и использует старый ost, yay!
- Подготовка почтовых ящиков к перемещению, "миграция" групп, контактов и mailusers.
- Перемещение ящиков.
- Изменение типов домена в целевом лесу на authorative, удаление send коннекторов.
- Разрыв доверительных отношений и траблшутинг.
На всякий случай предупреждаю, что после миграции надо предупредить пользователей почистить список автоподстановки и автоматических адресов в Outlook, чтобы не было проблем с отправкой на несуществующие адреса. Возможно я зря сначала делаю mailuser, а потом prepare-moverequest т.к. prepare-moverequest по идее должен переносить legacyexchangedn и все proxyaddresses сам.
Миграция групп и контактов производится достаточно просто: включаем группы в целевом лесу после миграции и копируем аттрибуты из исходного леса. Для справки: у меня в customattribute1 хранится параметр\домен для политики адресов
$remotedc="dc.forest.remote"
$localdc="dc.forest.local"
$groups=Get-DistributionGroup -DomainController $remotedc | select Name,displayname,alias,customattribute1,RequireSenderAuthenticationEnabled,HiddenFromAddressListsEnabled,emailaddresses
foreach ($gr in $groups) {
if (!$gr.customattribute1){
$gr.customattribute1="remote.ru"
}
$attr=@{}
$attr['extensionAttribute1']=$gr.customattribute1
set-adgroup $gr.name -add $attr
Enable-DistributionGroup $gr.name -displayname $gr.displayname -alias $gr.alias
#мигрируем альтернативные адреса
$current=(get-distributiongroup $gr.displayname).EmailAddresses
foreach ($addr in $gr.emailaddresses) {
if (!$current.contains($addr.ProxyAddressString)) {
$current+=$addr.ProxyAddressString
}
}
set-distributiongroup $gr.name -displayname $gr.displayname -alias $gr.alias -customattribute1 $gr.customattribute1 -RequireSenderAuthenticationEnabled $gr.RequireSenderAuthenticationEnabled -HiddenFromAddressListsEnabled $gr.HiddenFromAddressListsEnabled -EmailAddresses $current -EmailAddressPolicyEnabled $false
}
Побочным эффектом этого безобразия является добавление адреса, присваиваемого политикой адресов по умолчанию. Так как мне это не мешало, я банально забил. Аналогично необходимо поступить с mailuser'ами и контактами. Для них я код не писал, так как их не надо было мигрировать.
А теперь самая интересная часть: миграция почтовых ящиков. Данный момент стоит разделить на несколько этапов, особенно если в лесу несколько контроллеров. Я честно забил на миграцию grantsendonbehalfto и не проверял миграцию этого аттрибута, sendas мигрируется как security разрешение через ADMT, а вот forward надо мигрировать вручную, так как после переезда ящика она показывает непонятно куда.
Этапы миграции:
- Миграция учетной записи через ADMT
- enable-mailuser в целевом лесу
- Prepare-MoveRequest для переноса аттрибутов
- Сохранение форвардов
- New-MoveRequest для переноса содержимого ящика. Кстати автоответ\правила являются скрытыми объектами в почтовом ящике и переносятся без проблем.
- Remve-MoveRequest для завершения перемещения ящика. Превращает пользователя в целевом лесу в почтовый ящик, а в исходном в mailuser
Код:
$remotedc="dc.forest.remote"
$localdc="dc.forest.local"
function PrepareMigrateMailbox($sam, $mail,$cred1,$cred2) {
#$user is SAM in both forests
#cred1 is local credential (target)
#cred2 is remote credential (source)
#нет адреса - пропускаем
if(!$mail) {continue}
#move mailbox
$alias=$mail.split("@")[0]
$attr=$mail.split("@")[1]
enable-mailuser $sam -ExternalEmailAddress $mail -DomainController $localdc -Alias $alias
start-sleep 10
Set-MailUser $sam -CustomAttribute1 $attr -alias $alias
#алиасы мигрируются?
& 'C:\Program Files\Microsoft\Exchange Server\V14\Scripts\Prepare-MoveRequest.ps1' -Identity $mail -LocalForestDomainController $localdc -RemoteForestDomainController $remotedc -LocalForestCredential $cred1 -RemoteForestCredential $cred2 -UseLocalObject -OverWriteLocalObject
}
#при миграции переадресация сбивается, сохраним
function SaveForward () {
$users=get-mailbox -DomainController $remotedc | select PrimarySmtpAddress, ForwardingAddress, DeliverToMailboxAndForward
foreach ($u in $users) {
if ($u.ForwardingAddress) {
$u.ForwardingAddress=$u.ForwardingAddress.name
}
}
$users | export-csv -path 'c:\scripts\csv\forward.csv'
}
#это надо запустить после миграции (вручную)
function LoadForward () {
$users=import-csv -path 'c:\scripts\csv\forward.csv'
foreach ($u in $users) {
if($u.ForwardingAddress) {
$mbx=get-mailbox $u.PrimarySmtpAddress
write-host ($u.PrimarySmtpAddress) -ForwardingAddress ($u.ForwardingAddress) -DeliverToMailboxAndForward ($u.DeliverToMailboxAndForward)
if ($mbx) {
if ($u.DeliverToMailboxAndForward -eq "False") { $fwd=$false } else {$fwd=$true}
Set-Mailbox $u.PrimarySmtpAddress -ForwardingAddress $u.ForwardingAddress -DeliverToMailboxAndForward $fwd
}
}
}
}
#local\target forest
$cred1=Get-Credential
#remote\source forest
$cred2=Get-Credential
#получаем пользователей для миграции из исходного леса
$users =get-aduser -filter * -searchbase "ou=accounts,dc=forest,dc=remote" -Server $remotedc -properties mail
SaveForward
foreach ($u in $users) {
MigrateMailbox -sam $u.SamAccountName -mail $u.mail -cred1 $cred1 -cred2 $cred2
}
#желательно разделить подготовку и запуск перемещения ящика по времени для окончания репликации между контроллерами
start-sleep 30
foreach ($u in $users) {
New-MoveRequest -Identity $u.mail -RemoteLegacy -TargetDatabase mdb01 -RemoteGlobalCatalog $remotedc -RemoteCredential $cred2 -TargetDeliveryDomain remote.ru
}
Пожалуй всё. По ходу миграции необходимо делать Remove-MoveRequest (у меня делается автоматов каждые 4 часа) и после окончания запустить вручную LoadForward. Не стоит надеяться, что всё будет сверхбыстро и без ошибок и проблем, после миграции надо будет еще недлю производить траблшутинг того, что было пропущено и не учтено. У меня в частности почему-то не переехали алиасы.
Еще одним пунктом при миграции является миграция Lync. О ней я напишу чуть позже
Комментариев нет:
Отправить комментарий