VMware Host Cluster VM memory balancing script implementation

I recently found a replacement DRS script using PowerCLI from Scott Warren’s Blog http://www.scottwarren.info/2011/03/24/scripting-a-drs-replacement-using-powercli/

I wanted to run this as a daily task to ensure that my standard edition ESX cluster was load balanced.

Firstly I needed to create the folders on the Vcenter server to store the scripts and log files.

In the root directory C: I created two folders VMware Logs and Scheduled tasks.

You will need to download PowerCLI from VMware, ensure you download the correct version that matches your environment.

I then created two scripts.

1. Copy the powershell script from Scott Warrens blog in to the notepad and save as VMware Drs Script.ps1

Set-StrictMode -version 2

function GetPercentages(){
       # get all the hosts
       $objHosts = get-vmhost;

       # loop through each of the hosts and calculate the percentage of memory used
       foreach($objHost in $objHosts){
               $objHost | add-member NoteProperty PercentMemory ($objHost.MemoryUsageMB/$objHost.MemoryTotalMB *100)

function GetVMToMove($strHost, $arrAllVMs){
       #get all the VMs that are powered on on this host
       $objVMs = get-vm | where {($_.Host.Name -eq $strHost) -and ($_.PowerState -eq "PoweredOn")}

       # check to see if there is a static file
       if(test-path "balanced.csv"){
               # read in the static file
               $arrStatic = import-csv "balanced.csv"

               # loop through all the static entries
               foreach($objStatic in $arrStatic){
                       #echo $objStatic.VM;
                       $objVM = $objVM | where {$_.Name -ne ($objStatic.Name)}

       # sort based on the amount of memory used
       $objVMs = $objVMs | sort "Memory*"

       # return the VM using the least amount of RAM

# get all the VMs
$arrAllVMs = get-vm | where {$_.PowerState -eq "PoweredOn"}

# check to see if there is a static file
if(test-path "balanced2.csv"){
       # read in the static file
       $arrStatic = import-csv "balanced.csv"

       # move the static VMs to the correct location
       echo "Moving static VMs to the correct host."

       # loop through all the VMs
       foreach($objStatic in $arrStatic){
               # get the VM
               $objVM = get-VM $objStatic.Name;

               # check to see if the VM is not on the correct host
               if($objVM.Host.Name -ne $objStatic.Host){
                       echo ("Moving " + $objStatic.Name);
                       #move the VM
                       $objVM | move-vm -destination (get-vmhost $objStatic.Host)

# a flag to indicate that we moved a VM
$bMoved = $true;

# keep looping through the list until no VMs have been moved
       # get the hosts with percentages
       $objHosts = GetPercentages | sort PercentMemory -descending | select Name, PercentMemory

       # calculate the average memory
       $intAverage = 0;
       $intCount = 0;
       foreach($objHost in $objHosts){
               $intAverage += $objHost.PercentMemory;
       $intAverage /= $intCount;

       # display the average memory used
       echo ("Average is " + $intAverage);

       # display the hosts so it's easier to know what's going on
       $objHosts | select Name, PercentMemory;

       # determine the host with the least amount of RAM used
       $strDest = $objHosts[$objHosts.Count-1].Name;

       # this is a flag to see if anything has been moved
       $bMoved = $false;

       # loop through the hosts
       foreach($objHost in $objHosts){
               # check to see if this is more than 10% of the average
               if($objHost.PercentMemory -gt ($intAverage + 10)){
                       # get the name of the VM to move
                       $objVM = GetVMToMove $objHost.Name

                       # display some output to let the user know what is being moved
                       echo ('Moving ' + $objVM.Name + " from " + $objHost.Name);

                       #move the VM
                       $objVM | move-vm -destination (get-vmhost $strDest);

                       # flag that a VM has been moved
                       $bMoved = $true;

2.open Notepad again and copy the following script:

Set-ExecutionPolicy -ExecutionPolicy remotesigned -Force; add-pssnapin VMware.VimAutomation.Core; Connect-VIServer vcenter; & "C:\Scheduled tasks\Vmware DRS Script.ps1" >>c:\Log\VMHOSTCluster.log

change the name of Vcenter to your Vcenter server name and save the script as Run_DRS_script.ps1.

You will need to test this by running the following in the Run prompt:

powershell "C:\Scheduled_tasks\Run_DRS_Script"

once completed, check the log folder to see if a log file has been generated. You would also see Vm’s migrating if there was a requirement to load balance.

Once happy you will need to create a task using Task Scheduler.

Open Task Scheduler and create a new task.

Create Task 1

ensure you select Run whether user is logged on or not. I would recommend creating a service account for this. ensure the account has the appropriate permissions.

select the tick box: run with Highest Privileges .

Create task 2

Set the time and date the frequency of times you want this to Run

Create task 3

Create task 4

Create task 5

Enter PowerShell into the program/script and in the Add arguments field enter:


Once you have finished, confirm the settings and ok out of the create task. You should then run the task to ensure it works and look at the task logs and log folder to ensure that the script has run successfully.

One thought on “VMware Host Cluster VM memory balancing script implementation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s