<#
.SYNOPSIS
Perform steps to migrate VMs.
.DESCRIPTION
Use this script to move VMs.
Possible scenarios are:
- vMotion VMs from DC1 hosts to temporary DC3 hosts, including a Storage vMotion.
- vMotion VMs from DC1 hosts to new DC3 hosts, including a Storage vMotion.
- vMotion VMs from temporary DC3 hosts to relocated AMS hosts.
- Storage vMotion from DC2 storage to new DC2 storage.
- vMotion VMs from DC2 hosts to new DC2 hosts, including a Storage vMotion
Only VMs without Raw Device Mappings (RDM) are moved.
This script assumes the availability of the following modules:
- VMware-PowerCli
.PARAMETER
- Cluster (String value with the name of the cluster) [Mandatory]
- NewCluster (String value with the name of the new cluster)
.EXAMPLE
.\Migrate-Cluster.ps1 -Cluster CLS01
.\Migrate-Cluster.ps1 -Cluster CLS01 -NewCluster CLS05
.NOTES
Script name: Migrate-Cluster.ps1
Author: Jeroen Buren
DateCreated: 19-06-2020
Version: 1.0
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param (
[parameter(mandatory = $true)][string]$Cluster,
[parameter(Mandatory = $false)][string]$NewCluster
)
$version = "1.0"
Get-Module -Name VMware* -ListAvailable | Import-Module
####################################################################################
# #
# Variables #
# #
####################################################################################
$vMotion = 0
$SvMotion = 0
####################################################################################
# #
# Functions #
# #
####################################################################################
function Get-ScriptDirectory {
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
# Logfile
Set-Variable logFile ((Get-ScriptDirectory) + "\Migrate-Cluster.log") -Option Constant -ErrorAction SilentlyContinue
function Write-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 {
Write-Log ("Failed to write to log file: """ + $logFile + """.") -OutputMode Console -Type Error
Write-Log ("[" + $_.Exception.GetType().FullName + "] " + $_.Exception.Message) -OutputMode Console -Type Error
}
}
}
function Connect_vCenter {
Clear-Host
# vCenter connection details
Write-Host `n" Getting connection details of vCenter..." -ForegroundColor Green
Write-Host `n" Enter vCenter details..."`n
$vc = Read-Host -Prompt "`tHost Name/IP address`t"
$vcuser = Read-Host -Prompt "`tUser Name`t`t"
$vcpass = Read-Host -Prompt "`tPassword`t`t" -AsSecureString
$vccreds = New-Object System.Management.Automation.PSCredential ($vcuser, $vcpass)
# make connection to vCenter
Try {
Write-Log -Message "Connecting to vCenter." -Type Info -OutputMode LogFile
Connect-VIServer -Server $vc -Credential $vccreds -ErrorAction Stop| Out-Null
Write-Log -Message "Connection to vCenter is successful." -Type Info -OutputMode LogFile
}
Catch {
Write-Host `n" Oeps... There was an error connecting to the vCenter server..." -ForegroundColor Yellow
Write-Log -Message "There was an error connecting to the vCenter server." -Type Error -OutputMode LogFile
Pause
return
}
# Displaying runtime information
Write-Host `n"`tConnected to vCenter Server`t: $global:defaultviserver"
Write-Host "`tSource Cluster to be migrated`t: $Cluster"
Write-Host "`tDestination Cluster`t`t: $NewCluster"`n
Pause
return
}
function Remote_Migration {
Clear-Host
Write-Host `n"Moving VMs from datacenter DC1 to remote datacenter DC3..."`n
Write-Log -Message "Moving VMs from datacenter DC1 to remote datacenter DC3." -Type Info -OutputMode LogFile
foreach ($vmhost in Get-Cluster -Name $Cluster | Get-VMHost -Tag "DC1") { # Select all the DC1 hosts in the cluster
Write-Host "Starting migration for host $($vmhost.Name)..."
Write-Log -Message "Starting migration for host $($vmhost.Name)." -Type Info -OutputMode LogFile
$VMswithRDM = $vmhost | Get-VM | Where-Object {$_ | Get-HardDisk -DiskType RawPhysical,RawVirtual}
foreach ($vm in $vmhost | Get-VM | Where-Object {$_ -notin $VMswithRDM}) { # Perform steps for each VM on a host but only for VMs without RDM
Try {
$Destination_Host = Get-Cluster -Name $NewCluster | Get-VMHost -Tag "DC3" | Get-Random # Pick a random destination host from the new cluster in the DC3 datacenter
$Destination_Datastore = Get-DatastoreCluster -Tag "DC3" | Where-Object {$_.Name -like "$cluster*"} # Get a destination datastore in the DC3 datacenter
Move-VM -VM $vm -Destination $Destination_Host -Datastore $Destination_Datastore -RunAsync -ErrorAction Stop | Out-Null # Create a Move-VM task to move the VM
Write-Log -Message "Moved $($vm.Name) to $($Destination_Host.Name) and $($Destination_Datastore.Name)" -Type Info -OutputMode LogFile
}
Catch {
Write-Host " Oeps... There was an error moving VM $($vm.Name)..."
Write-Log -Message "There was an error moving VM $($vm.Name)." -Type Error -OutputMode LogFile
}
}
Write-Host "Done migrating VMs from the host $($vmhost.Name). Do you wish to continue with the next host?"
Pause
}
Write-Host "Remote migration of cluster $Cluster is finished..."
Write-Log -Message "Remote migration of cluster $Cluster is finished." -Type Info -OutputMode LogFile
Pause
return
}
function Local_Migration {
#region Ask for details
Clear-Host
# Asking what type of vMotion should be performed
Write-Host `n" Getting migration details..."
Do {
Write-host `n" In which datacenter would you like to perform the migration? ( DC2 / DC3 ) : " -NoNewLine
$Location = Read-Host
$Location = $Location.ToUpper()
} while ($Location -notin "DC2", "DC3")
if ($Location -eq "DC2") {
Do {
Write-host `n" Would you like to perform a host migration (vMotion)? ( y / n ) : " -NoNewLine
$Readhost = Read-Host
} while ($Readhost -notin "y","n")
Switch ($ReadHost) {
Y {$vMotion = 1}
N {$vMotion = 0}
Default {}
}
$SvMotion = 1
}
if ($Location -eq "DC3") {
$vMotion = 1
$SvMotion = 0
}
#endregion
#region DC3 vMotion
if ($Location -eq "DC3") { # Only vMotion
Clear-Host
Write-Host `n"Moving VMs in datacenter DC3 to the old DC1 hosts..."`n
Write-Log -Message "Moving VMs in datacenter DC3 to the old DC1 hosts." -Type Info -OutputMode LogFile
foreach ($vmhost in Get-Cluster -Name $Cluster | Get-VMHost -Tag "DC3") { # Select all the DC3 hosts in the cluster
Write-Host "Starting migration for host $($vmhost.Name)..."
Write-Log -Message "Starting migration for host $($vmhost.Name)." -Type Info -OutputMode LogFile
$VMswithRDM = $vmhost | Get-VM | Where-Object { $_ | Get-HardDisk -DiskType RawPhysical, RawVirtual }
foreach ($vm in $vmhost | Get-VM | Where-Object { $_ -notin $VMswithRDM }) {
# Perform steps for each VM on a host but only for VMs without RDM
Try {
$Destination_Host = Get-VMHost -Tag "DC1" | Get-Random # Get a random destination host with the DC1 tag. These are the relocated hosts from the old DC1 datacenter.
Move-VM -VM $vm -Destination $Destination_Host -RunAsync -ErrorAction Stop | Out-Null # Create a Move-VM task to move the VM
Write-Log -Message "Moved $($vm.Name) to $($Destination_Host.Name)" -Type Info -OutputMode LogFile
}
Catch {
Write-Host " Oeps... There was an error moving VM $($vm.Name)..."
Write-Log -Message "There was an error moving VM $($vm.Name)." -Type Error -OutputMode LogFile
}
}
Write-Host "Done migrating VMs from the host $($vmhost.Name). Do you wish to continue with the next host?"
Pause
}
Write-Host "Local migration of cluster $Cluster is finished..."
Write-Log -Message "Local migration of cluster $Cluster is finished." -Type Info -OutputMode LogFile
Pause
return
}
#endregion
#region DC2 storage vMotion
if (($Location -eq "DC2") -and ($vMotion -eq 0)) { # Only Storage vMotion
Clear-Host
Write-Host `n"Moving VMs in datacenter DC2 to new storage..."`n
Write-Log -Message "Moving VMs in datacenter DC2 to new storage." -Type Info -OutputMode LogFile
foreach ($vmhost in Get-Cluster -Name $Cluster | Get-VMHost -Tag "DC2") { # Select all the DC2 hosts in the cluster
Write-Host "Starting migration for host $($vmhost.Name)..."
Write-Log -Message "Starting migration for host $($vmhost.Name)." -Type Info -OutputMode LogFile
$VMswithRDM = $vmhost | Get-VM | Where-Object { $_ | Get-HardDisk -DiskType RawPhysical, RawVirtual }
foreach ($vm in $vmhost | Get-VM | Where-Object { $_ -notin $VMswithRDM }) { # Perform steps for each VM on a host but only for VMs without RDM
Try {
$Destination_Datastore = Get-DatastoreCluster -Tag "DC2" | Where-Object { $_.Name -like "$cluster*" } # Get a destination datastore in the DC2 datacenter
Move-VM -VM $vm -Datastore $Destination_Datastore -RunAsync -ErrorAction Stop | Out-Null # Create a Move-VM task to move the VM
Write-Log -Message "Moved $($vm.Name) to $($Destination_Datastore.Name)" -Type Info -OutputMode LogFile
}
Catch {
Write-Host " Oeps... There was an error moving VM $($vm.Name)..."
Write-Log -Message "There was an error moving VM $($vm.Name)." -Type Error -OutputMode LogFile
}
}
Write-Host "Done migrating VMs from the host $($vmhost.Name). Do you wish to continue with the next host?"
Pause
}
Write-Host "Local migration of cluster $Cluster is finished..."
Write-Log -Message "Local migration of cluster $Cluster is finished." -Type Info -OutputMode LogFile
Pause
return
}
#endregion
#region DC2 vMotion and Storage vMotion
if (($Location -eq "DC2") -and ($vMotion -eq 1)) { # Both vMotion and Storage vMotion
Clear-Host
Write-Host `n"Moving VMs in datacenter DC2 to new hosts and storage..."`n
Write-Log -Message "Moving VMs in datacenter DC2 to new hosts and storage." -Type Info -OutputMode LogFile
foreach ($vmhost in Get-Cluster -Name $Cluster | Get-VMHost -Tag "DC2") {
# Select all the DC2 hosts in the cluster
Write-Host "Starting migration for host $($vmhost.Name)..."
Write-Log -Message "Starting migration for host $($vmhost.Name)." -Type Info -OutputMode LogFile
$VMswithRDM = $vmhost | Get-VM | Where-Object { $_ | Get-HardDisk -DiskType RawPhysical, RawVirtual }
foreach ($vm in $vmhost | Get-VM | Where-Object { $_ -notin $VMswithRDM }) {
# Perform steps for each VM on a host but only for VMs without RDM
Try {
$Destination_Host = Get-Cluster -Name $NewCluster | Get-VMHost -Tag "DC2" | Get-Random # Pick a random destination host from the new cluster in the DC2 datacenter
$Destination_Datastore = Get-DatastoreCluster -Tag "DC2" | Where-Object { $_.Name -like "$cluster*" } # Get a destination datastore in the WSN datacenter
Move-VM -VM $vm -Destination $Destination_Host -Datastore $Destination_Datastore -RunAsync -ErrorAction Stop | Out-Null # Create a Move-VM task to move the VM
Write-Log -Message "Moved $($vm.Name) to $($Destination_Host.Name) and $($Destination_Datastore.Name)" -Type Info -OutputMode LogFile
}
Catch {
Write-Host " Oeps... There was an error moving VM $($vm.Name)..."
Write-Log -Message "There was an error moving VM $($vm.Name)." -Type Error -OutputMode LogFile
}
}
Write-Host "Done migrating VMs from the host $($vmhost.Name). Do you wish to continue with the next host?"
Pause
}
Write-Host "Local migration of cluster $Cluster is finished..."
Write-Log -Message "Local migration of cluster $Cluster is finished." -Type Info -OutputMode LogFile
Pause
return
}
#endregion
}
####################################################################################
# #
# Main code #
# #
####################################################################################
$Cluster = $Cluster.ToUpper()
if (!$NewCluster) {$NewCluster = $Cluster}
$NewCluster = $NewCluster.ToUpper()
Write-Log -Message "Migration Tool Version: $version started" -Type Info -OutputMode Both
Do {
Clear-Host
Write-Host `n" Cluster Migration Tool"
Write-Host `n" Version $version"`n
Write-Host "Type 'q' or press enter to quit..."`n
Write-Host " 1. Connect to vCenter"
Write-Host " Connect to vCenter Server with supplied credentials."`n
Write-Host " 2. Remote Migration"
Write-Host " Move VMs from datacenter DC1 to remote datacenter DC3."`n
Write-Host " 3. Local Migration"
Write-Host " Move VMs within the same location to different hosts and/or storage."`n`n
$selection = Read-Host -Prompt "Select Option "
Switch ($selection) {
"1" {Connect_vCenter}
"2" {Remote_Migration}
"3" {Local_Migration}
{($_ -like "*q*") -or ($_ -eq "")} {
Clear-Host
Write-Host `n"`tDisconnecting from vCenter Server..." -ForegroundColor Yellow
Disconnect-VIServer -erroraction ignore -Confirm:$false | Out-Null
Write-Host `n
pause
Clear-Host
exit
}
default {}
}
} While ($selection -le 3)