It’s always a challenge to ensure HA restarts Virtual Machines in case of a Hardware failure.
We had long discussions with VMware consultants and other specialists but at least the only suitable way is to enable admission control on the Cluster object and set resource reservation on each Virtual Machine.
As more host are within a cluster as higher is the risk of an outage that’s why I different between Clusters with more than 5 Host and increase the resource reservation for bigger clusters. You can change this value in row 8
Load Vi Toolkit in powershell
add-pssnapin VMware.VimAutomation.Core
Connect to one or more vCenter Server
Connect-VIServer "<VISever1>","<VISever2>","..." -wa 0 | out-null
Check if min one vCenter Server is connected
if ($global:DefaultVIServers.Count -gt 0){
Load only clusters who are HA and admission control enabled. This makes sense to control this script with the vCenter client. To exclude a Cluster simply disable AC
foreach($cluster in (get-view -viewtype "clustercomputeresource"|?{$_.configuration.dasconfig.admissioncontrolenabled -eq $true -and $_.configuration.dasconfig.enabled -eq $true})){
Count hosts within a cluster and calculate the correct percentage of reserved cluster resources as failover spare capacity. In this example a cluster with more than 6 hosts I calculate a failover spare capacity for two possible failing host
$amount_hosts=$cluster.host.count
$currentCpuFailoverResourcesPercent=$cluster.configuration.dasconfig.admissioncontrolpolicy.cpufailoverresourcespercent
$currentMemoryFailoverResourcesPercent=$cluster.configuration.dasconfig.admissioncontrolpolicy.memoryfailoverresourcespercent
if ($amount_hosts -gt 0 -and $amount_hosts -lt 6){
$cpuFailoverResourcesPercent = [math]::round(100/$amount_hosts)
$memoryFailoverResourcesPercent = [math]::round(100/$amount_hosts)
}
if ($amount_hosts -ge 6){
$cpuFailoverResourcesPercent = [math]::round(200/$amount_hosts)
$memoryFailoverResourcesPercent = [math]::round(200/$amount_hosts)
}
Load Cluster objects and handover previously defined variables. Compare the current failover capacity values and apply the newly calculated values only if they don’t match.
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$spec.vmSwapPlacement = "vmDirectory"
$spec.dasconfig = New-Object VMware.Vim.ClusterDasConfigInfo
$spec.dasconfig.admissioncontrolpolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
$spec.dasconfig.admissioncontrolpolicy.cpufailoverresourcespercent = $cpuFailoverResourcesPercent
$spec.dasconfig.admissioncontrolpolicy.memoryfailoverresourcespercent = $memoryFailoverResourcesPercent
if($currentCpuFailoverResourcesPercent -ne $cpuFailoverResourcesPercent -or $currentMemoryFailoverResourcesPercent -ne $memoryFailoverResourcesPercent){
$cluster.ReconfigureComputeResource_Task($spec, $true)
}
}
At his point we are finished with the cluster configuration and continue in the same loop with the VMs within this cluster. The folowing query searchs for VMs within the previously checked or configured cluster that are NOT Fault Tolerance (FT) enabled and loads Virtual machine PS objects
foreach($vm in (get-view -viewtype "virtualmachine" -searchroot $cluster.moref|?{$_.Config.FtInfo -eq $null})){
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.cpuAllocation = New-Object VMware.Vim.ResourceAllocationInfo
$spec.memoryAllocation = New-Object VMware.Vim.ResourceAllocationInfo
If you make difference between more or less important VMs like Production and Development or Test VMs you have to identify them accordantly and set the proper reservation. In my case I’m looking for Production VMs and reserve 75% of the allocated memory. (VIEPAPPAT101)
if($vm.name.length -eq 12 -and $vm.name.substring(3,1)-eq "p"){
$MemReservationMB=[math]::round($vm.config.hardware.memorymb*0.75,0)
if($vm.config.memoryAllocation.Reservation -ne $MemReservationMB -and $vm.runtime.connectionstate -eq "connected"){
$spec.memoryAllocation.reservation = $MemReservationMB
$vm.ReconfigVM_Task($spec)
}
}
Same for Development and UAT VMs but with only 50% memory reservation of the actual allocated memory (VIEDAPPAT101)
if($vm.name.length -eq 12 -and $vm.name.substring(3,1)-eq "d" -or $vm.name.substring(3,1)-eq "u"){
$MemReservationMB=[math]::round($vm.config.hardware.memorymb*0.50,0)
if($vm.config.memoryAllocation.reservation -ne $MemReservationMB -and $vm.runtime.connectionstate -eq "connected"){
$spec.memoryAllocation.reservation = $MemReservationMB
$vm.ReconfigVM_Task($spec)
}
}
Close open brakets
}
}
}
Copy the whole code
add-pssnapin VMware.VimAutomation.Core
Connect-VIServer "<VISever1>","<VISever2>","..." -wa 0 | out-null
if ($global:DefaultVIServers.Count -gt 0){
foreach($cluster in (get-view -viewtype "clustercomputeresource"|?{$_.configuration.dasconfig.admissioncontrolenabled -eq $true -and $_.configuration.dasconfig.enabled -eq $true})){
$amount_hosts=$cluster.host.count
$currentCpuFailoverResourcesPercent=$cluster.configuration.dasconfig.admissioncontrolpolicy.cpufailoverresourcespercent
$currentMemoryFailoverResourcesPercent=$cluster.configuration.dasconfig.admissioncontrolpolicy.memoryfailoverresourcespercent
if ($amount_hosts -gt 0 -and $amount_hosts -lt 6){
$cpuFailoverResourcesPercent = [math]::round(100/$amount_hosts)
$memoryFailoverResourcesPercent = [math]::round(100/$amount_hosts)
}
if ($amount_hosts -ge 6){
$cpuFailoverResourcesPercent = [math]::round(200/$amount_hosts)
$memoryFailoverResourcesPercent = [math]::round(200/$amount_hosts)
}
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$spec.vmSwapPlacement = "vmDirectory"
$spec.dasconfig = New-Object VMware.Vim.ClusterDasConfigInfo
$spec.dasconfig.admissioncontrolpolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
$spec.dasconfig.admissioncontrolpolicy.cpufailoverresourcespercent = $cpuFailoverResourcesPercent
$spec.dasconfig.admissioncontrolpolicy.memoryfailoverresourcespercent = $memoryFailoverResourcesPercent
# set failover capacaty if cpu or memory value are unequal to current configuration
if($currentCpuFailoverResourcesPercent -ne $cpuFailoverResourcesPercent -or $currentMemoryFailoverResourcesPercent -ne $memoryFailoverResourcesPercent){
$cluster.ReconfigureComputeResource_Task($spec, $true)
}
foreach($vm in (get-view -viewtype "virtualmachine" -searchroot $cluster.moref|?{$_.Config.FtInfo -eq $null})){
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.cpuAllocation = New-Object VMware.Vim.ResourceAllocationInfo
$spec.memoryAllocation = New-Object VMware.Vim.ResourceAllocationInfo
if($vm.name.length -eq 12 -and $vm.name.substring(3,1)-eq "p"){
$MemReservationMB=[math]::round($vm.config.hardware.memorymb*0.75,0)
if($vm.config.memoryAllocation.Reservation -ne $MemReservationMB -and $vm.runtime.connectionstate -eq "connected"){
$spec.memoryAllocation.reservation = $MemReservationMB
$vm.ReconfigVM_Task($spec)
}
if($vm.name.length -eq 12 -and $vm.name.substring(3,1)-eq "d" -or $vm.name.substring(3,1)-eq "u"){
$MemReservationMB=[math]::round($vm.config.hardware.memorymb*0.50,0)
if($vm.config.memoryAllocation.reservation -ne $MemReservationMB -and $vm.runtime.connectionstate -eq "connected"){
$spec.memoryAllocation.reservation = $MemReservationMB
$vm.ReconfigVM_Task($spec)
}
}
}
}
}