Free PowerShell Script for Hyper-V: Get-ClusterVM

Table of contents

 

I recently had a need to locate a specific VM in a cluster. Turns out, there’s no truly direct way to do it. Therefore, I have developed a simple script that will allow you to find one, many, or all VMs in a cluster.

This script isn’t entirely necessary. You can fairly easily retrieve all these VMs with the following:

Get-VM –Name VMNAME –ComputerName (Get-ClusterNode –Cluster CLUSTER)

That works, and works pretty well. But then, I came up with another need: I only wanted to look at highly available VMs. That changes things. You could do this:

Get-VM –ComputerName (Get-ClusterNode –Cluster CLUSTER) | where { $_.IsClustered –eq $true }

There’s nothing wrong with this, but it’s a bit much for regular use. Of course, the-powers-that-be in the PowerShell world would likely tell me to just stick that in a .ps1 and make sure it’s accessible. But it’s still less flexible than I would like. So, I started working on something more elegant. The more I worked on it, the more complicated it got. The end result is actually a one-liner, although I broke it out into multiple lines because legibility trumps cleverness in a saved script. The best part of this is that it’s pretty simple to use. You can just run Get-ClusterVM without any parameters from a cluster node and it will retrieve all the highly available VMs on the entire cluster. You can use the –VMName parameter to select one or more specific VMs. You can also use –Cluster to remotely target a cluster. Another nice thing about this is, in my unscientific testing, it seems to be a little quicker than the Get-VM run. I’m assuming that’s because once it gets to the point of querying for VMs, it queries for them with very specific parameters instead of using open-ended wildcards. There is a potential shorter path that would work for most situations. You could just query cluster groups, as the name is usually matched to the VM. However, it is entirely possible to have a VM name that is different from its cluster resource name, especially if you’re using VMM. The only guaranteed option they match on is the VmID. The complete script is below. It works on 2012 and above. Just save it as Get-ClusterVM.ps1 and execute from PowerShell. Use Get-Help to view the parameters.

<#
.SYNOPSIS
	Retrieves clustered virtual machines.

.DESCRIPTION
	Enumerates the virtual machine resources on a cluster and retrieves the related virtual machine object.
	If specific VM names are supplied, only those objects are retrieved.

.PARAMETER VMName
	A string array that specifies the names of VMs to look for.

.PARAMETER Cluster
	The cluster to scan for virtual machines.

	Accepts a string that contains the cluster or any node name.
	Accepts a Cluster object (from Get-Cluster).
	Accepts a VMHost object (from Get-VMHost).

.OUTPUTS
	Microsoft.Virtualization.Powershell.VirtualMachine

.EXAMPLE
	C:PS> .Get-ClusterVM

	Description
	-----------
	Retrieves all VMs on the cluster that this computer is a member of.

.EXAMPLE
	C:PS> .Get-ClusterVM svMail1

	Description
	-----------
	Retrieves the VM named "svMail1" on the cluster that this computer is a member of.

.EXAMPLE
	C:PS> .Get-ClusterVM svMail1, svSQL1 hvcluster1

	Description
	-----------
	Retrieves the virtual machines named "svMail1" and "svSQL1" from the cluster named "hvcluster1"

.EXAMPLE
	C:PS> .Get-ClusterVM -VMName svMail1, svSQL1 -Cluster hvcluster1

	Description
	-----------
	Exactly like the previous example, using named parameters.

.LINK
	
Free PowerShell Script for Hyper-V: Get-ClusterVM
#> #requires -Version 3 #requires -Modules Hyper-V, FailoverClusters [CmdletBinding()] param( [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelinebyPropertyName=$true)] [Alias("Name", "VM")] [String[]]$VMName = @(), [Parameter(Position=1, ValueFromPipeline=$true, ValueFromPipelinebyPropertyName=$true)] [Alias("ComputerName", "ClusterName" , "HostName", "VMHost")] [PSObject]$Cluster = $env:COMPUTERNAME ) BEGIN {} PROCESS { Set-StrictMode -Version Latest # Convert input to a string switch( $Cluster.GetType().Name) { "Cluster" { $Cluster = $Cluster.Name } "VMHost" { $Cluster = $Cluster.Name } default { $Cluster = [String]$Cluster } } <# Legend for following script # 1. Retrieve a list of cluster resources of type "Virtual Machine" 2. Extract the computer name of the owner node and the VMId from 1. 3. Use each node and ID set from 2. as Get-VM parameters 4. Did the user specify one or more VMs? 4yes. Retrieve only those from 3. 4no. Allow all VMs to be retrieved from 3. 5. Leave the VMs retrieved in 4. in the pipeline #> Get-ClusterResource -Cluster $Cluster | where { $_.ResourceType -like "Virtual Machine" } | #1. select -Property OwnerNode, @{ Name ="VmID";Expression ={ (Get-ClusterParameter -InputObject $_ | where { $_.Name -eq "VmID" } | select -Property Value).Value } # 2. } | foreach { Get-VM -ID $_.VmID -ComputerName $_.OwnerNode } | # 3. Where-Object { if($VMName.Count -gt 0) # 4. { $VMName -contains $_.Name # 4yes. } else { 1 } # 4No. } # 5. } END {}

 

Altaro Hyper-V Backup
Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!

5 thoughts on "Free PowerShell Script for Hyper-V: Get-ClusterVM"

Leave a comment or ask a question

Your email address will not be published. Required fields are marked *

Your email address will not be published.

Notify me of follow-up replies via email

Yes, I would like to receive new blog posts by email

What is the color of grass?

Please note: If you’re not already a member on the Dojo Forums you will create a new account and receive an activation email.