VMware Cloud Community
DennieTidwell
Enthusiast
Enthusiast
Jump to solution

Backup/Restore DRS VM affinity/anti-affinity rules - can these be backed up and restored without manually re-entering after DRS disable?

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.

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

Reply
0 Kudos
26 Replies
JoeLyons
Enthusiast
Enthusiast
Jump to solution

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

Remember to back EVERYTHING up before you change ANYTHING and consider awarding points if answers where helpful to you.
DennieTidwell
Enthusiast
Enthusiast
Jump to solution

Thanks Joe. This is a good start. Maybe I need to post in VI Toolkit community.

Reply
0 Kudos
oreeh
Immortal
Immortal
Jump to solution

FYI: this thread has been moved to the VI Toolkit forum.

Oliver Reeh[/i]

[VMware Communities User Moderator|http://communities.vmware.com/docs/DOC-2444][/i]

DennieTidwell
Enthusiast
Enthusiast
Jump to solution

Thanks for moving the thread.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
DennieTidwell
Enthusiast
Enthusiast
Jump to solution

LucD -

You rock. I will review and test asap. Thank you very much.

Reply
0 Kudos
milling
Contributor
Contributor
Jump to solution

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

Reply
0 Kudos
DennieTidwell
Enthusiast
Enthusiast
Jump to solution

Sorry, I am not seeing the change ... can you elaborate?

Reply
0 Kudos
milling
Contributor
Contributor
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, the forum SW has problems with square brackets.

I attached both scripts.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
milling
Contributor
Contributor
Jump to solution

Thanks LucD, much appreciated.

Reply
0 Kudos
jlewko98
Contributor
Contributor
Jump to solution

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 =&lt;cluster-name&gt;

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jlewko98
Contributor
Contributor
Jump to solution

LucD,

Thank you, the script is working now. I appreciate your expertise and time.

Reply
0 Kudos
jlewko98
Contributor
Contributor
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jlewko98
Contributor
Contributor
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
jlewko98
Contributor
Contributor
Jump to solution

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.

Reply
0 Kudos