Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- .SYNOPSIS
- Perform steps to migrate all ESXi hosts in a cluster to another vCenter Server.
- .DESCRIPTION
- Use this script to migrate all ESXi hosts in a cluster to another vCenter Server.
- After the host is migrated the running VMs are moved to the folder they were in on the source vCenter Server.
- The folders must be available before this script is used.
- This script assumes availability of the following modules:
- - VMware-PowerCli
- .PARAMETER
- - Cluster: name of the cluster to migrate.
- .EXAMPLE
- .\Migrate-Hosts.ps1 -Cluster <clustername>
- .NOTES
- Script name: Migrate-Hosts.ps1
- Author: Jeroen Buren
- DateCreated: 03-03-2020
- #>
- [CmdletBinding(SupportsShouldProcess=$true)]
- param(
- [parameter(Mandatory=$true,HelpMessage="Which cluster do you want to migrate?")][string]$Cluster,
- [parameter(Mandatory=$true,HelpMessage="What is the root folder for VMs?")][string]$RootFolder
- )
- ####################################################################################
- # #
- # Functions #
- # #
- ####################################################################################
- function Get-ScriptDirectory {
- $Invocation = (Get-Variable MyInvocation -Scope 1).Value
- Split-Path $Invocation.MyCommand.Path
- }
- function Log {
- param(
- [Parameter(Mandatory=$true)][String]$Message,
- [Parameter(Mandatory=$true)][ValidateSet("Info","Debug","Warn","Error")][String]$Type,
- [Parameter(Mandatory=$true)][ValidateSet("Console","LogFile","Both")][String]$OutputMode
- )
- $dateTimeString = Get-Date -Format "yyyy-MM-dd HH:mm:sszz"
- $output = ($dateTimeString + " " + $type.ToUpper() + " " + $message)
- if ($outputMode -eq "Console" -OR $outputMode -eq "Both") {
- Write-Host $output
- }
- if ($outputMode -eq "LogFile" -OR $outputMode -eq "Both") {
- try {
- Add-Content $logFile -Value $output -ErrorAction Stop
- }
- catch {
- Log ("Failed to write to log file: """ + $logFile + """.") -OutputMode Console -Type Error
- Log ("[" + $_.Exception.GetType().FullName + "] " + $_.Exception.Message) -OutputMode Console -Type Error
- }
- }
- }
- filter Get-FolderPath {
- $_ | Get-View | % {
- $row = "" | select Name, Path
- $row.Name = $_.Name
- $current = Get-View -Server $SourcevCenter $_.Parent
- $path = $_.Name
- do {
- $parent = $current
- if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
- $current = Get-View -Server $SourcevCenter $current.Parent
- } while ($current.Parent -ne $null)
- $row.Path = $path
- $row
- }
- }
- ####################################################################################
- # #
- # Variables #
- # #
- ####################################################################################
- # Logfile
- Set-Variable logFile ((Get-ScriptDirectory) + "\Migrate-Hosts.log") -Option Constant -ErrorAction SilentlyContinue
- $SourcevCenter = "<source vcenter>"
- $DestinationvCenter = "<destination vcenter>"
- ####################################################################################
- # #
- # Main Code #
- # #
- ####################################################################################
- Log -Message "Script started" -Type Info -OutputMode LogFile
- $cred = Get-Credential -Message "Enter valid ESXi host credentials"
- # Connect source vCenter Server
- Connect-VIserver -Server $SourcevCenter | Out-Null
- Log -Message "Connected to source vCenter Server" -Type Info -OutputMode Both
- # Connect destination vCenter Server
- Connect-VIServer -Server $DestinationvCenter | Out-Null
- Log -Message "Connected to destination vCenter Server" -Type Info -OutputMode Both
- # Get DRS Host rules from cluster
- $DRSVmHostRules = Get-DrsVMHostRule -Cluster $Cluster -Server $SourcevCenter
- # Get DRS VM rules from cluster
- $rules = @()
- foreach ($rule in Get-DrsRule -Cluster $Cluster -Server $SourcevCenter) {
- $line = ($rule.Name + "," + $rule.Enabled + "," + $rule.Type)
- foreach ($vmId in $rule.VMIds) {
- $line += ("," + (Get-View -Id $vmId).Name)
- }
- $rules += $line
- $rules | Out-File D:\Scripts\VMware\Temp\$Cluster-DRSRules.txt
- }
- # Get DRS VM groups from cluster
- 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
- 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
- # Start migration
- foreach ($esxi in Get-Cluster -Name $Cluster -Server $SourcevCenter | Get-VMHost) {
- Log -Message "Migrating host $($esxi.Name)" -Type Info -OutputMode Both
- # Get folderpath from VMs on host
- $report = @()
- $report = Get-VMHost $esxi -Server $SourcevCenter | Get-VM | Get-Folderpath
- $report | Export-Csv "D:\Scripts\VMware\Temp\$($esxi)-VMs-With-FolderPath.csv" -NoTypeInformation
- Log -Message "Exported folder paths from VMs" -Type Info -OutputMode Both
- # Disconnect host from source vCenter
- Set-VMHost -Server $SourcevCenter -VMHost $esxi -State Disconnected -Confirm:$false
- Log -Message "Disconnected host $($esxi.Name) from source vCenter Server" -Type Info -OutputMode Both
- # Remove host from source vCenter
- Remove-VMHost -Server $SourcevCenter -VMHost $esxi -Confirm:$false
- Log -Message "Removed host $($esxi.Name) from source vCenter Server" -Type Info -OutputMode Both
- # Add host to destination vCenter
- Try {Add-VMHost -Server $DestinationvCenter -Name $esxi.Name -Credential $cred -Location "Datacenter" -Force}
- Catch {Log -Message "Oops... Something went wrong..." -Type Error -OutputMode Both}
- Log -Message "Added host $($esxi.Name) to destination vCenter Server" -Type Info -OutputMode Both
- # Move host to cluster
- Try {Move-VMHost -Server $DestinationvCenter -VMHost $(Get-VMHost -Name $esxi.Name -Server $DestinationvCenter) -Destination $Cluster}
- Catch {Log -Message "Oops... Something went wrong..." -Type Error -OutputMode Both}
- Log -Message "Moved host $($esxi.Name) to cluster $Cluster" -Type Info -OutputMode Both
- # Move VMs to folder and start with next host
- $VMfolder = @()
- $VMfolder = Import-Csv "D:\Scripts\VMware\Temp\$($esxi)-VMs-With-FolderPath.csv" | Sort-Object -Property Path
- foreach ($guest in $VMfolder) {
- $key = @()
- $key = Split-Path $guest.Path | split-path -leaf
- if ($key -eq "Datacenter") {
- Log -Message "Moving $($guest.Name) to folder $RootFolder" -Type Info -OutputMode Both
- Move-VM (Get-VM $guest.Name -Server $DestinationvCenter) -InventoryLocation (Get-Folder -Name $RootFolder -Type VM -Server $DestinationvCenter) | Out-Null
- }
- else {
- Log -Message "Moving $($guest.Name) to folder $key" -Type Info -OutputMode Both
- Move-VM (Get-VM $guest.Name -Server $DestinationvCenter) -InventoryLocation (Get-Folder $key -Server $DestinationvCenter -Location $RootFolder) -ErrorAction SilentlyContinue | Out-Null
- }
- }
- }
- # Create DRS Cluster Host Groups
- $Hosts1 = Get-Cluster -Name $Cluster -Server $DestinationvCenter | Get-VMHost | where {$_.Name.Substring(4,1) -eq "0"}
- $Hosts2 = Get-Cluster -Name $Cluster -Server $DestinationvCenter | Get-VMHost | where {$_.Name.Substring(4,1) -eq "1"}
- Log -Message "Creating DRS Host Groups" -Type Info -OutputMode Both
- New-DrsClusterGroup -Name "Host DRS Group 1" -Cluster $Cluster -VMHost $Hosts1 | Out-Null
- New-DrsClusterGroup -Name "Host DRS Group 2" -Cluster $Cluster -VMHost $Hosts2 | Out-Null
- # Create DRS Cluster VM Groups
- $VMsAMS = @()
- $VMsWSN = @()
- foreach ($vm in Import-Csv "D:\Scripts\VMware\Temp\$Cluster-1.csv") {$VMs1 += Get-VM -Name $vm.Name -Server $DestinationvCenter}
- foreach ($vm in Import-Csv "D:\Scripts\VMware\Temp\$Cluster-2.csv") {$VMs2 += Get-VM -Name $vm.Name -Server $DestinationvCenter}
- Log -Message "Creating DRS VM Groups" -Type Info -OutputMode Both
- New-DrsClusterGroup -Name "VM DRS Group 1" -Cluster $Cluster -Server $DestinationvCenter -VM $VMs1 | Out-Null
- New-DrsClusterGroup -Name "VM DRS Group 2" -Cluster $Cluster -Server $DestinationvCenter -VM $VMs2 | Out-Null
- # Enable DRS on the cluster
- Set-Cluster -Cluster $Cluster -Server $DestinationvCenter -DrsEnabled $true -Confirm:$false | Out-Null
- # Create DRS Host rules
- foreach ($rule in $DRSVmHostRules) {
- $VMGroup = Get-DrsClusterGroup -Name $rule.VMGroup -Cluster $Cluster -Type VMGroup -Server $DestinationvCenter
- $VMHostGroup = Get-DrsClusterGroup -Name $rule.VMHostGroup -Cluster $Cluster -Type VMHostGroup -Server $DestinationvCenter
- New-DrsVMHostRule -Name $rule.Name -Enabled $true -Cluster $Cluster -VMGroup $VMGroup -VMHostGroup $VMHostGroup -Type ShouldRunOn -Server $DestinationvCenter | Out-Null
- }
- # Create DRS VM rules
- foreach ($rule in $rules) {
- $rulearr = $rule.Split(",")
- if ($rulearr[1] -eq "True") {$enabled = $true}
- if ($rulearr[2] -eq "VMAntiAffinity") {$together = $false}
- New-DrsRule -Server $DestinationvCenter -Name $rulearr[0] -Cluster $Cluster -Enabled $enabled -KeepTogether $together -VM (Get-VM -Name ($rulearr[3..($rulearr.Count -1)]) -Server $DestinationvCenter)
- }
- # Disconnect from vCenter Servers
- Disconnect-VIServer -Server $SourcevCenter -Confirm:$false
- Disconnect-VIServer -Server $DestinationvCenter -Confirm:$false
- Log -Message "Script Ended" -Type Info -OutputMode LogFile
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement