Last active
April 26, 2022 02:04
-
-
Save abix-/a8ffdaaa3d9dd1206cd112ac64fb9b3e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Optimize-DRSSeparateVMs { | |
<# | |
.SYNOPSIS | |
Creates DRS rules to keep similar VMs on separate VMHosts.Existing AntiAffinity rules are removed. | |
If VMHosts.count is less than or equal to 4, the max VMs per group is count-1. Otherwise count-2 | |
.EXAMPLE | |
Create DRS rules on MYCLUSTER | |
Optimize-DRSSeparateVMs -Cluster MYCLUSTER | |
.EXAMPLE | |
Create DRS rules on all clusters | |
Get-Cluster | Sort Name | %{ Optimize-DRSSeparateVMs -Cluster $_.Name } | |
#> | |
[cmdletbinding()] | |
param ( | |
[Parameter(Mandatory=$true)] | |
[string]$Cluster, | |
[string]$ExclusionFilter = "*Veeam*" | |
) | |
try { | |
$ErrorActionPreference = "STOP" | |
# Get Cluster object | |
$ClusterObj = Get-cluster -Name $Cluster | |
# Remove existing VMAntiAffinity rules that dont match exclusion filter | |
Get-Drsrule -Cluster $ClusterObj | Where-Object { $_.Name -notlike $ExclusionFilter -and $_.Type -eq "VMAntiAffinity" } | Remove-DrsRule -Confirm:$false | |
# Get VMs in Cluster except for VMware DRS VMs and Veeam replicas | |
$vms = $ClusterObj | get-vm | Sort-Object name | Where-Object { $_.name -notlike "*vcls*" -and $_.name -notlike "*replica*" } | |
# Get VMHost in Cluster | |
$vmhosts = @($ClusterObj | get-vmhost) | |
if($vmhosts.count -le 4) { | |
# Max VMs per group. Less than count to minimize issues with maintenance/failed VMHosts | |
$max = $vmhosts.count - 1 | |
} else { | |
$max = $vmhosts.count - 2 | |
} | |
# Determine VM Type from characters 3-7 in VMName | |
$vms | ForEach-Object { Add-Member -InputObject $_ -MemberType NoteProperty -Name Type -Value ($_.Name.Substring(3,4)) -Force } | |
# Group VMs by Type. DRS groups are not needed with only 1 VM | |
$groups = $vms | Group-Object -Property Type | Where-Object { $_.Count -gt 1 } | |
# Split groups based on maximum of VMHosts-2 VMs per group | |
$groups2 = foreach ($group in $groups) { | |
Write-Host "Processing $($Group.Name)" | |
# If group is greater than number of vmhosts then create multiple groups | |
if ($group.count -gt $max) { | |
# Counter for DRS rule index | |
$index = 1 | |
for ($skip = 0; $skip -lt $group.group.count; $skip += $max) { | |
$members = $group.group | Select-Object -First $max -Skip $skip | |
if ($members.count -ne 1) { | |
[pscustomobject]@{ | |
Count = $vmhosts.count | |
Name = $group.Name | |
Group = $members | |
Counter = $index | |
} | |
$index++ | |
} | |
else { | |
Write-Host "Only 1 member for $($group.Name + $index). No DRS rule needed" | |
} | |
} | |
} | |
else { | |
$group | |
} | |
} | |
# Create DRS rules from groups | |
foreach($group in $groups2) { | |
if($null -ne $group.Counter) { | |
$newName = "$($group.Name.ToUpper()) on Separate Hosts - $($group.Counter)" | |
} else { | |
$newName = "$($group.Name.ToUpper()) on Separate Hosts" | |
} | |
Write-Host "$($ClusterObj.Name)`: Creating $newName" | |
New-DrsRule -Cluster $ClusterObj -Name "$newName" -KeepTogether:$false -VM $group.group | |
} | |
} | |
catch { | |
throw | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment