Skip to content

Instantly share code, notes, and snippets.

@phyoewaipaing
Last active November 12, 2023 13:39
Show Gist options
  • Save phyoewaipaing/7c8d609de500c5bd11a33af24827da76 to your computer and use it in GitHub Desktop.
Save phyoewaipaing/7c8d609de500c5bd11a33af24827da76 to your computer and use it in GitHub Desktop.
The script that will check the IP network connectivity of the each esxi portgroup by automatic vMotions within the cluster(s)
<#
.SYNOPSIS
The script that will check the IP network connectivity of the each esxi portgroup by automatic vMotions within the cluster(s)
.DESCRIPTION
This script will output the VM ICMP Ping status of the testing VM after circular vMotions within the hosts in the specified cluster(s)
You need to run this script on host where it has connectivity to your destined VM. VMwareTools also need to be running on that VM.
vCenter must already be connected with the following command.
Connect-VIServer -Server XXXXX -Credential (Get-Credential)
Example usage:
.\Vlan_Portgroup_Check_with_Circular_VM_vMotions.ps1 -VMName "Testing-VM"
Example usage:
.\Vlan_Portgroup_Check_with_Circular_VM_vMotions.ps1 -VMName "Testing-VM" -ClusterNames vmware-cluster1,vmware-cluster2
Example usage:
.\Vlan_Portgroup_Check_with_Circular_VM_vMotions.ps1 -VMName "Testing-VM" -PingCount 2
Author: Phyoe Wai Paing
Country: Myanmar(Burma)
Initial Released: 24.Feb.2020
Changed Log : v1.0 : 24.Feb.2020 : Initial Released
: v.2.0 : 06.Jan2021 : Added the -RunAsync option in Move-VM and check the vCenter tasks for that specific VM migration event.
Added error handling with detail error message. Added Count of native Ping command
vMotion failed VMs will be tried again at the end of the script
Tested and Verfied on: vCenter 6.7u1, PowerCLI 11.5 and Powershell 5, PowerCLI 12.1.0 and Powershell 5
.EXAMPLE
.\Vlan_Portgroup_Check_with_Circular_VM_vMotions.ps1 -VMName "Testing-VM"
It will do the automatic vMotion and Ping check of "Testing-VM" within the current cluster
.\Vlan_Portgroup_Check_with_Circular_VM_vMotions.ps1 -VMName "Testing-VM" -ClusterNames vmware-cluster1,vmware-cluster2
It will do the automatic vMotion and Ping check of "Testing-VM" within the vmware-cluster1 and vmware-cluster2
.\Vlan_Portgroup_Check_with_Circular_VM_vMotions.ps1 -VMName "Testing-VM" -PingCount 2
It will do the automatic vMotion and Ping check of "Testing-VM" within the current cluster with threshold of 2 Ping-Packet loss
.PARAMETER VMName
The Name of the VM as seen in vCenter
.PARAMETER ClusterNames
The Name of the Vmware Cluster that VM will make circular vMotion. You can defined multiple clusters by separating commas
.PARAMETER PingCount
The number of 32-byte packets used to determine for the success and failure of the IP connectivity. Default is 3.
If the sending ICMP 3 packets are lost (100% loss), then the VM is assumed as no IP connectivity
.LINK
You can find this script and more at: https://www.scriptinghouse.com/
#>
param([Parameter(Position=0,Mandatory=$true)][string]$VMName,[int]$PingCount=3,[array]$ClusterNames)
Function PingCheck {
param([Parameter(Position=0,Mandatory=$true)][string]$IPAddress,[int]$sec)
############## Ping the specific host and manipulate output #################
Ping -t $IPAddress -n $sec -w 2000 | where { !($_ -match "ping" -OR $_ -Match "Approximate" -OR $_ -Match "Minimum" -OR $_ -eq "") } | foreach {
### Grep the last line output and extract 0% or 100% ####
If ($_ -match "Packets: Sent" )
{
$PingResult = $_ | % { ($_.Split(',') -match " loss").Split('(')[1].split(' ')[0] }
If ($PingResult -eq "100%")
{ $False }
else { $True }
}
}
}
$VMObj = get-vm -Name $VMName
If ($ClusterNames) {
$ToLoopVMHostNames = ($ClusterNames | % { Get-Cluster -Name $_ | Get-VMHost} ).Name | sort
}
else {
$ToLoopVMHostNames = ((Get-Cluster -VMHost ($VMObj.vmhost).Name) | get-vmhost).Name | sort
}
Write-Host "`nTotal Number of Clusters for vMotion: $($ClusterNames.Count)"
Write-Host "Total Number of Hosts for vMotion: $($ToLoopVMHostNames.Count)"
$PortGroupName = (Get-Vm -Name $VMName | Get-NetworkAdapter | ? { $_.ConnectionState.Connected -eq $True } ).NetworkName
$VmIPAddress = ((get-vm -Name $VMName).guest.IPaddress -Notmatch "fe80")[0]
#### Loop each VMhost in the current Cluster where this VM exists and make vMotion ####
Function Loop_vMotions
{
param([string]$VMName,[array]$ToLoopVMHostNames,[int]$PingCount,[string]$PortGroupName,[string]$VmIPAddress)
$Script:ToLoopVMHostNamesExtra = @(); ## Declare the variable which is dynamically updated within the first function call (Loop_vMotions) ##
$ToLoopVMHostNames | % {
$Task = $NULL;
$SourceVMObj = Get-VM -Name $VMName
$Task = Move-VM -VM $VMName -Destination $_ -RunAsync
Start-Sleep -Milliseconds 500
Try
{
## If there is the Task gives error immediately, then the output the detail error output ##
If ((Get-Task -id $Task.id -EA Stop ).State -eq "Error")
{
Write-Host -fore yellow "Error moving the $VMName from $($SourceVMObj.VMHost.Name) to $($_). Error Details:$((get-task -id $Task.id).extensiondata.info.Error.LocalizedMessage)"
## If the VM error is the 'Operation is not allowed' error, then wait for 1 min & try again ##
If ( $((get-task -id $Task.id).extensiondata.info.Error.LocalizedMessage) -match "The operation is not allowed in the current state")
{
Write-Host -fore Cyan "We will wait 1 min to proceed."
Start-Sleep 60;
$Task = Move-VM -VM $VMName -Destination $_ -RunAsync
Start-Sleep -Milliseconds 500
}
else
{
## If it's the other vMotion related error, we will record the VM name & try again on next function call at the end of the script ##
$Script:ToLoopVMHostNamesExtra += $_;
}
}
#### Wait until vMotion task for this VM is completed ####
while( (Get-Task -id $Task.id -EA Stop).PercentComplete -ne 100 -AND (Get-Task -id $Task.id -EA Stop ).State -ne "Error")
{
If ((Get-Task -id $Task.id).State -eq "Error")
{
Write-Host -fore yellow "Error moving the $VMName from $($SourceVMObj.VMHost.Name) to $($_). Error Details:$((get-task -id $Task.id).extensiondata.info.Error.LocalizedMessage)"
}
Start-Sleep -Milliseconds 1000
}
Start-Sleep 1;
## It will output the result only when the task is 100% completed & there was no error ##
If ((Get-Task -id $Task.id -EA Stop).PercentComplete -eq 100 -AND (Get-Task -id $Task.id -EA Stop ).State -ne "Error")
{
$DestVMObj = get-vm -Name $VMName
$DestVMObj | select Name, @{N='VMHostName';Exp={ $DestVMObj.VMHost.Name }},
@{N='VmIPAddress';Exp= {$VmIPAddress}},
@{N='PingStatusIPAddress';Exp= { If($VmIPAddress) {PingCheck -IPAddress $VmIPAddress -sec $PingCount}} },
@{N="$([char]::ConvertFromUtf32(0x266A)*5) PortGroupName $([char]::ConvertFromUtf32(0x266A)*5)";Exp= {$PortGroupName}},
@{N="$([char]::ConvertFromUtf32(0x266A)*5) ClusterName $([char]::ConvertFromUtf32(0x266A)*5)";Exp={ $DestVMObj.VMHost.Parent.Name }}
}
}
catch
{
Write-Host "The Migration Task $($Task.id) cannot be found. Skipping to next object."
}
}
}
## Loop vMotion for the initial batch of VMhosts ##
Loop_vMotions $VMName $ToLoopVMHostNames $PingCount $PortGroupName $VmIPAddress
## vMotion over the problematic hosts again ##
Loop_vMotions $VMName $ToLoopVMHostNamesExtra $PingCount $PortGroupName $VmIPAddress
[system.media.systemsounds]::Hand.Play()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment