DRS VM affinity/anti-affinity rules - these are lost when DRS is disabled - they can be "listed" via perl script or VI Toolkit for manual re-entering if needed ...
But can they be backed up / restored via automated methods for easy restoration in case of required or accidental disabling of DRS? What if a vCenter user disables instead of setting to manual during operations?
I have over 100+ DRS VM affinity/anti-affinity rules to maintain.
There are indeed several DRS rules related cmdlets in the VITK 1.5.
The following script will save all rules to a .txt file.
$outfile = "C:\rules.txt" Remove-Item $outfile $clusterName = <cluster-name> $rules = get-cluster -Name $clusterName | Get-DrsRule foreach($rule in $rules){ $line = (Get-View -Id $rule.ClusterId).Name $line += ("," + $rule.Name + "," + $rule.Enabled + "," + $rule.KeepTogether) foreach($vmId in $rule.VMIds){ $line += ("," + (Get-View -Id $vmId).Name) } $line | Out-File -Append $outfile }
The reason we write the rules to a .txt file is because the "Keep together" type of rules can have 2 or more guests defined.
This type of info (variable length array) is impossible to export to a .CSV file.
The 2nd script reads this external file and defines the rules.
$file = "C:\rules.txt" $rules = Get-Content $file foreach($rule in $rules){ $ruleArr = $rule.Split(",") if($ruleArr[2] -eq "True"){$rEnabled = $true} else {$rEnabled = $false} if($ruleArr[3] -eq "True"){$rTogether = $true} else {$rTogether = $false} get-cluster $ruleArr[0] | ` New-DrsRule -Name $ruleArr[1] -Enabled $rEnabled -KeepTogether $rTogether -VM (Get-VM -Name ($ruleArr[http://4..($ruleArr.Count - 1)|http://4..($ruleArr.Count - 1)])) }
The trick used for the guests is that we select part of an array with the \[a..b\] notation.
Currently you will have to run the first script for each cluster separately but this could easily be adapted to run against all cluster in your VI.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I havnt tried this but there is a set-drsrule in the vi toolkit,
It might work for you if you use get-drsrule and output it to a text file first.
Joe
Thanks Joe. This is a good start. Maybe I need to post in VI Toolkit community.
Thanks for moving the thread.
There are indeed several DRS rules related cmdlets in the VITK 1.5.
The following script will save all rules to a .txt file.
$outfile = "C:\rules.txt" Remove-Item $outfile $clusterName = <cluster-name> $rules = get-cluster -Name $clusterName | Get-DrsRule foreach($rule in $rules){ $line = (Get-View -Id $rule.ClusterId).Name $line += ("," + $rule.Name + "," + $rule.Enabled + "," + $rule.KeepTogether) foreach($vmId in $rule.VMIds){ $line += ("," + (Get-View -Id $vmId).Name) } $line | Out-File -Append $outfile }
The reason we write the rules to a .txt file is because the "Keep together" type of rules can have 2 or more guests defined.
This type of info (variable length array) is impossible to export to a .CSV file.
The 2nd script reads this external file and defines the rules.
$file = "C:\rules.txt" $rules = Get-Content $file foreach($rule in $rules){ $ruleArr = $rule.Split(",") if($ruleArr[2] -eq "True"){$rEnabled = $true} else {$rEnabled = $false} if($ruleArr[3] -eq "True"){$rTogether = $true} else {$rTogether = $false} get-cluster $ruleArr[0] | ` New-DrsRule -Name $ruleArr[1] -Enabled $rEnabled -KeepTogether $rTogether -VM (Get-VM -Name ($ruleArr[http://4..($ruleArr.Count - 1)|http://4..($ruleArr.Count - 1)])) }
The trick used for the guests is that we select part of an array with the \[a..b\] notation.
Currently you will have to run the first script for each cluster separately but this could easily be adapted to run against all cluster in your VI.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD -
You rock. I will review and test asap. Thank you very much.
Hi,
thanks for the scripts . They did help but I had some problems with the restore script. When I ran the restore it complained about "Missing or invalid array index expression". I changed the last line from "(Get-VM -Name ($ruleArr[http://4..($ruleArr.Count - 1)|http://4..($ruleArr.Count - 1)]))" to "(Get-VM -Name ($ruleArr[http://4..($ruleArr.Count - 1)|http://4..($ruleArr.Count - 1)]))" and the restore ran successfully.
Thanks,
M
Sorry, I am not seeing the change ... can you elaborate?
Hi,
that might be the problem. Something is adding the "http://" to the script when its posted. I resolved the issue this way "(Get-VM -Name ($ruleArr[http://4..($ruleArr.Count - 1)|http://4..($ruleArr.Count - 1)]))" without the "http://"
Thanks
Yes, the forum SW has problems with square brackets.
I attached both scripts.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks LucD, much appreciated.
When trying to run this script I am getting the following error:
<span style="color: #ff0000">Get-View : Cannot validate argument on parameter 'Id'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again. At C:\DRS-export-rules.PS1:7 char:24 + $line = (Get-View -Id <<<< $rule.ClusterId).Name + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingVal idationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.Commands.DotNetInterop.GetVIView Get-View : Cannot validate argument on parameter 'Id'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again. At C:\DRS-export-rules.PS1:10 char:34 + $line += ("," + (Get-View -Id <<<< $vmId).Name) + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingVal idationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.Commands.DotNetInterop.GetVIView</span>
I have changed the script so that
$clusterName =<cluster-name>
is now
$clusterName = "Temp" (this is a test cluster that I am using for this script).
I apologize as I am not very savvy with scripting, let alone the vSphere PowerCLI, and am trying to learn. Any help / pointing in the right direction is much appreciated.
It could be that you have no DRS rules defined on the cluster.
And PowerShell will always execute the loop once, even if the collection is $null.
With this updated version, the problem is avoided.
$outfile = "C:\rules.txt" Remove-Item $outfile $clusterName = <cluster-name> $rules = get-cluster -Name $clusterName | Get-DrsRule if($rules){ foreach($rule in $rules){ $line = (Get-View -Id $rule.ClusterId).Name $line += ("," + $rule.Name + "," + $rule.Enabled + "," + $rule.KeepTogether) foreach($vmId in $rule.VMIds){ $line += ("," + (Get-View -Id $vmId).Name) } $line | Out-File -Append $outfile } }
____________
Blog: LucD notes
Twitter: lucd22
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD,
Thank you, the script is working now. I appreciate your expertise and time.
LuCD,
I was curious as to how to add a check for DataCenter in this script, as our vCenter has multiple DataCenters and unfortunately some have the same Cluster names, and this script is stopping as soon it hits the first cluster. For example
vCenter
--DataCenter1
-
ClusterABC
-
Cluster-SERVERS
--DataCenter2
-
ClusterXYZ
-
Cluster-SERVERS
If I would run the export script against this type of environement I would only get the rules from the first Cluster-SERVERS (in DataCenter1). I havent yet tested importing, but my guess is that it would be the same.
Is there any way for me to alter the script to capture a Data Center Variable? Would appreciate any input.
Thanks
You can use the -Location parameter for that.
Adapt the line as follows
... $rules = get-cluster -Name $clusterName -Location (Get-Datacenter -Name "Datacenter2") | Get-DrsRule ...
____________
Blog: LucD notes
Twitter: lucd22
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LuCD,
Thanks again, this line of code is exactly what I need. Now I think I have to loop through a set of variables (Datacenter and Cluster names) to grab all the info at once, but Ill try tackling that project at another time. Same for Importing I guess.
Thanks for the info and quick response time, its much appreciated.
You could even automate this with two nested loops
Get-Datacenter | %{ Get-Cluster -Location $_ | %{ ... } }
The first line will run through all your datacenters one-by-one.
The second line will run through all your cluster in that specific datacenter
____________
Blog: LucD notes
Twitter: lucd22
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Great, I am going to have to take some time and get used to the syntax and process. Still very new but looking forward to learning. Appreciate the information. Had a tough time looking for the info I needed.