Using the CIM Cmdlets in Windows PowerShell to solve a challenge

Introduced in PowerShell 3.0 and further enhanced in PowerShell 4.0, the CIM (Common Information Model) Cmdlets makes it easier to work with WMI (Windows Management Instrumentation). You can find an introduction to the new CIM Cmdlets in this article on the Windows PowerShell Teams blog.

In this article we will look at a usage scenario for the new CIM Cmdlets.

The Challenge

When adding a disk to a Windows Failover Cluster, the clustered disk is added to the cluster as a resource. The resource is automatically named “Cluster Disk N”, where N is the first available number. The challenge we are going to solve is renaming the newly added cluster disk based on the name (File System Label) of the underlying disk volume. This is typically an NTFS volume which is initialized and formatted before the disk is added to the cluster:

image

Using the Failover Cluster Manager in Windows Server we can view the name of the underlying volume:

image

Based on this observation we can manually rename the cluster resource. However, in a large cluster with many disks this task is a good candidate for automation.

Solving the challenge using CIM Cmdlets

By using the Get-ClusterResource cmdlet in the FailoverClusters PowerShell module we can view information about the disk, but there isnt an easy way to view the name of the underlying volume.

Due to that, we can rather leverage the Get-CimInstance cmdlet to list all cluster resources in the MSCluster_Resource class:

image

We use the –Filter parameter to specify that we only want cluster resources of the type “Physical Disk”, if not we would also get cluster resources such as cluster IP addresses, cluster names and so on.

Based on the information available on the object produced by Get-CimInstance, we can see many cluster related properties. However, no information about the underlying volume is available.

There is one cmdlet in the CIMCmdlets module which can get all the associated instances for a particular instance – the Get-CimAssociatedInstance cmdlet. In this scenario, we want to find all related volumes for the cluster disks. We start by finding all related instances:

image

This produced a large list of different kind of objects. We can use Get-Member to view information about the objects, and Select-Object to view the unique object types:

image

Based on the above output, the MSCluster_DiskPartition looks like a good candidate. We can use the –ResultClass parameter of Get-CimAssociatedInstance in order to narrow down the results to the class we want:

image

This is excactly what we want, as we can see the VolumeLabel property on the above output.

Now that we have the information we want – the VolumeLabel property – we need to find a way to rename the cluster resource (“Cluster Disk 1”). We can start by looking for a Rename method on the MSCluster_DiskPartition object. Normally, we would use Get-Member to view the available methods:

image

Since the CIM cmdlets is using the Ws-Man (WS-Management) protocol, the objects we get returned is serialized/deserialized. Thus the objects methods is remove since we arent working with a “live” object. The Get-CimClass cmdlet can be used to get the class schema of a CIM class, which includes the methods.
Instead let`s try the Get-CimClass cmdlet to view the methods available on the mscluster_resource class:

image

As we can see, there is a Rename method which takes one parameter: newName.

In order to invoke the method, we can use the Invoke-CimMethod cmdlet where we specify Rename as the MethodName and provide the value we want to configure as a hash table on the Arguments parameter:

image

We provided the VolumeLabel property returned by the Get-CimAssociatedInstance cmdlet as the value for the newName parameter, effectively solving the challenge.

After invoking the method, we can see the name of the cluster disk is immediately updated in Failover Cluster Manager:

image

When working with multiple cluster disks, we can use a foreach loop in order to invoke the rename method for all disks  if the name of the cluster resource does not match the name of the underlying disk volume:

Resources

How to configure AntiAffinityClassNames in Failover Clustering using Windows PowerShell

AntiAffinityClassNames is a cluster group property in Windows Failover Clustering used to identify cluster groups that should not be hosted on the same node. When working with clustered Hyper-V environments there is a 1:1 relationship between a cluster group and a virtual machine, and thus we can configure Anti-Affinity for virtual machines using the AntiAffinityClassNames property. For more information, see the links in the resource section in the bottom of the article.

What I want to show in this article is how to configure the AntiAffinityClassNames property using PowerShell. Most articles I have seen in regards to AntiAffinityClassNames covers how to use cluster.exe to configure the property, and since the cluster.exe was deprecated in Windows Server 2008 R2 (it`s still available as a deprecated command) it might be a good idea to learn how to configure this using the new Failover Clustering PowerShell module. In addition you also get other benefits available in PowerShell such as pipelining, export/import to/from different data sources, grouping and so on.

AntiAffinityClassNames is a property of a cluster group, but before we configure the property we need to look at what type it is. We can do this by piping the output of Get-ClusterGroup to the Get-Member cmdlet:

image

We can see in the definition of the property that it is a System.Collections.Specialized.StringCollection type. This means we can not just pass a text string as the property value, we need to create a object of the correct type. The reason this property is not just a System.String (text string) is that a Cluster Group can have more than one AntiAffinityClassNames values. System.Collections.Specialized.StringCollection has a method called Add which can be used to to add values to the collection. Here is a complete example on how to create such an object, add a couple of values to it and at the end assign it to the AntiAffinityClassNames property of a cluster group:

Note that this will overwrite any existing values. As we can see it is not very hard to configure a new value, but it might be harder if you want to preserve existing values remove single items of the existing value and so on. In order to make this easier I have created a PowerShell module which contains 3 script cmdlets for managing AntiAffinityClassNames:

image

As you can see in the cmdlet help there is support for pipeline input, which makes it possible to configure the AntiAffinityClassNames values based on input such as a CSV-file:

image

I have also provided examples for the script cmdlets:

image

 

Installing the AntiAffinityClassNames module

Download and unzip AntiAffinityClassNames.zip in the following location: %userprofile%DocumentsWindowsPowerShellModulesAntiAffinityClassNames

Alternatively you may save the module in any of the folders in the $Env:PSMODULEPATH variable or import the module from a custom path (Import-Module <path>AntiAffinityClassNames). Here is some more examples to get you started:

 

Resources

MSDN: AntiAffinityClassNames

Failover behavior on clusters of three or more nodes

Understanding Hyper-V Virtual Machine (VM) Failover Policies

Private Cloud: Configuring anti-affinity between VMs on Hyper-V 2008 R2 SP1 and VMM 2012

How to automatically avoid running Exchange VMs on the same Hyper-V server after a host failure

Get started with the Failover Clustering PowerShell-module

Enable Persistent Mode for Cluster Resource Groups using the PowerShell Failover Clustering module

Enable Persistent Mode for Cluster Resource Groups using the PowerShell Failover Clustering module

In Failover Clustering in Windows Server 2008 R2, Persistent Mode is intended to allow resource groups to come online on the node which an admin last moved them to. This setting is enabled by default when a virtual machine is created with Failover Cluster Manager. If you create virtual machine via System Center Virtual Manager this setting is not enabled.

By default, cluster roles have this setting disabled, except for Hyper-V virtual machine cluster roles, which have this enabled by default. This setting is useful when the cluster is shutdown and later started, in order to better distribute the resources across the nodes and allow them to come online faster, as they were likely spread across the nodes before the cluster was offlined. Otherwise, all the resources will attempt to restart on the first nodes which achieve quorum and compete for resources. This only applies to a group if it did not failover after being placed by the administrator. If a group has failed over since the last administrator placement, it is brought online on the node which the administrator last move it to.

Reference and more info regarding the Auto Start, Persistent Mode and Group Wait Delay features is available on the Clustering and High-Availability blog.

Auto Start can be enabled/disabled in bulk by marking all Cluster Resource Groups in Failover Cluster Manager and selecting “Enable auto start”/”Disable auto start”.

For Persistent Mode the only available option in Failover Cluster Manager is to right click each Cluster Resource Group and selecting/de-selecting the checkbox for “Enable persistent mode”:

image

To change this setting for all Cluster Resource Groups in an automated fashion you can use the Failover Cluster module for PowerShell, which I wrote an introduction to here.

Here is an example on how you can do this:

001
002
003
004
005
006
007
Import-Module FailoverClusters
$clustergroups = Get-ClusterGroup -Cluster cluster01.domain.local
foreach ($clustergroup in $clustergroups) {
#To enable persistent mode: x To disable persistent mode: 4294967295
$clustergroup.DefaultOwner=x
}

Although you can change the Auto Start setting in bulk in Failover Cluster Manager you might also want to do this in an automated fashion:

001
002
003
004
005
006
007
Import-Module FailoverClusters
$clustergroups = Get-ClusterGroup -Cluster cluster01.domain.local
foreach ($clustergroup in $clustergroups) {
#To enable Auto Start: 1 To disable Auto Start: 0
$clustergroup.Priority=1
}

You can also change the Group Wait Delay cluster-wide property from the PowerShell Failover Clustering module, how to do this is explained in the above referenced blog-post from the Clustering and High-Availability blog.

For the next version of System Center Virtual Machine Manager I would expect that Persistent Mode is enabled by default, since Microsoft do recommend customers to enable this setting.

Update 08.12.2011: The value of the DefaultOwner property for configuring Persistent Mode is the number of the node you want to be the default owner. In example a value of 1 means the first node in the cluster.

Get started with the Failover Clustering PowerShell-module

In Windows Server 2008 R2 the Failover Clustering feature contains a Windows PowerShell-module for administering Failover Clusters. This module replaces the old cluster.exe tool which existed in previous versions of Windows Server.

The cmdlets in the Failover Clustering module for PowerShell are well documented on Microsoft TechNet: “Using Windows PowerShell Cmdlets on Failover Clusters in Windows Server 2008 R2”.

There is also a guide on “Mapping Cluster.exe Commands to Windows PowerShell Cmdlets for Failover Clusters”, which a member of the File Server team at Microsoft, Jose Barreto, has posted additional details on in a blog-post.

I recently created two new Failover Cluster for Hyper-V, and leveraged the Failover Clustering PowerShell module. Here is a sample on how easy it is to accomplish this:

001

002 

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

 

#Import Server Manager module

Import-Module ServerManager 

# Add Failover Cluster and Hyper-V (requires a reboot)

Add-WindowsFeature “Failover-Clustering”,“Hyper-V”

#Configure networks in Hyper-V before moving on

#Import Failover Clustering module

Import-Module FailoverClusters

#Create cluster validation report

Test-Cluster -Node Node01,Node02

#Inspect cluster validation report before moving on

#Create a new failover cluster

New-Cluster -Name Cluster01 -Node Node01,Node02 -StaticAddress 10.10.10.10

#Inspect available cluster disks

Get-ClusterAvailableDisk -Cluster Cluster01

#Add all available cluster disks

Get-ClusterAvailableDisk -Cluster Cluster01 | Add-ClusterDisk

#Configure cluster quorom

Set-ClusterQuorum -Cluster Cluster01 -NodeAndDiskMajority “Cluster Disk 01″

#Enable Cluster Shared Volumes

(Get-Cluster -Name Cluster01).EnableSharedVolumes=“Enable/NoticeRead”

#Add Cluster Shared Volume

Add-ClusterSharedVolume -Cluster Cluster01 -Name “Cluster Disk 02″

#Make VM 01 Highly Available

Add-ClusterVirtualMachineRole -Cluster Cluster01 -VirtualMachine “VM 01″ -Name “VM 01″

#Test cluster failover on VM 01

Move-ClusterVirtualMachineRole -Cluster Cluster01 “VM 01″ -Node Node02

Before running the commands in the example above, you must install the operating system and configure disks and networking for Failover Clusters according to the product documentation on Microsoft TechNet. If you are using a Windows Server 2008 R2 Core edition, the Core Configurator 2.0 might be handy if you`re not comfortable configuring IP-addresses and so on from the command line.


Additional resources

Failover Clustering and Network Load Balancing Team Blog

Cluster Related Sessions at TechEd Berlin 2010

Joachim Nässlander (Cluster MVP)

John Toner (Cluster MVP)