27 July 2011

Backup/Export Full DRS Rule Info via PowerShell

Updated 22 Jan 2015
Luc Dekens and I got together on a new PowerShell module for managing/exporting/importing DRS Rules and Groups. See our posts at http://www.lucd.info/2015/01/22/drsrule-drs-rules-and-groups-module and http://www.vnugglets.com/2015/01/drsrule-new-powershell-module-for-drs.html for all of the juicy details. Going forward, that DRSRule module is the way to go. I am leaving this post intact for posterity. Enjoy!
End of update - 22 Jan 2015

We, like many, had the need for a way to backup our DRS rules. Searches turned up many pages, all of which had the same basic recipe: use the Get-DrsRule to grab the rules, get a few properties, and export to CSV.

The problem: Addressing the task getting all of the pertinent info for rules of type ClusterVmHostRuleInfo, or, "VM-to-Host" rules. Rules of this type do not have the VM IDs in a property of the rule, but rather have the VMGroupName and HostGroupNames properties. From these properties, and the .NET view object of the given cluster, one can retrieve the VMs' and hosts' info.

So, we did a little work, and wrote the following to, for all DRS rule types, get the information that would be required if one wanted to recreate the rules:
## Script function: Gather/export DRS rule info, including VMGroup and HostGroup members
## Author: vNugglets.com

## file to which to write the DRS rules' info
$strOutputFilespec = "e:\someFolder\DRSrules_export.csv"

## get cluster .NET view objects, which hold the info about the DRS rules
Get-View -ViewType ClusterComputeResource -Property Name, ConfigurationEx | %{
    ## if the cluster has any DRS rules
    if ($_.ConfigurationEx.Rule -ne $null) {
        $viewCurrClus = $_
        $viewCurrClus.ConfigurationEx.Rule | %{
            $oRuleInfo = New-Object -Type PSObject -Property @{
                ClusterName = $viewCurrClus.Name
                RuleName = $_.Name
                RuleType = $_.GetType().Name
                bRuleEnabled = $_.Enabled
                bMandatory = $_.Mandatory
            } ## end new-object

            ## add members to the output object, to be populated in a bit
            "bKeepTogether,VMNames,VMGroupName,VMGroupMembers,AffineHostGrpName,AffineHostGrpMembers,AntiAffineHostGrpName,AntiAffineHostGrpMembers".Split(",") | %{Add-Member -InputObject $oRuleInfo -MemberType NoteProperty -Name $_ -Value $null}

            ## switch statement based on the object type of the .NET view object
            switch ($_){
                ## if it is a ClusterVmHostRuleInfo rule, get the VM info from the cluster View object
                #   a ClusterVmHostRuleInfo item "identifies virtual machines and host groups that determine virtual machine placement"
                {$_ -is [VMware.Vim.ClusterVmHostRuleInfo]} {
                    $oRuleInfo.VMGroupName = $_.VmGroupName
                    ## get the VM group members' names
                    $oRuleInfo.VMGroupMembers = (Get-View -Property Name -Id ($viewCurrClus.ConfigurationEx.Group | ?{($_ -is [VMware.Vim.ClusterVmGroup]) -and ($_.Name -eq $oRuleInfo.VMGroupName)}).Vm | %{$_.Name}) -join ","
                    $oRuleInfo.AffineHostGrpName = $_.AffineHostGroupName
                    ## get affine hosts' names
                    $oRuleInfo.AffineHostGrpMembers = if ($_.AffineHostGroupName -ne $null) {(Get-View -Property Name -Id ($viewCurrClus.ConfigurationEx.Group | ?{($_ -is [VMware.Vim.ClusterHostGroup]) -and ($_.Name -eq $oRuleInfo.AffineHostGrpName)}).Host | %{$_.Name}) -join ","}
                    $oRuleInfo.AntiAffineHostGrpName = $_.AntiAffineHostGroupName
                    ## get anti-affine hosts' names
                    $oRuleInfo.AntiAffineHostGrpMembers = if ($_.AntiAffineHostGroupName -ne $null) {(Get-View -Property Name -Id ($viewCurrClus.ConfigurationEx.Group | ?{($_ -is [VMware.Vim.ClusterHostGroup]) -and ($_.Name -eq $oRuleInfo.AntiAffineHostGrpName)}).Host | %{$_.Name}) -join ","}
                    break;
                } ## end block
                ## if ClusterAffinityRuleSpec (or AntiAffinity), get the VM names (using Get-View)
                {($_ -is [VMware.Vim.ClusterAffinityRuleSpec]) -or ($_ -is [VMware.Vim.ClusterAntiAffinityRuleSpec])} {
                    $oRuleInfo.VMNames = if ($_.Vm.Count -gt 0) {(Get-View -Property Name -Id $_.Vm | %{$_.Name}) -join ","}
                } ## end block
                {$_ -is [VMware.Vim.ClusterAffinityRuleSpec]} {
                    $oRuleInfo.bKeepTogether = $true
                } ## end block
                {$_ -is [VMware.Vim.ClusterAntiAffinityRuleSpec]} {
                    $oRuleInfo.bKeepTogether = $false
                } ## end block
                default {"none of the above"}
            } ## end switch

            $oRuleInfo
        } ## end foreach-object
    } ## end if
} | Export-Csv -NoTypeInformation $strOutputFilespec

This bit of code, using the Get-View cmdlet for max speed and min memory footprint, starts off by getting a couple of select properties for all clusters. If the cluster has any DRS rules defined, then the code, for each rule:
  • creates a new PSObject to hold the pertinent info about the rule
  • includes basic rule info, the rule type, and info about the objects involved with the rule, including the VM group names/members and the host group names/members (for both Affine- and AntiAffine host groups)
  • returns the object
  • exports all of the gathered info to CSV for later consumption

Arnim van Lieshout wrote a good post with more information about DRS rules themselves at Managing VMware DRS rules using PowerCLI, and included a few functions for creating VMGroups ("Virtual Machines DRS Groups" in the vSphere client) and HostGroups ("Host DRS Groups"), and for creating new VM-to-Host rules. We will likely be using said functions for our "recreate the DRS rules/groups" work.

16 comments:

  1. This is great! Thanks.

    Tom

    ReplyDelete
    Replies
    1. Thanks for the feedback, Tom. One day we will get around to posting the complementary Restore/Import kin article...

      Delete
    2. This Script is fast and gets the job done!
      Please post the Restore script to match ASAP!

      Nick

      Delete
  2. Hi there!

    Totally awesome script! Thank you for your good work! Do you plan on making a restore-script anytime soon? :-)

    ReplyDelete
  3. Excellent Script. Thank you. It does throw some minor (ignoreable) errors for those clusters that it cannot find Host/VM groups for. i.e. that only have vm anti or affinity rules but not groups.

    ReplyDelete
    Replies
    1. Is that the cause of the following error?

      Get-View : Cannot validate argument on parameter 'Id'. The argument is null or empty. Provide an argument that is not null or empty, and then try the
      command again.
      At line:30 char:78
      + $oRuleInfo.VMGroupMembers = (Get-View -Property Name -Id ($v ...
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingValidationException
      + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

      Delete
    2. I received this same error. It was because one of my DRS groups didn't actually have any members. I was able to ignore the message.

      Delete
    3. Hi all ,I got same problem and did you fix this issue ?? if fix this issue can you share me the way to me?my email address is owengo@qq.com

      Delete
    4. Hello, Guocai Liang-

      The DRSRule PowerShell module supercedes the code in this post. Luc Dekens and I wrote said PowerShell module for managing/exporting/importing DRS Rules and Groups. See our posts at http://www.lucd.info/2015/01/22/drsrule-drs-rules-and-groups-module and http://www.vnugglets.com/2015/01/drsrule-new-powershell-module-for-drs.html.

      And, if you find issues with the module, or have some feature requests, or want to contribute, check out the module at GitHub at https://github.com/PowerCLIGoodies/DRSRule.

      Cheers! Matt

      Delete
  4. A downfall to this script I noticed is that it won't export any groups that are not used. I have a few DRS groups defined but they aren't currently used in any rules.

    ReplyDelete
    Replies
    1. To get all group membership I was able to use the Get-DrsGroup function located here https://communities.vmware.com/message/1699823#1699823

      and run these commands...

      foreach ($group in (Get-DrsGroup -Cluster "ClusterName")) {
      $group.Name
      foreach ($obj in $group.vm) {
      (get-view -id $obj).name
      }
      foreach ($obj in $group.host) {
      (get-view -id $obj).name
      }
      Write-Output ""
      }

      Delete
  5. Any update on the import script? I'm looking to migrate a datacenter/cluster to a new vcenter and the import would greatly help.

    Thanks!

    ReplyDelete
    Replies
    1. Hello, Anonymous-

      If you didn't see, Luc Dekens and I wrote a PowerShell module to handle imports and much more -- managing/exporting/importing DRS Rules and Groups. See our posts at http://www.lucd.info/2015/01/22/drsrule-drs-rules-and-groups-module and http://www.vnugglets.com/2015/01/drsrule-new-powershell-module-for-drs.html. Enjoy!

      Delete
  6. Good job! Could you please tell me how to import the rule from exported csv files?

    My email is owengo@qq.com.Thanks for your help.

    ReplyDelete
    Replies
    1. Hello, Owengo@qq-

      Thanks! As for importing from exports: the way to go now would to be to use the DRSRule PowerShell module that supercedes the code in this post. Luc Dekens and I wrote said PowerShell module to handle imports and much more -- managing/exporting/importing DRS Rules and Groups. See our posts at http://www.lucd.info/2015/01/22/drsrule-drs-rules-and-groups-module and http://www.vnugglets.com/2015/01/drsrule-new-powershell-module-for-drs.html.

      And, particularly for your use cases, see the Export-DrsRule and Import-DrsRule cmdlets in the module. Enjoy!

      Delete