Cluster Shared Volume Monitoring Script Data Source

Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume.Monitoring.ScriptDataSource (DataSourceModuleType)

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
OutputTypeSystem.PropertyBagData

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource Microsoft.Windows.TimedScript.PropertyBagProvider Default
Filter ConditionDetection System.ExpressionFilter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval
LogSuccessEventbool$Config/LogSuccessEvent$Log Successful Event
ScriptGroupIdstring$Config/ScriptGroupId$Event Log Source
TimeoutSecondsint$Config/TimeoutSeconds$Timeout

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume.Monitoring.ScriptDataSource" Accessibility="Internal" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer" minOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SyncTime" type="xsd:string" minOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="LogSuccessEvent" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ScriptGroupId" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TargetComputer" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ClusterName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ClusterSharedVolumeName" type="xsd:string"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="LogSuccessEvent" Selector="$Config/LogSuccessEvent$" ParameterType="bool"/>
<OverrideableParameter ID="ScriptGroupId" Selector="$Config/ScriptGroupId$" ParameterType="string"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedScript.PropertyBagProvider">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime>$Config/SyncTime$</SyncTime>
<ScriptName>Microsoft.Windows.Server.CSV.MonitorClusterSharedVolume.vbs</ScriptName>
<Arguments>$Config/LogSuccessEvent$ "$Config/ScriptGroupId$" "$Config/TargetComputer$" "$Config/ClusterName$"</Arguments>
<ScriptBody><Script>
Option Explicit
Const SCRIPT_VERSION = "1.02"
Const LOG_SUCCESS_EVENT_PARAMETER_NAME = "LogSuccessEvent"
Const MP_ELEMENT_PARAMETER_NAME = "MP Element"
Const MANAGED_ENTITY_ID_PARAMETER_NAME = "Managed Entity"
Const TARGET_COMPUTER_PARAMETER_NAME = "Target Computer"
Const CLUSTER_NAME_PARAMETER_NAME = "Cluster Name"

'WMI constants
Const WMI_MSCLUSTER_NAMESPACE = "root\MSCluster"
Const WMI_CIMV2_NAMESPACE = "root\cimv2"
Const WMI_MSCLUSTER_CLUSTER_SHARED_VOLUME = "MSCluster_ClusterSharedVolume"
Const WMI_CLUSTER_SHARED_VOLUME_TO_PARTITION_ASSOCIATOR_CLASS = "MSCluster_ClusterSharedVolumeToPartition"
Const WMI_CLUSTER_SHARED_VOLUME_TO_RESOURCE_ASSOCIATOR_CLASS = "MSCluster_ClusterSharedVolumeToResource"

Const WMI_MSCLUSTER_CLUSTER_CLASS = "MSCluster_Cluster"
Const WMI_NAME_PROPERTY_NAME = "Name"
Const WMI_PATH_PROPERTY_NAME = "Path"
Const WMI_FILESYSTEM_PROPERTY_NAME = "FileSystem"
Const WMI_TOTALSIZE_PROPERTY_NAME = "TotalSize"
Const WMI_FREESPACE_PROPERTY_NAME = "FreeSpace"
Const WMI_FAULTSTATE_PROPERTY_NAME = "FaultState"
Const WMI_VOLUMELABEL_PROPERTY_NAME = "VolumeLabel"

'State property bag constants
Const STATE_DATA_TYPE = 3
Const STATE_PROPERTY_NAME = "State"
Const STATE_NTFS_NAME = "NTFSIsDirty"
Const STATE_GOOD = "GOOD"
Const STATE_BAD = "BAD"

'Performance property bag constants
Const INSTANCE_NAME = "ClusterSharedVolumeName"
Const PERFORMANCE_DATA_TYPE = 2
Const PERFORMANCE_OBJECT_NAME = "PerfObject"
Const PERFORMANCE_COUNTER_NAME = "PerfCounter"
Const PERFORMANCE_INSTANCE_NAME = "PerfInstance"
Const PERFORMANCE_VALUE_NAME = "PerfValue"
Const PERF_OBJECT_CSV = "Cluster Shared Volume"
Const PERF_COUNTER_TOTAL_SIZE_MB = "Total size / MB"
Const PERF_COUNTER_FREE_SPACE_MB = "Free space / MB"
Const PERF_COUNTER_FREE_SPACE_PERCENT = "Free space / Percent"
Const PERF_COUNTER_STATE_PROPERTY_NAME = "State"
Const PERF_COUNTER_STATE_NTFS_NAME = "NTFSIsDirty"

'Event constants
Const EVENT_TYPE_SUCCESS = 0
Const EVENT_TYPE_ERROR = 1
Const EVENT_TYPE_WARNING = 2
Const EVENT_TYPE_INFORMATION = 4

Const EVENT_ID_SUCCESS = 1000 'Use IDs in the range 1 - 1000
Const EVENT_ID_SCRIPTERROR = 999 'Then you can use eventcreate.exe to test the MP

'Scripting.FileSystemObject constants
Const FOR_READING = 1 'Open a file for reading only. You can't write to this file.
Const FOR_WRITING = 2 'Open a file for writing.
Const FOR_APPENDING = 8 'Open a file and write to the end of the file.

'Global vars
Dim mblnLogSuccessEvent 'As Boolean
Dim mstrIdentifier 'As String

Call Main

'*********************************************************************************************
' PROCEDURE: Main
' DESCRIPTION: Reads the script parameters and creates the cluster shared volume discovery data.
' PARAMETERS: void
'*********************************************************************************************
Private Sub Main()

' Targeted at Microsoft.Windows.Cluster.VirtualServer (based on Microsoft.Windows.Server.Computer)
Dim objFSO 'As Scripting.FileSystemObject


Dim strTargetComputer 'As String '= oArgs(6)
Dim strClusterName 'As String '= oArgs(7)
Dim objMomScriptAPI 'As MOM.ScriptAPI
Dim objDiscoveryData 'As DiscoveryData
Dim blnSuccess 'As Boolean

Call SetLocale("en-us")

Set objMomScriptAPI = CreateObject("MOM.ScriptAPI")
If Not GetScriptParameters(strTargetComputer, strClusterName) Then
' If the script is called without the required arguments,
' create an information event and then quit.
Call objMomScriptAPI.LogScriptEvent("Cluster Shared Volumes Monitoring Script -- " &amp; vbCr &amp; vbLf &amp; vbCr &amp; vbLf &amp; " -- " &amp; "Script name: " &amp; WScript.ScriptName &amp; vbCr &amp; vbLf &amp; "Version: " &amp; SCRIPT_VERSION &amp; vbCr &amp; vbLf, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, _
vbCr &amp; vbLf &amp; "The script was called with fewer than four arguments or the arguments could not be parsed.")
WScript.Quit -1
End If

Set objFSO = CreateObject("Scripting.FileSystemObject")

'On Error Resume Next

'Monitor instances
blnSuccess = MonitorClusterSharedVolumes(strTargetComputer, strClusterName, objMomScriptAPI)

If blnSuccess Then
If mblnLogSuccessEvent Then Call objMomScriptAPI.LogScriptEvent("Cluster Shared Volumes Monitoring Script -- " &amp; vbCr &amp; vbLf &amp; vbCr &amp; vbLf &amp; "Script name: " &amp; WScript.ScriptName &amp; vbCr &amp; vbLf &amp; "Version: " &amp; SCRIPT_VERSION &amp; vbCr &amp; vbLf, EVENT_ID_SUCCESS, EVENT_TYPE_INFORMATION, _
vbCr &amp; vbLf &amp; "Script executed successfully.")
Else
Call objMomScriptAPI.LogScriptEvent("Cluster Shared Volumes Monitoring Script -- " &amp; vbCr &amp; vbLf &amp; vbCr &amp; vbLf &amp; " -- " &amp; "Script name: " &amp; WScript.ScriptName &amp; vbCr &amp; vbLf &amp; "Version: " &amp; SCRIPT_VERSION &amp; vbCr &amp; vbLf, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, _
vbCr &amp; vbLf &amp; "An error occurred while running script")
End If

'Return the typed property bags
If blnSuccess Then Call objMomScriptAPI.ReturnItems

End Sub

'****************************************************************************************************************
' FUNCTION: MonitorClusterSharedVolumes
' DESCRIPTION: Creates monitoring data for all instances of the class 'Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume' using WMI.
' PARAMETERS: IN String strTargetComputer: principal name of the targeted 'Microsoft.Windows.Cluster.VirtualServer' instance.
' IN String strClusterName: the cluster containing the cluster shared volume
' RETURNS: Boolean: True if successful
'****************************************************************************************************************
Private Function MonitorClusterSharedVolumes(ByRef strTargetComputer, ByRef strClusterName, ByRef objMomScriptAPI) 'As Boolean

Dim objMSClusterSWbemServices 'As SWbemServices
Dim objClusterSharedVolumes 'As SWbemObjectSet
Dim objClusterSharedVolume 'As SWbemObject
Dim objClusterDiskPartition 'As SWbemObject
Dim objClusterResource 'As SWbemObject
Dim blnSuccess 'As Boolean

'Connect to WMI NS \\.\root\MSCluster
If ConnectToWbemNS(".", WMI_MSCLUSTER_NAMESPACE, objMSClusterSWbemServices) Then
Set objClusterSharedVolumes = objMSClusterSWbemServices.ExecQuery("select * from " &amp; WMI_MSCLUSTER_CLUSTER_SHARED_VOLUME)
'Loop through all returned cluster shared volumes
For Each objClusterSharedVolume In objClusterSharedVolumes
'Get the associated disk partition
For Each objClusterDiskPartition In objClusterSharedVolume.Associators_(WMI_CLUSTER_SHARED_VOLUME_TO_PARTITION_ASSOCIATOR_CLASS, "", "", "", False, False, "", "", 0)
'Get the associated resource
For Each objClusterResource In objClusterSharedVolume.Associators_(WMI_CLUSTER_SHARED_VOLUME_TO_RESOURCE_ASSOCIATOR_CLASS, "", "", "", False, False, "", "", 0)
blnSuccess = CreateMonitoringData(objClusterSharedVolume, objClusterDiskPartition, objClusterResource, _
strTargetComputer, strClusterName, objMomScriptAPI)
Next 'objClusterResource
Next 'objClusterDiskPartition
Next 'objClusterSharedVolume
MonitorClusterSharedVolumes = blnSuccess
Else
If mblnDebug Then Call mobjDebugLog.WriteLine("Error! Could not connect to WMI namespaces '" &amp; WMI_MSCLUSTER_NAMESPACE &amp; "'.")
End If

End Function

'****************************************************************************************************************
' FUNCTION: CreateMonitoringData
' DESCRIPTION: Create monitoring data for a cluster shared volume.
'
' PARAMETERS: IN Object objClusterSharedVolume: the cluster shared volume as SWbemObject of type MSCluster_ClusterSharedVolume.
' IN Object objClusterDiskPartition: the associated disk partition as SWbemObject of type MSCluster_DiskPartition.
' IN Object objClusterResource: the associated cluster resource as SWbemObject of type MSCluster_Resource.
' IN String strTargetComputer: the principal name of the targeted cluster virtual server hosting the cluster shared volume,
' i.e. the cluster name and not the current owner!
' IN String strClusterName: the cluster containing the cluster shared volume
' RETURNS: Boolean: True if successful
'****************************************************************************************************************
Private Function CreateMonitoringData(ByRef objClusterSharedVolume, ByRef objClusterDiskPartition, ByRef objClusterResource, _
ByRef strTargetComputer, ByRef strClusterName, ByRef objMomScriptAPI) 'As Boolean

'Create performance data
'CSV State
Call CreatePerformanceTypedPropertyBag(PERF_OBJECT_CSV, PERF_COUNTER_STATE_PROPERTY_NAME, objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), _
CStr(objClusterSharedVolume.Properties_(WMI_FAULTSTATE_PROPERTY_NAME)), _
objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), objMomScriptAPI)

'NTFSDirty (for future use)
Call CreatePerformanceTypedPropertyBag(PERF_OBJECT_CSV, PERF_COUNTER_STATE_NTFS_NAME, objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), _
0, objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), objMomScriptAPI)

'Total Size /MB
Call CreatePerformanceTypedPropertyBag(PERF_OBJECT_CSV, PERF_COUNTER_TOTAL_SIZE_MB, objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), _
objClusterDiskPartition.Properties_(WMI_TOTALSIZE_PROPERTY_NAME), objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), objMomScriptAPI)

'Free Space /MB
Call CreatePerformanceTypedPropertyBag(PERF_OBJECT_CSV, PERF_COUNTER_FREE_SPACE_MB, objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), _
objClusterDiskPartition.Properties_(WMI_FREESPACE_PROPERTY_NAME), objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), objMomScriptAPI)

'Free Space /%
Call CreatePerformanceTypedPropertyBag(PERF_OBJECT_CSV, PERF_COUNTER_FREE_SPACE_PERCENT, objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), _
Round(CLng(objClusterDiskPartition.Properties_(WMI_FREESPACE_PROPERTY_NAME)) / CLng(objClusterDiskPartition.Properties_(WMI_TOTALSIZE_PROPERTY_NAME)) * 100), _
objClusterResource.Properties_(WMI_NAME_PROPERTY_NAME), objMomScriptAPI)


CreateMonitoringData = True

End Function

'******************************************************************************
' FUNCTION: GetScriptParameters
' DESCRIPTION: Reads the script's parameters
' and sets the global variables.
'
' PARAMETERS: OUT String strTargetComputer: Principal name of executing computer
' (-Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName-)
' OUT String strClusterName: Cluster name
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function GetScriptParameters(ByRef strTargetComputer, ByRef strClusterName) 'As Boolean

Dim objArguments

On Error Resume Next

'cmdline: &lt;script&gt; True|False &lt;path to debug log&gt; True|False &lt;script id&gt; .MPElement. .Target/Id. .Target/Property[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName.
Set objArguments = WScript.Arguments
If objArguments.Count &lt; 4 Then Exit Function

'Get parameters and set global variables
mblnLogSuccessEvent = CBool(objArguments(0))
mstrIdentifier = Replace(objArguments(1), Chr(34), "")
strTargetComputer = Replace(objArguments(2), Chr(34), "")
strClusterName = Replace(objArguments(3), Chr(34), "")

If Len(strTargetComputer) &gt; 0 And Len(strClusterName) &gt; 0 Then GetScriptParameters = True

End Function

'**************************************************************
' FUNCTION: MakeFolder
' DESCRIPTION: Creates a folder and all necessary parent
' folders.
' PARAMETERS: IN String strFolder: full path of the folder
' IN Object objFSO: Scripting.FileSystemObject object
' RETURNS: Boolean: True if successful
'**************************************************************
Private Function MakeFolder(ByRef strFolder, ByRef objFSO) 'As Boolean

Dim strParentFolder 'As String

On Error Resume Next

'Get parent folder of given folder
strParentFolder = Left(strFolder, InStrRev(strFolder, "\") - 1)
'If the parent folder does not exist create it. (recursive call)
If Not objFSO.FolderExists(strParentFolder) Then Call MakeFolder(strParentFolder, objFSO)
'Create folder
Call objFSO.CreateFolder(strFolder)
'If error no equals zero function is successful
If Err.Number = 0 Then MakeFolder = True
Call Err.Clear

End Function

'******************************************************************************
' FUNCTION: ConnectToWbemNs
' DESCRIPTION: Connects to a WMI namespace
' PARAMETERS: IN String strServerName: name of the computer. If empty the local computer will be used.
' IN String strNameSpace: WMI namespace
' OUT Object objSWbemServices: WbemScripting.SWbemServices object connected to the given
' namespace on the given server
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function ConnectToWbemNS(ByRef strServerName, ByRef strNameSpace, ByRef objSWbemServices) 'As Boolean

Dim objSWbemLocator 'as WbemScripting.SWbemLocator

'Create a new WMI Locator object
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")

'Connect to WMI namespace on strServerName computer and create WMI Services object
Set objSWbemServices = objSWbemLocator.ConnectServer(strServerName, strNameSpace)

'Connect to WMI namespace on strServerName computer with alternative credentials and create WMI Services object
'Set objSWbemServices = objSWbemLocator.ConnectServer(strServerName, strNameSpace, strUserName, strPassWd)

'If object is initialised function will be successful
If objSWbemServices Is Nothing Then ConnectToWbemNS = False Else ConnectToWbemNS = True

End Function

'***************************************************************************************
' PROCEDURE: CreatePerformanceTypedPropertyBag
' DESCRIPTION: Generates a performance typed property bag and adds it to the script's XML output.
' PARAMETERS: IN String strObjectName: name of the performance object
' IN String strCounterName: name of the performance counter
' IN String strInstanceName: name of the performance counter in instance
' IN Variant varValue: value of the performance counter
' IN String strCSVInstanceName: Friendly volume name of the cluster shared volume
' IN Object objMomScriptAPI: initialised MOM.ScriptAPI object
'***************************************************************************************
Sub CreatePerformanceTypedPropertyBag(ByRef strObjectName, ByRef strCounterName, ByRef strInstanceName, _
ByRef varValue, ByRef strCSVInstanceName, ByRef objMomScriptAPI)

Dim objTypedPropertyBag 'As MOM.ScriptAPI.TypedPropertyBag

'Create a new typed property bag of the performance data type
Set objTypedPropertyBag = objMomScriptAPI.CreateTypedPropertyBag(PERFORMANCE_DATA_TYPE)

'Add the values for the perf counter's object name, counter name, instance name and the value)
Call objTypedPropertyBag.AddValue(PERFORMANCE_OBJECT_NAME, CStr(strObjectName))
Call objTypedPropertyBag.AddValue(PERFORMANCE_COUNTER_NAME, CStr(strCounterName))
Call objTypedPropertyBag.AddValue(PERFORMANCE_INSTANCE_NAME, CStr(strInstanceName))
Call objTypedPropertyBag.AddValue(PERFORMANCE_VALUE_NAME, CStr(varValue))

'Necessary information for the property bag data source filter condition
'to enable Agent cook down
Call objTypedPropertyBag.AddValue(INSTANCE_NAME, CStr(strCSVInstanceName))

'Add the property bag to the script's XML output
Call objMomScriptAPI.AddItem(objTypedPropertyBag)

End Sub

'***************************************************************************************
' PROCEDURE: CreateStateTypedPropertyBag
' DESCRIPTION: Generates a state typed property bag and adds it to the script's XML output.
' PARAMETERS: IN String strState: the state to return
' IN String strNTFSSTate: the NTFS state to return
' IN String strCSVInstanceName: Friendly volume name of the cluster shared volume
' IN Object objMomScriptAPI: initialised MOM.ScriptAPI object
'***************************************************************************************
Sub CreateStateTypedPropertyBag(ByRef strState, ByRef strNTFSSTate, ByRef strCSVInstanceName, ByRef objMomScriptAPI)

Dim objTypedPropertyBag 'As MOM.ScriptAPI.TypedPropertyBag

'Create a new typed property bag of the state data type
Set objTypedPropertyBag = objMomScriptAPI.CreateTypedPropertyBag(STATE_DATA_TYPE)

'Return State
Call objTypedPropertyBag.AddValue(STATE_PROPERTY_NAME, strState)
Call objTypedPropertyBag.AddValue(STATE_NTFS_NAME, strNTFSSTate)

'Necessary information for the property bag data source filter condition
'to enable Agent cook down
Call objTypedPropertyBag.AddValue(INSTANCE_NAME, strCSVInstanceName)

'Add the property bag to the script's XML output
Call objMomScriptAPI.AddItem(objTypedPropertyBag)

End Sub

</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</DataSource>
<ConditionDetection ID="Filter" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='ClusterSharedVolumeName']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">$Config/ClusterSharedVolumeName$</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
</MemberModules>
<Composition>
<Node ID="Filter">
<Node ID="DS"/>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
</DataSourceModuleType>