VMware Cloud Community
AaronAnderson
Contributor
Contributor
Jump to solution

Looking for a way to create an automated, and large number of DRS rules.

For example, I have a lot of machines named like this;

Fs001a

Fs001b

I need to create AntiAffinity rules to keep the the "a" and "b" machines on seperate hosts.

The rule created should be like "Fs001" and contain both machines.

New-DrsRule -Cluster Development -Name Fs001 -KeepTogether $false -VM Fs001a,Fs001b

Any direction/help with a powercli script that can do this would be greatly appreciated. I'm not sure how to handle name matching in powershell. This is something I would like to run as a scheduled job to avoid any human error in missed or incorrect rules.

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try like this

Get-VM -Name *[ab] |
Group-Object -Property {$_ -match "(?<name>.*)[a|b]"; $Matches["name"]} |
where {$_.Count -eq 2} | %{
   
New-DrsRule -Cluster Development -Name $_.Values[0][1] -KeepTogether $false -VM $_.Group
}

Only when the script finds 2 matching names (one ends with a, and the other with b), will it create a DRS rule


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

View solution in original post

Reply
0 Kudos
13 Replies
LucD
Leadership
Leadership
Jump to solution

Do the VM names always consist of 6 characters ?


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

Reply
0 Kudos
AaronAnderson
Contributor
Contributor
Jump to solution

No.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

But they always end with 'a' or 'b' ?


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

Reply
0 Kudos
AaronAnderson
Contributor
Contributor
Jump to solution

The machines I want to create rules for will always end in 'a' or 'b' - but there are other machines that we don't want to touch.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try like this

Get-VM -Name *[ab] |
Group-Object -Property {$_ -match "(?<name>.*)[a|b]"; $Matches["name"]} |
where {$_.Count -eq 2} | %{
   
New-DrsRule -Cluster Development -Name $_.Values[0][1] -KeepTogether $false -VM $_.Group
}

Only when the script finds 2 matching names (one ends with a, and the other with b), will it create a DRS rule


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

Reply
0 Kudos
AaronAnderson
Contributor
Contributor
Jump to solution

LucD, that's a fantastic bit of code. Using some things in powershell that I wasn't familiar with. Thank you!

Reply
0 Kudos
AaronAnderson
Contributor
Contributor
Jump to solution

Is there any way to only fire the DRS creation if the rule name does not already exist? It seems that New-DrsRule allows duplicate rule names... not ideal. I assumed it would error out and I could ignore those.

Reply
0 Kudos
AaronAnderson
Contributor
Contributor
Jump to solution

I stood on the shoulders of smarter men than me, but I did it. Here's a version that can be run on a schedule and not create duplicate entries.

Clear-Host

$VCenterServer = server

$VMCluster = "Production"

Connect-ViServer $VCenterServer

# Stick current DRS rules into an array

$DrsRules = Get-DrsRule -Cluster $VMCluster

Get-Cluster $VMCluster | Get-VM -Name *[ab] |

Group-Object -Property {$_ -match "(?<name>.*)[a|b]"; $Matches["name"]} |

Where-Object {$_.Count -eq 2} |

ForEach-Object {if($DrsRules.name -notcontains $_.Values[0][1]){New-DrsRule -Cluster $VMCluster -Name $_.Values[0][1] -KeepTogether $false -VM $_.Group}}

Revan5236
Contributor
Contributor
Jump to solution

The script looks great.  All our VMs end with av or bv, can the script be modified to do the same for our naming convention?

Thanks,

Michael

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try like this, it just needs a change in the Name parameter value and the RegEx pattern for the match operator.

$VCenterServer = server

$VMCluster = "Production"

Connect-ViServer $VCenterServer

# Stick current DRS rules into an array

$DrsRules = Get-DrsRule -Cluster $VMCluster

Get-Cluster $VMCluster | Get-VM -Name '*[ab]v' |

Group-Object -Property {$_ -match "(?<name>.*)[a|b]v"; $Matches["name"]} |

Where-Object {$_.Count -eq 2} |

ForEach-Object {

    if($DrsRules.name -notcontains $_.Values[0][1]){

        New-DrsRule -Cluster $VMCluster -Name $_.Values[0][1] -KeepTogether $false -VM $_.Group

    }

}


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

Revan5236
Contributor
Contributor
Jump to solution

Thank you.  That works.

Reply
0 Kudos
Revan5236
Contributor
Contributor
Jump to solution

Is there a way to add -AB to the name of the rule that is created?  I've tried a couple different arguments, but my currently knowledge of powershell and powercli is lacking.  (reading and learning daily)

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Like this ?

$VCenterServer = server

$VMCluster = "Production"

Connect-ViServer $VCenterServer

# Stick current DRS rules into an array

$DrsRules = Get-DrsRule -Cluster $VMCluster

Get-Cluster $VMCluster | Get-VM -Name '*[ab]v' |

Group-Object -Property {$_ -match "(?<name>.*)[a|b]v"; $Matches["name"]} |

Where-Object {$_.Count -eq 2} |

ForEach-Object {

    if($DrsRules.name -notcontains "$($_.Values[0][1])-AB"){

        New-DrsRule -Cluster $VMCluster -Name "$($_.Values[0][1])-AB" -KeepTogether $false -VM $_.Group

    }

}


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

Reply
0 Kudos