PowerCLI: Add & remove VMs from DRS Groups based on datastore location

Lately I have been working on a number of virtualization projects which make use of VMware vSphere Metro Storage Clusters (vMSC). With most of these types of implementations, virtual machines must be pinned to a preferred site to minimise impact to virtual machines in the event of a site failure. DRS groups are the most common way to achieve this, however I was wanting to find a way to automate the add/remove of virtual machines based on each VM’s datastore location.

To begin, I configured each of the datastores with a prefix of the site which was its preferred site, e.g. DC1-VMFS-01 or DC2-VMFS-01. I then placed VMs on a datastore which corresponded to their preferred site.

With the help of DRSRule I was then able to create two PowerCLI functions to automate the process to add the VMs to a corresponding DRS VM group based on their datastore location. The function can be used with a datastore name, prefix or suffix.

function Add-DrsVMToDrsVMGroup{
#Requires -Modules VMware.VimAutomation.Core, DRSRule
#region script help
<#
.SYNOPSIS  
    Adds virtual machines to a DRS VM group based on datastore location
.DESCRIPTION
    Adds virtual machines to a DRS VM group based on datastore location
.NOTES
    Version:        1.0
    Author:         Tim Carman
    Twitter:        @tpcarman
    Github:         tpcarman
.LINK
    https://github.com/tpcarman/PowerCLI-Scripts	
.PARAMETER DrsVMGroup
    Specifies the DRS VM Group
    This parameter is mandatory but does not have a default value.
.PARAMETER Cluster
    Specifies the cluster which contains the DRS VM Group
    This parameter is mandatory but does not have a default value.
.PARAMETER Prefix
    Specifies a prefix string for the datastore name
    This parameter is optional and does not have a default value.
.PARAMETER Suffix
    Specifies a suffix string for the datastore name
    This parameter is optional and does not have a default value.
.PARAMETER Datastore
    Specifies a datastore name
    This parameter is optional and does not have a default value.
.EXAMPLE
    Add-DrsVMtoDrsVMGroup -DRSVMGroup 'SiteA-VMs' -Cluster 'Production' -Prefix 'SiteA-'
.EXAMPLE
    Add-DrsVMtoDrsVMGroup -DRSVMGroup 'SiteA-VMs' -Cluster 'Production' -Suffix '-02'
.EXAMPLE
    Add-DrsVMtoDrsVMGroup -DRSVMGroup 'SiteB-VMs' -Cluster 'Production' -Datastore 'VMFS-01'
#>
#endregion script help
#region script parameters
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True,HelpMessage='Specify the name of the DRS VM Group')]
    [ValidateNotNullOrEmpty()]
    [String]$DrsVMGroup='',
    [Parameter(Mandatory=$True,HelpMessage='Specify the cluster name')]
    [ValidateNotNullOrEmpty()] 
    [String]$Cluster='',  
    [Parameter(Mandatory=$False,ParameterSetName=’Prefix’,HelpMessage='Specify the prefix string for the datastore name')]
    [ValidateNotNullOrEmpty()]
    [String]$Prefix='',
    [Parameter(Mandatory=$False,ParameterSetName=’Suffix’,HelpMessage='Specify the suffix string for the datastore name')]
    [ValidateNotNullOrEmpty()]
    [String]$Suffix='',      
    [Parameter(Mandatory=$False,ParameterSetName=’Datastore’,HelpMessage='Specify the datastore name')]
    [ValidateNotNullOrEmpty()]
    [String]$Datastore=''
	)
#endregion script parameters
#region script body
if($Prefix){
    $VMs = Get-Datastore | where{($_.name).StartsWith($Prefix)} | Get-VM
    }
if($Datastore){
    $VMs = Get-Datastore | where{($_.name) -eq $Datastore} | Get-VM
    }
if($Suffix){
    $VMs = Get-Datastore | where{($_.name).EndsWith($Suffix)} | Get-VM
    }
$objDrsVMGroup = Get-DrsVMGroup -Name $DrsVMGroup -Cluster $Cluster
foreach($VM in $VMs){
    if(($objDrsVMGroup).VM -notcontains $VM){
    	Write-Host "Adding virtual machine $VM to DRS VM Group $DrsVMGroup"
        try{
            Set-DrsVMGroup -Name $DrsVMGroup -Cluster $Cluster -Append -VM $VM
        }
        catch{
            Write-Error "Error adding virtual machine $VM to DRS VM Group $DrsVMGroup"
        } 
    }
}
#endregion script body
}

Continue reading