Posts Tagged ‘Failover Cluster Powershell’

Powershell-Generate Automated CSVFreespace and Memory Report

December 4, 2014

This script relies the Hyper-V clusters are been managed by VMM but if you do not use VMM you can also modify based on your environment. It should just give you an idea how to collect data and use sentmail function to get a daily report of your resource status.

Note: script version 1.3 is targeted to be run as a task so no console outputs are considered, just a logfile is written into same folder where is script is located

as no user interaction is possible because we want to use this as a task following variables has to be updated in the script

$smtpServer = "YOURSMTP"
$smtpFrom = ""
$SMTPPort = "25"
$Username = ""
$Password = ‘YOURPASSWORD’
$smtpTo =

#Creator: Ramazan Can
#V1.2 	- dumping into log and generating mail with function "SentReportviaMail"
#		- mail sender, recipient, account for authentification can be modified in function "SentReportviaMail"
# 				$smtpFrom - $Username - $smtpTo 
#V1.3	- task scheduler version

#Write-Host " "
import-module virtualmachinemanager
import-module failoverclusters
$VMMClusters=(Get-SCVMHostCluster -vmmserver $VMMServer).Name
$timestamp=(get-date -Format d).Replace("/","_")
Get-item ".\CSVandMemory_Report_$timestamp.txt" -ea 0 | Remove-Item -ea 0

"This Report was run at $date " | out-file -filepath $logfile -append
" " | out-file -filepath $logfile -append

function GetCSVFreeSpace {
#incorporated and modified from
$objs = @()

$csvs = Get-ClusterSharedVolume -Cluster $Cluster
foreach ( $csv in $csvs )
   $csvinfos = $csv | select -Property Name -ExpandProperty SharedVolumeInfo
   foreach ( $csvinfo in $csvinfos )
      $obj = New-Object PSObject -Property @{
         Name        = $csv.Name
         Path        = $csvinfo.FriendlyVolumeName
         Size        = $csvinfo.Partition.Size
         FreeSpace   = $csvinfo.Partition.FreeSpace
         UsedSpace   = $csvinfo.Partition.UsedSpace
         PercentFree = $csvinfo.Partition.PercentFree
      $objs += $obj

$objs | ft -auto Name,Path,@{ Label = "Size(GB)" ; Expression = { "{0:N2}" -f ($_.Size/1024/1024/1024) } },@{ Label = "FreeSpace(GB)" ; Expression = { "{0:N2}" -f ($_.FreeSpace/1024/1024/1024) } },@{ Label = "UsedSpace(GB)" ; Expression = { "{0:N2}" -f ($_.UsedSpace/1024/1024/1024) } },@{ Label = "PercentFree" ; Expression = { "{0:N2}" -f ($_.PercentFree) }}

function SentReportviaMail {
$logfile=(Get-item ".\CSVandMemory_Report*" -ea 0).Name
$Logs=Get-Content $logfile
$smtpServer = "YOURSMTP"
$smtpFrom = ""
$SMTPPort = "25"
$Username = ""
$Password = 'YOURPASSWORD'
$smtpTo = ""
$messageSubject = "$VMMServer - Automated CSV FreeSpace and Total Memory Report"

[string]$messagebody = ""

foreach ($log in $logs )
	$messagebody = $messagebody + $log + "`r`n"
#Write-Host " "
#Write-Host "Starting to sent mail to $smtpTo via $smtpServer ...." -ForegroundColor green
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
#Write-Host "mail sent completed " -ForegroundColor green
#Write-Host " "

foreach ($Cluster in $VMMClusters)
	#Write-Host "Starting to collect memory and CSV free space data in $Cluster ....." -foregroundcolor green
	[int]$TotalFreeMemory = 0;
	[int]$TotalMemory = 0;
	$ClusterNodes = Get-Cluster $Cluster | Get-ClusterNode
	foreach ($ClusterNode in $ClusterNodes)
		[int]$FreeMemory = [math]::round(((Get-WmiObject -ComputerName $ClusterNode -Class Win32_OperatingSystem).FreePhysicalMemory / 1MB), 0)
		[int]$TotalFreeMemory = [int]$TotalFreeMemory + [int]$FreeMemory
		[int]$NodeMemory = [math]::round(((Get-WmiObject -ComputerName $ClusterNode -Class Win32_OperatingSystem).TotalVisibleMemorySize / 1MB), 0)
		[int]$TotalMemory = [int]$TotalMemory + [int]$NodeMemory


	$TotalAvailableMemory = $TotalFreeMemory - $NodeMemory
	"Cluster: $Cluster" | out-file -filepath $logfile -append
	"Total Memory: $TotalMemory" | out-file -filepath $logfile -append
	"Total Free Memory: $TotalFreeMemory" | out-file -filepath $logfile -append
	"Total Available Memory: $TotalAvailableMemory" | out-file -filepath $logfile -append
	" " | out-file -filepath $logfile -append
	"CSV Freespace : " | out-file -filepath $logfile -append
	GetCSVFreeSpace | out-file -filepath $logfile -append
	" " | out-file -filepath $logfile -append

example output mail:


Disclaimer: Please read, understand and test script before you run put in production! This should just give you an idea around the power of powershell and automation



Powershell – How to get total VM memory overview (dynamic, static and startup memory) per node in a cluster?

June 16, 2014

Host Memory Pressure – I think this is one of the keys (in addition to storage, network, CPU) in performance when running virtualization with dynamic memory and should be monitored. An balance between high density of running VMs on a host and memory calculation/demand is something to consider when managing self service clouds and/or running memory intensive workloads.

Write-host " "
Write-Host " "
$Cluster = Read-Host "Cluster Name "
Write-Host " "
Write-Host "Starting to check VM Memory pressure on $Cluster nodes " -ForegroundColor green
Write-Host " "
Write-Host "Collecting data like nodes, VMs Memory….please be patient" -ForegroundColor green
Write-Host " "
Write-Host " "
$Hostnames=(Get-Cluster $Cluster | Get-ClusterNode).Name

foreach ($Host1 in $Hostnames) {
[int]$hostmem=@{} | Out-Null
[int]$totalstartupmem=@{} | Out-Null
[int]$totalmaxmem=@{} | Out-Null
[int]$staticmemory=@{} | Out-Null
[int]$overcommited=@{} | Out-Null
[int]$totalramrequired=@{} | Out-Null

$AllVMs=(get-vm -ComputerName $Host1).Name
$Hostmem=(Get-VMhost -ComputerName $Host1).MemoryCapacity / 1024 / 1024 / 1024

foreach ($VM in $AllVMs) {
$CurrentVM=(get-VM $VM -ComputerName "$Host1" | fl *)
if ((Get-VMMemory -vmname $VM -ComputerName "$Host1").DynamicMemoryEnabled -eq "True") {
$memorystartup=(get-vm $VM -ComputerName "$Host1" | select-object MemoryStartup).MemoryStartup /1024 / 1024 / 1024
$MemoryMaximum=(get-vm $VM -ComputerName "$Host1" | select-object MemoryMaximum).memorymaximum /1024 / 1024 / 1024
$totalstartupmem += $memorystartup
$totalmaxmem += $MemoryMaximum
else {
$static=(get-vm $VM -ComputerName "$Host1" | select-object MemoryStartup).MemoryStartup /1024 / 1024 / 1024
$staticmemory += $static
$totalramrequired=$totalstartupmem + $staticmemory

write-host "Summary Report for Host $Host1" -foregroundcolor green
write-host "Total Startupmem for Dynamic VMs $totalstartupmem GB " -foregroundcolor green
write-host "Total Staticmem for Static VMs $staticmemory GB " -foregroundcolor green
write-host "Total minimum RAM (Startup+Static) required $totalramrequired GB " -foregroundcolor yellow
write-host "Total Maxmem for Dynamic VMs $totalmaxmem GB " -foregroundcolor yellow
write-host "Total available memory $Hostmem GB " -foregroundcolor green
if ($totalmaxmem -gt $Hostmem) {Write-Host "$Host1 is overcomitted " -foregroundcolor red}
write-host " "
write-host " "


This is just one way to get a total summary per node in your Hyper-V cluster and their configured memory demand. It provides a quick view on memory utilization of your Hyper-V nodes. Be creative and modify based on your needs.

Disclaimer: Please read and test script before you run in your production!

Dynamic Memory Pressure Monitoring:

…a “bad” configuration can result in “bad” performance 🙂

Stay tuned…

How to configure Preferred Owners and AutoFailback with Powershell in Failover Cluster?

April 7, 2014

Consider scenario, you “balanced” your VMs across your nodes and you come back in the morning and they are migrated “for whatever reason” to different nodes. But as a typical administrator 😉 you know your workload best and you want to keep them preferred on a targeted node. In case of an unexpected reboot the VMs will get migrated to next available node in your Failover Cluster and goal is as soon as the node is back the VM should automatically fail back = PreferredOwners. 

Here is a quick example where you configure all clustered VM roles in a targeted cluster for preferred owners based on the current owner node. this should only give you an idea how things can be automated very easily with Powershell:

$Cluster = Read-Host "Cluster Name "
$Praefix = Read-Host "Please provide präfix for your clustered VM role names (a.e.SCVMM) "
Write-Host " "
Write-Host "Getting all clustered VM roles and configure Preferred Owners in cluster $Cluster" -ForegroundColor yellow
Write-Host " "
Write-Host " "
$AllClusterGroup = Get-ClusterGroup -Cluster $Cluster -Name $Praefix*

Write-Host "….running loop for all Clustered VMs"
Write-Host " "
Write-Host " "
foreach ($ClusterGroup in $AllClusterGroup)
    $ClusterGroupDetails = Get-ClusterGroup -Name "$ClusterGroup"
    Write-Host "Getting current Owner for $ClusterGroup…." -ForegroundColor yellow
    $CurrentOwner = $ClusterGroupDetails.OwnerNode.Name

    Set-ClusterOwnerNode -Group $ClusterGroup $CurrentOwner
    Write-Host "Current owner for VM $ClusterGroup is $CurrentOwner, configure Preferred Owner…done" -ForegroundColor yellow
    #Enable Autofailback
    (Get-ClusterGroup -Name "$ClusterGroup").AutoFailbackType=1
    Write-Host "Enabling Autofailback VM $ClusterGroup…done" -ForegroundColor yellow
    Write-Host " "

Disclaimer: Please read and test script before you run in your production, this reconfigures the preferred owner property at all your clustered VM roles in your cluster !!

There are more options how you can control clustered roles, like “AntiAffinityClass” – when a group is moved during failover, anti-affinity affects the algorithm used to determine the destination node. a.e. never run together at same node…

Here are just a few more good resources around failover options in a Failover Cluster:

Preferred Owners in a Cluster

Failover behavior on clusters of three or more nodes

Understanding Hyper-V Virtual Machine (VM) Failover Policies

Modify the Failover Settings for a Clustered Service or Application

Configure Failover and Failback Settings for a Clustered Service or Application


Using Guest Clustering for High Availability

How to use Powershell in Failover Clustering–Part 1

August 5, 2011

Powershell is a really powerful toy for any Windows administrator where tasks need to be automated and or repeated several times.

Here I would like to start an blog series of how to use Powershell in Windows Server Failover Cluster (WSFC) environments.

Let’s start over with some basic commandlet’s to get status of clustered groups, resources and cluster core resources, move groups and soon. Later we will do some advanced operations with Powershell.

The WSFC Powershell (CLI) interface is everywhere available where WSFC feature is installed:

  • Windows Server 2008 R2 (SP1)
    • Full
    • Core (not installed by default)
  • Microsoft Hyper-V Server 2008 R2 (SP1)
  • Remote Server Administration Tools (RSAT) for Windows 7 (SP1)

First of all, you must import the “FailoverCluster” module to get the commandlet’s. To get a list of all available modules you can use:

PS:\ Get-Module -ListAvailable


To import the module you need to use “Import-Module” commandlet:

PS:\ Import-Module FailoverClusters


YUHUU Smile We have now the full set of all Failover Cluster commandlet’s available, let’s have a look which they are:

PS:\ Get-Command –Module FailoverClusters or Get-Command | findstr Cluster



As you can see, there are for the most of the GUI actions an cmdlet available, sometimes more. In total there are 69 Failover Cluster specific cmdlet’s which gives you many many *creative* usage ways.

NOTE: A really helpful method with Powershell is the Get-Help cmdlet:
Built-in help:
Get-Help cmdlet -Full
Get-Help cmdlet –Examples
Online help (INET connection is required):
Get-Help cmdlet –Online

Let’s start with some easy commandlet to do some basic operations:

How to get a list of all clustered groups via Powershell?

PS:\ Get-ClusterGroup



As you can see I do have some resources offline. Let’s bring them online

How to bring online a Cluster Group via Powershell?

PS:\ Start-ClusterGroup “GROUPNAME” image

Now, let’s move a group to a different node to balance the workloads in my *test* cluster Smile

How to move a cluster group via Powershell?

PS:\ Move-ClusterGroup “GROUPNAME” –Node “NODENAME”


How to get a list of all clustered resources via Powershell?

PS:\ Get-ClusterResource


How to get a list of all clustered groups from an node via Powershell?

PS:\ Get-ClusterNode –Name “NODENAME” | Get-ClusterGroup


How to get a list of all clustered resources within a cluster group via Powershell?

PS:\  Get-ClusterGroup "GROUPNAME" | Get-ClusterResource


How to get more parameters from a clustered disk (resource)?

PS:\ Get-ClusterResource "Cluster Disk 1" | Get-ClusterParameter



How can I test/validate my cluster via Powershell?

Since R2 you can also validate your cluster via CLI Powershell:

PS:\ Get-Help Test-Cluster

A.e.: PS:\ Test-Cluster –Node Node1,Node2



A list of all available Test-Cluster scenarios – which can be *in-/excluded*- can you find here:


Hope this has opened your interest in more around Powershell for Failover Clustering – stay tuned for more or start with playing with PS…..Winking smile

Some additional reference can you find here:

Mapping Cluster.exe Commands to Windows PowerShell Cmdlets for Failover Clusters

PowerShell Quick Reference

Clustering with PowerShell

PowerShell for Failover Clustering: Finding the Drive Letter

PowerShell for Failover Clustering: Understanding Error Codes

PowerShell for Failover Clustering: Frequently Asked Questions


Ramazan Can

Alle 20 Minuten ein Event ID 1069 und 1558?

May 15, 2011

HINWEIS: Da der Event 1069 sehr “generisch” ist und auf unterschiedliche Fehlerquellen zeigen kann, ist dies nur eine mögliche Beispiellösung und soll als Erfahrungsbericht dienen. Zum Verfizieren, ob dieser Artikel bei Eurem Problem helfen kann, bitte die Cluster Logs überprüfen nach “’Failed to create cluster directory on witness”!


Bei einem Kunden hatten wir etwa alle 20 min die Events 1069 und 1558, obwohl es mit dem Quroum Laufwerk – Cluster Ressource online – keine sichtbaren Probleme gab und wir es auch ohne Probleme auf andere Knoten verschieben konnten.

Event ID 1069 — Clustered Service or Application Availability

Event ID 1558 — Cluster Witness Functionality

Nach weiterer System und Cluster Log Analyze habe ich folgenden interessanten Hinweis entdeckt:

ERR mscs::QuorumAgent::PostOnline: ERROR_PATH_NOT_FOUND(3)’ because of ‘Failed to create cluster directory on witness, path \\?\Volume{5c65f7b0-15e4-11e0-b316-002655db949a}\Cluster

Dies deutet auf einen Fehler hin, das der Cluster Service nicht auf die Quorum Disk zugreifen (schreiben/lesen) konnte und daher wir auch die Events 1069/1558 erhalten haben.

Da die Quorum Struktur (Cluster Hive=Cluster Konfiguration) “redundant” im Cluster verfügbar ist und diese auch durch die Quorum Konfiguration manuell neu generiert werden kann, war die Lösung in meimem Falle, ganz einfach:


1. Quorum Modell temporär geändert damit Qurom Disk “Q:” aus Cluster entfernt werden konnte



2. Quorum Disk aus Cluster entfernt, Neu-formatiert und wieder Cluster hinzugefügt

3. Quorum Konfiguration wiederhergestellt – in meinem Falle Node und Disk Majority


Ergebnis: Die Cluster DB wurde neu auf der Quorum erstellt


Nachdem die Cluster “Hive” auf der Quorum Disk erfolgreich erstellt worden ist, waren die Einträge im Cluster Log verschwunden und auch die Eventlogs wieder sauber.


Generelle Informationen zu Cluster Logs sind zu finden unter:

How to create the cluster.log in Windows Server 2008 Failover Clustering

Troubleshooting Cluster Logs 101 – Why did the resources failover to the other node?

Introduction to Cluster Diagnostics and Verification Tool for Exchange Administrators

Viele Spass beim “Troubleshooten” Winking smile



Powershell–How to write your own custom functions in Powershell?

May 15, 2011

How to write your own functions within Powershell?

As most of you knows, Powershell is a really powerful toy for administrators which are dealing with a lot of systems. Most of the time, you do same operations and need to write your own scripts. I usually use here the "function" method to build my own Powershell functions which I call later in my script anytime.

Function Example: Enumerate all drives/partitions on a server
function GetDrives
    Get-WmiObject Win32_DiskPartition | select-Object Name, VolumeName, DiskIndex, Index 

Function Example: Start all VMs
function StartVM ([string]$VMName) {
    write-host (‘INFOTEXTBOX: Starting all VM now: ‘+$VMName)
    Get-VM -Suspended $VMName | Start-VM -Force
    Get-VM -Stopped $VMName | Start-VM -Force
    while (!(Get-VM $VMName -Running)) {sleep 1}

Function Example: Cleanup or Remove all VM
function RemoveVM ([string]$VMName) {
    write-host (‘INFO: Remove VMs now:’+$VMName)
    Get-VM $VMName| Remove-VM -force | Out-Null
    while (Get-VM $VMName) {sleep 3}

Function Example: Remove ISO drive from VM
function RemoveISO ([string]$VMName) {
    $DVD=Get-VMDisk $VMName | Where-Object {$_.DriveName -like ‘DVD Drive’} | Where-Object {$_.DiskImage -like ‘*.iso’}
    if ($DVD) {
        ForEach ($actDVD in $DVD) {
            write-host (‘INFO: Remove Mounted ISO from VM ‘+$VMName)
            Remove-VMDrive $VMName -ControllerID $actDVD.ControllerID -LUN $actDVD.DriveLUN -DiskOnly | Out-Null

These are examples for Hyper-V and Cluster Environments where we do utilize command like  “Remove-VMDrive” or “Get-VM” from the Powershell Hyper-V library module from Codeplex or built in Failover Cluster module.

PowerShell: calling a function with parameters

PowerShell Tutorial 10: Functions and Filters

Stay tuned for further PS examples Winking smile