Adding disks into a cluster using PowerShell

With Windows 2008 R2, we now have the option to use PowerShell when you want to look at things in the cluster from a command line along with the cluster.exe command. If you want to add a disk to a cluster using PowerShell, there are several different options.


In my previous article, I explained how to add a disk in Windows 2008. This still applies to 2008 R2, but if you’re more comfortable using PowerShell, here are a couple of ways to do this. I am a novice PowerShell user so my examples are just some of the ways of accomplishing this task. Of course there are other ways to do it, so feel free to leave comments with your examples.


If you’ve got a disk that shows up as an available disk, adding a disk through PowerShell is very straight forward. Here’s how we can check to see if there are any available disks for cluster:


PS C:\> Get-ClusterAvailableDisk

Cluster    : MyCluster
Name       : Cluster Disk 2
Number     : 6
Size       : 17425367040
Partitions : {X:}
Id         : 0xB6F579CA
                                                                                   

For this disk, the easiest way to add it to the cluster would be to use the following command:


PS C:\> Get-ClusterAvailableDisk | Add-ClusterDisk

Name                          State                         Group                         ResourceType
----                          -----                         -----                         ------------
Cluster Disk 2                OnlinePending                 Available Storage             Physical Disk


This command would add all disks from the Get-ClusterAvailableDisk output into the Available Storage group in your cluster using the default (terrible) naming convention for cluster disks. This is a nice little command to quickly add disks to the cluster. However, if you’re in a situation where the disk is NOT showing up in the Get-ClusterAvailableDisk output, like in a multi-site cluster, we’ll need to work a little harder to add the disk into the cluster. Previously, I showed how this was done using cluster.exe so we can apply these same concepts to PowerShell. First, we’ll create the empty resource:


PS C:\> Add-ClusterResource -Group "Available Storage"

cmdlet Add-ClusterResource at command pipeline position 1
Supply values for the following parameters:
Name: Disk X:
ResourceType: Physical Disk

Name                          State                         Group                         ResourceType
----                          -----                         -----                         ------------
Disk X:                       Offline                       Available Storage             Physical Disk


In this example, the Add-ClusterResource command prompted me for the missing parameters for the command. I manually specified the Disk X: value and the Physical Disk resource type. I can avoid having to manually enter these by specifying the -Name and -ResourceType values in the command:


PS C:\> Add-ClusterResource -Name "Disk X:" -ResourceType "Physical Disk" -Group "Available Storage"
	
Name                          State                         Group                         ResourceType
----                          -----                         -----                         ------------
Disk X:                       Offline                       Available Storage             Physical Disk


So at this point, I have an empty disk resource with no parameters to identify the disk:


PS C:\> Get-ClusterResource "Disk X:" | Get-ClusterParameter

Object                        Name                          Value                         Type
------                        ----                          -----                         ----
Disk X:                       DiskIdType                    5000                          UInt32
Disk X:                       DiskSignature                 0x0                           UInt32
Disk X:                       DiskIdGuid                                                  String
Disk X:                       DiskRunChkDsk                 0                             UInt32
Disk X:                       DiskUniqueIds                 {}                            ByteArray
Disk X:                       DiskVolumeInfo                {}                            ByteArray
Disk X:                       DiskArbInterval               3                             UInt32
Disk X:                       DiskPath                                                    String
Disk X:                       DiskReload                    0                             UInt32
Disk X:                       MaintenanceMode               0                             UInt32
Disk X:                       MaxIoLatency                  1000                          UInt32
Disk X:                       CsvEnforceWriteThrough        0                             UInt32
Disk X:                       DiskPnpUpdate                 {}                            ByteArray



I would then need to issue the following command in order to set the DiskPath value and query the output:


PS C:\> Get-ClusterResource "Disk X:" | Set-ClusterParameter DiskPath "X:"

PS C:\> Get-ClusterResource "Disk X:" | Get-ClusterParameter

Object                        Name                          Value                         Type
------                        ----                          -----                         ----
Disk X:                       DiskIdType                    5000                          UInt32
Disk X:                       DiskSignature                 0x0                           UInt32
Disk X:                       DiskIdGuid                                                  String
Disk X:                       DiskRunChkDsk                 0                             UInt32
Disk X:                       DiskUniqueIds                 {}                            ByteArray
Disk X:                       DiskVolumeInfo                {}                            ByteArray
Disk X:                       DiskArbInterval               3                             UInt32
Disk X:                       DiskPath                      X:                            String
Disk X:                       DiskReload                    0                             UInt32
Disk X:                       MaintenanceMode               0                             UInt32
Disk X:                       MaxIoLatency                  1000                          UInt32
Disk X:                       CsvEnforceWriteThrough        0                             UInt32
Disk X:                       DiskPnpUpdate                 {}                            ByteArray


At this point, I would bring the disk online and the cluster will then perform its magic to translate the DiskPath into the DiskSignature and other properties of the disk. Much like cluster.exe, I can use PowerShell to online the disk using the Start-ClusterResource command:


PS C:\> Start-ClusterResource "Disk X:"

Name                          State                         Group                         ResourceType
----                          -----                         -----                         ------------
Disk X:                       Online                        Available Storage             Physical Disk

PS C:\> Get-ClusterResource "Disk X:" | Get-ClusterParameter

Object                        Name                          Value                         Type
------                        ----                          -----                         ----
Disk X:                       DiskIdType                    0                             UInt32
Disk X:                       DiskSignature                 0xB6F579CA                    UInt32
Disk X:                       DiskIdGuid                                                  String
Disk X:                       DiskRunChkDsk                 0                             UInt32
Disk X:                       DiskUniqueIds                 {16, 0, 0, 0...}              ByteArray
Disk X:                       DiskVolumeInfo                {1, 0, 0, 0...}               ByteArray
Disk X:                       DiskArbInterval               3                             UInt32
Disk X:                       DiskPath                                                    String
Disk X:                       DiskReload                    0                             UInt32
Disk X:                       MaintenanceMode               0                             UInt32
Disk X:                       MaxIoLatency                  1000                          UInt32
Disk X:                       CsvEnforceWriteThrough        0                             UInt32
Disk X:                       DiskPnpUpdate                 {0, 0, 0, 0...}               ByteArray


Much like using the DiskPath value with cluster.exe, the cluster identifies the mount point specified in the DiskPath property value and then updates the cluster disk resource properties.


As this is PowerShell, we can combine the creation of the resource, setting of the private properties and the online of the resource all in one big, ugly command:


PS C:\> Add-ClusterResource -Name "Disk X:" -ResourceType "Physical Disk" -Group "Available Storage" |Set-ClusterParameter DiskPath "X:" ; Start-ClusterResource "Disk X:"

Name                          State                         Group                         ResourceType
----                          -----                         -----                         ------------
Disk X:                       Online                        Available Storage             Physical Disk


If you want more info on other available PowerShell commands for use with Failover clustering, I’d recommend reviewing this article which maps cluster.exe commands to their equivalent PowerShell commands.

5 thoughts on “Adding disks into a cluster using PowerShell”

  1. Wondering if you can assist.

    I am trying to write a PS script to create a cluster and add a fileserver resource to it if it asked for.

    I tried to use the new-cluster command but there is no parameter to control which disk it picks for the witness disk so I am trying it by using the -NoStorage parameter and the add the disks in a more controlled manner.

    I have 5 disks on a test cluster. I want to first add the disk that will be my quorum, our standard is drive letter Q.

    A Get-ClusterAvailableDisk | fl *
    command gives me,

    Cluster : u0132130-a01c
    Name : Cluster Disk 1
    Number : 1
    Size : 526417920
    Partitions : {Q:}
    Id : 0x3769E2E1

    Cluster : u0132130-a01c
    Name : Cluster Disk 2
    Number : 2
    Size : 5371107840
    Partitions : {E:}
    Id : 0x3769E2E0

    Cluster : u0132130-a01c
    Name : Cluster Disk 3
    Number : 3
    Size : 5371107840
    Partitions : {F:}
    Id : 0x3769E2E2

    Cluster : u0132130-a01c
    Name : Cluster Disk 4
    Number : 4
    Size : 1077511680
    Partitions : {G:}
    Id : 0x3769E2E7

    Cluster : u0132130-a01c
    Name : Cluster Disk 5
    Number : 5
    Size : 1077511680
    Partitions : {H:}
    Id : 0x3769E2E3

    I want to isolate the Q disk by filtering on partitions property but having trouble with the where clause working.

    Get-ClusterAvailableDisk | ? { $_.Partitions -contains “Q” } | fl *

    I have tried -contains, -eq, -like and I can not isolate the Q disk.

    If I can filter this, then I will add just this volume and then proceed to configure the quorum configuration then add the rest of the disk after that is done.

    Can you assist me with the partitions filter?

    What am I doing wrong?

    Thx

  2. Has anyone an idea how to identify a disk when the disk does not have a drive letter?
    We have 22 drives on our Fileserver-Cluster and another 22 drives for Snapshots without a drive letter. We need to get the right disk for each service, so we know which service to take down if a LUN in the SAN will go in maintenance.

Leave a Reply

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


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>