/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Monad NewYears Clock "," Using ADO to get data from Excel to Dataset in Mon... "," Monad Really Does Rock "," Passing (not so) mandatory Parameters to WMI metho... "," Saving a WMI instance to a XML-file from MSH "," MSH Orphan share remover Tool "," MSH Welcome screen "," Read the raw Monad XML helpfiles "," MSH prompt-User function with Help "," Monad IRC Bot "," ")

Wednesday, December 28, 2005

 


MSH Cluster Watcher script



The following script will watch a 2003 Cluster for Events using a WMI Event Query.

As it’s the 100th post is a bit more descriptive ;-)

First it will make a WMI Connection to the Cluster, note that the Namespace path is not root\CimV2 but root\MSCluster as the Cluster WMI classes reside in there own namespace.

In the next part of the script we make the ManagementEventWatcher object.
And we provide it with a Query.

Note we use MSCluster_Event , this is the BaseClass of all other MS_cluster event classes, so this will give us all Events, You can also use the more specific classes as MSCluster_EventGroupStateChange to get only that events.

Next I set a Timeout on the EventWatcher,

this is because you can not break the script with Ctrl-C when the EventWatcher is waiting for an event, (you can break with ctrl-Break but this will exit the complete MSH shell session.), I did set it to 1 second, so I can Break the script every 1 seconds, more about this you can find here :MSH directory watcher with popup-balloon(there I did attach it to a hidden form and a pop-up baloon so I could do A-Sync event handling, this time the Eventwatcher is not in another Thread state, but I could not get the eventhandlers working for the start() and Stop() Methods, I did get the Stopped eventhandler script-block fired but only after a WaitForNextEvent() call)

Note, that this is the Timeout on waiting for an event to come into the Client queue, not how often WMI is looking for Events !

That is stated in the Event Query :

SELECT * FROM MSCluster_Event WITHIN 10

The Within 10 is the interval that WMI will check for changes on the server side !.
So WMI will check for changes every 10 seconds, we are only stating that we only wait 1 second for an event and then go on to check for a key press and look in the Queue again.

So with a 1 second wait, we can check more servers in this loop or we can set the timeout higher for example 1 minute, still WMI will check every 10 Seconds and put changes in the queue, (for the example as we check all the events so sometimes we get 10 events or more in a couple of seconds this is not very handy (it will take us 10 loops to read them out, but in a production environment a warning on only a group change would be enough.)

So be aware of the difference between WITHIN 10 in the Event Query and the timeout on the check of the Event watcher Queue!.

In the next part of the Script,

We call FillTables, this is a helper function below the main function in the script that fills some HashTable Variables to do the translation of the Eventcodes we get back from WMI.
Note that it is called with a “Dot” so the variables get loaded in the current scope, in this case the Main function’s scope (That is the scripts not the Global!) as we do call it from there.

You see also that Main get called at the end of the script so that the FillTables function is declared before it gets called, but I still can place it below the main script.

Next the script enters the loop here :,

while (!$host.ui.rawui.KeyAvailable){

so it will loop until a key gets pressed (the timing we did in the event watcher timeout as explained earlier.

Then we wait for an event and display some info if we get an event.

First we have to translate the Date (as it is in Filetime Format).

"$([datetime]::fromfiletime($e.TIME_CREATED))"

Then we use the created HashTables to translate the codes we get back, for example :

“$($ClusterObject[[int]$e.EventObjectType])”

$e.EventObjectType is the Type of Object the change is about, this can be :.

0 = "Handle";
1 = "Cluster";
2 = "Node";
3 = "Group";
4 = "Resource";
5 = "ResourceType";
6 = "Network";
7 = "NetworkInterface";
8 = "Registry";
9 = "Quorum"

This number we give as an index to the HashTable (I had to explicitly cast it to an INT to get this working) so we get a more descriptive value back for our Message.

We do this a couple of times more till we come to the EventNewState property.

This one is a bit tricky because the Code returned will have a different meaning Depending on the Object type of the Event.!!

So we do a Switch to select the right HashTable for the Translation.
(note I did not implement all hashTables yet.)

After all the translations we have the Following output :

.\clusterWatch.msh ClusterName
Watching ClusterName, Press Any Key to Quit

12/28/2005 5:10:10 PM
Resource : TestApp
Change : RESOURCE_STATE
Node : Node1
State : OnlinePending

In this case I Brought a Test Application on Line.
But As we did subscribe to all events we get some more events as the loops goes on.

Cluster ClusterName
Event : 12/28/2005 5:10:10 PM
Group : TestGroup
Change : GROUP_STATE
Node : Node1
State : Pending

Cluster ClusterName
Event : 12/28/2005 5:10:10 PM
Resource : TestApp
Change : RESOURCE_STATE
Node : Node1
State : Online

Cluster ClusterName
Event : 12/28/2005 5:10:10 PM
Group : TestGroup
Change : GROUP_STATE
Node : Node1
State : Online

With a Application Down the State of the Goup was PartialOnline, the resource comes online, hence the state of the resourcegroup will also change now.

Also you can see how important the Switch statement is, !
The Resourcestate 2 means "Online" and GroupstateType 2 means Fialed !!

That’s it,

my next step would be to get the messages in a popup-balloon as in the :MSH directory watcher with popup-balloon, example, I started with this but could not get the eventhandler scriptblocks called, but you still use the notify icon to output the Message, but I would do that Only for the GroupChanged Events By using the MSCluster_EventGroupStateChange Class, to not overflow yourself with balloons.

I will post a example to output the current status of a cluster later.

gr /\/\o\/\/

Reference :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mscs/mscs/mscluster_event.asp

And The Script !

# ClusterWatch.msh
#
# Watch a Cluster for Events,
#  
# /\/\o\/\/ 2005
# http://mow001.blogspot.com

Param ($cluster = "ClusterName")

Function Main {
  "Watching $cluster, Press Any Key to Quit"
  trap {Break}

  # Make a WMI Connection to the Cluster

  $ms = new-object system.management.managementscope
  $ms.path = "\\$cluster\root\MSCluster"
  $ms.connect()

  # Make Event Watcher

  $ew = new-object system.management.ManagementEventWatcher
  $ew.scope = $ms
  $ew.query = "SELECT * FROM MSCluster_Event WITHIN 10"
  $opt = new-object System.Management.EventWatcherOptions
  $opt.Timeout = [timespan]::FromSeconds(1)
  $ew.options = $opt

  # Fill Lookup Tables :

  . FillTables

  # Wait for event :

  while (!$host.ui.rawui.KeyAvailable){
    trap {Continue}
    $e = $null
    $e = $ew.WaitForNextEvent() 2> $null
    if ($e) {
      "`nCluster $cluster Event :`n"
      "$([datetime]::fromfiletime($e.TIME_CREATED))"
      "$($ClusterObject[[int]$e.EventObjectType]) : $($e.EventObjectName)"
      "Change : $($ChangeType[[int]$e.EventTypeMinor])"
      "Node : $($e.EventNode)"
      switch  ($e.EventObjectType) {
        2 {"State : $($NodeState[[int]$e.EventNewState])"}
        3 {"State : $($GroupstateType[[int]$e.EventNewState])"}
        4 {"State : $($ResourceState[[int]$e.EventNewState])"}
      }
    }
  }
}

# Definition of LookUp Tables :

Function FillTables {

  $NodeState = @{
    0 = "Up"
    1 = "Down"
    2 = "Joining"  
    3 = "Paused"
    -1 = "StateUnknown"
  }

  $GroupstateType = @{
    -1 = "StateUnknown";
    0 = "Online";
    1 = "Offline";
    2 = "Failed";
    3 = "PartialOnline";
    4 = "Pending"
  }

  $ResourceState = @{
    -1 = "StateUnknown"
    0 = "Inherited"
    1 = "Initializing"
    2 = "Online"
    3 = "Offline"
    4 = "Failed"
    128 = "Pending"
    129 = "OnlinePending"
    130 = "OfflinePending"
  }

  $ClusterObject = @{
    0 = "Handle";
    1 = "Cluster";
    2 = "Node";
    3 = "Group";
    4 = "Resource";
    5 = "ResourceType";
    6 = "Network";
    7 = "NetworkInterface";
    8 = "Registry";
    9 = "Quorum"
  }

  $ChangeType = @{
    0x00000001  =  "NODE_STATE";
    0x00000002  =  "NODE_DELETED";
    0x00000004  =  "NODE_ADDED";
    0x00000008  =  "NODE_PROPERTY";
    0x00000010  =  "REGISTRY_NAME";
    0x00000020  =  "REGISTRY_ATTRIBUTES";
    0x00000040  =  "REGISTRY_VALUE";
    0x00000080  =  "REGISTRY_SUBTREE";
    0x00000100  =  "RESOURCE_STATE";
    0x00000200  =  "RESOURCE_DELETED";
    0x00000400  =  "RESOURCE_ADDED";
    0x00000800  =  "RESOURCE_PROPERTY";
    0x00001000  =  "GROUP_STATE";
    0x00002000  =  "GROUP_DELETED";
    0x00004000  =  "GROUP_ADDED";
    0x00008000  =  "GROUP_PROPERTY";
    0x00010000  =  "RESOURCE_TYPE_DELETED";
    0x00020000  =  "RESOURCE_TYPE_ADDED";
    0x00100000  =  "NETWORK_STATE";
    0x00200000  =  "NETWORK_DELETED";
    0x00400000  =  "NETWORK_ADDED";
    0x00800000  =  "NETWORK_PROPERTY";
    0x01000000  =  "NETINTERFACE_STATE";
    0x02000000  =  "NETINTERFACE_DELETED";
    0x04000000  =  "NETINTERFACE_ADDED";
    0x08000000  =  "NETINTERFACE_PROPERTY";
    0x10000000  =  "QUORUM_STATE";
    0x20000000  =  "CLUSTER_STATE";
    0x40000000  =  "CLUSTER_PROPERTY";
    0x80000000  =  "HANDLE_CLOSE"
  }
}

. main 



Comments:
Anonymous Anonymous
$NodeState = @{
0 = "Up"
1 = "Down"
2 = "Joining"
3 = "Paused"
-1 = "StateUnknown"
}

doesn't match http://support.microsoft.com/default.aspx?scid=kb;en-us;Q286052
you have joining and paused swapped.
 
Post a Comment

Links to this post:

Create a Link



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?