Advertisement
jeroenburen

Migrate-Hosts

Mar 6th, 2020
505
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .SYNOPSIS
  3.     Perform steps to migrate all ESXi hosts in a cluster to another vCenter Server.
  4. .DESCRIPTION
  5.     Use this script to migrate all ESXi hosts in a cluster to another vCenter Server.
  6.     After the host is migrated the running VMs are moved to the folder they were in on the source vCenter Server.
  7.     The folders must be available before this script is used.
  8.  
  9.     This script assumes availability of the following modules:
  10.     - VMware-PowerCli
  11. .PARAMETER
  12.     - Cluster: name of the cluster to migrate.
  13. .EXAMPLE
  14.     .\Migrate-Hosts.ps1 -Cluster <clustername>
  15. .NOTES
  16.     Script name: Migrate-Hosts.ps1
  17.     Author:      Jeroen Buren
  18.     DateCreated: 03-03-2020
  19. #>
  20.  
  21. [CmdletBinding(SupportsShouldProcess=$true)]
  22.  
  23. param(
  24.     [parameter(Mandatory=$true,HelpMessage="Which cluster do you want to migrate?")][string]$Cluster,
  25.     [parameter(Mandatory=$true,HelpMessage="What is the root folder for VMs?")][string]$RootFolder
  26. )
  27.  
  28. ####################################################################################
  29. #                                                                                  #
  30. # Functions                                                                        #
  31. #                                                                                  #
  32. ####################################################################################
  33.  
  34. function Get-ScriptDirectory {
  35.   $Invocation = (Get-Variable MyInvocation -Scope 1).Value
  36.   Split-Path $Invocation.MyCommand.Path
  37. }
  38.  
  39. function Log {
  40.   param(
  41.     [Parameter(Mandatory=$true)][String]$Message,
  42.     [Parameter(Mandatory=$true)][ValidateSet("Info","Debug","Warn","Error")][String]$Type,
  43.     [Parameter(Mandatory=$true)][ValidateSet("Console","LogFile","Both")][String]$OutputMode
  44.   )
  45.  
  46.   $dateTimeString = Get-Date -Format "yyyy-MM-dd HH:mm:sszz"
  47.   $output = ($dateTimeString + " " + $type.ToUpper() + " " + $message)
  48.   if ($outputMode -eq "Console" -OR $outputMode -eq "Both") {
  49.     Write-Host $output
  50.   }
  51.   if ($outputMode -eq "LogFile" -OR $outputMode -eq "Both") {
  52.     try {
  53.       Add-Content $logFile -Value $output -ErrorAction Stop
  54.     }
  55.     catch {
  56.       Log ("Failed to write to log file: """ + $logFile + """.") -OutputMode Console -Type Error
  57.       Log ("[" + $_.Exception.GetType().FullName + "] " + $_.Exception.Message) -OutputMode Console -Type Error
  58.     }
  59.   }
  60. }
  61.  
  62. filter Get-FolderPath {
  63.     $_ | Get-View | % {
  64.         $row = "" | select Name, Path
  65.         $row.Name = $_.Name
  66.  
  67.         $current = Get-View -Server $SourcevCenter $_.Parent
  68.         $path = $_.Name
  69.         do {
  70.             $parent = $current
  71.             if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
  72.             $current = Get-View -Server $SourcevCenter $current.Parent
  73.         } while ($current.Parent -ne $null)
  74.         $row.Path = $path
  75.         $row
  76.     }
  77. }
  78.  
  79. ####################################################################################
  80. #                                                                                  #
  81. # Variables                                                                        #
  82. #                                                                                  #
  83. ####################################################################################
  84.  
  85. # Logfile
  86. Set-Variable logFile ((Get-ScriptDirectory) + "\Migrate-Hosts.log") -Option Constant -ErrorAction SilentlyContinue
  87. $SourcevCenter = "<source vcenter>"
  88. $DestinationvCenter = "<destination vcenter>"
  89.  
  90. ####################################################################################
  91. #                                                                                  #
  92. # Main Code                                                                        #
  93. #                                                                                  #
  94. ####################################################################################
  95.  
  96. Log -Message "Script started" -Type Info -OutputMode LogFile
  97.  
  98. $cred = Get-Credential -Message "Enter valid ESXi host credentials"
  99.  
  100. # Connect source vCenter Server
  101. Connect-VIserver -Server $SourcevCenter | Out-Null
  102. Log -Message "Connected to source vCenter Server" -Type Info -OutputMode Both
  103.  
  104. # Connect destination vCenter Server
  105. Connect-VIServer -Server $DestinationvCenter | Out-Null
  106. Log -Message "Connected to destination vCenter Server" -Type Info -OutputMode Both
  107.  
  108. # Get DRS Host rules from cluster
  109. $DRSVmHostRules = Get-DrsVMHostRule -Cluster $Cluster -Server $SourcevCenter
  110.  
  111. # Get DRS VM rules from cluster
  112. $rules = @()
  113. foreach ($rule in Get-DrsRule -Cluster $Cluster -Server $SourcevCenter) {
  114.   $line = ($rule.Name + "," + $rule.Enabled + "," + $rule.Type)
  115.   foreach ($vmId in $rule.VMIds) {
  116.     $line += ("," + (Get-View -Id $vmId).Name)
  117.   }
  118. $rules += $line
  119. $rules | Out-File D:\Scripts\VMware\Temp\$Cluster-DRSRules.txt
  120. }
  121.  
  122. # Get DRS VM groups from cluster
  123. Get-DrsClusterGroup -Cluster $Cluster -Type VMGroup -Name "VM DRS Group 1" -Server $SourcevCenter | Select -ExpandProperty Member | Select Name | Export-Csv "D:\Scripts\VMware\Temp\$Cluster-1.csv" -NoTypeInformation
  124. Get-DrsClusterGroup -Cluster $Cluster -Type VMGroup -Name "VM DRS Group 2" -Server $SourcevCenter | Select -ExpandProperty Member | Select Name | Export-Csv "D:\Scripts\VMware\Temp\$Cluster-2.csv" -NoTypeInformation
  125.  
  126. # Start migration
  127. foreach ($esxi in Get-Cluster -Name $Cluster -Server $SourcevCenter | Get-VMHost) {
  128.   Log -Message "Migrating host $($esxi.Name)" -Type Info -OutputMode Both
  129.  
  130.   # Get folderpath from VMs on host
  131.   $report = @()
  132.   $report = Get-VMHost $esxi -Server $SourcevCenter | Get-VM | Get-Folderpath
  133.   $report | Export-Csv "D:\Scripts\VMware\Temp\$($esxi)-VMs-With-FolderPath.csv" -NoTypeInformation
  134.   Log -Message "Exported folder paths from VMs" -Type Info -OutputMode Both
  135.  
  136.   # Disconnect host from source vCenter
  137.   Set-VMHost -Server $SourcevCenter -VMHost $esxi -State Disconnected -Confirm:$false
  138.   Log -Message "Disconnected host $($esxi.Name) from source vCenter Server" -Type Info -OutputMode Both
  139.    
  140.   # Remove host from source vCenter
  141.   Remove-VMHost -Server $SourcevCenter -VMHost $esxi -Confirm:$false
  142.   Log -Message "Removed host $($esxi.Name) from source vCenter Server" -Type Info -OutputMode Both
  143.    
  144.   # Add host to destination vCenter
  145.   Try {Add-VMHost -Server $DestinationvCenter -Name $esxi.Name -Credential $cred -Location "Datacenter" -Force}
  146.   Catch {Log -Message "Oops... Something went wrong..." -Type Error -OutputMode Both}
  147.   Log -Message "Added host $($esxi.Name) to destination vCenter Server" -Type Info -OutputMode Both
  148.    
  149.   # Move host to cluster
  150.   Try {Move-VMHost -Server $DestinationvCenter -VMHost $(Get-VMHost -Name $esxi.Name -Server $DestinationvCenter) -Destination $Cluster}
  151.   Catch {Log -Message "Oops... Something went wrong..." -Type Error -OutputMode Both}
  152.   Log -Message "Moved host $($esxi.Name) to cluster $Cluster" -Type Info -OutputMode Both
  153.  
  154.   # Move VMs to folder and start with next host
  155.   $VMfolder = @()
  156.   $VMfolder = Import-Csv "D:\Scripts\VMware\Temp\$($esxi)-VMs-With-FolderPath.csv" | Sort-Object -Property Path
  157.  
  158.   foreach ($guest in $VMfolder) {
  159.       $key = @()
  160.       $key =  Split-Path $guest.Path | split-path -leaf
  161.       if ($key -eq "Datacenter") {
  162.         Log -Message "Moving $($guest.Name) to folder $RootFolder" -Type Info -OutputMode Both
  163.         Move-VM (Get-VM $guest.Name -Server $DestinationvCenter) -InventoryLocation (Get-Folder -Name $RootFolder -Type VM -Server $DestinationvCenter) | Out-Null
  164.       }
  165.       else {
  166.         Log -Message "Moving $($guest.Name) to folder $key" -Type Info -OutputMode Both
  167.       Move-VM (Get-VM $guest.Name -Server $DestinationvCenter) -InventoryLocation (Get-Folder $key -Server $DestinationvCenter -Location $RootFolder) -ErrorAction SilentlyContinue | Out-Null
  168.       }
  169.   }
  170. }
  171.  
  172. # Create DRS Cluster Host Groups
  173. $Hosts1 = Get-Cluster -Name $Cluster -Server $DestinationvCenter | Get-VMHost | where {$_.Name.Substring(4,1) -eq "0"}
  174. $Hosts2 = Get-Cluster -Name $Cluster -Server $DestinationvCenter | Get-VMHost | where {$_.Name.Substring(4,1) -eq "1"}
  175.  
  176. Log -Message "Creating DRS Host Groups" -Type Info -OutputMode Both
  177. New-DrsClusterGroup -Name "Host DRS Group 1" -Cluster $Cluster -VMHost $Hosts1 | Out-Null
  178. New-DrsClusterGroup -Name "Host DRS Group 2" -Cluster $Cluster -VMHost $Hosts2 | Out-Null
  179.  
  180. # Create DRS Cluster VM Groups
  181. $VMsAMS = @()
  182. $VMsWSN = @()
  183.  
  184. foreach ($vm in Import-Csv "D:\Scripts\VMware\Temp\$Cluster-1.csv") {$VMs1 += Get-VM -Name $vm.Name -Server $DestinationvCenter}
  185. foreach ($vm in Import-Csv "D:\Scripts\VMware\Temp\$Cluster-2.csv") {$VMs2 += Get-VM -Name $vm.Name -Server $DestinationvCenter}
  186.  
  187. Log -Message "Creating DRS VM Groups" -Type Info -OutputMode Both
  188. New-DrsClusterGroup -Name "VM DRS Group 1" -Cluster $Cluster -Server $DestinationvCenter -VM $VMs1 | Out-Null
  189. New-DrsClusterGroup -Name "VM DRS Group 2" -Cluster $Cluster -Server $DestinationvCenter -VM $VMs2 | Out-Null
  190.  
  191. # Enable DRS on the cluster
  192. Set-Cluster -Cluster $Cluster -Server $DestinationvCenter -DrsEnabled $true -Confirm:$false | Out-Null
  193.  
  194. # Create DRS Host rules
  195. foreach ($rule in $DRSVmHostRules) {
  196.   $VMGroup = Get-DrsClusterGroup -Name $rule.VMGroup -Cluster $Cluster -Type VMGroup -Server $DestinationvCenter
  197.   $VMHostGroup = Get-DrsClusterGroup -Name $rule.VMHostGroup -Cluster $Cluster -Type VMHostGroup -Server $DestinationvCenter
  198.   New-DrsVMHostRule -Name $rule.Name -Enabled $true -Cluster $Cluster -VMGroup $VMGroup -VMHostGroup $VMHostGroup -Type ShouldRunOn -Server $DestinationvCenter | Out-Null
  199. }
  200.  
  201. # Create DRS VM rules
  202. foreach ($rule in $rules) {
  203.   $rulearr = $rule.Split(",")
  204.   if ($rulearr[1] -eq "True") {$enabled = $true}
  205.   if ($rulearr[2] -eq "VMAntiAffinity") {$together = $false}
  206.   New-DrsRule -Server $DestinationvCenter -Name $rulearr[0] -Cluster $Cluster -Enabled $enabled -KeepTogether $together -VM (Get-VM -Name ($rulearr[3..($rulearr.Count -1)]) -Server $DestinationvCenter)
  207. }
  208.  
  209. # Disconnect from vCenter Servers
  210. Disconnect-VIServer -Server $SourcevCenter -Confirm:$false
  211. Disconnect-VIServer -Server $DestinationvCenter -Confirm:$false
  212.  
  213. Log -Message "Script Ended" -Type Info -OutputMode LogFile
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement