Automation

 View Only
Expand all | Collapse all

Script to automate DRS-Groups Manger affinity

  • 1.  Script to automate DRS-Groups Manger affinity

    Posted Dec 20, 2010 06:06 PM

    Hello

    I'm trying to automate affinity rules for drs groups manger. The idea is to let certain VMs run on

    assigned esx hosts (Type "Run VMs on Hosts" / "Should run on hosts in group").

    Background: We've esx hosts in two datacenters interconnected with 10Gig and a netapp metrocluster on each site hosting nfs exports. I have created two groups of type "Host DRS Groups" (esx hosts in datacenter a go into one, hosts in datacenter b go into the other) plus two groups of type "Virtual Machine DRS Groups" (VMs hosted on nfs export a go into one while VMs hosted on nfs export b go into the other). This way we can prevent nfs/iscsi traffic to run across datacenters.

    Creating the rules manually in a small cluster does work. However with dozens of VMs in other clusters there must be a way to automate the task and have it run regualary. I would let powercli generate a list of VMs according to nfs export (location of .vmdk is either on site a or site b) then import this into the relevant Virtual Machine DRS Group.

    Using get-drsrule -Cluster "cluster" | Export-CliXml does not show details for HOST DRS Groups or Virtual Machine DRS Groups. Is it possible to do this at all? I recon using set-drsrule would let me import the rules.

    Any help / ideas is appreceated!

    Regards

    Sascha



  • 2.  RE: Script to automate DRS-Groups Manger affinity
    Best Answer

    Posted Dec 20, 2010 07:32 PM

    The current DrsRule cmdlets do not, afaik, allow you to work with DRS groups.

    As an alternative you can use the ReconfigureComputeResource method that is available.

    The script would look something like this

    $clusterName = "MyCluster"
    $cluster = Get-Cluster -Name $clusterName

    $spec = New-Object VMware.Vim.ClusterConfigSpecEx $groupVM = New-Object VMware.Vim.ClusterGroupSpec
    $groupVM.operation = "add"
    $groupVM
    .Info = New-Object VMware.Vim.ClusterVmGroup
    $groupVM.Info.Name = "Grouped VM"

    Get-VM
    -Name MyVM1* | %{     $groupVM.Info.VM += $_.Extensiondata.MoRef } $spec.GroupSpec += $groupVM
    $groupESX
    = New-Object VMware.Vim.ClusterGroupSpec
    $groupESX
    .operation = "add"
    $groupESX.Info = New-Object VMware.Vim.ClusterHostGroup
    $groupESX.Info.Name = "Grouped Host"

    Get-VMHost
    -Name MyHost1* | %{     $groupESX.Info.Host += $_.Extensiondata.MoRef } $spec.GroupSpec += $groupESX
    $rule
    = New-Object VMware.Vim.ClusterRuleSpec
    $rule
    .operation = "add"
    $rule.info = New-Object VMware.Vim.ClusterVmHostRuleInfo
    $rule.info.enabled = $true
    $rule.info.name = "Test DRS group rule"
    $rule.info.mandatory = $true
    $rule
    .info.vmGroupName = "Grouped VM"
    $rule
    .info.affineHostGroupName = "Group Host"
    $spec.RulesSpec += $rule
    $cluster.ExtensionData.ReconfigureComputeResource($spec,$true)

    The script first creates 2 DRS groups. One with the VMs and one with the ESX(i) servers.

    In the example it takes all guests whose name starts with "MyVM1" for one group and all hosts whose name starts with "MyHost1" for the other group.

    These 2 selections will of course have to be changed for your setup. Let me know what selection rules you want to implement for the VMs and the hosts and I can update the script.

    Then the script creates a rule. Notice that the rule specifies $true for the 'mandatory' property.

    This means that a VM will not be powered on if its host placement doesn't correspond with the rule.

    The 2nd parameter on the ReconfigureComputeResource method allows you to specify if the changes defined in the $spec are incremental or not.

    If this is not $true all your cluster settings, except for the groups and the rule will be removed. So watch out!



  • 3.  RE: Script to automate DRS-Groups Manger affinity

    Posted Dec 21, 2010 05:12 PM

    Awesome! Just what I was looking for :smileyhappy:



  • 4.  RE: Script to automate DRS-Groups Manger affinity

    Posted Feb 15, 2011 07:46 PM

    Hi,

    great script! :-)

    Is it possible to create an example how to add additional VMs to that existing Group "Grouped VM"?

    Thanks!



  • 5.  RE: Script to automate DRS-Groups Manger affinity

    Posted Feb 21, 2011 02:58 PM

    I was also looking for a script to modify/update Virtual Machine DRS Groups in the DRS Group Manager.

    I modified the script above to create this:

    $vCenterServer = "vCenter.Example.com"
    #authenticating and Connecting to the VC

    $CurrentUserName = [Security.Principal.WindowsIdentity]::getcurrent().name
    $cred = Get-Credential $CurrentUserName
    Write-Output "Connecting to vCenter. Please stand by..."
    Connect-VIServer -Server $vCenterServer -Credential $Cred


    #Function for updating the Resource VM Groups
    function updateDrsVmGroup ($clusterName,$resourcePoolName,$groupVMName){
        $cluster = Get-Cluster -Name $clusterName
        $spec = New-Object VMware.Vim.ClusterConfigSpecEx
        $groupVM = New-Object VMware.Vim.ClusterGroupSpec
        #Operation edit will replace the contents of the GroupVMName with the new contents seleced below.
        $groupVM.operation = "edit"

        $groupVM.Info = New-Object VMware.Vim.ClusterVmGroup
        $groupVM.Info.Name = $groupVMName

    # Perform your VM selection here. I use resource pools per cluster to identify group members,
    # but you could use any method to select your VM's.
        get-cluster $clusterName | Get-ResourcePool $resourcePoolName | get-vm | %{
            $groupVM.Info.VM += $_.Extensiondata.MoRef
        }
        $spec.GroupSpec += $groupVM

        #Apply the settings to the cluster
        $cluster.ExtensionData.ReconfigureComputeResource($spec,$true)
    }

    # Calling the function. I've found the group names to be case sensitive, so watch for that.
    #updateDrsVmGroup ("ClusterName") ("ResourcePool Name") ("DRS VM Groupname")
    updateDrsVmGroup ("Cluster_PROD") ("Group A") ("Group A VMs (Odd)")
    updateDrsVmGroup ("Cluster_PROD") ("Group B") ("Group B VMs (Even)")
    updateDrsVmGroup ("Cluster_STAGE") ("Group A") ("Group A VMs (Odd)")
    updateDrsVmGroup ("Cluster_STAGE") ("Group B") ("Group B VMs (Even)")


    Disconnect-VIServer -Confirm:$False

    This script allows me to manage guest to host affinity across clusters on the same hardware (blade chassis) based on resource pool membership.  The VM group contents will be overwritten by whatever the script finds in the resource pools matching the name.



  • 6.  RE: Script to automate DRS-Groups Manger affinity

    Posted Mar 06, 2011 10:57 PM

    LucD and GotMoo,

    Thanks for posting your scripts to create and modify DRS Groups.  Work great and give me peace of mind that I'm not forgetting to seperate any of my clustered VM nodes.

    J



  • 7.  RE: Script to automate DRS-Groups Manger affinity

    Posted Apr 27, 2012 06:12 AM

    Hi,

    I'm want to set the Group affinity based on a cutom attribute that we are using. I tried it using get-annotation but it's not really working.

    Get-Cluster $clusterName | Get-VM | Get-Annotation | where {$_.value -eq $Datacenter} | Select-Object AnnotatedEntity

    With that I get the needed output, but placed in the whole script it's doesn't work.

    Somebody have any Ideas?

    THX, Stefan



  • 8.  RE: Script to automate DRS-Groups Manger affinity

    Posted Apr 27, 2012 06:38 AM

    Could you perhaps explain in which context in your script you want to use the AnnotatedEntity property ?



  • 9.  RE: Script to automate DRS-Groups Manger affinity

    Posted Apr 27, 2012 07:13 AM

    Of cource, sorry.

    I want to set the affinity of my VM's to DR's groups based on a custom attribute we set (Datacenter). It should work like the script of GotMoo, but instead of based on RessourcePools it should be based on the entry of the Datacenter-Attribute.

    "Get-Cluster $clusterName | Get-VM | Get-Annotation | where {$_.value -eq $Datacenter} | Select-Object AnnotatedEntity" gives me the names of the VM's as output. Similar to "get-cluster $clusterName | Get-ResourcePool $resourcePoolName | get-vm" in the script of GotMoo.

    I just started using PS, so maybe it's the total different way. Please don't gve to much attention on what I've done, if there is a better way I'm happy for tips.



  • 10.  RE: Script to automate DRS-Groups Manger affinity

    Posted Apr 27, 2012 07:33 AM

    Try replacing that part of the script with this

        Get-Cluster $clusterName | Get-VM | 
        where {Get-Annotation -Entity $_ | where {$_.Value -eq $Datacenter}} | %{
            $groupVM.Info.VM += $_.Extensiondata.MoRef
        }
    }

    This will get all the VMs in the cluster and then filter, with a Where-clause, the ones that have the content of the $Datacenter variable in one of their custom attributes.



  • 11.  RE: Script to automate DRS-Groups Manger affinity

    Posted Apr 27, 2012 07:47 AM

    Works perfect!!! :smileylaugh:

    THX very much!!!



  • 12.  RE: Script to automate DRS-Groups Manger affinity

    Posted Aug 12, 2014 02:51 PM

    I hacked together a script using just machines

    #https://communities.vmware.com/message/1666605#1666605

    #http://pubs.vmware.com/vsphere-50/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc_50%2Fvim.cluster.VmGroup.html

    #https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.cluster.GroupSpec.html

    # Loading PowerCLI Snapins

    function LoadSnapin{

      param($PSSnapinName)

      if (!(Get-PSSnapin | where {$_.Name   -eq $PSSnapinName})){

        Add-pssnapin -name $PSSnapinName

      }

    }

    LoadSnapin -PSSnapinName   "VMware.VimAutomation.Core"

    #Function for updating the Resource VM Groups

    function updateDrsVmGroup ($clusterName,$VMFilter,$groupVMName)

    {

    #Get Cluster Information

      $cluster = Get-Cluster -Name $clusterName

      $spec = New-Object VMware.Vim.ClusterConfigSpecEx

      $groupVM = New-Object VMware.Vim.ClusterGroupSpec

      $groupVM.operation = "edit"

      $groupVM.Info = New-Object VMware.Vim.ClusterVmGroup

      $groupVM.Info.Name = $groupVMName

    #Perform your VM selection here.

      Get-VM -Name $VMFilter | % {$groupVM.Info.VM += $_.Extensiondata.MoRef}

      $spec.GroupSpec += $groupVM

        #Apply the settings to the cluster

        $cluster.ExtensionData.ReconfigureComputeResource($spec,$true)

    }

    $CredentialID="domain\user"

    $vCenterServer="vCenter1"

    $cred = Get-Credential $CredentialID

    Connect-VIServer -server $vCenterServer -credential $cred

    # Calling the function. I've found the group names to be case sensitive, so watch for that.

    updateDrsVmGroup -clusterName "Lab1" -VMFilter "ABC*" -groupVMName "MACHINE-GROUP"

    Disconnect-VIServer -Confirm:$False



  • 13.  RE: Script to automate DRS-Groups Manger affinity

    Posted Mar 30, 2011 06:45 PM

    Hello LucD

    Do you have a similar script the will output the contents of a DRS group as well as the Virtual Machine DRS groups and the Host DRS groups

    Thanks

    BobR



  • 14.  RE: Script to automate DRS-Groups Manger affinity

    Posted Feb 21, 2014 09:51 AM

    Hello,

     

    I’m not a PowerShell expert and I need your help.

    I want to write a PS Script to compare where the VM actually running (ESX host) -> may be like “Get-VM | select name, VMhost” with the DRS hosts Group (list of ESX hosts) where she should run, if it doesn’t violate the DRS Host Affinity.

    I don’t know how to collect the list of ESX Host (in DRS host group) which are associated with the VM DRS Group?

    Thanks a lot for your help

    Philippe



  • 15.  RE: Script to automate DRS-Groups Manger affinity

    Posted Feb 21, 2014 10:10 AM

    Try something like this

    $clusterName = "MyCluster"

    $rules = Get-DrsRule -Cluster $clusterName -Type VMHostAffinity
    $rules |
    Select @{N="VM";E={Get-View $_.VMIDS | Select -ExpandProperty Name}},
     
    @{N="Rule Host";E={Get-View $_.AffineHostIds | Select -ExpandProperty Name}},
     
    @{N="Running on";E={
       
    Get-View (Get-View $_.VMIDS | %{$_.Runtime.Host}) | Select -ExpandProperty Name
      }}


  • 16.  RE: Script to automate DRS-Groups Manger affinity

    Posted Feb 22, 2014 09:26 AM

    Thank you very much Luc for your quick response. I have to find now how to compare by script the VM affinity host and where (esx host) their actually running.

    Regards,

    Philippe



  • 17.  RE: Script to automate DRS-Groups Manger affinity

    Posted Jun 04, 2014 04:50 AM

    hi LucD

    i am looking for a script that can separate Windows VMs & Linux VMs onto a separate DRS hostgroup so i can have the windows VMs running on a particular set of hosts in a cluster and linux VMs separate. how do i go about scripting this.

    regards

    Suresh



  • 18.  RE: Script to automate DRS-Groups Manger affinity

    Posted Jun 29, 2012 08:44 AM

    Hi fellas,

    Looking for a way to use Datastore Clusters in the same way you use Resource pools/annotations.

    Is there a way to select the VMs stored on a specific datastore cluster? I find the get-datastorecluster to be very limited.

    Basically what we want to do is to fill our two VM DRS Groups (stretched HA cluster) with the VMs filled in the resource pool named PROD.

    We have two Datastore Clusters named PROD_SITE_A and PROD_SITE_B.

    I can get the output of where all the VM resides, but I don't see a way to implement it into the script.

    Get-ResourcePool PROD |Get-VM | Select Name, @{N="Datastore";E={Get-Datastorecluster -VM $_}}

    Will give a nice output of each VM and what Datastore Cluster its stored on.

    It would be so much easier if you just could get-datastorecluster PROD_SITE_A | get-vm ...

    Any suggestions?



  • 19.  RE: Script to automate DRS-Groups Manger affinity

    Posted Jun 29, 2012 09:17 AM

    I agree that the Datastorecluster related cmdlets should be expanded.

    Let's hope the next PowerCLI release will bring that.

    In the meantime, you can use this function to retrieve the VMs that are located on a Datastorecluster

    function Get-VMonDsc{
      param(
      [CmdletBinding()]
      [parameter(Position = 0, ValueFromPipeline = $true)]
      [string]$Name = "*"  )
    
      begin{
       function Get-StoragePodInternal{
         param(
         [CmdletBinding()]
         [parameter(Mandatory = $true,ValueFromPipeline = $true)]
         [VMware.Vim.Folder]$Folder     )
    
         $Folder.ChildEntity | %{
           if($_.Type -eq "StoragePod"){
             Get-View -Id $_
           }       
    elseif($_.Type -eq "Folder"){          Get-View -Id $_ | Get-StoragePodInternal
           }      }     }   }     process{     Get-Folder -Name datastore | %{       Get-StoragePodInternal -Folder $_.ExtensionData | where {$_.Name -like $Name} | %{         Get-VIObjectByVIView -MORef $_.ChildEntity | Get-VM
          }     }   } }
    $vms = Get-VMOnDsc -Name "DSC1"

    The function is based on my vSphere 5 Top 10 – Storage DRS post.



  • 20.  RE: Script to automate DRS-Groups Manger affinity

    Posted Jul 02, 2012 06:20 AM

    Thanks alot Luc!

    It works like a charm.



  • 21.  RE: Script to automate DRS-Groups Manger affinity

    Posted Jul 02, 2012 06:56 AM

    If you want to use a .ps1 file like that, you can add a param stateent at the top and call the function with that parameter.

    The script becomes

    param([string]$Name)
    
    function Get-VMonDsc{
      param(
      [CmdletBinding()]
      [parameter(Position = 0, ValueFromPipeline = $true)]
      [string]$Name = "*"  )
    
      begin{
       function Get-StoragePodInternal{
         param(
         [CmdletBinding()]
         [parameter(Mandatory = $true,ValueFromPipeline = $true)]
         [VMware.Vim.Folder]$Folder
         )     
    $Folder.ChildEntity | %{        if($_.Type -eq "StoragePod"){          Get-View -Id $_       }        elseif($_.Type -eq "Folder"){          Get-View -Id $_ | Get-StoragePodInternal
           }      }     }   }    
    process{     Get-Folder -Name datastore | %{       Get-StoragePodInternal -Folder $_.ExtensionData | where {$_.Name -like $Name} | %{         Get-VIObjectByVIView -MORef $_.ChildEntity | Get-VM
          }     }   } }
    Get-VMOnDsc -Name $name

    Save this as a .ps1 file and the you can call it like you tried.

    <ps1> -name PROD_SITE_A


  • 22.  RE: Script to automate DRS-Groups Manger affinity

    Posted Jul 02, 2012 07:03 AM

    Again, Thanks ALOT Luc! This also works like a charm.

    Please remind me to buy you a beer at VMworldUS if you're going. :smileyhappy:



  • 23.  RE: Script to automate DRS-Groups Manger affinity

    Posted Feb 28, 2013 07:30 PM

    I need to create a script (scheduled to run at least once a day) that will check the datastore names for VMs in one or more stretched clusters and their VM DRS group membership and add them (or change them) to the correct VM DRS group based on the first several characters of a datastore name (if it starts with xyz it's at this site, if it starts with abc it's at this site).  Would also like to have it send an email with what was found and what changes were made.

    Another thought would be including a check to see if someone accidentally split the disks for a VM so they're hosted on datastores at separate sites.

    Since I'm still a PowerCLI noob, any assistance/feedback would be appreciated!