- server1.root.com
- server2.root.com
- server3.root.com
- server1.child1.root.com
- server2.child1.root.com
- server3.child1.root.com
- server1.sub1.child1.root.com
- server2.sub1.child1.root.com
- server3.sub1.child1.root.com
- server1.sub2.child1.root.com
- server2.sub2.child1.root.com
- server3.sub2.child1.root.com
- server1.sub3.child1.root.com
- server2.sub3.child1.root.com
- server3.sub3.child1.root.com
To avoid an impact on the production, there is at least one Global catalog available in a domain/site. These are the configuration files and the schedule plan for the rehost :
- Day 1 : rehost the first root.com domain controller
- conf1-1.txt :
- Execute the following command :
- Day 1 : when the rehost, of the first domain controller of root.com is successful, launch the rehost script for the remaining root.com domain controllers
- conf1-2.txt :
- Execute the following command :
- Day 2 : rehost the first child1.root.com domain controller
- conf2-1.txt :
- Execute the following command :
- Day 2 : when the rehost, of the first domain controller of child1.root.com is successful, launch the rehost script for the remaining child1.root.com domain controllers
- conf2-2.txt :
- Execute the following command :
- Day 3 : rehost the first domain controller of the domains sub1, sub2 and sub3
- conf3-1.txt :
- Execute the following command :
- Day 3 : when the rehost, of the first domain controllers are successful, launch the rehost script for the remaining domain controllers
- conf3-2.txt :
- Execute the following command :
- test if the source and destination server are reachable on the network
- test if the remote registry is available on the destination server
- a registry key and value will be created to unregister the global catalog of the destination server on the DNS (gc._msdcs zone). This step will avoid errors, if a user try to reach a Global Catalog during the rehost task
- the script will pause for 30 minutes to let the DNS synchronize on all other domain controllers
- unhost the partition on the destination server
- check if the unhost task is successful by checking the event id 1660 on the destination server
- rehost the partition on the destination server using the valid one located on the source server
- wait for the user reply : you will have to check the generated log files and validate the rehost is successful. If you need to restart the rehost, press “r” and then Enter to restart the task. Else, just press Enter
- the registry key and value are removed to register back the server in the DNS
The rehost task is successful if you find the following message in the log file : [mardi 20 août 2013 07:46:18] : Rehosting the partition dc=child2,dc=root,dc=com on the server server2.sub1.child1.root.com using the valid source server1.sub1.child1.root.com… New DSA Options: IS_GC DISABLE_NTDSCONN_XLATE Removal of partition dc=child2,dc=root,dc=com is in progress… Replication link from source:(null) to dest:server2.sub1.child1.root.com deleted. Full sync of partition dc=child2,dc=root,dc=com is in progress. Please be patient. This step may take many hours on a large partition. You can monitor the progress of the full sync using repadmin /showreps /v in another window. One-way replication from source:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx._msdcs. to dest:server2.sub1.child1.root.com established. New DSA Options: IS_GC ==== INBOUND NEIGHBORS ====================================== dc=child2,dc=root,dc=com SUB1-SITE\SERVER1 via RPC DSA object GUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Address: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx._msdcs. DSA invocationID: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy SYNC_ON_STARTUP DO_SCHEDULED_SYNCS USNs: 123456789/OU, 123456789/PU Last attempt @ 2013-08-20 07:49:56 was successful.
Script :
# VARIABLES $seq_file=$args[0] $global:scriptpath=$pwd.path.ToString() + "\" $global:file_content = gc $seq_file ############# # FUNCTIONS # ############# # ENABLE THE GLOBAL CATALOG function enable_gc([string]$servername) { $gcrehostlog=$scriptpath + $servername + ".log" Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Global catalog rehosting task on the server $servername [MANUAL CHECK OK]" -Encoding Unicode start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "`n//////////////////////////`n/ Enable Global Catalog /`n//////////////////////////`n" -Encoding Unicode Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Enabling the Global Catalog on $servername..." -Encoding Unicode # CONNECT TO THE SERVER REMOTE REGISTRY try{ $reg=[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $servername) Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Connect to the $servername remote registry [SUCCESS]" -Encoding Unicode Start-Sleep -Seconds 1 } catch{ Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Connect to the $servername remote registry [ERROR]`n---- EXIT -----`n" -Encoding Unicode continue } # DELETE THE REGISTRY KEY $regparentkey=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft",$true) $regparentkey.deletesubkeytree("Netlogon") # TEST IF THE NEW PARAM KEY HAS BEEN DELETED SUCCESSFULLY $ref_param=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft\\Netlogon\\Parameters",$true) if (!$ref_param) { Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Remove the registry key HKLM\SOFTWARE\Policies\Microsoft\Netlogon and the subkeys on $servername [SUCCESS]" -Encoding Unicode Start-Sleep -Seconds 1 } else { Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Remove the registry key HKLM\SOFTWARE\Policies\Microsoft\Netlogon and the subkeys on $servername [ERROR]`n---- EXIT -----`n" -Encoding Unicode continue } Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : ----- END OF THE SCRIPT -----`n" -Encoding Unicode } # RESTART REHOST FUNCTION function restart_rehost_task($file_content) { $servername = "" $job_list = get-job -State Completed if ($job_list){ foreach ($job in $job_list){ $servername = $job.name $gcrehostlog = $scriptpath + $servername + ".log" Get-Job -Name $servername | Receive-Job Get-Job -Name $servername | Remove-Job Write-Host "`n --> Do you want to restart the Global catalog rehosting on $servername ? `n`n`tPress r to restart `n`n`tor `n`n`tany other key to cancel" $continue = Read-Host If ($continue -eq "r"){ $fc_tmp = $file_content | select-string $servername $servername_valid_source = $fc_tmp.tostring().split(";")[1] $partition = $fc_tmp.tostring().split(";")[2] # RESTART THE REHOST Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Restarting the GC rehost operation of the partition $partition on the server $servername using the valid source $servername_valid_source..." -Encoding Unicode Start-Sleep -Seconds 1 $RESTART_SCRIPT_BLOCK = { $servername=$args[0] $servername_valid_source=$args[1] $partition=$args[2] $gcrehostlog=$args[3] $repadmin_rehost_output = @(repadmin /rehost $servername "$partition" $servername_valid_source) $repadmin_rehost_output | Out-File -FilePath $gcrehostlog -Append -Encoding Unicode } Start-Job -name $servername -ScriptBlock $RESTART_SCRIPT_BLOCK -ArgumentList $servername,$servername_valid_source,$partition,$gcrehostlog } Else { enable_gc($servername) } } Write-Host "`n" } } ##################### #PREREQUESITE CHECKS# ##################### foreach ($line in $file_content){ $servername = ($line).split(";")[0] $servername_valid_source = ($line).split(";")[1] $partition = ($line).split(";")[2] $temp="" $script_path = $scriptpath $SCRIPT_BLOCK = { $servername=$args[0] $servername_valid_source=$args[1] $partition=$args[2] $temp=$args[3] $script_path=$args[4] $gcrehostlog=$script_path + $servername + ".log" Add-Content $gcrehostlog -Value "*********************" -Encoding Unicode Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Starting the Active Directory Global Catalog Rehosting script" -Encoding Unicode Add-Content $gcrehostlog -Value "//////////////////////`n/ Prerequesite tests /`n//////////////////////`n" -Encoding Unicode Start-Sleep -Seconds 1 # PING FUNCTION function pingtest([string]$MachineName){ $PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$MachineName'" | Select-Object StatusCode If ($PingStatus.StatusCode -eq 0){ Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test network connectivity (ping) > $MachineName [SUCCESS]" -Encoding Unicode } Else { Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test network connectivity (ping) > $MachineName [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } } # TEST PING pingtest($servername_valid_source) pingtest($servername) # TEST REMOTE REGISTRY try{ $reg=[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $servername) Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test remote registry > $servername [SUCCESS]" -Encoding Unicode } catch{ Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test remote registry > $servername [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } # TEST REMOTE EVENT LOG try{ $temp = get-eventlog -ComputerName $servername -LogName 'Directory Service' -newest 1 -ErrorAction Stop Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test remote eventlog (get the last event) > $servername [SUCCESS]" -Encoding Unicode } catch{ Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test remote eventlog (get the last event) > $servername [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Test result [SUCCESS]" -Encoding Unicode ############################ #DISABLE THE GLOBAL CATALOG# ############################ Add-Content $gcrehostlog -Value "`n//////////////////////////`n/ Disable Global Catalog /`n//////////////////////////`n" -Encoding Unicode Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Disabling the Global Catalog on $servername" -Encoding Unicode Start-Sleep -Seconds 1 try{ $reg=[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $servername) Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Connect to the $servername remote registry [SUCCESS]" -Encoding Unicode } catch{ Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Connect to the $servername remote registry [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } $ref=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft\\Netlogon\\Parameters",$true) if (!$ref) { Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : [WARNING] The registry key HKLM\SOFTWARE\Policies\Microsoft\Netlogon\Parameters does not exist on $servername" -Encoding Unicode Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : [WARNING] Creating the registry key HKLM\SOFTWARE\Policies\Microsoft\Netlogon\Parameters on $servername..." -Encoding Unicode $regparentkey=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft\\Netlogon",$true) $temp=$regparentkey.createSubKey("Parameters") # TEST IF THE NEW PARAM KEY HAS BEEN CREATED SUCCESSFULLY $ref_param=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft\\Netlogon\\Parameters",$true) if (!$ref_param) { Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Create the registry key HKLM\SOFTWARE\Policies\Microsoft\Netlogon\Parameters on $servername [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } else { Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Create the registry key HKLM\SOFTWARE\Policies\Microsoft\Netlogon\Parameters on $servername [SUCCESS]" -Encoding Unicode } } Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Creating the registry value DnsAvoidRegisterRecords on $servername..." -Encoding Unicode $regchildkey=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft\\Netlogon\\Parameters",$true) $regchildKey.SetValue("DnsAvoidRegisterRecords","Gc GcAtSite GcIpAddress GenericGc GenericGcAStSite",[Microsoft.Win32.RegistryValueKind]::String) # TEST IF THE NEW REGISTRY VALUE HAS BEEN CREATED SUCCESSFULLY $ref_value=$reg.Opensubkey("SOFTWARE\\Policies\\Microsoft\\Netlogon\\Parameters",$true) $reg_ref_value = $ref_value.GetValue("DnsAvoidRegisterRecords") if (!$reg_ref_value) { Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Create the registry value HKLM\SOFTWARE\Policies\Microsoft\Netlogon\Parameters\DnsAvoidRegisterRecords on $servername [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } else { Start-Sleep -Seconds 1 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Create the registry value HKLM\SOFTWARE\Policies\Microsoft\Netlogon\Parameters\DnsAvoidRegisterRecords on $servername [SUCCESS]" -Encoding Unicode } ################## #WAIT REPLICATION# ################## Add-Content $gcrehostlog -Value "`n[$((Get-Date).DateTime)] : Waiting for replication..." -Encoding Unicode Start-Sleep -Seconds 1800 Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : End of replication timeout" -Encoding Unicode Start-Sleep -Seconds 1 ########################### #UNHOST/QUERY EVENT/REHOST# ########################### Add-Content $gcrehostlog -Value "//////////////////////////////`n/ Unhost/Rehost AD partition /`n//////////////////////////////`n" -Encoding Unicode Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Unhosting the partition $partition on the server $servername..." -Encoding Unicode Start-Sleep -Seconds 1 # UNHOST GC $repadmin_unhost_output = @(repadmin /unhost $servername "$partition") $repadmin_unhost_output | Out-File -FilePath $gcrehostlog -Append -Encoding Unicode $eventfound = "false" $inc=1 while($eventfound -eq "false"){ try{ # UNHOST EVENT CHECK (EVENT 1660 / INSTANCEID 1073743484) $temp = get-eventlog -ComputerName $servername -LogName 'Directory Service' -InstanceId 1073743484 -newest 1 -ErrorAction Stop -after (get-date).addminutes(-120) $eventfound = "true" Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : GC unhosting check on $servername (event 1660) [SUCCESS]" -Encoding Unicode Start-Sleep -Seconds 1 # REHOST GC Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Rehosting the partition $partition on the server $servername using the valid source $servername_valid_source..." -Encoding Unicode Start-Sleep -Seconds 1 $repadmin_rehost_output = @(repadmin /rehost $servername "$partition" $servername_valid_source) $repadmin_rehost_output | Out-File -FilePath $gcrehostlog -Append -Encoding Unicode } catch{ # WAIT WHILE EVENT 1660 NOT REGISTERED $string = $error[0].Exception.message.Tostring() if (($string -eq "No matches found") -and ($inc -le 6)){ Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : GC unhosting check on $servername (event 1660). Next retry in 10 seconds... [WARNING]" -Encoding Unicode Start-Sleep -Seconds 10 $inc++ } else { Add-Content $gcrehostlog -Value "[$((Get-Date).DateTime)] : Cannot find event 1660. GC unhosting process fails on $servername [ERROR]`n---- EXIT -----`n" -Encoding Unicode exit } } } Write-Host "`n-----------------------------------`n" } Start-Job -name $servername -ScriptBlock $SCRIPT_BLOCK -ArgumentList $servername,$servername_valid_source,$partition,$temp,$script_path } # WAIT FOR IT ALL TO COMPLETE While (Get-Job -State "Running") { Write-Host "." -NoNewline Start-Sleep -Seconds 5 if (Get-Job -State Completed) { restart_rehost_task($file_content) } } restart_rehost_task($file_content) Write-Host "`n" # GETTING THE INFORMATION BACK FROM THE JOBS Get-Job | Receive-Job Get-Job | Remove-Job