build 7bbbddf7 | content blog-content@c8490fa · 338 posts | profiles 20 · corpus 267 | 0 skipped | | format
apiVersion: soultec.ch/v1kind: Postmetadata: name: powercli-change-admission-control-percentages locale: en labels: author: dario-doerflinger series: scripting capability/automation: 1.78 vendor/vmware: 0.88 annotations: source: blog-content/posts/en/powercli-change-admission-control-percentages.md route: /en/insights/powercli-change-admission-control-percentages/ schema: /nerd/schema/posts.json markdown: /en/insights/powercli-change-admission-control-percentages.mdspec: title: Change Admission Control Percentages date: 2018-06-05 author: dario-doerflinger locale: en summary: >- I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment. capabilities: [automation] vendors: [vmware] series: scripting legacySlug: powercli-change-admission-control-percentages migrated: 2026-08-24 draft: false sections: - body: | I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment. I knew the environment so I pointed out some things that 6.5 does better than the currently installed 6.0. One of those things I mentioned was the automated adjustment of the resource percentage in the HA admission control settings. For those of you who don't know: vSphere 6.5 does automatically change the resource percentage when you add or remove hosts to a cluster. For example: You have a 4-Node cluster and set the HA admission control setting to cluster resource percentage and you want to tolerate 1 host failure. vSphere sets the percentages to 25% for CPU and Memory. If you now go ahead and add one host those settings are automatically updated to 20% memory and cpu. Anyways, the customer wanted that feature because he does that quite often (adding/removing hosts) but he could not update to 6.5 for a couple of reasons (Hardware compatibility and 3rd party software that integrates into vCenter, etc). So he asked me if there was a way to get that feature without updating. My response was: "Everything is possible with PowerCLI". So, long story, here is the script to backport this 6.5 feature to 6.0. Now, you'd have to call this script every time a change of hosts has occurred in your clusters, or you could let it run twice a day or something (still not as elegant as the 6.5 feature, but close enough). Update: this script is now published at [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts). Oh, almost forgot: This script uses the [PSLogging](https://www.powershellgallery.com/packages/PSLogging/2.5.2) Module that is available from the powershellgallery. ```powershell #---------------------------------------------------------[Script Parameters]------------------------------------------------------ Param ( #Script parameters go here [Parameter(Mandatory = $true)][string]$vCenter, [Parameter(Mandatory = $true)][string]$cluster, [Parameter(Mandatory = $true)][string]$failuresToTolerate ) #---------------------------------------------------------[Initialisations]-------------------------------------------------------- #Set Error Action to Silently Continue $ErrorActionPreference = 'SilentlyContinue' #Import Modules & Snap-ins Import-Module PSLogging #----------------------------------------------------------[Declarations]---------------------------------------------------------- #Script Version $sScriptVersion = '1.0' #Log File Info $sLogPath = 'C:\Temp' $sLogName = 'HA_AdmissionControlLog.log' $sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName #-----------------------------------------------------------[Functions]------------------------------------------------------------ Function Connect-VMwareServer { Param ([Parameter(Mandatory = $true)][string]$VMServer) Begin { Write-LogInfo -LogPath $sLogFile -Message "Connecting to vCenter Server [$VMServer]..." } Process { Try { $oCred = Get-Credential -Message 'Enter credentials to connect to vCenter Server' Connect-VIServer -Server $VMServer -Credential $oCred -ErrorAction Stop } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function checkRAMCompliance { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same amount of RAM..." $myHostsRAM = @() } Process { Try { $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop foreach ($hostObject in $hostObjects) { $HostInfoMEM = "" | Select-Object MEM $HostInfoMEM.MEM = $hostObject.MemoryTotalGB $myHostsRAM += $HostInfoMEM } #Check if all values are correct: return true, otherwise return false if (@($myHostsRAM | Select-Object -Unique).Count -eq 1) { #CPU are the same Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is the same" return $true } else { Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is NOT the same" return $false } } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function checkCPUCompliance { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same CPU..." $myHostsCPU = @() } Process { Try { $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop foreach ($hostObject in $hostObjects) { $HostInfoCPU = "" | Select-Object CPU $HostInfoCPU.CPU = $hostObject.CpuTotalMhz $myHostsCPU += $HostInfoCPU } #Check if all values are correct: return true, otherwise return false if (@($myHostsCPU | Select-Object -Unique).Count -eq 1) { Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is the same" return $true } else { Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is NOT the same" return $false } } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function getBiggestCPUInCluster { Param ([Parameter(Mandatory=$true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest CPU resource in cluster [$clusterName]..." } Process { Try { $clusterObject = Get-Cluster $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop $cpuResources = @() foreach ($hostObject in $hostObjects) { $cpuInfo = "" | Select-Object CPU $cpuInfo.CPU = $hostObject.CpuTotalMhz $cpuResources += $cpuInfo } return ($cpuResources | Measure-Object -Maximum) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function getBiggestRAMInCluster { Param ([Parameter(Mandatory=$true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest RAM resource in cluster [$clusterName]..." } Process { Try { $clusterObject = Get-Cluster $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop $ramResources = @() foreach ($hostObject in $hostObjects) { $ramInfo = "" | Select-Object RAM $ramInfo.RAM = $hostObject.MemoryTotalGB $ramResources += $ramInfo } return ($ramResources | Measure-Object -Maximum) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function SetAdmissionControl { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Setting the admission policy on cluster [$clusterName].." } Process { Try { $RAMCompliance = checkRAMCompliance $clusterName $CPUCompliance = checkCPUCompliance $clusterName $totalAmountofHostsInCluster = (Get-Cluster -Name $clusterName -ErrorAction Stop | Get-VMHost -ErrorAction Stop).Count if (($RAMCompliance -eq $true) -and ($CPUCompliance -eq $true)) { #Same hardware. calculation very simple [int]$ramPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0) [int]$cpuPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0) } if ($CPUCompliance -eq $false) { #calculate with different CPU resources but same RAM resources #get biggest CPU amount, total amount and number of hosts in cluster $biggestCPUValue = getBiggestCPUInCluster $clusterName $totalCPUMhz = (Get-Cluster $clusterName).ExtensionData.Summary.TotalCPU [int]$cpuPercentageToReserve = [math]::Round(((($biggestCPUValue) * 100) / ($totalCPUMhz)*($failuresToTolerate)),0) } if ($RAMCompliance -eq $false) { #in this case RAM is the decisive factor #get biggest RAM amount, total amount and number of hosts in cluster $biggestMemoryValue = getBiggestRAMInCluster $clusterName $totalMemoryGB = [math]::Round(((Get-Cluster $clusterName).ExtensionData.Summary.TotalMemory /1024 /1024 /1024),0) [int]$ramPercentageToReserve = [math]::Round(((($biggestMemoryValue) * 100) / ($totalMemoryGB)*($failuresToTolerate)),0) } Write-LogInfo -LogPath $sLogFile -Message "CPU Value calculated: [$cpuPercentageToReserve].." Write-LogInfo -LogPath $sLogFile -Message "RAM Value calculated: [$ramPercentageToReserve].." $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo $spec.dasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy $spec.dasConfig.AdmissionControlEnabled = $true $spec.dasConfig.AdmissionControlPolicy.cpuFailoverResourcesPercent = $cpuPercentageToReserve $spec.dasConfig.AdmissionControlPolicy.memoryFailoverResourcesPercent = $ramPercentageToReserve $clusterObject = Get-Cluster $clusterName $clusterView = Get-View $clusterObject $clusterView.ReconfigureComputeResource_Task($spec, $true) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } #-----------------------------------------------------------[Execution]------------------------------------------------------------ Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersion Connect-VMwareServer -VMServer $vCenter SetAdmissionControl -clusterName $cluster Stop-Log -LogPath $sLogFile ```status: corpus: 267 alsoLike: - {ref: posts/vmware-explore-las-vegas-hackathon-2025, score: 1.00} - {ref: posts/vmware-hackathon-2024-project, score: 1.00} - {ref: solutions/vmware/vmware-cloud-foundation/addon/application-services, score: 0.60}
{ "apiVersion": "soultec.ch/v1", "kind": "Post", "metadata": { "name": "powercli-change-admission-control-percentages", "locale": "en", "labels": { "author": "dario-doerflinger", "series": "scripting", "capability/automation": "1.78", "vendor/vmware": "0.88" }, "annotations": { "source": "blog-content/posts/en/powercli-change-admission-control-percentages.md", "route": "/en/insights/powercli-change-admission-control-percentages/", "schema": "/nerd/schema/posts.json", "markdown": "/en/insights/powercli-change-admission-control-percentages.md" } }, "spec": { "title": "Change Admission Control Percentages", "date": "2018-06-05", "author": "dario-doerflinger", "locale": "en", "summary": "I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment.", "capabilities": [ "automation" ], "vendors": [ "vmware" ], "series": "scripting", "legacySlug": "powercli-change-admission-control-percentages", "migrated": "2026-08-24", "draft": false }, "sections": [ { "body": "I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment. I knew the environment so I pointed out some things that 6.5 does better than the currently installed 6.0. One of those things I mentioned was the automated adjustment of the resource percentage in the HA admission control settings.\n\nFor those of you who don't know: vSphere 6.5 does automatically change the resource percentage when you add or remove hosts to a cluster. For example: You have a 4-Node cluster and set the HA admission control setting to cluster resource percentage and you want to tolerate 1 host failure. vSphere sets the percentages to 25% for CPU and Memory. If you now go ahead and add one host those settings are automatically updated to 20% memory and cpu.\n\nAnyways, the customer wanted that feature because he does that quite often (adding/removing hosts) but he could not update to 6.5 for a couple of reasons (Hardware compatibility and 3rd party software that integrates into vCenter, etc). So he asked me if there was a way to get that feature without updating. My response was: \"Everything is possible with PowerCLI\".\n\nSo, long story, here is the script to backport this 6.5 feature to 6.0. Now, you'd have to call this script every time a change of hosts has occurred in your clusters, or you could let it run twice a day or something (still not as elegant as the 6.5 feature, but close enough).\n\nUpdate: this script is now published at [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts).\n\nOh, almost forgot: This script uses the [PSLogging](https://www.powershellgallery.com/packages/PSLogging/2.5.2) Module that is available from the powershellgallery.\n\n```powershell\n\n#---------------------------------------------------------[Script Parameters]------------------------------------------------------\n\nParam (\n #Script parameters go here\n [Parameter(Mandatory = $true)][string]$vCenter,\n [Parameter(Mandatory = $true)][string]$cluster,\n [Parameter(Mandatory = $true)][string]$failuresToTolerate\n)\n\n#---------------------------------------------------------[Initialisations]--------------------------------------------------------\n\n#Set Error Action to Silently Continue\n$ErrorActionPreference = 'SilentlyContinue'\n\n#Import Modules & Snap-ins\nImport-Module PSLogging\n\n#----------------------------------------------------------[Declarations]----------------------------------------------------------\n\n#Script Version\n$sScriptVersion = '1.0'\n\n#Log File Info\n$sLogPath = 'C:\\Temp'\n$sLogName = 'HA_AdmissionControlLog.log'\n$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName\n\n#-----------------------------------------------------------[Functions]------------------------------------------------------------\n\nFunction Connect-VMwareServer {\n Param ([Parameter(Mandatory = $true)][string]$VMServer)\n\n Begin {\n Write-LogInfo -LogPath $sLogFile -Message \"Connecting to vCenter Server [$VMServer]...\"\n }\n\n Process {\n Try {\n $oCred = Get-Credential -Message 'Enter credentials to connect to vCenter Server'\n Connect-VIServer -Server $VMServer -Credential $oCred -ErrorAction Stop\n }\n\n Catch {\n Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully\n Break\n }\n }\n\n End {\n If ($?) {\n Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'\n Write-LogInfo -LogPath $sLogFile -Message ' '\n }\n }\n}\n\nFunction checkRAMCompliance {\n Param ([Parameter(Mandatory = $true)][string]$clusterName)\n Begin {\n Write-LogInfo -LogPath $sLogFile -Message \"Checking if all hosts in cluster [$clusterName] have the same amount of RAM...\"\n $myHostsRAM = @()\n }\n Process {\n Try {\n $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop\n $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop\n\n foreach ($hostObject in $hostObjects) {\n\n $HostInfoMEM = \"\" | Select-Object MEM\n\n $HostInfoMEM.MEM = $hostObject.MemoryTotalGB\n\n $myHostsRAM += $HostInfoMEM\n }\n #Check if all values are correct: return true, otherwise return false\n if (@($myHostsRAM | Select-Object -Unique).Count -eq 1) {\n #CPU are the same\n Write-LogInfo -LogPath $sLogFile -Message \"RAM in the cluster is the same\"\n return $true\n }\n else {\n Write-LogInfo -LogPath $sLogFile -Message \"RAM in the cluster is NOT the same\"\n return $false\n }\n\n }\n Catch {\n Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully\n Break\n }\n }\n End {\n If ($?) {\n Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'\n Write-LogInfo -LogPath $sLogFile -Message ' '\n }\n }\n}\n\nFunction checkCPUCompliance {\n Param ([Parameter(Mandatory = $true)][string]$clusterName)\n Begin {\n Write-LogInfo -LogPath $sLogFile -Message \"Checking if all hosts in cluster [$clusterName] have the same CPU...\"\n $myHostsCPU = @()\n }\n Process {\n Try {\n $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop\n $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop\n\n foreach ($hostObject in $hostObjects) {\n $HostInfoCPU = \"\" | Select-Object CPU\n\n $HostInfoCPU.CPU = $hostObject.CpuTotalMhz\n\n $myHostsCPU += $HostInfoCPU\n }\n #Check if all values are correct: return true, otherwise return false\n\n if (@($myHostsCPU | Select-Object -Unique).Count -eq 1) {\n Write-LogInfo -LogPath $sLogFile -Message \"CPU in the cluster is the same\"\n return $true\n }\n else {\n Write-LogInfo -LogPath $sLogFile -Message \"CPU in the cluster is NOT the same\"\n return $false\n }\n\n }\n Catch {\n Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully\n Break\n }\n }\n End {\n If ($?) {\n Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'\n Write-LogInfo -LogPath $sLogFile -Message ' '\n }\n }\n}\n\nFunction getBiggestCPUInCluster {\n Param ([Parameter(Mandatory=$true)][string]$clusterName)\n Begin {\n Write-LogInfo -LogPath $sLogFile -Message \"Trying to get the biggest CPU resource in cluster [$clusterName]...\"\n }\n Process {\n Try {\n $clusterObject = Get-Cluster $clusterName -ErrorAction Stop\n $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop\n $cpuResources = @()\n foreach ($hostObject in $hostObjects) {\n $cpuInfo = \"\" | Select-Object CPU\n $cpuInfo.CPU = $hostObject.CpuTotalMhz\n\n $cpuResources += $cpuInfo\n }\n return ($cpuResources | Measure-Object -Maximum)\n\n }\n Catch {\n Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully\n Break\n }\n }\n End {\n If ($?) {\n Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'\n Write-LogInfo -LogPath $sLogFile -Message ' '\n }\n }\n }\n\n Function getBiggestRAMInCluster {\n Param ([Parameter(Mandatory=$true)][string]$clusterName)\n Begin {\n Write-LogInfo -LogPath $sLogFile -Message \"Trying to get the biggest RAM resource in cluster [$clusterName]...\"\n }\n Process {\n Try {\n $clusterObject = Get-Cluster $clusterName -ErrorAction Stop\n $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop\n $ramResources = @()\n foreach ($hostObject in $hostObjects) {\n $ramInfo = \"\" | Select-Object RAM\n $ramInfo.RAM = $hostObject.MemoryTotalGB\n\n $ramResources += $ramInfo\n }\n return ($ramResources | Measure-Object -Maximum)\n\n }\n Catch {\n Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully\n Break\n }\n }\n End {\n If ($?) {\n Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'\n Write-LogInfo -LogPath $sLogFile -Message ' '\n }\n }\n }\n\nFunction SetAdmissionControl {\n Param ([Parameter(Mandatory = $true)][string]$clusterName)\n Begin {\n Write-LogInfo -LogPath $sLogFile -Message \"Setting the admission policy on cluster [$clusterName]..\"\n }\n Process {\n Try {\n $RAMCompliance = checkRAMCompliance $clusterName\n $CPUCompliance = checkCPUCompliance $clusterName\n $totalAmountofHostsInCluster = (Get-Cluster -Name $clusterName -ErrorAction Stop | Get-VMHost -ErrorAction Stop).Count\n if (($RAMCompliance -eq $true) -and ($CPUCompliance -eq $true)) {\n #Same hardware. calculation very simple\n [int]$ramPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0)\n [int]$cpuPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0)\n\n }\n if ($CPUCompliance -eq $false) {\n #calculate with different CPU resources but same RAM resources\n #get biggest CPU amount, total amount and number of hosts in cluster\n $biggestCPUValue = getBiggestCPUInCluster $clusterName\n $totalCPUMhz = (Get-Cluster $clusterName).ExtensionData.Summary.TotalCPU\n\n [int]$cpuPercentageToReserve = [math]::Round(((($biggestCPUValue) * 100) / ($totalCPUMhz)*($failuresToTolerate)),0)\n }\n if ($RAMCompliance -eq $false) {\n #in this case RAM is the decisive factor\n #get biggest RAM amount, total amount and number of hosts in cluster\n $biggestMemoryValue = getBiggestRAMInCluster $clusterName\n $totalMemoryGB = [math]::Round(((Get-Cluster $clusterName).ExtensionData.Summary.TotalMemory /1024 /1024 /1024),0)\n\n [int]$ramPercentageToReserve = [math]::Round(((($biggestMemoryValue) * 100) / ($totalMemoryGB)*($failuresToTolerate)),0)\n }\n\n Write-LogInfo -LogPath $sLogFile -Message \"CPU Value calculated: [$cpuPercentageToReserve]..\"\n Write-LogInfo -LogPath $sLogFile -Message \"RAM Value calculated: [$ramPercentageToReserve]..\"\n\n $spec = New-Object VMware.Vim.ClusterConfigSpecEx\n $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo\n $spec.dasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy\n $spec.dasConfig.AdmissionControlEnabled = $true\n $spec.dasConfig.AdmissionControlPolicy.cpuFailoverResourcesPercent = $cpuPercentageToReserve\n $spec.dasConfig.AdmissionControlPolicy.memoryFailoverResourcesPercent = $ramPercentageToReserve\n\n $clusterObject = Get-Cluster $clusterName\n $clusterView = Get-View $clusterObject\n $clusterView.ReconfigureComputeResource_Task($spec, $true)\n\n }\n Catch {\n Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully\n Break\n }\n }\n End {\n If ($?) {\n Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'\n Write-LogInfo -LogPath $sLogFile -Message ' '\n }\n }\n}\n\n#-----------------------------------------------------------[Execution]------------------------------------------------------------\n\nStart-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersion\nConnect-VMwareServer -VMServer $vCenter\nSetAdmissionControl -clusterName $cluster\nStop-Log -LogPath $sLogFile\n```" } ], "status": { "corpus": 267, "alsoLike": [ { "ref": "posts/vmware-explore-las-vegas-hackathon-2025", "score": "1.00" }, { "ref": "posts/vmware-hackathon-2024-project", "score": "1.00" }, { "ref": "solutions/vmware/vmware-cloud-foundation/addon/application-services", "score": "0.60" } ] }}
apiVersion = "soultec.ch/v1"kind = "Post"[metadata]name = "powercli-change-admission-control-percentages"locale = "en"[metadata.labels]author = "dario-doerflinger"series = "scripting""capability/automation" = "1.78""vendor/vmware" = "0.88"[metadata.annotations]source = "blog-content/posts/en/powercli-change-admission-control-percentages.md"route = "/en/insights/powercli-change-admission-control-percentages/"schema = "/nerd/schema/posts.json"markdown = "/en/insights/powercli-change-admission-control-percentages.md"[spec]title = "Change Admission Control Percentages"date = 2018-06-05author = "dario-doerflinger"locale = "en"summary = "I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment."capabilities = ["automation"]vendors = ["vmware"]series = "scripting"legacySlug = "powercli-change-admission-control-percentages"migrated = 2026-08-24draft = false[[sections]]body = '''I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment. I knew the environment so I pointed out some things that 6.5 does better than the currently installed 6.0. One of those things I mentioned was the automated adjustment of the resource percentage in the HA admission control settings.For those of you who don't know: vSphere 6.5 does automatically change the resource percentage when you add or remove hosts to a cluster. For example: You have a 4-Node cluster and set the HA admission control setting to cluster resource percentage and you want to tolerate 1 host failure. vSphere sets the percentages to 25% for CPU and Memory. If you now go ahead and add one host those settings are automatically updated to 20% memory and cpu.Anyways, the customer wanted that feature because he does that quite often (adding/removing hosts) but he could not update to 6.5 for a couple of reasons (Hardware compatibility and 3rd party software that integrates into vCenter, etc). So he asked me if there was a way to get that feature without updating. My response was: "Everything is possible with PowerCLI".So, long story, here is the script to backport this 6.5 feature to 6.0. Now, you'd have to call this script every time a change of hosts has occurred in your clusters, or you could let it run twice a day or something (still not as elegant as the 6.5 feature, but close enough).Update: this script is now published at [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts).Oh, almost forgot: This script uses the [PSLogging](https://www.powershellgallery.com/packages/PSLogging/2.5.2) Module that is available from the powershellgallery.```powershell#---------------------------------------------------------[Script Parameters]------------------------------------------------------Param ( #Script parameters go here [Parameter(Mandatory = $true)][string]$vCenter, [Parameter(Mandatory = $true)][string]$cluster, [Parameter(Mandatory = $true)][string]$failuresToTolerate)#---------------------------------------------------------[Initialisations]--------------------------------------------------------#Set Error Action to Silently Continue$ErrorActionPreference = 'SilentlyContinue'#Import Modules & Snap-insImport-Module PSLogging#----------------------------------------------------------[Declarations]----------------------------------------------------------#Script Version$sScriptVersion = '1.0'#Log File Info$sLogPath = 'C:\Temp'$sLogName = 'HA_AdmissionControlLog.log'$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName#-----------------------------------------------------------[Functions]------------------------------------------------------------Function Connect-VMwareServer { Param ([Parameter(Mandatory = $true)][string]$VMServer) Begin { Write-LogInfo -LogPath $sLogFile -Message "Connecting to vCenter Server [$VMServer]..." } Process { Try { $oCred = Get-Credential -Message 'Enter credentials to connect to vCenter Server' Connect-VIServer -Server $VMServer -Credential $oCred -ErrorAction Stop } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}Function checkRAMCompliance { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same amount of RAM..." $myHostsRAM = @() } Process { Try { $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop foreach ($hostObject in $hostObjects) { $HostInfoMEM = "" | Select-Object MEM $HostInfoMEM.MEM = $hostObject.MemoryTotalGB $myHostsRAM += $HostInfoMEM } #Check if all values are correct: return true, otherwise return false if (@($myHostsRAM | Select-Object -Unique).Count -eq 1) { #CPU are the same Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is the same" return $true } else { Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is NOT the same" return $false } } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}Function checkCPUCompliance { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same CPU..." $myHostsCPU = @() } Process { Try { $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop foreach ($hostObject in $hostObjects) { $HostInfoCPU = "" | Select-Object CPU $HostInfoCPU.CPU = $hostObject.CpuTotalMhz $myHostsCPU += $HostInfoCPU } #Check if all values are correct: return true, otherwise return false if (@($myHostsCPU | Select-Object -Unique).Count -eq 1) { Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is the same" return $true } else { Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is NOT the same" return $false } } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}Function getBiggestCPUInCluster { Param ([Parameter(Mandatory=$true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest CPU resource in cluster [$clusterName]..." } Process { Try { $clusterObject = Get-Cluster $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop $cpuResources = @() foreach ($hostObject in $hostObjects) { $cpuInfo = "" | Select-Object CPU $cpuInfo.CPU = $hostObject.CpuTotalMhz $cpuResources += $cpuInfo } return ($cpuResources | Measure-Object -Maximum) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function getBiggestRAMInCluster { Param ([Parameter(Mandatory=$true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest RAM resource in cluster [$clusterName]..." } Process { Try { $clusterObject = Get-Cluster $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop $ramResources = @() foreach ($hostObject in $hostObjects) { $ramInfo = "" | Select-Object RAM $ramInfo.RAM = $hostObject.MemoryTotalGB $ramResources += $ramInfo } return ($ramResources | Measure-Object -Maximum) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } }Function SetAdmissionControl { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Setting the admission policy on cluster [$clusterName].." } Process { Try { $RAMCompliance = checkRAMCompliance $clusterName $CPUCompliance = checkCPUCompliance $clusterName $totalAmountofHostsInCluster = (Get-Cluster -Name $clusterName -ErrorAction Stop | Get-VMHost -ErrorAction Stop).Count if (($RAMCompliance -eq $true) -and ($CPUCompliance -eq $true)) { #Same hardware. calculation very simple [int]$ramPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0) [int]$cpuPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0) } if ($CPUCompliance -eq $false) { #calculate with different CPU resources but same RAM resources #get biggest CPU amount, total amount and number of hosts in cluster $biggestCPUValue = getBiggestCPUInCluster $clusterName $totalCPUMhz = (Get-Cluster $clusterName).ExtensionData.Summary.TotalCPU [int]$cpuPercentageToReserve = [math]::Round(((($biggestCPUValue) * 100) / ($totalCPUMhz)*($failuresToTolerate)),0) } if ($RAMCompliance -eq $false) { #in this case RAM is the decisive factor #get biggest RAM amount, total amount and number of hosts in cluster $biggestMemoryValue = getBiggestRAMInCluster $clusterName $totalMemoryGB = [math]::Round(((Get-Cluster $clusterName).ExtensionData.Summary.TotalMemory /1024 /1024 /1024),0) [int]$ramPercentageToReserve = [math]::Round(((($biggestMemoryValue) * 100) / ($totalMemoryGB)*($failuresToTolerate)),0) } Write-LogInfo -LogPath $sLogFile -Message "CPU Value calculated: [$cpuPercentageToReserve].." Write-LogInfo -LogPath $sLogFile -Message "RAM Value calculated: [$ramPercentageToReserve].." $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo $spec.dasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy $spec.dasConfig.AdmissionControlEnabled = $true $spec.dasConfig.AdmissionControlPolicy.cpuFailoverResourcesPercent = $cpuPercentageToReserve $spec.dasConfig.AdmissionControlPolicy.memoryFailoverResourcesPercent = $ramPercentageToReserve $clusterObject = Get-Cluster $clusterName $clusterView = Get-View $clusterObject $clusterView.ReconfigureComputeResource_Task($spec, $true) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}#-----------------------------------------------------------[Execution]------------------------------------------------------------Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersionConnect-VMwareServer -VMServer $vCenterSetAdmissionControl -clusterName $clusterStop-Log -LogPath $sLogFile```'''[status]corpus = 267[[status.alsoLike]]ref = "posts/vmware-explore-las-vegas-hackathon-2025"score = "1.00"[[status.alsoLike]]ref = "posts/vmware-hackathon-2024-project"score = "1.00"[[status.alsoLike]]ref = "solutions/vmware/vmware-cloud-foundation/addon/application-services"score = "0.60"
<?xml version="1.0" encoding="UTF-8"?><manifest kind="Post"> <apiVersion>soultec.ch/v1</apiVersion> <metadata> <name>powercli-change-admission-control-percentages</name> <locale>en</locale> <labels> <author>dario-doerflinger</author> <series>scripting</series> <entry key="capability/automation">1.78</entry> <entry key="vendor/vmware">0.88</entry> </labels> <annotations> <source>blog-content/posts/en/powercli-change-admission-control-percentages.md</source> <route>/en/insights/powercli-change-admission-control-percentages/</route> <schema>/nerd/schema/posts.json</schema> <markdown>/en/insights/powercli-change-admission-control-percentages.md</markdown> </annotations> </metadata> <spec> <title>Change Admission Control Percentages</title> <date>2018-06-05</date> <author>dario-doerflinger</author> <locale>en</locale> <summary>I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment.</summary> <capabilities> <item>automation</item> </capabilities> <vendors> <item>vmware</item> </vendors> <series>scripting</series> <legacySlug>powercli-change-admission-control-percentages</legacySlug> <migrated>2026-08-24</migrated> <draft>false</draft> </spec> <sections> <section> <body>I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment. I knew the environment so I pointed out some things that 6.5 does better than the currently installed 6.0. One of those things I mentioned was the automated adjustment of the resource percentage in the HA admission control settings.For those of you who don't know: vSphere 6.5 does automatically change the resource percentage when you add or remove hosts to a cluster. For example: You have a 4-Node cluster and set the HA admission control setting to cluster resource percentage and you want to tolerate 1 host failure. vSphere sets the percentages to 25% for CPU and Memory. If you now go ahead and add one host those settings are automatically updated to 20% memory and cpu.Anyways, the customer wanted that feature because he does that quite often (adding/removing hosts) but he could not update to 6.5 for a couple of reasons (Hardware compatibility and 3rd party software that integrates into vCenter, etc). So he asked me if there was a way to get that feature without updating. My response was: "Everything is possible with PowerCLI".So, long story, here is the script to backport this 6.5 feature to 6.0. Now, you'd have to call this script every time a change of hosts has occurred in your clusters, or you could let it run twice a day or something (still not as elegant as the 6.5 feature, but close enough).Update: this script is now published at [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts).Oh, almost forgot: This script uses the [PSLogging](https://www.powershellgallery.com/packages/PSLogging/2.5.2) Module that is available from the powershellgallery.```powershell#---------------------------------------------------------[Script Parameters]------------------------------------------------------Param ( #Script parameters go here [Parameter(Mandatory = $true)][string]$vCenter, [Parameter(Mandatory = $true)][string]$cluster, [Parameter(Mandatory = $true)][string]$failuresToTolerate)#---------------------------------------------------------[Initialisations]--------------------------------------------------------#Set Error Action to Silently Continue$ErrorActionPreference = 'SilentlyContinue'#Import Modules &amp; Snap-insImport-Module PSLogging#----------------------------------------------------------[Declarations]----------------------------------------------------------#Script Version$sScriptVersion = '1.0'#Log File Info$sLogPath = 'C:\Temp'$sLogName = 'HA_AdmissionControlLog.log'$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName#-----------------------------------------------------------[Functions]------------------------------------------------------------Function Connect-VMwareServer { Param ([Parameter(Mandatory = $true)][string]$VMServer) Begin { Write-LogInfo -LogPath $sLogFile -Message "Connecting to vCenter Server [$VMServer]..." } Process { Try { $oCred = Get-Credential -Message 'Enter credentials to connect to vCenter Server' Connect-VIServer -Server $VMServer -Credential $oCred -ErrorAction Stop } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}Function checkRAMCompliance { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same amount of RAM..." $myHostsRAM = @() } Process { Try { $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop foreach ($hostObject in $hostObjects) { $HostInfoMEM = "" | Select-Object MEM $HostInfoMEM.MEM = $hostObject.MemoryTotalGB $myHostsRAM += $HostInfoMEM } #Check if all values are correct: return true, otherwise return false if (@($myHostsRAM | Select-Object -Unique).Count -eq 1) { #CPU are the same Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is the same" return $true } else { Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is NOT the same" return $false } } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}Function checkCPUCompliance { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same CPU..." $myHostsCPU = @() } Process { Try { $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop foreach ($hostObject in $hostObjects) { $HostInfoCPU = "" | Select-Object CPU $HostInfoCPU.CPU = $hostObject.CpuTotalMhz $myHostsCPU += $HostInfoCPU } #Check if all values are correct: return true, otherwise return false if (@($myHostsCPU | Select-Object -Unique).Count -eq 1) { Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is the same" return $true } else { Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is NOT the same" return $false } } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}Function getBiggestCPUInCluster { Param ([Parameter(Mandatory=$true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest CPU resource in cluster [$clusterName]..." } Process { Try { $clusterObject = Get-Cluster $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop $cpuResources = @() foreach ($hostObject in $hostObjects) { $cpuInfo = "" | Select-Object CPU $cpuInfo.CPU = $hostObject.CpuTotalMhz $cpuResources += $cpuInfo } return ($cpuResources | Measure-Object -Maximum) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } } Function getBiggestRAMInCluster { Param ([Parameter(Mandatory=$true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest RAM resource in cluster [$clusterName]..." } Process { Try { $clusterObject = Get-Cluster $clusterName -ErrorAction Stop $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop $ramResources = @() foreach ($hostObject in $hostObjects) { $ramInfo = "" | Select-Object RAM $ramInfo.RAM = $hostObject.MemoryTotalGB $ramResources += $ramInfo } return ($ramResources | Measure-Object -Maximum) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } } }Function SetAdmissionControl { Param ([Parameter(Mandatory = $true)][string]$clusterName) Begin { Write-LogInfo -LogPath $sLogFile -Message "Setting the admission policy on cluster [$clusterName].." } Process { Try { $RAMCompliance = checkRAMCompliance $clusterName $CPUCompliance = checkCPUCompliance $clusterName $totalAmountofHostsInCluster = (Get-Cluster -Name $clusterName -ErrorAction Stop | Get-VMHost -ErrorAction Stop).Count if (($RAMCompliance -eq $true) -and ($CPUCompliance -eq $true)) { #Same hardware. calculation very simple [int]$ramPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0) [int]$cpuPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0) } if ($CPUCompliance -eq $false) { #calculate with different CPU resources but same RAM resources #get biggest CPU amount, total amount and number of hosts in cluster $biggestCPUValue = getBiggestCPUInCluster $clusterName $totalCPUMhz = (Get-Cluster $clusterName).ExtensionData.Summary.TotalCPU [int]$cpuPercentageToReserve = [math]::Round(((($biggestCPUValue) * 100) / ($totalCPUMhz)*($failuresToTolerate)),0) } if ($RAMCompliance -eq $false) { #in this case RAM is the decisive factor #get biggest RAM amount, total amount and number of hosts in cluster $biggestMemoryValue = getBiggestRAMInCluster $clusterName $totalMemoryGB = [math]::Round(((Get-Cluster $clusterName).ExtensionData.Summary.TotalMemory /1024 /1024 /1024),0) [int]$ramPercentageToReserve = [math]::Round(((($biggestMemoryValue) * 100) / ($totalMemoryGB)*($failuresToTolerate)),0) } Write-LogInfo -LogPath $sLogFile -Message "CPU Value calculated: [$cpuPercentageToReserve].." Write-LogInfo -LogPath $sLogFile -Message "RAM Value calculated: [$ramPercentageToReserve].." $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo $spec.dasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy $spec.dasConfig.AdmissionControlEnabled = $true $spec.dasConfig.AdmissionControlPolicy.cpuFailoverResourcesPercent = $cpuPercentageToReserve $spec.dasConfig.AdmissionControlPolicy.memoryFailoverResourcesPercent = $ramPercentageToReserve $clusterObject = Get-Cluster $clusterName $clusterView = Get-View $clusterObject $clusterView.ReconfigureComputeResource_Task($spec, $true) } Catch { Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully Break } } End { If ($?) { Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.' Write-LogInfo -LogPath $sLogFile -Message ' ' } }}#-----------------------------------------------------------[Execution]------------------------------------------------------------Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersionConnect-VMwareServer -VMServer $vCenterSetAdmissionControl -clusterName $clusterStop-Log -LogPath $sLogFile``` </body> </section> </sections> <status> <corpus>267</corpus> <alsoLike> <item> <ref>posts/vmware-explore-las-vegas-hackathon-2025</ref> <score>1.00</score> </item> <item> <ref>posts/vmware-hackathon-2024-project</ref> <score>1.00</score> </item> <item> <ref>solutions/vmware/vmware-cloud-foundation/addon/application-services</ref> <score>0.60</score> </item> </alsoLike> </status></manifest>
Scripting · 2018-06-05

Change Admission Control Percentages

I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment.

2018-06-05Date
Dario DörflingerAuthor
6Min read
Topics Automation 1.78
Vendors VMware 0.88

This post is from 2018. It stays online because people still look for it, but it describes the products as they were then.

I was recently asked by a customer to explain some of the vSphere 6.5 features that would be interesting for his environment. I knew the environment so I pointed out some things that 6.5 does better than the currently installed 6.0. One of those things I mentioned was the automated adjustment of the resource percentage in the HA admission control settings.

For those of you who don’t know: vSphere 6.5 does automatically change the resource percentage when you add or remove hosts to a cluster. For example: You have a 4-Node cluster and set the HA admission control setting to cluster resource percentage and you want to tolerate 1 host failure. vSphere sets the percentages to 25% for CPU and Memory. If you now go ahead and add one host those settings are automatically updated to 20% memory and cpu.

Anyways, the customer wanted that feature because he does that quite often (adding/removing hosts) but he could not update to 6.5 for a couple of reasons (Hardware compatibility and 3rd party software that integrates into vCenter, etc). So he asked me if there was a way to get that feature without updating. My response was: “Everything is possible with PowerCLI”.

So, long story, here is the script to backport this 6.5 feature to 6.0. Now, you’d have to call this script every time a change of hosts has occurred in your clusters, or you could let it run twice a day or something (still not as elegant as the 6.5 feature, but close enough).

Update: this script is now published at GitHub.

Oh, almost forgot: This script uses the PSLogging Module that is available from the powershellgallery.


#---------------------------------------------------------[Script Parameters]------------------------------------------------------

Param (
    #Script parameters go here
    [Parameter(Mandatory = $true)][string]$vCenter,
    [Parameter(Mandatory = $true)][string]$cluster,
    [Parameter(Mandatory = $true)][string]$failuresToTolerate
)

#---------------------------------------------------------[Initialisations]--------------------------------------------------------

#Set Error Action to Silently Continue
$ErrorActionPreference = 'SilentlyContinue'

#Import Modules & Snap-ins
Import-Module PSLogging

#----------------------------------------------------------[Declarations]----------------------------------------------------------

#Script Version
$sScriptVersion = '1.0'

#Log File Info
$sLogPath = 'C:\Temp'
$sLogName = 'HA_AdmissionControlLog.log'
$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName

#-----------------------------------------------------------[Functions]------------------------------------------------------------

Function Connect-VMwareServer {
    Param ([Parameter(Mandatory = $true)][string]$VMServer)

    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Connecting to vCenter Server [$VMServer]..."
    }

    Process {
        Try {
            $oCred = Get-Credential -Message 'Enter credentials to connect to vCenter Server'
            Connect-VIServer -Server $VMServer -Credential $oCred -ErrorAction Stop
        }

        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }

    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

Function checkRAMCompliance {
    Param ([Parameter(Mandatory = $true)][string]$clusterName)
    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same amount of RAM..."
        $myHostsRAM = @()
    }
    Process {
        Try {
            $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop
            $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop

            foreach ($hostObject in $hostObjects) {

                $HostInfoMEM = "" | Select-Object MEM

                $HostInfoMEM.MEM = $hostObject.MemoryTotalGB

                $myHostsRAM += $HostInfoMEM
            }
            #Check if all values are correct: return true, otherwise return false
            if (@($myHostsRAM | Select-Object -Unique).Count -eq 1) {
                #CPU are the same
                Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is the same"
                return $true
            }
            else {
                Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is NOT the same"
                return $false
            }

        }
        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }
    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

Function checkCPUCompliance {
    Param ([Parameter(Mandatory = $true)][string]$clusterName)
    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same CPU..."
        $myHostsCPU = @()
    }
    Process {
        Try {
            $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop
            $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop

            foreach ($hostObject in $hostObjects) {
                $HostInfoCPU = "" | Select-Object CPU

                $HostInfoCPU.CPU = $hostObject.CpuTotalMhz

                $myHostsCPU += $HostInfoCPU
            }
            #Check if all values are correct: return true, otherwise return false

            if (@($myHostsCPU | Select-Object -Unique).Count -eq 1) {
                Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is the same"
                return $true
            }
            else {
                Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is NOT the same"
                return $false
            }

        }
        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }
    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

Function getBiggestCPUInCluster {
    Param ([Parameter(Mandatory=$true)][string]$clusterName)
    Begin {
      Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest CPU resource in cluster [$clusterName]..."
    }
    Process {
      Try {
        $clusterObject = Get-Cluster $clusterName -ErrorAction Stop
        $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop
        $cpuResources =  @()
        foreach ($hostObject in $hostObjects) {
            $cpuInfo = "" | Select-Object CPU
            $cpuInfo.CPU = $hostObject.CpuTotalMhz

            $cpuResources += $cpuInfo
        }
        return ($cpuResources | Measure-Object -Maximum)

      }
      Catch {
        Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
        Break
      }
    }
    End {
      If ($?) {
        Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
        Write-LogInfo -LogPath $sLogFile -Message ' '
      }
    }
  }

  Function getBiggestRAMInCluster {
    Param ([Parameter(Mandatory=$true)][string]$clusterName)
    Begin {
      Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest RAM resource in cluster [$clusterName]..."
    }
    Process {
      Try {
        $clusterObject = Get-Cluster $clusterName -ErrorAction Stop
        $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop
        $ramResources =  @()
        foreach ($hostObject in $hostObjects) {
            $ramInfo = "" | Select-Object RAM
            $ramInfo.RAM = $hostObject.MemoryTotalGB

            $ramResources += $ramInfo
        }
        return ($ramResources | Measure-Object -Maximum)

      }
      Catch {
        Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
        Break
      }
    }
    End {
      If ($?) {
        Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
        Write-LogInfo -LogPath $sLogFile -Message ' '
      }
    }
  }

Function SetAdmissionControl {
    Param ([Parameter(Mandatory = $true)][string]$clusterName)
    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Setting the admission policy on cluster [$clusterName].."
    }
    Process {
        Try {
            $RAMCompliance = checkRAMCompliance $clusterName
            $CPUCompliance = checkCPUCompliance $clusterName
            $totalAmountofHostsInCluster = (Get-Cluster -Name $clusterName -ErrorAction Stop | Get-VMHost -ErrorAction Stop).Count
            if (($RAMCompliance -eq $true) -and ($CPUCompliance -eq $true)) {
                #Same hardware. calculation very simple
                [int]$ramPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0)
                [int]$cpuPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0)

            }
            if ($CPUCompliance -eq $false) {
                #calculate with different CPU resources but same RAM resources
                #get biggest CPU amount, total amount and number of hosts in cluster
                $biggestCPUValue = getBiggestCPUInCluster $clusterName
                $totalCPUMhz = (Get-Cluster $clusterName).ExtensionData.Summary.TotalCPU

                [int]$cpuPercentageToReserve = [math]::Round(((($biggestCPUValue) * 100) / ($totalCPUMhz)*($failuresToTolerate)),0)
            }
            if ($RAMCompliance -eq $false) {
                #in this case RAM is the decisive factor
                #get biggest RAM amount, total amount and number of hosts in cluster
                $biggestMemoryValue = getBiggestRAMInCluster $clusterName
                $totalMemoryGB = [math]::Round(((Get-Cluster $clusterName).ExtensionData.Summary.TotalMemory /1024 /1024 /1024),0)

                [int]$ramPercentageToReserve = [math]::Round(((($biggestMemoryValue) * 100) / ($totalMemoryGB)*($failuresToTolerate)),0)
            }

            Write-LogInfo -LogPath $sLogFile -Message "CPU Value calculated: [$cpuPercentageToReserve].."
            Write-LogInfo -LogPath $sLogFile -Message "RAM Value calculated: [$ramPercentageToReserve].."

            $spec = New-Object VMware.Vim.ClusterConfigSpecEx
            $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
            $spec.dasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
            $spec.dasConfig.AdmissionControlEnabled = $true
            $spec.dasConfig.AdmissionControlPolicy.cpuFailoverResourcesPercent = $cpuPercentageToReserve
            $spec.dasConfig.AdmissionControlPolicy.memoryFailoverResourcesPercent = $ramPercentageToReserve

            $clusterObject = Get-Cluster $clusterName
            $clusterView =  Get-View $clusterObject
            $clusterView.ReconfigureComputeResource_Task($spec, $true)

        }
        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }
    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

#-----------------------------------------------------------[Execution]------------------------------------------------------------

Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersion
Connect-VMwareServer -VMServer $vCenter
SetAdmissionControl -clusterName $cluster
Stop-Log -LogPath $sLogFile

You might also like