HVDRS
1.7.0
Hyper-V Distributed Resource Scheduler — VM Happiness-based compute and storage load balancing for Failover Clusters, with affinity/anti-affinity rule enforcement
Minimum PowerShell version
5.1
Installation Options
Owners
Copyright
(c) 2026 Jason Huebel. Licensed under the MIT License.
Package Details
Author(s)
- Jason Huebel
Tags
Hyper-V HyperV DRS FailoverCluster LoadBalancing VirtualMachine VM LiveMigration StorageMigration CSV ClusterSharedVolume Affinity WindowsServer Automation
Functions
Invoke-HvDRS Get-HvDRSCluster Enable-HvDRSMaintenance Disable-HvDRSMaintenance Get-HvDRSMaintenanceStatus Enter-HvDRSNodeMaintenance Exit-HvDRSNodeMaintenance Get-HvDRSNodeMaintenanceStatus Add-HvDRSAffinityRule Get-HvDRSAffinityRule Remove-HvDRSAffinityRule Set-HvDRSAffinityRule Test-HvDRSAffinityCompliance Test-HvDRSStorageAffinityCompliance Add-HvDRSGroup Get-HvDRSGroup Remove-HvDRSGroup Set-HvDRSGroup Set-HvDRSVMAutomationLevel Get-HvDRSVMAutomationLevel Remove-HvDRSVMAutomationLevel Get-HvDRSCapacityForecast Invoke-HvStorageDRS
Dependencies
This module has no dependencies.
Release Notes
## 1.7.0
- Fixed several correctness bugs in the compute and storage DRS planners:
rule-impact checks now use a live simulated placement, so a second
migration planned in the same pass sees the moves the first one already
made instead of stale snapshot data. A hard affinity/anti-affinity
violation spanning 3 or more VMs (e.g. three VMs sharing one host under an
enforced anti-affinity rule) is now actually resolved, with as many moves
as needed, instead of being reported unfixable forever because no single
move could fully satisfy it. The storage happiness planner no longer
"fixes" one CSV by pushing another below the aggression threshold, and
keeps moving VMs off a badly-unhappy CSV until it recovers instead of
stopping after one move. VMs pinned to Manual automation are now excluded
from planning entirely, not just skipped at execution after already being
chosen as the fix for a hard-rule violation.
- Fixed the possible-owner lookup querying the wrong cluster object
(Get-ClusterOwnerNode -Group instead of -Resource), which meant the
possible-owner constraint documented in the README never actually applied.
- Fixed Invoke-HvStorageDRS's ConfirmImpact ('High') blocking scheduled
-NonInteractive runs, and storage moves colliding when two VMs' VHDs
shared a file name — moves now land in a per-VM destination folder.
- Fixed the Network-Aware gate double-counting Hyper-V virtual switch
adapter traffic (now -Physical-only), CSV path matching colliding between
e.g. "Volume1" and "Volume10", and per-VHD size using the maximum virtual
size instead of actual on-disk footprint.
- Enter-HvDRSNodeMaintenance now holds the HVDRS maintenance lock for the
duration of an evacuation — closing a race with a concurrently-scheduled
Invoke-HvDRS/Invoke-HvStorageDRS pass — via a new -MaintenanceLockFile
parameter, and reports any stopped VM or non-VM cluster role left on the
node via a new OtherRolesOnNode property instead of silently ignoring them.
- Fixed -TrendWindow smoothing persisting to the shared history file under
-WhatIf, and added an automatic history reset after a pass that actually
migrates a VM so smoothing doesn't keep pulling toward a placement that no
longer exists.
- Fixed Test-HvDRSAffinityCompliance / Test-HvDRSStorageAffinityCompliance
leaking Format-Table's own formatting objects into their return value.
- The rules/groups/automation-overrides JSON stores now fail closed (throw)
when the file exists but is corrupt, instead of silently treating it as
"nothing configured" — which previously risked the next rule/group/
override edit overwriting the corrupt file and permanently losing
everything in it.
- Expanded the test suite substantially to cover all of the above.
## 1.6.1
- Fixed latent bugs, of the same class fixed in 1.5.1, that only surfaced under
Set-StrictMode (which the publish pipeline enables) and were caught while
preparing this release:
- Invoke-HvStorageDRS and Test-HvDRSStorageAffinityCompliance both piped
Get-AffinityRuleSet's output directly into Where-Object to filter storage
rule types. When no rules are configured at all, this threw under strict
mode — PowerShell enumerates the ",@()" empty-result wrapper as a single
pipeline item when piped directly (rather than assigned to a variable
first), so the Where-Object script block's $_.Type access failed. Both
call sites now capture into a variable before filtering.
- Get-HvDRSVMAutomationLevel's no-"-VMName" branch returned an empty result
without the leading-comma protection Get-AffinityRuleSet and similar
loaders use, so it collapsed to $null (and threw on .Count) when no
overrides were configured for a cluster.
- Get-HvDRSCapacityForecast's -RemoveNode path could return $null for
VMPlacements/NodeImpact instead of an empty array when a node has no VMs
or a cluster has only one remaining node.
No production behavior changes for callers who already handled populated
results correctly — these only affected the zero-result / no-rules-configured
edge cases under strict-mode callers.
## 1.6.0
- Added -TrendWindow / -HistoryPath to Invoke-HvDRS: optional rolling-average
smoothing of node CPU/network utilization and VM CPU/memory-pressure across
consecutive passes, so a single transient spike doesn't trigger a migration.
Disabled by default (-TrendWindow 1) — zero behavior change unless opted in.
- Added Enter-HvDRSNodeMaintenance / Exit-HvDRSNodeMaintenance /
Get-HvDRSNodeMaintenanceStatus: happiness-aware node evacuation (a Hyper-V
analog of vSphere's "Enter Maintenance Mode") that live-migrates every VM off
a node using the same Network-Aware/memory-reserve/affinity-rule destination
selection as Invoke-HvDRS, then pauses the node — or refuses to pause it if
any VM couldn't be placed.
- Added VM/Host/CSV Groups (Add/Get/Remove/Set-HvDRSGroup) and new
-VMGroups/-HostGroups/-CSVGroups parameters on Add/Set-HvDRSAffinityRule:
reusable named groups that affinity rules can reference instead of listing
members directly. Group membership resolves dynamically at rule-load time —
editing a group takes effect immediately, with no rule re-save needed.
- Added per-VM automation-level overrides (Set/Get/Remove-HvDRSVMAutomationLevel):
pin specific VMs to Manual so Invoke-HvDRS/Invoke-HvStorageDRS keep scoring
and recommending them but never execute a migration/move for them.
- Added Get-HvDRSCapacityForecast: read-only what-if capacity analysis —
simulate draining a node (-RemoveNode) to check whether every VM on it has a
valid destination, or simulate adding a hypothetical node (-AddNode) to see
which currently-unhappy VMs it could absorb.
- Added -WebhookUrl / -WriteEventLog to Invoke-HvDRS and Invoke-HvStorageDRS:
optional JSON webhook POST and/or Windows Application event log entry
summarizing each pass. A notification failure is logged as a warning and
never fails an otherwise-successful pass.
- Added -PassThru to Invoke-HvStorageDRS (previously compute-only), and
extended the optional ProPack VMM PRO Tips integration to cover storage DRS
recommendations (ConvertTo-HvDrsStorageProTip, Resolve-VmmStorageIdentity,
Invoke-HvDrsStorageProTipProbe, and a parallel monitor/rule pair in the
Management Pack) — previously compute-only.
- Fixed a latent bug in Invoke-HvStorageDRS where its Format-Table calls were
never piped to Out-Host, so capturing its return value (now needed by
-PassThru) leaked PowerShell formatting objects onto the output stream. Same
class of bug already fixed for Invoke-HvDRS in 1.5.0.
- Moved all documentation except README.md into a new docs/ folder
(docs/INSTALL.md, docs/USAGE.md, docs/TESTS.md, docs/PUBLISH.md) and added
docs/ARCHITECTURE.md, a new technical design reference.
## 1.5.1
- Fixed three latent bugs where a zero-match result collapsed to $null instead
of an empty array/collection at a function or switch-expression output
boundary: Find-MigrationCandidates (no migrations recommended),
Get-HvDRSAffinityRule (no rules match a filter), and an internal switch-to-
variable assignment in the same function. These were silently tolerated by
PowerShell's default null.Count convenience behavior but threw under
Set-StrictMode, which the publish pipeline enables — surfaced while
preparing this release. No behavior change for non-strict-mode callers.
## 1.5.0
- Added -PassThru to Invoke-HvDRS: emits each migration recommendation as a structured
object (ClusterName, VMName, VMId, SourceNode, DestinationNode, scores, ComplianceReason)
in addition to the existing console output, for programmatic consumers. Fully additive
and backward compatible — omitting the switch preserves prior behavior.
- Fixed internal Format-Table calls leaking formatting objects onto the function's output
stream when callers capture Invoke-HvDRS's return value; they now render to the console
only via Out-Host.
## 1.4.0
- Added Get-HvDRSCluster: lightweight, read-only discovery of cluster nodes, VMs, and
Cluster Shared Volumes, with no performance-counter collection and no migrations proposed
## 1.3.0
- CRITICAL FIX: the module manifest was missing RootModule, so Import-Module HVDRS
never loaded HVDRS.psm1 and exported zero functions in every prior published
version. RootModule = 'HVDRS.psm1' is now set and the module works correctly.
- Fixed Get-AffinityRuleSet returning $null instead of an empty array on a fresh
rules store, which broke adding the very first affinity rule
- Added storage-specific affinity/anti-affinity rules: VmVmCsvAffinity, VmVmCsvAntiAffinity,
VmCsvAffinity, VmCsvAntiAffinity
- Add-HvDRSAffinityRule / Set-HvDRSAffinityRule accept -CSVs (and -AddCSVs/-RemoveCSVs)
- Invoke-HvStorageDRS now loads storage rules, runs a compliance pass ahead of the
happiness pass, and applies soft-rule penalties / compliance bonuses to candidate scoring
- Added Test-HvDRSStorageAffinityCompliance for live VM-to-CSV placement auditing
## 1.2.1
- Documentation only: promoted PowerShell Gallery install to the recommended option in INSTALL.md
- Updated README Quick Start to use Install-Module instead of Copy-Item
## 1.2.0
- Added per-cluster scoping for affinity/anti-affinity rules
- Rules stored in shared JSON file are now filtered by ClusterName at load time
- Add-HvDRSAffinityRule, Get-HvDRSAffinityRule, Remove-HvDRSAffinityRule all accept -ClusterName
- Same rule name may now exist independently across different clusters
## 1.1.0
- Added Storage DRS (Invoke-HvStorageDRS): CSV space and latency happiness scoring,
greedy storage migration planner, Move-VMStorage execution
- Added affinity/anti-affinity rules (VmVmAffinity, VmVmAntiAffinity, VmHostAffinity,
VmHostAntiAffinity) with hard (enforced) and soft enforcement modes
- Added two-pass migration planner: compliance pass fixes hard violations first,
happiness pass applies rule impact scoring
- Added Test-HvDRSAffinityCompliance for live placement auditing
## 1.0.0
- Initial release: VM Happiness scoring, compute DRS, Network-Aware destination
filtering, aggression levels 1–5, maintenance mode
FileList
- HVDRS.nuspec
- Functions\Private\Find-EvacuationDestination.ps1
- Functions\Private\Find-MigrationCandidates.ps1
- Functions\Private\Find-StorageMigrationCandidates.ps1
- Functions\Private\Get-AffinityRuleSet.ps1
- Functions\Private\Get-ClusterInventory.ps1
- Functions\Private\Get-ClusterSnapshot.ps1
- Functions\Private\Get-HvDRSAutomationOverrideSet.ps1
- Functions\Private\Get-HvDRSDataRoot.ps1
- Functions\Private\Get-HvDRSGroupSet.ps1
- Functions\Private\Get-MigrationRuleImpact.ps1
- Functions\Private\Get-StorageMigrationRuleImpact.ps1
- Functions\Private\Get-StorageSnapshot.ps1
- Functions\Private\Measure-CsvHappiness.ps1
- Functions\Private\Measure-VmHappiness.ps1
- Functions\Private\Merge-HvDRSTrendSnapshot.ps1
- Functions\Private\Send-HvDRSNotification.ps1
- Functions\Private\Test-AffinityCompliance.ps1
- Functions\Private\Test-StorageAffinityCompliance.ps1
- Functions\Public\AffinityRules.ps1
- Functions\Public\AutomationOverrides.ps1
- Functions\Public\Get-HvDRSCapacityForecast.ps1
- Functions\Public\Get-HvDRSCluster.ps1
- Functions\Public\Groups.ps1
- Functions\Public\Invoke-HvDRS.ps1
- Functions\Public\Invoke-HvStorageDRS.ps1
- Functions\Public\Maintenance.ps1
- HVDRS.psd1
- HVDRS.psm1
- LICENSE
- README.md
- docs\ARCHITECTURE.md
- docs\INSTALL.md
- docs\TESTS.md
- docs\USAGE.md