One of the hot new features in vSphere 5 was the introduction of SDRS. And with SDRS came the concept of affinity rules for VMs and VMDKs. Cormac, aka @VMwareStorage, posted a nice overview of the SDRS affinity rules in Storage DRS Affinity & Anti-Affinity Rules.
Since then several posts have appeared on the subject of SDRS affinity rules. To list just a few:
- Frank Denneman: Impact of Intra VM affinity rules on Storage DRS. This post contains Alan Renouf‘s function Set-DatastoreClusterDefaultIntraVmAffinity which allows you to configure the default intra-VM affinity rule on a DatastoreCluster.
- Frank Denneman: (Storage) DRS (anti-) affinity rule types and HA interoperability
- Duncan Epping: Setting the default affinity rule for Storage DRS
Currently there are no PowerCLI cmdlets to define the inter- and intra-vm anti-affinity rules for SDRS. After a question in the VMTN PowerCLI Community I decided to write a function. This function will allow you to automate the creation of the SDRS anti-affinity rules.
The Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
function Set-SdrsAntiAffinity { <# .SYNOPSIS Configure SDRS affinity rules .DESCRIPTION The function will create SDRS anti-affinity rules (VMDK and VM) .NOTES Author: Luc Dekens .PARAMETER VM One virtual machines for which to create a VMDK SDRS anti-affinity rule .PARAMETER VMGroup Two or more virtual machines for which to create a VM SDRS anti-affinity rule .PARAMETER DatastoreCLuster The datastorecluster where the anti-affinity rule shall be created .PARAMETER RuleName The name of the rule .PARAMETER Enabled A switch that indicates if the rule should be enabled .EXAMPLE PS> Set-SdrsAntiAffinity -VM $vm -Harddisk 1 .EXAMPLE PS> Get-VM -Name VM1 | Set-SdrsAntiAffinity .EXAMPLE PS> Set-SdrsAntiAffinity -VMGroup VM1,VM2,VM3 #> param( [CmdletBinding()] [Parameter(ParameterSetName='VMDK', Mandatory=$true, ValueFromPipeline=$true)] [PSObject]$VM, [Parameter(ParameterSetName='VMDK')] [ValidateCount(2,60)] [int[]]$Harddisk, [Parameter(ParameterSetName='VM', Mandatory=$true)] [ValidateCount(2,2147483647)] [PSObject[]]$VMGroup, [Parameter(Mandatory=$true)] [PSObject]$DatastoreCluster, [String]$RuleName = "Rule", [Switch]$Enabled = $false ) begin{ $storMgr = Get-View StorageResourceManager if($DatastoreCluster -is [System.String]){ $DatastoreCluster = Get-DatastoreCluster -Name $DatastoreCluster } $spec = New-Object VMware.Vim.StorageDrsConfigSpec $ruleNumber = 1 $disk = &{if(!$Harddisk){1..60} else{$Harddisk}} } process{ switch ($PsCmdlet.ParameterSetName){ 'VM' { $VMGroup = $VMGroup | %{ if($_ -is [System.String]){ Get-VM -Name $_ } else{$_} } if(!$spec.podConfigSpec){ $spec.podConfigSpec = New-Object VMware.Vim.StorageDrsPodConfigSpec } $rule = New-Object VMware.Vim.ClusterRuleSpec $rule.operation = "add" $rule.info = New-Object VMware.Vim.ClusterAntiAffinityRuleSpec $rule.info.enabled = $Enabled $rule.info.name = $RuleName $rule.info.vm = $VMGroup | %{$_.ExtensionData.MoRef} $spec.podConfigSpec.rule += $rule } 'VMDK' { if($VM -is [System.String]){ $vm = Get-VM -Name $vm } $vmSpec = New-Object VMware.Vim.StorageDrsVmConfigSpec $vmSpec.operation = "add" $vmSpec.info = New-Object VMware.Vim.StorageDrsVmConfigInfo $vmSpec.info.vm = $VM.ExtensionData.MoRef $vmSpec.info.enabled = $true $vmSpec.info.intraVmAffinity = $false $vmSpec.info.intraVmAntiAffinity = New-Object VMware.Vim.VirtualDiskAntiAffinityRuleSpec $vmSpec.info.intraVmAntiAffinity.enabled = $Enabled $vmSpec.info.intraVmAntiAffinity.name = $RuleName + $ruleNumber++ $vmSpec.info.intraVmAntiAffinity.diskId = &{ $vm.ExtensionData.Config.Hardware.Device | where {$_ -is [VMware.Vim.VirtualDisk] -and $disk -contains $_.DeviceInfo.Label.Split(' ')[2]} | Select -ExpandProperty Key } if($vmspec.info.intraVmAntiAffinity.diskId.Count -ge 2){ $spec.vmConfigSpec += $vmSpec } } } } end{ $storMgr.ConfigureStorageDrsForPod($DatastoreCluster.ExtensionData.MoRef,$spec,$true) } } |
Annotations
Line 28-45: The function uses 2 parametersets. One, named VMDK, for the intra-VM anti-affinity rules, and one, named VM, for the inter-VM anti-affinity rules.
Line 35: The Harddisk parameter, from the VMDK parameterset, requires at least 2 harddisks. The validation if there are at least 2 values passed is done through the ValidateCount option. The 2nd number is the maximum number of vDisks a VM can have.
Line 39: Again the ValidateCount option is used to check that there are at least 2 values passed. The 2nd number is in fact the value from [Int]::MaxValue.
Line 52: The specification object to reconfigure the datastorecluster is created, it’s a StorageDrsPodConfigSpec object.
Line 54: If the Harddisk parameter was not used for a intra-VM anti-affinity rule, then this line sets the value to the maximum number of harddisks.
Line 58: The handling of the 2 possible parametersets is done through this Switch statement.
Line 60-65,79-81: A cheap implementation of OBN
Line 66-68: The first time the function passes through this part, the podConfigSpec property is set up.
Line 74: The MoRef for each VM that is specified for the inter-VM anti-affinity rule is stored
Line 89: Since the VMDK, intra-VM anti-affinity, accepts pipeline input, the provided rulename is used as the basename and a number is added for each VM that was passed through the pipeline.
Line 90-95: If the call to the function contains values for the Harddisk parameter, only those harddisks will be included in the rule. If no Harddisk parameter is passed, all the harddisks of the VM will be included in the rule. The parameter expects at least 2 integer values that correspond with the number in the label of the vDisk. For example, the number 2 indicates Hard disk 2.
Line 97-99: If the VM only has 1 vDisk, then obviously no rule is created.
Line 105: When all objects passed through the pipeline or through the parameters are handled, the actual call to add the anti-affinity rules is done.
Sample Usage
First lets have a look at the antra-VM anti-affinity rules. These rules specify that specific vDisks of a VM should be stored on different datastores in the datastorecluster.
1 |
Set-SdrsAntiAffinity -VM VM2 -DatastoreCluster MyDSC |
No specific vDisks were specified, so the function will include all VMDKs of the VM in the rule. This specific VM has 2 vDisks.
We can also use the function in a pipeline to define intra-VM anti-affinity rules. Something like this.
1 2 |
Get-VM -Name VM3,VM4 | Set-SdrsAntiAffinity -DatastoreCluster MyDSC -RuleName MyRule -Harddisk 1,3 -Enabled:$false |
In this example the function will create an intra-VM anti-affinity rule for each VM that comes through the pipeline. The Harddisk parameter states that on Hard disk 1 and Hard disk 3 shall be included in the rules.
The 2 anti-affinity rules have been created, they contain Hard disk 1 and Hard disk 3 for both VMs and the rules are not enabled.
To create an inter-VM anti-affinity rule, we have to call the function with at least 2 VMs.
1 2 |
$vm = Get-VM -Name VM1,VM2,VM3 Set-SdrsAntiAffinity -VMGroup $vm -DatastoreCluster MyDSC -RuleName AnotherRule -Enabled:$false |
In this call we configure the datastorecluster to seperate the 3 VMs. The generated rule looks like this.
Enjoy !
Roman Gelman
Hi Luc,
I started to write some functions to automate SDRS rules operations. One of them is based on your Set-SdrsAntiAffinity function. Currently there are 7 functions and I hope will be more … I share these functions with community throw my PowerCLi Vi-Module.
I have an issue with Remove-SdrsAntiAffinityRule function which are successfully able to delete Inter-VM rules but with VMDK rules it throws an error. Can you please point me out the problem (https://ps1code.com/2017/09/06/sdrs-powercli-part2).
Thanks in advance
LucD
Hi Roman,
We are currently finalising our new version of our DRSRule module. It will include working with SDRS rules.
Currently I’m prepping my trip to VMworld in Barcelona, will have a look at your code when I’m back.
Luc
Kevin
Hi Luc,
Were you ever able to create a module that removes SDRS rules?
I am trying to mass enable SDRS intra-vm affinity on some VMs, and mass disable it on others, but at the individual VM level, not anything larger.
Thanks!
Kevin
LucD
Not yet I’m afraid, it’s on the todo list for the DRSRule module.
vNOkk
I noticed this when deploying a few VMs to a SDRS cluster using the New-VM cmdlet. If the SDRS cluster is set to No Automation(Manual Mode), the per VM Automation Level gets set to Fully Automated by default.
According to the documentation this is correct. However how do I not see any documentation in order to set it to not be Fully Automated, but instead set to “AsSpecifiedByCluster” as you would with DrsAutomationLevel.
Any Ideas?
Maekee
Hi,
Do you have any script that removes SDRS Rules also?
Thanks
/Maekee