Discover Cluster Name Script Data Source

Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.VirtualServer.DiscoverClusterName.ScriptDataSource (DataSourceModuleType)

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource System.CommandExecuterDiscoveryDataSource 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.VirtualServer.DiscoverClusterName.ScriptDataSource" Accessibility="Internal" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:int"/>
<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="MPElementID" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TargetID" 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="TimeoutSeconds" type="xsd:int"/>
</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="System!System.CommandExecuterDiscoveryDataSource">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<ApplicationName>%windir%\System32\cscript.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>$file/Microsoft.Windows.Server.CSV.DiscoverClusterName.vbs$ $Config/LogSuccessEvent$ "$Config/ScriptGroupId$" "$Config/MPElementID$" "$Config/TargetID$" "$Config/TargetComputer$"</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Microsoft.Windows.Server.CSV.DiscoverClusterName.vbs</Name>
<Contents><Script>
Option Explicit

Const SCRIPT_VERSION = "1.01"
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"

'WMI constants
Const CIMV2_WMI_NAMESPACE = "root\cimv2"
Const WMI_MSCLUSTER_NAMESPACE = "root\MSCluster"
Const WMI_MSCLUSTER_CLUSTER_CLASS = "MSCluster_Cluster"

Const WIN_SRV_2008_BUILD_NUMBER = 6000

'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 mobjDebugLog 'As TextStream
Dim mblnLogSuccessEvent 'As Boolean
Dim mstrIdentifier 'As String

Call Main

'*********************************************************************************************
' PROCEDURE: Main
' DESCRIPTION: Reads the script parameters, gets the cluster name and
' discovers the containment relationship between a cluster and
' the targeted cluster virtual server.
' PARAMETERS: void
'*********************************************************************************************
Private Sub Main()

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

Dim strSourceID 'As String '= oArgs(4). strSourceId is the GUID of the discovery object that runs the script (MPElement).
Dim strManagedEntityId 'As String '= oArgs(5) - strManagedEntityId is the GUID of the computer class that is targeted by the script (Target/Id).
Dim strTargetComputer 'As String '= oArgs(6)
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(strSourceID, strManagedEntityId, strTargetComputer) Then
' If the script is called without the required arguments,
' create an information event and then quit.
Call objMomScriptAPI.LogScriptEvent("-- Cluster Shared Volumes Cluster Discovery 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_SCRIPTERROR, EVENT_TYPE_WARNING, _
vbCr &amp; vbLf &amp; "The script was called with fewer than five arguments or the arguments could not be parsed.")
WScript.Quit -1
End If

Set objFSO = CreateObject("Scripting.FileSystemObject")

On Error Resume Next
'Create new discovery data object
Set objDiscoveryData = objMomScriptAPI.CreateDiscoveryData(0, strSourceID, strManagedEntityId)

'DiscoverRelationship
If CheckOSBuildNumber(WIN_SRV_2008_BUILD_NUMBER) Then
blnSuccess = DiscoverClusterName(strTargetComputer, objDiscoveryData)
Else
blnSuccess = True
End If

If blnSuccess Then
If mblnLogSuccessEvent Then Call objMomScriptAPI.LogScriptEvent("-- Cluster Shared Volumes Cluster Discovery 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 Cluster Discovery 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_SCRIPTERROR, EVENT_TYPE_WARNING, _
vbCr &amp; vbLf &amp; "An error occurred while running script")
End If

'Return discovery data
If blnSuccess Then Call objMomScriptAPI.Return(objDiscoveryData)

End Sub

'****************************************************************************************************************
' FUNCTION: DiscoverClusterName
' DESCRIPTION: Discover instances of the relationship class
' 'Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.VirtualServer'.
' PARAMETERS: IN String strTargetComputer: principal name of the targeted 'Microsoft.Windows.Cluster.VirtualServer' instance.
' OUT Object objDiscoveryData: initialised DiscoveryData instance
' RETURNS: Boolean: True if successful
'****************************************************************************************************************
Private Function DiscoverClusterName(ByRef strTargetComputer, ByRef objDiscoveryData) 'As Boolean

Dim strTargetComputerShortName 'As String

Dim strClusterName 'As String
Dim blnCreateDiscoveryData 'As Boolean
Dim objClusterNameInstance 'As ClassInstance

'Get the hostname of the target computer from its principal name
If InStr(strTargetComputer, ".") &gt; 0 Then strTargetComputerShortName = Left(strTargetComputer, InStr(strTargetComputer, ".") - 1) _
Else strTargetComputerShortName = strTargetComputer

'Retrieve the cluster name from WMI and
'discover the relationship
If GetClusterName(strClusterName) Then

'Create the cluster name instance
Set objClusterNameInstance = objDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.Cluster']$")
'Add key property (is hosted on Microsoft.Windows.Cluster.VirtualServer
Call objClusterNameInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", strTargetComputer)
'Property ClusterName
Call objClusterNameInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.Cluster']/ClusterName$", strClusterName)

'add the instance to the discovery data
Call objDiscoveryData.AddInstance(objClusterNameInstance)

DiscoverClusterName = True

Else
Exit Function
End If

End Function

'****************************************************************************************************************
' FUNCTION: GetClusterName
' DESCRIPTION: Returns the cluster name of the given cluster virtual name
' PARAMETERS: OUT String strClusterName: string to return the cluster name
' RETURNS: Boolean: True if successful
'****************************************************************************************************************
Private Function GetClusterName(ByRef strClusterName) 'As Boolean

Dim objMSClusterSWbemServices 'As SWbemServices
Dim strWQLQuery 'As String
Dim objClusters 'As SWbemObjectSet
Dim objCluster 'As SWbemObject

'Connect to WMI NS \\.\root\MSCluster
If ConnectToWbemNS(".", WMI_MSCLUSTER_NAMESPACE, objMSClusterSWbemServices) Then

strWQLQuery = "select * from " &amp; WMI_MSCLUSTER_CLUSTER_CLASS
Set objClusters = objMSClusterSWbemServices.ExecQuery(strWQLQuery)
For Each objCluster In objClusters
strClusterName = objCluster.Name
Next 'objCluster

If Len(strClusterName) &gt; 0 Then GetClusterName = True

Else
End If

End Function

'******************************************************************************
' FUNCTION: CheckOSBuildNumber
' DESCRIPTION: Returns True if the property BuildNumber from the Win32_OperatingSystem
' instance is greater or equal the given build number using the CIMv2 WMI namespace.
' PARAMETERS: IN Long lngBuildNumber: build number to check
' RETURNS: Boolean: True, if build is greater or equal than the given number
'******************************************************************************
Private Function CheckOSBuildNumber(ByRef lngBuildNumber) 'As Boolean

Dim objSWbemServices 'As WbemScripting.SWbemServices
Dim objSWbemObjectSet 'As WbemScripting.SWbemObjectSet
Dim objSWbemObject 'As WbemScripting.SWbemObject

'Connect to CIMv2 WMI namespace
If ConnectToWbemNS(".", CIMV2_WMI_NAMESPACE, objSWbemServices) Then
'Get the computersystem instance
Set objSWbemObjectSet = objSWbemServices.ExecQuery("select * from Win32_OperatingSystem")
For Each objSWbemObject In objSWbemObjectSet
'If the OS build number is larger than the given number return True
If CLng(objSWbemObject.BuildNumber) &gt;= lngBuildNumber Then
CheckOSBuildNumber = True
Exit Function
End If
Next 'objSWbemObject
End If

End Function

'******************************************************************************
' FUNCTION: GetScriptParameters
' DESCRIPTION: Reads the script's parameters
' and sets the global variables.
'
' PARAMETERS: OUT String strSourceID: Id of MP element ($MPElement$)
' OUT String strManagedEntityId: Id of targeted entity ($Target/Id$)
' OUT String strTargetComputer: Principal name of executing computer
' ($Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$)
' RETURNS: Boolean: True if successful
'******************************************************************************
Private Function GetScriptParameters(ByRef strSourceID, ByRef strManagedEntityId, ByRef strTargetComputer) '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; 5 Then Exit Function

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

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

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

</Script></Contents>
</File>
</Files>
</DataSource>
</MemberModules>
<Composition>
<Node ID="DS"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>