To control the placement of virtual machines on hosts in a cluster, you can use DRS affinity rules or anti-affinity rules. There are two types of affinity rules:
In PowerCLI, there are cmdlets to use VM-VM affinity rules. To use VM-Host affinity rules, you have to, unfortunately, use the vSphere API.
To create a VM-VM DRS rule, you can use the New-DrsRule
cmdlet that has the following syntax:
New-DrsRule [-Name] <String> [-Cluster] <Cluster[]> [-Enabled
[<Boolean>]] -KeepTogether [<Boolean>] -VM <VirtualMachine[]>
[-RunAsync] [-Server <VIServer[]>] [-WhatIf] [-Confirm]
[<CommonParameters>]
The -Name
, -Cluster
, -KeepTogether
, and -VM
parameters are required.
If the value of the -KeepTogether
parameter is $true
, the new DRS rule is an affinity rule. If the value is $false
, the new DRS rule is an anti-affinity rule.
If the value of -Enabled
parameter is $true
, the new DRS rule is enabled. If the value is $false
, it is disabled.
In the following example, you will create a new, enabled DRS VM-VM affinity rule named Keep VM1 and VM2 together
for Cluster01
. The DRS rule will keep the two virtual machines VM1
and VM2
together on the same host:
PowerCLI C:> New-DrsRule -Name 'Keep VM1 and VM2 together' -Cluster Cluster01 -VM VM1,VM2 -KeepTogether:$true -Enabled:$true Name Enabled Type VMIDs ---- ------- ---- ----- Keep VM1 and VM2 together True VMAffinity {VirtualMachine-vm-125, VirtualMachine-vm-105}
In the following screenshot of the vSphere Web Client, you will see the window of the vSphere Web Client, which you can use to create a DRS rule filled with the same settings as in the preceding PowerCLI command:
In the second example, you will create a new DRS VM-VM anti-affinity rule named Separate VM3 and VM4
for Cluster01
:
PowerCLI C:> New-DrsRule -Name 'Separate VM3 and VM4' -Cluster Cluster01 -VM VM3,VM4 -KeepTogether:$false -Enabled:$true Name Enabled Type VMIDs ---- ------- ---- ----- Separate VM3 and VM4 True VMAntiAffinity {VirtualMachine-vm-107, VirtualMachine-vm-126}
Unfortunately, there are no PowerCLI cmdlets to create a VM-Host affinity rule. You have to use the vSphere API to do this. There are three steps involved in creating a VM-Host affinity rule:
While creating a virtual machines DRS group, you have to add at least one virtual machine to this group. In the following example, you will create a virtual machines DRS group named Cluster01 VMs should run on host 192.168.0.133
for Cluster01
and add virtual machine VM1
to this DRS group.
First, you create a ClusterConfigSpecEx
object. Then, you add an array containing one ClusterGroupSpec
object to the GroupSpec
property of the ClusterConfigSpecEx
object. The operation
property of the ClusterGroupSpec
object is given the value add
. A ClusterVmGroup
object is assigned to the info
property of the ClusterGroupSpec
object. The name of the DRS group is assigned to the name
property of the ClusterVmGroup
object. The MoRef
of the virtual machine that will be added to the DRS group is assigned to the vm
property of the ClusterVmGroup
object. Finally, the cluster's ReconfigureComputeResource_Task()
method is called to reconfigure the cluster and to add the DRS group:
# Creating a Virtual Machines DRS Group $Cluster = Get-Cluster -Name Cluster01 $VM = Get-VM -Name VM1 -Location $Cluster $DRSGroupName = 'Cluster01 VMs should run on host 192.168.0.133' $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[] (1) $spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec $spec.groupSpec[0].operation = 'add' $spec.groupSpec[0].info = New-Object VMware.Vim.ClusterVmGroup $spec.groupSpec[0].info.name = $DRSGroupName $spec.groupSpec[0].info.vm += $VM.ExtensionData.MoRef $Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
Creating a hosts DRS group is similar to creating a virtual machine DRS group. Instead of adding a ClusterVmGroup
object to the info
property of the ClusterGroupSpec
object, you have to add a ClusterHostGroup
object. The host
property of the ClusterHostGroup
will get the MoRef of the host you want to add to the DRS group assigned. You have to add at least one host to a hosts DRS group.
In the following example, you will create a hosts DRS group named Cluster01 192.168.0.133 Hosts DRS Group
, and you will add the host 192.168.0.133
to this group:
# Creating a Hosts DRS Group $Cluster = Get-Cluster -Name Cluster01 $VMHost = Get-VMHost -Name 192.168.0.133 -Location $Cluster $DRSGroupName = 'Cluster01 192.168.0.133 Hosts DRS Group' $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[] (1) $spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec $spec.groupSpec[0].operation = "add" $spec.groupSpec[0].info = New-Object VMware.Vim.ClusterHostGroup $spec.groupSpec[0].info.name = $DRSGroupName $spec.groupSpec[0].info.host += $VMHost.ExtensionData.MoRef $Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
There are no cmdlets to retrieve DRS groups. You will have to use the vSphere API. The DRS groups are in the ConfigurationEx.Group
property of a vSphere ClusterComputeResource
object.
The following example will show you how to retrieve the DRS groups of Cluster01
:
PowerCLI C:> (Get-Cluster -Name Cluster01).ExtensionData .ConfigurationEx.Group Vm : {VirtualMachine-vm-125} LinkedView : Name : Cluster01 VMs should run on host 192.168.0.133 UserCreated : UniqueID : Host : {HostSystem-host-109} LinkedView : Name : Cluster01 192.168.0.133 Hosts DRS Group UserCreated : UniqueID :
If you want to modify a DRS group, the only thing you can do is add or remove virtual machines or hosts to or from the DRS group. There are no PowerCLI cmdlets to do this, so you have to use the vSphere API.
In the first example, you will add virtual machines VM2
, VM4
, and VM7
to the DRS group Cluster01 VMs should run on host 192.168.0.133
. Because the structure of ClusterConfigSpecEx
objects is always the same, I will explain only what is unique in this example. In this case, the operation is edit
. The DRS group is assigned to the info
property. All of the new group members are added to the info.vm
property:
# Adding virtual machines to a DRS group $Cluster = Get-Cluster -Name Cluster01 $GroupName = "Cluster01 VMs should run on host 192.168.0.133" $VMs = Get-VM -Name VM2,VM4,VM7 $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[] (1) $spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec $spec.groupSpec[0].operation = "edit" $spec.groupSpec[0].info = $Cluster.ExtensionData.ConfigurationEx.Group | Where-Object {$_.Name -eq $GroupName} foreach ($VM in $VMs) { $spec.groupSpec[0].info.vm += $VM.ExtensionData.MoRef } $Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
In the second example about modifying DRS groups, the virtual machines VM4
and VM7
will be removed from the DRS group Cluster01 VMs should run on host 192.168.0.133
.
This example looks a lot like the preceding one. The difference is that virtual machines are removed from the info.vm
property using the Where-Object
cmdlet and the -notcontains
operator. Only the virtual machines that are not in the list of virtual machines to be removed are assigned to the info.vm
property:
# Removing virtual machines from a DRS group $Cluster = Get-Cluster -Name Cluster01 $GroupName = "Cluster01 VMs should run on host 192.168.0.133" $VMs = Get-VM -Name VM4,VM7 $VMsMorefs = $VMs | ForEach-Object {$_.ExtensionData.MoRef} $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[] (1) $spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec $spec.groupSpec[0].operation = "edit" $spec.groupSpec[0].info = New-Object VMware.Vim.ClusterVmGroup $spec.groupSpec[0].info.name = $GroupName $spec.groupSpec[0].info.vm = $Cluster.ExtensionData.ConfigurationEx.Group | Where-Object {$_.Name -eq $GroupName} | Select-Object -ExpandProperty vm | Where-Object {$VMsMorefs -notcontains $_} $Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
Adding hosts to a DRS group and removing hosts from a DRS group is similar to adding virtual machines to a DRS group or removing virtual machines from a DRS group. I leave this to you as an exercise to solve (Hint: use Get-VMHost
instead of Get-VM
).
More information about the VMware.VIM.*
objects used in the preceding examples can be found in VMware vSphere API Reference Documentation:
http://pubs.vmware.com/vsphere-65/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
.
Removing DRS groups is similar to preceding DRS groups operations. To remove a DRS group, the operation
is remove
, and the removeKey
is the DRS group's name.
The following example will remove the DRS group Cluster01 VMs should run on host 192.168.0.133
:
# Removing a DRS group $Cluster = Get-Cluster -Name Cluster01 $GroupName = "Cluster01 VMs should run on host 192.168.0.133" $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[] (1) $spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec $spec.groupSpec[0].operation = "remove" $spec.groupSpec[0].removeKey = $GroupName $Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
Finally, you have to relate the virtual machines DRS group to the hosts DRS group in a virtual machines to hosts DRS rule. There are four possible relations:
Must run on hosts in group
Should run on hosts in group
Must not run on hosts in group
Should not run on hosts in group
In the example given, you will create a Should run on hosts in group
virtual machines to hosts DRS rule to give preference to virtual machine VM1
to run on host 192.168.0.133
.
First, a ClusterConfigSpecEx
object is created. An array of one ClusterRuleSpec
object is assigned to the rulesSpec
property of the ClusterConfigSpecEx
object. The operation
property of rulesSpec
is set to add
. A ClusterVmHostRuleInfo
object is assigned to the info property of rulesSpec
. The enabled
property of the ClusterVmHostRuleInfo
object is set to $true
. The name
property is given the name of the DRS rule. Because it is a Should run on hosts in group
DRS rule, the mandatory
property is set to $false
. The userCreated
property is set to $true
. The vmGroupName
and affineHostGroupName
properties are assigned the names of the related DRS groups. Finally, the cluster's ReconfigureComputeResource_Task()
method is called to create the DRS rule:
# Creating a Virtual Machines to Hosts DRS rule $Cluster = Get-Cluster -Name Cluster01 $spec = New-Object VMware.Vim.ClusterConfigSpecEx $spec.rulesSpec = New-Object VMware.Vim.ClusterRuleSpec[] (1) $spec.rulesSpec[0] = New-Object VMware.Vim.ClusterRuleSpec $spec.rulesSpec[0].operation = "add" $spec.rulesSpec[0].info = New-Object VMware.Vim.ClusterVmHostRuleInfo $spec.rulesSpec[0].info.enabled = $true $spec.rulesSpec[0].info.name = "Cluster01 VM1 should run on host 192.168.0.133 DRS Rule" $spec.rulesSpec[0].info.mandatory = $false $spec.rulesSpec[0].info.userCreated = $true $spec.rulesSpec[0].info.vmGroupName = "Cluster01 VMs should run on host 192.168.0.133" $spec.rulesSpec[0].info.affineHostGroupName = "Cluster01 192.168.0.133 Hosts DRS Group" $Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
If you want to create a Must run on hosts in group
DRS rule, you only have to change the line $spec.rulesSpec[0].info.mandatory = $false
in the preceding code to the following:
$spec.rulesSpec[0].info.mandatory = $true
If you want to create a Must not run on hosts in group
or Should not run on hosts in group
DRS group, you have to assign the DRS hosts group name to $spec.rulesSpec[0].info.antiAffineHostGroupName
instead of $spec.rulesSpec[0].info.affineHostGroupName
.
In the following screenshot of the vSphere Web Client, you will see the virtual machines to hosts DRS rule Cluster01 VM1 should run on host 192.168.0.133 DRS Rule
created with the preceding PowerCLI commands:
You can use the Get-DrsRule
cmdlet to retrieve the DRS rules of the specified clusters. The syntax of this cmdlet is as follows. The first parameter set is the default:
Get-DrsRule [[-Name] <String[]>] [-Cluster] <Cluster[]>
[[-VM] <VirtualMachine[]>] [-Type <ResourceSchedulingRuleType[]>]
[-Server <VIServer[]>] [<CommonParameters>]
The second parameter set is to retrieve DRS rules that reference the specified ESXi hosts:
Get-DrsRule [[-Name] <String[]>] [-Cluster] <Cluster[]> [[-VM]
<VirtualMachine[]>] [-VMHost <VMHost[]>] [-Server <VIServer[]>]
[<CommonParameters>]
The -Cluster
parameter is required. You cannot use the -Type
and -VMHost
parameters in the same command because they are in different parameter sets.
If you don't specify the -Type
or -VMHost
parameters, you will only retrieve VM-VM affinity or VM-VM anti-affinity rules, as in the following example:
PowerCLI C:> Get-DrsRule -Cluster Cluster01 Name Enabled Type VMIDs ---- ------- ---- ----- Keep VM1 and VM2 together True VMAffinity {VirtualM... Separate VM3 and VM4 True VMAntiAffinity {VirtualM...
If you also want to retrieve VM-Host DRS rules, you have to specify all of the possible types as the value of the -Type
parameter, as we will do in the following example:
PowerCLI C:> Get-DrsRule -Cluster Cluster01 -Type VMAffinity,VMAntiAffinity,VMHostAffinity Name Enabled Type VMIDs ---- ------- ---- ----- Keep VM1 and VM2 together True VMAffinity {VirtualM... Separate VM3 and VM4 True VMAntiAffinity {VirtualM... Cluster01 VM1 should run on ho... True VMHostAffinity {VirtualM...
You can also retrieve all the DRS rules that involve certain virtual machines using the -VM
parameter:
PowerCLI C:> Get-DrsRule -Cluster Cluster01 -VM VM2 Name Enabled Type VMIDs ---- ------- ---- ----- Keep VM1 and VM2 together True VMAffinity {VirtualM...
To retrieve all of the DRS rules that involve specific hosts, use the -VMHost
parameter using the following command:
PowerCLI C:> Get-DrsRule -Cluster Cluster01 -VMHost 192.168.0.133 Name Enabled Type VMIDs ---- ------- ---- ----- Cluster01 VM1 should run on ho... True VMHostAffinity {VirtualM...
To modify a DRS rule, you can use the Set-DrsRule
cmdlet. The syntax of this cmdlet is as follows:
Set-DrsRule [[-Enabled] [<Boolean>]] [-Rule] <DrsRule[]>
[-Name <String>] [-VM <VirtualMachine[]>] [-RunAsync] [-Server
<VIServer[]>] [-WhatIf] [-Confirm] [<CommonParameters>]
The -Rule
parameter is required.
In the following example, the DRS rule Keep VM1 and VM2 together
of Cluster01
will be disabled:
PowerCLI C:> Get-DrsRule -Name 'Keep VM1 and VM2 together' -Cluster Cluster01 | Set-DrsRule -Enabled:$false Name Enabled Type VMIDs ---- ------- ---- ----- Keep VM1 and VM2 together False VMAffinity {VirtualM...
The Remove-DrsRule
cmdlet can be used to remove a DRS rule. The syntax of the Remove-DrsRule
cmdlet is as follows:
Remove-DrsRule [-Rule] <DrsRule[]> [-RunAsync] [-WhatIf]
[-Confirm] [<CommonParameters>]
The -Rule
parameter is required.
In the following example, the Keep VM1 and VM2 together
of Cluster01
is removed:
PowerCLI C:> Get-DrsRule -Cluster Cluster01 -Name 'Keep VM1
and VM2 together' | Remove-DrsRule -Confirm:$false
The preceding command does not return any output.
13.58.252.8