
- 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
