Adding Disk to Cluster

Adding Disk to Cluster

Rate This
  • Comments 4

Windows Cluster 2008 provides multiple ways of adding a disk to an existing cluster. This article will walk you through all the available choices.

Some Fundamentals:

Windows Server 2008 Failover Clustering (WSFC) supports both GPT and MBR disks.  There now exists a core resource group called “Available Storage” which functions a single container that will have all the available disks that can be used when creating various roles. When we create or Configure a Service or Application, the wizard allows you to select your disk from the list of “Available Storage”.  You can also add a disk to an existing group at a later time.  This list also dynamically updates with the addition or removal of available disks.

Cluster.exe and Cluster WMI are the other two interfaces for people who think they need more control over the resources they want to add and manipulate, but these are not necessarily intuitive. To some extent WMI takes care of the complicated processes, but when using cluster.exe you are on your own and have little guidance.

There are three ways to add a Disk to an existing cluster:

1.       Failover Cluster Management snap-in (GUI)

2.       Cluster.exe command line tool

3.       Cluster WMI Classes

 

 Failover Cluster Management snap-in:

Here is a screenshot from Cluster Administrator:

vikas1-1

When you navigate to the Storage branch in the left pane you have a complete view of all the disks available along with their utilization and owners.  This is an easy way to see how the disks are being used.

Witness Disk in Quorum:

WSFC supports 4 types of Quorum modes. Quorum is a membership view of the cluster which ensures that nodes host the correct applications and don’t write to the same disk. The quorum disk holds a copy of the cluster database and can be assigned a ‘vote’ for some quorum modes.  It is used as the only ‘vote’ with the No Majority: Disk Only mode, however this quorum configuration is not recommended as this disk becomes a single point of failure.

Available Storage:

This is the group of Disks that are available and can be used when creating a new highly available workload.

Add Disk:

This action button in the right navigation pain will show you a list of disks that are available and can be added to the cluster. You get the following screen when you click on "Add Node":

 vikas1-2

This Dialog box shows you all the disks that can be added to the cluster. As a user you need to select the disks that you want to add, by default all the disks are selected.  You are ready, click "OK" to add all the selected disks to the cluster and bring them online.

Isn't this simple and intuitive?

 

Cluster.exe (Command line tool):

When using Cluster Administrator to add a Disk, the following steps are carried out by the Failover Cluster Management tool. When using cluster.exe, these have to be done manually.

 Steps are:

1.       Adding a resource of type "Physical Disk".

2.       Setting the private properties of the resource, like DiskSignature or DiskGUID.

3.       Bringing the resource Online.

Let’s go through these steps with an example:

To create a resource using cluster.exe on the cluster node we need to provide few parameters

          >Cluster.exe res resource-name /CREATE /GROUP:group-name /TYPE:res-type

Resource-name: A name that you want to give to your resource.

/GROUP: This is the name of the group where you want the resource to be created. We suggest using "Available Storage" as the group name.

/Type: This is the type of resource we are creating. For disk we would be using "Physical Disk"

Run Cluster.exe ResType to get a list of available Resource Types.

 

Example:

>cluster res "Cluster Disk 9" /create /group:"Available Storage" /type:"Physical Disk"

On executing the following command, you would see that a resource of name resource-name has been created and is in Offline state. You should of course make sure you do not have an existing resource with same name.

It is not automatically onlined since a few properties need to first be set. For the Disk Resource, we need to set either DiskSignature or the DiskIDGUID private property of the resource, depending on the type of the resource. If you are not sure what the value for this parameter is, you can use the Diskpart tool:

C:\>diskpart

Microsoft DiskPart version 6.1.6552
Copyright (C) 1999-2007 Microsoft Corporation.
On computer: ABCDEFX64N4

DISKPART> select disk 9

Disk 9 is now the selected disk.

DISKPART> detail disk

HITACHI DF600F SCSI Disk Device

Disk ID: {E743EA77-5B49-4305-A081-A16EF94E2C63}

Type   : FIBRE

Bus    : 0

Target : 0

LUN ID : 8

Read-only  : Yes

Boot Disk  : No

Pagefile Disk  : No

Hibernation File Disk  : No

Crashdump Disk  : No

 There are no volumes.

 

Disk ID is what we are looking for. If the Disk ID is a GUID we set DiskIDGUID parameter or if the DISK ID is a number we set DiskSignature. Generally MBR disks have signatures and GPT disks have GUIDs.

Example:

cluster res "Cluster Disk 9" /priv DiskIDGuid={E743EA77-5B49-4305-A081-A16EF94E2C63}

NOTE:

/priv represents private properties of the resource. The string following /priv should be the property name. Be careful when assigning a value to a property as a typing mistake may prevent the resource from working properly, but you can always go back and change it.

We are all set to bring the resource online and see it in action. Execute:

 C:\>cluster res "Cluster Disk 9" /on

 Bringing resource 'Cluster Disk 9' online...

 Resource             Group                Node            Status

-------------------- -------------------- --------------- ------

Cluster Disk 9       Available Storage    c5c1f4x64n4     Online

The /on switch will bring the resource online. If this command fails double check the parameters to ensure they have the correct values.

 

Cluster WMI:

Many new classes have been added to Cluster WMI to make cluster administration simple and easy using WMI. We can either use any scripting language, C# code or even C++ to achieve this. For this post, I am going to provide a sample C# code and a VB script.  First a few classes should be described:

 MSCluster_Disk

Enumerating an instance of this class gives us a list of all the disks that are added to the cluster. More information about this class can be found at http://msdn2.microsoft.com/en-us/library/aa965285(vs.85).aspx

MSCluster_AvailableDisk

This is a new class that has been introduced in Windows Server 2008. This class provides a list of all the disks that are visible from all the nodes and can be added to the cluster.

MSCluster_ClusterToAvailableDisk

This is an associator class. Like other associater classes this provides an association between cluster and the available disks.

GroupComponent of this class is a reference of the MSCluster_Cluster class and the PartComponent is a reference to MSCluster_AvailableDisk 

 

Let see Cluster WMI in action through a VB Script:

 strClusterName = "."

 ' Connect to the MSCLuster name space on the Cluster

Set objWMIService = GetObject ("winmgmts:" _

& "{impersonationLevel=impersonate," _

& "authenticationLevel=pktPrivacy}!" _

& "\\" & strClusterName & "\root\MSCluster")

 ' Get the list of Disks with Cluster

Set objClusDisks = objWMIService.ExecQuery ("Select * from MSCLuster_Disk")

 ' Dump all the disks with cluster

WScript.Echo "Lists of Disks with cluster"

For each objDisk in objClusDisks

' If you wish you can dump other properties of the disk

WScript.Echo objDisk.ID

Next

 ' Lets get the disks that are available to be added to the cluster

Set objAvailableDisks = objWMIService.ExecQuery ("Select * from MSCluster_AvailableDisk")

 WScript.Echo "Looking for Available Disks"

' Dump all the available Disks

 for each objAvailDisk in objAvailableDisks

WScript.Echo "Found Disks with ID: " & objAvailDisk.ID

'Add the disk to the cluster

objRelPath = "MSCluster_AvailableDisk.ID='"

objRelPath = objRelPath & objAvailDisk.ID

objRelPath = objRelPath & "'"

WScript.Echo "Adding Disk " & objRelPath & " to the cluster"

Set objOutParams = objWMIService.ExecMethod(objRelPath, "AddToCluster")

Wscript.echo "Created Resource: " & objOutParams.Path

' Once the Disk has been added we need to online the disk

' We need to call "BringOnline" method with a timeout parameter

' Time out is specified in secs

WScript.Echo "Bringing Resource " & objOutParams.Path & " Online"

Set objResDisk = objWMIService.Get (objOutParams.Path)

Set objInParam = objResDisk.Methods_("BringOnline").inParameters.SpawnInstance_()

objInParam.Properties_.Item("TimeOut") =  60

Set objOut = objWMIService.ExecMethod(objOutParams.Path, "BringOnline", objInParam)

WScript.Echo "Resource " & objOutParams.Path & " Brougth Online"

 Next

 

Here is a code sample in C#:

        static void Main(string[] args)

        {

            String machineName = ".";

            String nameSpace = "MSCluster";

            System.Management.ConnectionOptions connOptions = new System.Management.ConnectionOptions();

            connOptions.Authentication = AuthenticationLevel.PacketPrivacy;

            connOptions.Username = null;

            connOptions.Password = null;

             System.Management.ManagementScope mgmtScope = new System.Management.ManagementScope(string.Format(@"\\{0}\root\{1}", machineName, nameSpace), connOptions);

            System.Management.ManagementObjectCollection mgmtObjColl = null;

            try

            {

                mgmtScope.Connect();

                // We are connected to WMI MSCluster namespace

                // Lets Get All the available Disks.

                String wmiClassName = "MSCluster_AvailableDisk";

                System.Management.ManagementClass mgmtClass = new ManagementClass(mgmtScope, new ManagementPath(wmiClassName), null);

                mgmtClass.Get();

                mgmtObjColl = mgmtClass.GetInstances();

                foreach (System.Management.ManagementObject clusDisk in mgmtObjColl)

                {

                    ManagementBaseObject inParamsMgmtObj = null;

                    ManagementBaseObject outParam = null;

                    System.Management.ManagementObject DiskResObj = null;

                    try

                    {

                        Console.WriteLine("Disk ID = {0}", clusDisk["ID"].ToString());

                        Console.WriteLine("Path = {0}", clusDisk.SystemProperties["__RELPATH"].Value.ToString());

                        Console.WriteLine("Adding the disk to cluster");

                        inParamsMgmtObj = clusDisk.GetMethodParameters("AddToCluster");

                        outParam = (ManagementBaseObject)clusDisk.InvokeMethod("AddToCluster", inParamsMgmtObj, null);

                        Console.WriteLine("Disk Added to cluster, now trying to bring it online");

                        PropertyDataCollection retPropDataColl = (PropertyDataCollection)outParam.Properties;

                        String ResPath = retPropDataColl["Path"].Value.ToString();

                        Console.WriteLine("Resource Path returned = {0}", ResPath);

                        DiskResObj = new ManagementObject(mgmtScope, new ManagementPath(ResPath), null);

                        DiskResObj.Get();

                        DiskResObj.InvokeMethod("BringOnline", new object[] { 60 });

                        Console.WriteLine("Resource = {0} is brought online", ResPath);

                    }

                    catch (ManagementException mgmtException)

                    {

                        Console.WriteLine("Management (WMI) exception occured. Exception message: {0}, Error Code: {1}.", mgmtException.Message, mgmtException.ErrorCode);

                         if (null != mgmtException.ErrorInformation)

                            Console.WriteLine("Status: '{0}', Description: '{1}'.", mgmtException.ErrorInformation["StatusCode"], mgmtException.ErrorInformation["Description"]);

                         Console.WriteLine("Stack Trace: {0}", mgmtException.StackTrace);

                        // If you wisht to continue adding other disks do that else bail out

                        // I choose to continue

                        continue;

                    }

                    finally

                    {

                        if (inParamsMgmtObj != null)

                            inParamsMgmtObj.Dispose();

                         if (outParam != null)

                            outParam.Dispose();

                         if (DiskResObj != null)

                            DiskResObj.Dispose();

                    }

                }

            }

            catch (ManagementException mgmtException)

            {

                Console.WriteLine("Management (WMI) exception occured. Exception message: {0}, Error Code: {1}.", mgmtException.Message, mgmtException.ErrorCode);

                 if (null != mgmtException.ErrorInformation)

                    Console.WriteLine("Status: '{0}', Description: '{1}'.", mgmtException.ErrorInformation["StatusCode"], mgmtException.ErrorInformation["Description"]);

                 Console.WriteLine("Stack Trace: {0}", mgmtException.StackTrace);

                return;

            }

            finally

            {

                if (mgmtObjColl != null)

                   mgmtObjColl.Dispose();

            }

        }

 

Known Issues with Cluster WMI:

1.       When we add a disk using Cluster WMI, the names given to the disk are not same as in the Failover Cluster Administrator snap-in. For example, when you add a disk through the GUI it would be assigned "Cluster Disk 1" whereas Cluster WMI would assign it "Disk 1".

2.       If any node of the Cluster is not online MSCluster_AvailableDisk/MSCLuster_CLusterToAvailableDisk would return 0 available Disks.

 

If you have any further questions, please post a comment to this blog entry and it will be addressed.

 

Thanks,

Vikas Kumar
Software Development Engineer in Test
Clustering & HA

Leave a Comment
  • Please add 5 and 7 and type the answer here:
  • Post
Page 1 of 1 (4 items)