Ops Note — Picking the best vSAN host with one PowerCLI check

Excerpt
Quick, repeatable way to see CPU/RAM/vSAN headroom across hosts and choose where to place the next VM. Today it pointed us to vsan2.


Intro
Before cloning a new Windows VM, I ran a fast PowerCLI sweep across three vSAN hosts to compare free CPU, free memory, and vSAN free space. All three had identical vSAN capacity; vsan2 had the most free RAM, so that’s the landing spot.


Straight line (what I did)
• Pulled CPU and memory usage per host (MHz/MB) and calculated free.
• Queried each host’s vSAN datastore(s) and summed free/total GB.
• Printed a compact table to compare vsan1/2/3 at a glance.
• Chose the host with the highest Mem_Free_GB (tie-break on vSAN free).


Command (copy/paste)

# Hosts to check (redacted)
$hosts = 'vsan1.example.local','vsan2.example.local','vsan3.example.local'

$report = foreach ($h in $hosts) {
  try {
    $vmh    = Get-VMHost -Name $h -ErrorAction Stop
    $cpuTot = $vmh.CpuTotalMhz;  $cpuUse = $vmh.CpuUsageMhz
    $memTot = $vmh.MemoryTotalMB; $memUse = $vmh.MemoryUsageMB

    $vsan      = $vmh | Get-Datastore | Where-Object { $_.Type -eq 'vsan' }
    $dsCapGB   = ($vsan | Measure-Object CapacityGB  -Sum).Sum
    $dsFreeGB  = ($vsan | Measure-Object FreeSpaceGB -Sum).Sum
    $dsFreePct = if ($dsCapGB) { [math]::Round(100*($dsFreeGB/$dsCapGB),2) } else { 0 }

    [pscustomobject]@{
      Host          = $vmh.Name
      CPU_Free_GHz  = [math]::Round(($cpuTot-$cpuUse)/1000,2)
      CPU_Total_GHz = [math]::Round($cpuTot/1000,2)
      CPU_Free_pct  = if ($cpuTot) { [math]::Round(100*(($cpuTot-$cpuUse)/$cpuTot),2) } else { 0 }
      Mem_Free_GB   = [math]::Round(($memTot-$memUse)/1024,2)
      Mem_Total_GB  = [math]::Round($memTot/1024,2)
      Mem_Free_pct  = if ($memTot) { [math]::Round(100*(($memTot-$memUse)/$memTot),2) } else { 0 }
      vSAN_Free_GB  = [math]::Round($dsFreeGB,2)
      vSAN_Total_GB = [math]::Round($dsCapGB,2)
      vSAN_Free_pct = $dsFreePct
    }
  } catch {
    [pscustomobject]@{ Host=$h; CPU_Free_GHz='n/a'; CPU_Total_GHz='n/a'; CPU_Free_pct='n/a';
      Mem_Free_GB='n/a'; Mem_Total_GB='n/a'; Mem_Free_pct='n/a';
      vSAN_Free_GB='n/a'; vSAN_Total_GB='n/a'; vSAN_Free_pct='n/a' }
  }
}

$report | Format-Table -AutoSize

# Optional: pick best host by RAM, then vSAN GB
$best = $report | Where-Object { $_.Mem_Free_GB -is [double] } |
        Sort-Object Mem_Free_GB, vSAN_Free_GB -Descending | Select-Object -First 1
"Suggested placement: $($best.Host) (Mem free: $($best.Mem_Free_GB) GB, vSAN free: $($best.vSAN_Free_GB) GB)"

Result today
• vsan2 showed the most free RAM, with CPU headroom similar across all three and identical vSAN free space.
• Suggested placement: vsan2.


Pocket I’m keeping
• Check host headroom before every clone—30 seconds now saves hours later.
• Prefer RAM headroom for Windows VDI/worker VMs; CPU is usually similar across nodes.
• Keep a one-liner that prints the table and the suggested host.


What I hear now
Clone to vsan2, power up, then let DRS/vMotion rebalance after the build window. Repeat this check whenever adding workloads or after maintenance.

© 2012–2025 Jet Mariano. All rights reserved.
For usage terms, please see the Legal Disclaimer.

error: Content is protected !!