So you want to Pin a VM to a host huh?
Maybe for some network mirror or span port entertainment?

Here is how you do it pcli style:

#set your vars:

$thecluster = “pcli-cluster1”
$thevmhost = “”
$thevm = “vm1”
$VMGroupName = “MyVMGroupName”
$HostGroupName = “MyHostGroupName”
$rulename = “MyAffinityRuleName”

#paste the code:

$cluster = Get-Cluster $thecluster | Get-View
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$group = New-Object VMware.Vim.ClusterGroupSpec
$group.operation = “add”
$group.Info = New-Object VMware.Vim.ClusterVmGroup
$group.Info.Name = $VMGroupName
Get-VM -Name $theVM | %{$group.Info.VM += $_.Extensiondata.MoRef}
$spec.GroupSpec += $group
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$group = New-Object VMware.Vim.ClusterGroupSpec
$group.operation = “add”
$group.Info = New-Object VMware.Vim.ClusterHostGroup
$group.Info.Name = $HostGroupName
Get-VMHost -Name $TheVMHost | %{$group.Info.Host += $_.Extensiondata.MoRef}
$spec.GroupSpec += $group
#Make the Rule
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
$rule = New-Object VMware.Vim.ClusterRuleSpec
$rule.operation = “add”
$ = New-Object VMware.Vim.ClusterVmHostRuleInfo
$ = $true
$ = $RuleName
$ = $true
$ = $VMGroupName
$ = $HostGroupName
$spec.RulesSpec += $rule

I’m sure someone can reduce the code but I left it broken out here to provide the section view.
IE : If you only want to create a Host group, take the middle part of the script.

This code will fully migrate a powered on VM to another cluster (On the same vcenter)
This will migrate the VMs storage and the memory state with one command.

### Set your vars
$vmname = “MyVM”
$going2Host = “”
$datastorename = “Datastore-1”

Get-VM $vmname | Move-VM -Destination $going2Host -Datastore (get-datastore “$datastorename”) -confirm:$false -RunAsync:$true


####### ####### ####### ####### ####### ####### #######
You can use this code if you want to select the datastore cluster instead of a single LUN.
This may error out if you have SDRS enabled on the VM.
Check this code to disable it before running the migration line below or just disable it via the GUI :

$vmname = “MyVM”
$going2Host = “”
$datastoreclustername = “MyDataStoreCluster”

Get-VM $vmname | Move-VM -Destination $going2Host -Datastore (get-datastorecluster “$datastoreclustername”) -confirm:$false -RunAsync:$true

VMware Links:

This code will reconfigure your Storage DRS Cluster Settings for a single VM.

### Set your vars ###
$theVM = “MyVM”
$theDatastoreCluster = “MyStorageCluster”

$SRMan = Get-View StorageResourceManager
$DSCluster = Get-DatastoreCluster -Name $theDatastoreCluster
$spec = New-Object VMware.Vim.StorageDrsConfigSpec
$DSCluster.ExtensionData.PodStorageDrsEntry.StorageDrsConfig.VmConfig |
where {(Get-View $_.VM | Select -ExpandProperty Name) -like $theVM} | %{
$entry = New-Object VMware.Vim.StorageDrsVmConfigSpec
$entry.Operation = “edit”
$entry.Info = $_
$entry.Info.Enabled = $false
$spec.vmConfigSpec += $entry

This code will aid in the automation of deleting Host Affinity rules via PowerCLI.

Currently the Get-DRSRule and Remove-DRSRule command does not allow the removal of VM-Host Affinity rules.
This code block will get a “VMHost Affinity” rule based on a string filter then delete it along with the VM group + Host group attached to it.
If you don’t want to delete the VM and host group, just remove the sub group specs below.

Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer “” -User “XX” -password “XX”

$Mycluster = get-cluster “MyCluster”
$therules = get-drsrule -cluster $mycluster -type vmhostaffinity | where {$ -match “RuleNameHere”}

foreach($rule in $therules){
$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 = “remove”
$spec.rulesSpec[0].removeKey = $rule.key
$spec.rulesSpec[0].info = New-Object VMware.Vim.ClusterVmHostRuleInfo
$spec.rulesSpec[0] = $
$spec.rulesSpec[0].info.vmGroupName = $rule.extensiondata.vmgroupname
$spec.rulesSpec[0].info.affineHostGroupName = $rule.extensiondata.AffineHostgroupname
$spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[](2)
$spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec
$spec.groupSpec[0].operation = “remove”
$spec.groupSpec[0].removeKey = $rule.extensiondata.vmgroupname
$spec.groupSpec[0].info = New-Object VMware.Vim.ClusterVmGroup
$spec.groupSpec[0] = $rule.extensiondata.vmgroupname
$spec.groupSpec[1] = New-Object VMware.Vim.ClusterGroupSpec
$spec.groupSpec[1].operation = “remove”
$spec.groupSpec[1].removeKey = $rule.extensiondata.AffineHostgroupname
$spec.groupSpec[1].info = New-Object VMware.Vim.ClusterHostGroup
$spec.groupSpec[1] = $rule.extensiondata.AffineHostgroupname
$_this = Get-View (get-cluster $Mycluster)
$_this.ReconfigureComputeResource_Task($spec, $true)

Here are some extra vars if you want to make a report from each rule”
#The name of the Rule

#name of the VM group and host group assigned to the Rule
$vmgroupname = $rule.extensiondata.vmgroupname
$hostgroupname = $rule.extensiondata.AffineHostgroupname

#list of VMs by name in the VM Group
$vmlist = get-vm -id $rule.vmids | %{$}

#list of hosts by name in the Host group
$hostlist = get-vmhost -id $rule.AffineHostIds | %{$}

VMware Links:

This code will grab the vmotion count that you see on the summary page of your cluster object. This counter is total vmotions to include system and manual migrations. If you want the manual ones you will need to parse out your vievents.

Get-Cluster | Select Name,@{N=”vMotion”;E={$_.ExtensionData.Summary.NumVmotions}}


This will help you Export/Import the settings for a vApp so you can restore it if vCenter dies or if you need to migrate it to another location.
If you can power off all of your VMs an Export is easy.
Just run this and it will dump to a flat file:
 get-vapp -name “MyvApp” | export-vapp -destination “c:\temp\”

If you cannot power off your VMs or Cannot find some down time, this will do it without any interruption to your VMs.
It may seem interruptive but it works!

1) Screen cap or document all of the vapp settings. This includes the startup order, resources, and any special settings in the Advanced tab under Options. A manual backup will save you if some setting does not fully export using the API.
2) Disconnect all of the hosts and remove from inventory. (This is because you cannot export settings from a powered on vApp.)
– If you are migrating the vApp to another vcenter, just add the hosts to the new vcenter. It will disconnect them on the old vcenter without impacting the VMs.

3) Once all of the hosts that contain the vApp VMs are disconnected and removed, shutdown the vapp.
4) Export the config with this code:
 get-vapp -name “MyVapp” | export-vapp -destination “c:\temp\”

5) Enable DRS on the new cluster you want to import the vapp to. (You cannot Import a vApp without DRS enabled.)
6) Import it with this command
Import-vApp -Source “c:\temp\MyVapp.ovf” -VMHost (get-vmhost “”) -Location (get-cluster MyCluster) -Name “MyVapp” -force

7) Verify and edit the settings on imported vapp. (This is where your notes from step one comes in handy)
8) Move the vms into the imported Vapp. (Just drag the VMs from the host to the vApp.)
9) Once all of the VMs are in the vApp, Edit settings again and fix the startup order.

VMware Links: