Evenly Distribute your VM's across your standalone Windows 8 Hyper-V Hosts using powershell

Interestingly enough the argument with people still happens about not wanting management tools for their system.

So I created this script as a basis which will load balance out VM's across multiple hosts using live migration

 

here is the code... I plan to "tweak" it a bit more to include some monitoring of core counters and trigger based on that. So essentially something like PRO in powershell! :)

 

For my scenario I have 480 vm's across 16 nodes running Windows 8 Datacenter With Hyper-V enabled (obviously!)

I worked out the amount of vm's per node that I require (but you could do an average calculation) and set the limits and yes I could use more variables :)

and you must have ps remoting turned on

 

# Created By John McCabe

# Email: johm@microsoft.com

#Twitter: mccabej

 

$hosts = $null
[array]$hosts += "bt001"
$hosts += "bt002"
$hosts += "bt003"
$hosts += "bt004"
$hosts += "bt005"
$hosts += "bt006"
$hosts += "bt007"
#$hosts += "bt008"
#$hosts += "bt009"
#$hosts += "bt010"
#$hosts += "bt011"
#$hosts += "bt012"
#$hosts += "bt013"
#$hosts += "bt014"
#$hosts += "bt015"
#$hosts += "bt016"
$min = 1
$destpath = "C:\VMSTORE\"
$VMPATH = "C:\VMSTORE\"

import-module hyper-v

foreach ($host1 in $hosts)
{

 write-host "checking host: `t" $host1
 $vms = get-vm -computername $host1
 $max = $vms.count
 
 
 if ($max -gt 35)
 {
  write-host "Host has more than 30 VMS"
  while ($max -gt 35)
  { 
   
   $vms = get-vm -computername $host1
   $max = $vms.count
   [int]$vmtomove = get-random -minimum $min -maximum $max
   $vmmove = $vms[$vmtomove]
   $vmname = $vmmove.name
   
   foreach ($hst in $hosts)
   {
 
    write-host "Checking which host we can move them to"
    write-host "Checking host:`t" $hst
    $vmsperhost = get-vm -computername $hst
    $noofvmperhost = $vmsperhost.count
   
    if ($noofvmperhost -lt 35)
    {

       write-host "Moving VM to Host:`t" $hst
      
       $servertomove = $hst
       $movepath = "\\" + $hst + "\c$\vmstore\" + $vmname
       $testdest = test-path $movepath
       if ($testdest -eq $false)
       {
     mkdir $movepath
       }
       $finalpath = $destpath + $vmname
    
       $session = new-pssession $host1
       invoke-command -session $session -scriptblock {import-module hyper-v}
       invoke-command -session $session -scriptblock {PARAM ($VM) $vmtomove = get-vm $vm} -argumentlist $vmname

       invoke-command -session $session -scriptblock {param ($destserver,$fpath) move-vm -vm $vmtomove -destinationhost $destserver -destinationstoragepath $fpath} -argumentlist $hst,$finalpath
       remove-pssession $session
 
     
     
    }
   }
  }
 }
}