MarcLaf
Enthusiast
Enthusiast

How can I optimize this command for finding VM's with multiple tags?

Jump to solution

I'm looking for a way to find all VM's that have multiple tags assigned. For the sake of the question let's assume the tags are Alpha and Beta. The command that I've come up with works but it's very slow.

get-vm -tag alpha | Where{$_.PowerState -eq 'PoweredOn' and (Get-TagAssignment -Entity $_ ).Tag -match 'Beta'}

If I run the following, it's faster but I get VM's with either or.

get-vm -tag alpha,beta

It's only when I add the additional filter (Get-TagAssignment) to only show the second tag where it slows down. Is there a way to specify both tags in the quicker command but only return when both are found?

Tags (2)
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

I would try something like this.

It avoids the Get-TagAssignment, which is an 'expensive' cmdlet.

$t1 = Get-Tag -Name Tag1

$t2 = Get-Tag -Name Tag2

$vm1 = Get-VM -Tag $t1

$vm2 = Get-VM -Tag $t2

$vm1 | where {$vm2.Name -contains $_.Name}


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

View solution in original post

8 Replies
LucD
Leadership
Leadership

Which PowerCLI version are you using?


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

0 Kudos
MarcLaf
Enthusiast
Enthusiast

Looks like 11.1

0 Kudos
ryanrpatel
Enthusiast
Enthusiast

Here's a script I wrote that we use to loop thru our vCenters (12 of them) and dump nightly. It doesn't matter how long it takes since I'm sleeping 😉

I hope this helps.

$file = $null

$report = @()

foreach ($VCSvr in $vCSrvLst) {

## Connect to vCenter

Connect-viserver "$VCSvr.Corp.Realpage.com"

    $report = @()

    $TagCats = Get-TagCategory

# Loop through each row in Input and Search for VM and Get Creation Info

ForEach ($TCat in $TagCats) {

        $TCatName = $TCat

        write-host Exporting list of VMs assigned to Tag Category: $TCatName

        $AssignedTags = Get-TagAssignment -Category $TCatName -ErrorAction SilentlyContinue

ForEach ($ATag in $AssignedTags) {

            $row = "" | select VMName, Tag

            $row.VMName = $ATag.Entity.Name

            $row.Tag = $ATag.Tag

            $report += $row

        }

}

    $report | sort -property @{Expression="VMName";Descending=$false} | Export-Csv TaggedVMs_$VCSvr.csv -NoTypeInformation

    Disconnect-VIServer -Server * -Force:$true -Confirm:$false

}

0 Kudos
LucD
Leadership
Leadership

That's the latest version, so your good.

There have been multiple reports about the slowness and even timeouts with the Get-TagAssignment.

You might want to give it a try with Kyle's module VMware.Community.CISTag.
Measurements showed that the cmdlets in that module are way faster.
There is a blog post, see New Community Module for Tag Management


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

0 Kudos
MarcLaf
Enthusiast
Enthusiast

Thanks Ryan - This is mainly used when I need to apply snapshots to a group of VM's (like all Production VM's for X Application) so I'm not sure the script would be useful for this case. But I do like to see and dissect what others create!

0 Kudos
MarcLaf
Enthusiast
Enthusiast

Thanks LucD.

I will check out that module. So my question is, am I doing the query the right way? Or is there a way to specify multiple tags requiring both using just the -Tag parameter?

0 Kudos
LucD
Leadership
Leadership

I would try something like this.

It avoids the Get-TagAssignment, which is an 'expensive' cmdlet.

$t1 = Get-Tag -Name Tag1

$t2 = Get-Tag -Name Tag2

$vm1 = Get-VM -Tag $t1

$vm2 = Get-VM -Tag $t2

$vm1 | where {$vm2.Name -contains $_.Name}


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

View solution in original post

MarcLaf
Enthusiast
Enthusiast

That's really cool LucD. I like that response. Yes describing Get-TagAssignment as 'expensive' is a good description. The solution is no longer a one liner but it'll work when I incorporate it into a script. Thanks for this.

0 Kudos