This script sets the state of the virtual machines on one or all of the nodes of a hyperV cluster.

PowerShell
Edit|Remove
<# 
.Synopsis 
    Change the state of the virtual machines.
    
.Description
    This script sets the state of the virtual machines on one or all of the nodes of a hyperV cluster.
	
.Parameter State
    Specifies the desired state of the virtual machines.State can be one of "All", "Saved", "Running", "Paused", "Stopped".
    
.Parameter VMName
    Specifies the name of the virtual machine. Use wildcard ('*') character to select multiple virtual machines.
	
.Parameter VMList
    Specifies an array of virtual machines. VMName and VMList cannot be used together	
    
.Parameter VMHosts
    Specifies an array of hyperV host machine names. If this paramter is not specified, the hyperV nodes in the cluster are considered.
	
.Parameter Asynchronous
    Switch to change the state of the virtual machines asynchronously.	

    
.Example 
    PS C:\> Set-ClusterVMState.ps1 -VMName myvm* -State Running 
    
    This example changes the state of all the VMs which have their names starting with 'myvm' to RUNNING state.
    
.Example 
    PS C:\> Set-ClusterVMState.ps1 -VMList myvm1,myvm2 -State Running
    
    This example changes the state of both the VMs (myvm1 and myvm2) to RUNNING state.
    
.Example 
    PS C:\> Set-ClusterVMState.ps1 -VMName myvm* -State Running -VMHost myhost
    
    This example changes the state of all the VMs with their name starting with 'myvm' on host 'myhost' to RUNNING state.
	 
.Example 
    PS C:\> Set-ClusterVMState.ps1 -VMName myvm* -State Running -VMHost myhost -Asynchronous
    
     This example changes the state of all the VMs with their name starting with 'myvm' on host 'myhost' to RUNNING state asynchronously.
	
.Example 
    PS C:\> $VMs = Get-ClusterVMList.ps1 -State Running
			Set-ClusterVMState.ps1 -VMList $VMs -State Saved
    
    This example changes the state of all the RUNNING VMs in the cluster to SAVED state.
    
#>
param (

	[ValidateNotNullOrEmpty()]
	[Parameter(Mandatory=$FALSE, parameterSetName="VMName")]
    [System.String]
    $VMName = "*",
	
	[ValidateNotNullOrEmpty()]
	[Parameter(Mandatory=$FALSE, parameterSetName="VMList")]
    [System.String[]]
    $VMList,
	
	[ValidateNotNullOrEmpty()]
    [Parameter(Mandatory=$FALSE)]
    [System.String[]]
    $VMHosts,
    
	[ValidateSet("Saved", "Running", "Paused", "Stopped", IgnoreCase = $true)]
    [Parameter(Mandatory=$TRUE, HelpMessage="Saved, Running, Paused, Stopped")]
    [System.String]
    $State = "All",
	
	[Parameter(Mandatory=$FALSE)]
    [switch]
    $Asynchronous
	
	)
	
$ClusterService = get-service -Name "ClusSvc" -ComputerName localhost
if($ClusterService -eq $null -or $ClusterService.Status -ne "Running")
{
	Write-Error("Failover Clustering feature is not installed or the clustering service is not in RUNNING state")
	Exit -1
}

Import-Module FailoverClusters

$VMStateHashTable = @{"Running" = 2; 	"Stopped" = 3; "Saved" = 32769; "Paused" = 32768}

if($VMHosts -eq $null)
{
	$VMHosts = @(Get-ClusterNode | %{ $_.Name })
}


function Get-VMObjWithStatus([string]$Name,
					      [string]$Server,		
                         [string]$VMStatus)  
{

	$Name=$Name.replace("*","%")
	
	#Write-Host $Name $Server $VMStatus
	
	$WQL="Select * From MsVM_ComputerSystem Where ElementName Like '$Name' AND Caption Like 'Virtual%'"
	if($VMStatus.ToLower() -ne "all")
	{
		$WQL += " AND enabledState = $($VMStateHashTable[$VMStatus])"
	}
	
	#Write-Host $WQL
	$VMs = Get-WmiObject -computername $Server -NameSpace "root\virtualization" -Query $WQL
	
	return $VMs
}	

function ProcessWMIJob 
{  
    param 
    (  
        [System.Management.ManagementBaseObject]$Result 
    )  

    if ($Result.ReturnValue -eq 4096) 
    {  
        $Job = [WMI]$Result.Job 

        while ($Job.JobState -eq 4) 
        {  
            Write-Progress $Job.Caption "% Complete" -PercentComplete $Job.PercentComplete 
            Start-Sleep -seconds 1 
            $Job.PSBase.Get() 
        }  
		
        if ($Job.JobState -eq 7) 
        {
			Write-Progress $Job.Caption "Completed" -Completed $TRUE 
			return $TRUE
        }
		else
		{
			return $FALSE 
		}
    }  
    elseif ($Result.ReturnValue -ne 0) 
    {  
        return $FALSE 
    }  
}  

function Get-StateFromVMObj([System.Management.ManagementObject]$VMObj)
{
	$ret = "Unknown"
	
	switch($VMObj.enabledState)
	{
		2
			{
				$ret = "Running"
			}
		3
			{
				$ret = "Stopped"
			}
		32769
			{
				$ret = "Saved"
			}
		32768
			{
				$ret = "Paused"
			}
	}
	
	return $ret
}



function Change-VMState([System.Management.ManagementObject]$VMObj,
					[string]$DesiredState,
					[bool]$Asynchronous)
{
	if($VMObj)
	{
		$JobResult = $VMObj.RequestStateChange($($VMStateHashTable[$DesiredState]), $null)
		
		if($Asynchronous -eq $true)
		{
			return
		}
		
		if($JobResult.ReturnValue -eq 32775)
		{
			$CurrentState = Get-StateFromVMObj $VMObj
			$CurrentVM = $VMObj.ElementName
			Write-Warning("Invalid state change request. VM $CurrentVM is in $CurrentState state")
			return
		}
		
		$Completed = ProcessWMIJob($JobResult)
		if($Completed -eq $TRUE)
		{
			Write-Host ([string]::Format("Successfully changed the status of VM {0} to {1}", $VMObj.ElementName, $DesiredState))
		}
		else
		{
			Write-Error ([string]::Format("Changing the state of the VM {0} to {1} Failed", $VMObj.ElementName, $DesiredState))
		}
	}
}

if($VMList)
{
	foreach ($VM in $VMList)
	{
		$VMObjs += $VMHosts | % { Get-VMObjWithStatus $VM $_ "All"}
	}	
}

if($VMName)
{
	$VMObjs = $VMHosts | % { Get-VMObjWithStatus $VMName $_ "All" }
}

$VMObjs | % { Change-VMState $_ $State $Asynchronous}