Skip to content

Instantly share code, notes, and snippets.

@abix-
Last active April 26, 2022 02:04
Show Gist options
  • Save abix-/a8ffdaaa3d9dd1206cd112ac64fb9b3e to your computer and use it in GitHub Desktop.
Save abix-/a8ffdaaa3d9dd1206cd112ac64fb9b3e to your computer and use it in GitHub Desktop.
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