Move a Virtual Machine from one host to another

After building a new set of VMware ESX servers in a new vCenter cluster, I was tasked with moving around 200 virtual servers from the old cluster to the new cluster. To do this in an orderly fashion and to make sure I didn’t miss a step, I turned to Powershell to help me accomplish the task. The below script does the following:

  • Validates that you’re logged in using an admin account. Hopefully, you are and your naming convention for all your admin accounts is the same. Simply edit that part to match your convention or comment it out
  • You then Enter the server name and it fetches the Cluster, Host and Server information from VMWare.
  • The script then queries VMware vSphere for the clusters available and puts them in a list for selection.
  • You are then presented with a list of hosts in that cluster to select the destination server to move the virtual server to.
  • Then it allows you to review what you’re going to do before any servers are shutdown, moved, VMware tools upgrade and and final reboot.
  • Sometimes the script gives some errors at the end as it has a hard time determining if the server is back online. Not a big deal and everything works great!
$starttime = get-date
 
#Region Validate Admin Account
Clear-Host
Write-Host "Validating this is running as an `"Admin`" account."
# If you use a naming convention in your administrative accounts, change this next line to check for that convention
IF ($ENV:USERNAME -notlike "*ADMIN") { THROW "SCRIPT MUST BE RUN WITH ADMIN ACCOUNT." }
 
Write-Host "Good Job! You're using your ADMIN account!!"
 
#EndRegion
 
#Region Gather Migration Information
 
#Region Connecting to VMWare
Write-Host "Adding VMWare Snapin."
Write-Host ""
 
IF ( -NOT ( Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue )) { Add-PSSnapin "VMware.VimAutomation.Core" }
TRY { Disconnect-VIServer -Server * -Force -Confirm:$FALSE -ErrorAction SilentlyContinue } CATCH { }
# Put in your FQDN of your virtual center server below
Connect-VIServer -Server FQDN.OF.VIRTUALCENTER -WarningAction SilentlyContinue | Out-Null
 
#EndRegion
 
#Region Get Server Info
# Search for server to move
$UserEntryVM = Read-Host "Enter the Virtual Machine you would like to move"
IF ( -NOT (Get-VM $UserEntryVM)) { THROW "Could not find $UserEntryVM." }
$VMToMove = Get-VM $UserEntryVM
 
#EndRegion
 
#Region Source Cluster And Host
# Get Cluster and VMHost server is on
 
$SourceCluster = $VMToMove.VMHost.Parent
$SourceHost = $VMToMove.VMHost
Write-Host
Write-Host "The Details of the Source machine are:"
Write-Host
Write-Host "Server to Move:`t`t$VMToMove"
Write-Host "Source Cluster Name:`t$SourceCluster"
Write-Host "Source Host:`t`t$SourceHost"
Write-Host ""
$UserResponse = Read-Host "Is This Informaiton Correct? (y/n)"
IF ($UserResponse.length -ne 0) {
IF ("y","Y" -NotContains $UserResponse) { THROW "INVALID ENV."}
}
 
#EndRegion
 
#Region Destination Cluster And Host
# Gather Destination VMWare Host Information
Write-Host
Write-Host "Which Cluster would you like to move $VMToMove to?"
$ESXClusters = (Get-Cluster)
 
$i = 0
FOREACH ( $Cluster IN $ESXClusters )
{
$i++
write-host "`t$i) $Cluster"
 
}
Write-Host ""
[int]$UserInput = Read-Host "Please make selection above (1 - $i)"
$ChosenCluster = $ESXClusters[($UserInput-1)]
 
$ClusterHosts = ( Get-VMHost -State Connected -Location "$ChosenCluster" )
Write-Host
Write-Host "This list does not list hosts in Maintenance Mode"
Write-Host "Which Host would you like to move $VMToMove to?"
$i = 0
FOREACH ( $ESXHost IN $ClusterHosts )
{
$i++
write-host "`t$i) $ESXHost"
 
}
Write-Host ""
[int]$UserInput = Read-Host "Please make selection above (1 - $i)"
$ChosenHost = $ClusterHosts[($UserInput-1)]
 
#EndRegion
 
#Region Validate Input
 
# Clear-Host
Write-Host ""
Write-Host "Below is what you want to do:"
Write-Host "-----------------------------"
Write-Host "Server To Move:`t`t$VMToMove"
Write-Host "Source Cluster:`t`t$SourceCluster"
Write-Host "Source Host Name:`t$SourceHost"
Write-Host ""
Write-Host "The Details of Destination ESX Host are:"
Write-Host "----------------------------------------"
Write-Host "Destination Cluster:`t$ChosenCluster"
Write-Host "Destination Host:`t$ChosenHost"
Write-Host ""
$UserMoveResponse = Read-Host "IS ALL THIS INFORMATION CORRECT? (y/n)"
IF ($UserMoveResponse.length -ne 0) {
IF ("y","Y" -NotContains $UserMoveResponse) { THROW "INVALID ENV."}
}
 
#EndRegion
 
#EndRegion
 
#Region Moving Server, Reboot, Update VMWare Tools
 
# Shutdown VM
Write-Host "Shutting Down $VMToMove"
Shutdown-VMGuest $VMToMove -Confirm:$false
WHILE ( $VMState = get-vm $VMToMove | WHERE {$_.PowerState -ne "PoweredOff"}) {start-sleep -Seconds 5}
Write-Host "$VMToMove is now off, beginning move from $SourceHost to $ChosenHost"
 
# Move VM
Get-VM $VMToMove | Move-VM -destination (Get-VMHost "$ChosenHost") -Confirm:$false
 
# Validate the move
 
# Power On VM
start-vm $VMToMove -Confirm:$false
WHILE ( $VMState = get-vm $VMToMove | WHERE {$_.PowerState -ne "PoweredOn"}) {start-sleep -Seconds 5}
WHILE ( Get-Task | WHERE {$_.Name -eq "PowerOnVM_Task" -and $_.State -ne "Success" } ) { Start-Sleep -Seconds 5 ; Get-VMQuestion | Set-VMQuestion –Default -Confirm:$False }
Write-Host "$VMToMove is powering up. This should take a minute"
 
# update vmware tools
WHILE ( -NOT ( test-connection $VMToMove -quiet ) ) {start-sleep -Seconds 5}
DO {start-sleep -Seconds 45} WHILE ( get-service -ComputerName $VMToMove -name VMTools | WHERE {$_.status -ne "running"})
Start-Sleep -Seconds 15
Write-Host "Server is online, trying to update tools..."
Update-Tools $VMToMove
#EndRegion
Write-Host "Server is rebooting after VMWare Tools Install..."
DO {start-sleep -Seconds 15} WHILE (!( test-connection $VMToMove ))
$TimeSpan = New-TimeSpan -Start $starttime
Write-Host "Server should be up..."
Write-Host ""
Write-Host "Pretty cool... Huh? This move took $TimeSpan.Minutes,$TimeSpan.Seconds"
Write-Host ""
Write-Host "You're Done! Please VALIDATE that the machine is running :)"

Leave a Reply

Your email address will not be published. Required fields are marked *