Tuesday, April 20, 2010

Change IP parameters on a Windows 2008 cluster using PowerShell

TASK:
Change TCP/IP settings on a Windows 2008 cluster. I had to do this when the network team needed to flatten out several subnets in one of the server rooms.

METHOD:
Parameters (private properties) are optional and a cluster object may or may not have them. Using Cluster.exe you can get these values by executing:

Cluster.exe res /priv /prop

With PowerShell CMDlets, all the common properties are attached with the cluster object that CMDlet returns:

Get-ClusterResource “Cluster Name” | format-list *

The above CMDlet would display all the properties of the ClusterResource Object returned by Get-ClusterResource CMDlet. The format-list CMDlet can be shortened to fl. The same data can be viewed different with different fomating CMDlets provided by PowerShell. By default we have provided some formatting where the execution of CMDLet would only display certain properties that the user cares the most about. For example, when you execute the below CMDlet, by default the Resource Name, State, Group and Resource Type, but then the resource object contains more properties (common properties).

Get-ClusterResource "Cluster Name"

Name          State   Group          ResourceType
------------  ------  -------------  ------------
Cluster Name  Online  Cluster Group  Network Name

To see a complete list of properties and its value you can use Format-List command (to get help on Format-List, use Get-Help).

Get-ClusterResource “Cluster Name”  |  Format-List *


Cluster                : MyCluster
IsCoreResource         : True
IsNetworkClassResource : False
IsStorageClassResource : False
OwnerNode              : MyCluster-node2
ResourceType           : Network Name
State                  : Online
OwnerGroup             : Cluster Group
Name                   : Cluster Name
MaintenanceMode        : False
MonitorProcessId       : 908
Description            :
SeparateMonitor        : False
PersistentState        : 1
LooksAlivePollInterval : 4294967295
IsAlivePollInterval    : 4294967295
RestartAction          : 2
RestartThreshold       : 1
RestartDelay           : 500
RestartPeriod          : 900000
RetryPeriodOnFailure   : 3600000
PendingTimeout         : 180000
DeadlockTimeout        : 300000
ResourceSpecificStatus :
Id                     : f6a82193-559c-4af3-9d... etc

The same data can be viewed differently by using Format-Custom CMDlet (please see Get-Help Format-Custom for more information on Format-Custom). Basically all the objects of the properties are expanded. For example, Cluster Group is an object of type ClusterGroup and contains more information like the node owning the group, and the state of the group. So when a Format-Custom CMDlet is executed, it gets expanded and you can see the values of those objects too.

Get-ClusterResource “Cluster Name”  | Format-Custom *


class ClusterResource
{ Cluster =
class Cluster
{ Name = MyCluster }
IsCoreResource = True
IsNetworkClassResource = False
IsStorageClassResource = False
OwnerNode =
class ClusterNode
{ Name = MyCluster-node2
State = Up }
ResourceType =
class ClusterResourceType
{ Name = Network Name
DisplayName = Network Name }
State = Online
OwnerGroup =
class ClusterGroup
{ Name = Cluster Group
OwnerNode =
class ClusterNode
{ Name = MyCluster-node2
State = Up }
State = Online }
Name = Cluster Name
MaintenanceMode = False
MonitorProcessId = 908
Description =
SeparateMonitor = False
PersistentState = 1
LooksAlivePollInterval = 4294967295
IsAlivePollInterval = 4294967295
RestartAction = 2
RestartThreshold = 1
RestartDelay = 500
RestartPeriod = 900000
RetryPeriodOnFailure = 3600000
PendingTimeout = 180000
DeadlockTimeout = 300000
ResourceSpecificStatus =
Id = f6a82193-559c-4af3-9d59-27b99b59ca07 }

Modifying Common Properties
To modify the value of any of the above property you need to cache the object, and set the value. For example, let say you want to change the name of the resource:

Get-ClusterResource “” | % { $_.Name=””}

Over here we are using foreach, where as we know the above CMDlet would only return one resource and piping the object to foreach object would result in processing on exactly one resource. Another way would be:

$res = Get-ClusterResource “
$res.Name=”

Another way of doing this is:

( Get-ClusterResource “” ).Name = “new name”

Keep in mind that some of the properties of the object are read only and cannot be modified.

Obtaining the Parameters
To get parameters (Private Properites) of a resource we use Get-ClusterParameter CMDlet:

Get-ClusterResource "Cluster Name" | Get-ClusterParameter

Object       Name            Value       Type
------       ----            -----       ----
Cluster Name Name            MyCluster   String
Cluster Name DnsName         MyCluster   String
Cluster Name RemapPipeNames  0           UInt32
Cluster Name HostRecordTTL   1200        UInt32

...etc

The output of the above command can also be formatted in different ways by using any of the Format-* CMDlet from PowerShell. For more information take a look at help of Get-ClusterParameter, by executing:

Get-Help Get-ClusterParameter –Full.

Modifying Parameters
To modify a parameter we need to use Set-ClusterParameter. For example if you want to change the value of DNSName for a “Cluster Name” resource:

Get-ClusterResource “Cluster Name”
Set-ClusterParameter –Name -Value

You can create a new parameter or modify an existing one or delete an existing one using Set-ClusterParameter. It is very uncommon to create a cluster object parameter (private property), but in case you have a need to create a new parameter, you need to pass the –Create switch to the CMDlet:

Get-ClusterResource “Cluster Name”
Set-ClusterParameter –Name -Value -Create

To delete an existing one you need to pass –Delete switch:

Get-ClusterResource “Cluster Name”
Set-ClusterParameter –Name -Value -Delete

Parameters are created dynamically and used by the specific resource(s) and the cluster service is not aware of it. These values are stored in the registry and can only support data types that are supported by the registry, so be precise when creating a parameter. The type of the parameter is determined by the type of the value passed. Make sure that value passed to Set-ClusterParameter is verified and intended. For example, if you want to create a parameter foo with type int:

$val=[int]10
Get-ClusterParameter “resource name” | Set-ClusterParameter –Name “Foo” –Value $val –create

The trickiest resource I have seen so far is “IP Address” type resource. Changing parameters (private properties) of IP address resource is not trivial, especially in cases where you would like to change the IP address (static) or change the network or subnet mask. All three parameters are linked to each other and every time you have to change one you need to modify all three:

$res = Get-ClusterResource
$param1 = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter –ArgumentList $res,”Network”,
$param2 = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter –ArgumentList $res,”Address”,
$param3 = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter –ArgumentList $res,”SubNet Mask”,
$params=$ param1,$ param2,$ param3
$params
Set-ClusterParameter

For more information run:

Get-Help Set-ClusterResource -Full

If you would have used either Get-ClusterParameter or Set-ClusterParameter, you would have noticed that they always require the object to be passed in as parameter. Hmm…that because these two CMDlets work with all the cluster objects, like Resources, Groups, Networks, NetworkInterfaces, ResourceType, etc. Using the name of the identity an object can be complicated, whereas passing the object through the pipeline works the best. It is not clear to me how IPv6 fits into this, maybe someone else can discuss that.

Cheers, Mick.

No comments:

Post a Comment