Update [21/02/2020] – I have updated these scripts to use the native PowerCLI commands which became available in PowerCLI 6.5.1. You can download the updated scripts from my GitHub page.
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