Discover Cluster Name Script Data Source

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

This module discover seed objects on Windows Server Cluster.

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource Microsoft.Windows.Universal.Script.Discovery.DS Default

Overrideable Parameters:

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

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="Scheduler" TypeID="Microsoft.Windows.Universal.Script.Discovery.DS">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<cScriptName>Microsoft.Windows.Server.CSV.DiscoverClusterName.vbs</cScriptName>
<cScriptParameters>"$Config/LogSuccessEvent$" "$Config/ScriptGroupId$" "$Config/MPElementID$" "$Config/TargetID$" "$Config/TargetComputer$"</cScriptParameters>
<cScriptBody>Option Explicit
SetLocale("en-us")

Const SCRIPT_VERSION = "1.06"
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_Version = 6
Const WIN_SRV_2012R2_BUILD_NUMBER = 9600


'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



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 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
Dim strErrorMessage
Dim bIsOsSupported

bIsOsSupported = False

On Error Resume Next
Err.Clear
Set objMomScriptAPI = CreateObject("MOM.ScriptAPI")

If Err.Number &lt;&gt; 0 Then
Exit Sub
End If

If Not GetScriptParameters(strSourceID, strManagedEntityId, strTargetComputer) Then
' If the script is called without the required arguments,
' create an information event and then quit.
strErrorMessage = "The script was called with fewer than five arguments or the arguments could not be parsed."
Call LogScriptEvent(0, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, strErrorMessage,objMomScriptAPI)
WScript.Quit(-1)

End If

'Create new discovery data object
Set objDiscoveryData = objMomScriptAPI.CreateDiscoveryData(0, strSourceID, strManagedEntityId)
If Err.Number &lt;&gt; 0 Then
strErrorMessage = vbCrLf &amp; "The script cannot create Discovery Data"
Call LogScriptEvent(0, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, strErrorMessage,objMomScriptAPI)
WScript.Quit(-1)

End If

bIsOsSupported = CheckOSBuildNumber(WIN_SRV_2008_Version,WIN_SRV_2012R2_BUILD_NUMBER)
If (True = bIsOsSupported) Then
blnSuccess = DiscoverClusterName(strTargetComputer, objDiscoveryData)
Else
blnSuccess = True
End If

If blnSuccess Then
If mblnLogSuccessEvent Then
strErrorMessage = "Script executed successfully."
Call LogScriptEvent(0, EVENT_ID_SUCCESS, EVENT_TYPE_INFORMATION, strErrorMessage,objMomScriptAPI)
End If
Call objMomScriptAPI.Return(objDiscoveryData)
Else
strErrorMessage = "An error occurred while running script"
Call LogScriptEvent(0, EVENT_ID_SCRIPTERROR, EVENT_TYPE_WARNING, strErrorMessage,objMomScriptAPI)
End If

On Error Goto 0
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

DiscoverClusterName = False

On Error Resume Next

Err.Clear
If Not GetClusterName(strClusterName) Then
Exit Function
End If
'Retrieve the cluster name from WMI and
'discover the relationship
Err.Clear
'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
If HasValue(objClusterNameInstance) Then

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)
'Call objClusterNameInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", "Windows Cluster (disk monitoring)")
'add the instance to the discovery data
If ( 0 = Err.Number) Then
Call objDiscoveryData.AddInstance(objClusterNameInstance)
If ( 0 = Err.Number) Then
DiscoverClusterName = True
End If

End If

Set objClusterNameInstance = Nothing
End If


On Error Goto 0

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( lngVersion, lngHighBuildNumber) 'As Boolean

Dim strOSVersion
Dim strBuild
Dim dblVersion
Dim lngBuild
CheckOSBuildNumber = False

strOSVersion = GetRegistryKeyValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "CurrentVersion")
If (0 = Len(strOSVersion)) Then
Exit Function
End If

' strBuild = GetRegistryKeyValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "CurrentBuild")
'If (0 = Len(strBuild)) Then
' Exit Function
'End If
On Error Resume Next
Err.Clear
dblVersion = CDbl(strOSVersion)
'lngBuild = CLng(strBuild)

If (0 = Err.Number) Then
If (dblVersion &gt;= lngVersion) Then
CheckOSBuildNumber = True
End If
End If

On Error Goto 0

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

Err.Clear
GetScriptParameters = False
'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))
If (Err.Number &lt;&gt; 0 ) Then
mblnLogSuccessEvent = False
End If

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

On Error Goto 0

End Function


Private Function GetLogScriptName()

GetLogScriptName = "-- Cluster Name Discovery Script -- " &amp; vbCrLf &amp; vbCrLf &amp; "Script name: " &amp; WScript.ScriptName &amp; vbCrLf &amp; "Version: " &amp; SCRIPT_VERSION &amp; vbCrLf

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
Dim bResult

GetClusterName = False
bResult = GetClusterNameFromRegistry(strClusterName)

If (True = bResult And Len(strClusterName) &gt; 0 ) Then
GetClusterName = bResult
Exit Function
End If

On Error Resume Next
Err.Clear

'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)
If HasValue(objClusters) Then
For Each objCluster In objClusters
strClusterName = objCluster.Name
Next 'objCluster

If Len(strClusterName) &gt; 0 Then GetClusterName = True
End If
Set objClusters = Nothing

End If

On Error Goto 0

End Function


'****************************************************************************************************************
' FUNCTION: GetClusterNameFromRegistry
' 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 GetClusterNameFromRegistry(ByRef strClusterName) 'As Boolean

Dim objReg 'Registry
Const ClusterNamePath = "HKLM\Cluster\"

strClusterName = GetRegistryKeyValue(ClusterNamePath,"ClusterName")
GetClusterNameFromRegistry = Len(strClusterName) &gt; 0

End Function

'****************************************************************************************************************
' FUNCTION: GetComputerName ' DESCRIPTION: return short computername
' PARAMETERS: IN String strTargetComputer: principal name of the targeted 'Microsoft.Windows.Cluster.VirtualServer' instance.
' RETURNS: Integer: 0 if successful and 1 if fails
'****************************************************************************************************************
Private Function GetComputerName(strTargetComputer)

Dim strComputerName
Dim PointPos

PointPos = InStr(strTargetComputer, ".")
If PointPos &gt; 0 Then
strComputerName = LCase(Left(strTargetComputer, PointPos - 1))
Else
strComputerName = LCase(strTargetComputer)
End If

GetComputerName = strComputerName
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

ConnectToWbemNS = False
Dim objSWbemLocator 'as WbemScripting.SWbemLocator
Set objSWbemServices = Nothing

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

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

'If object is initialised function will be successful
ConnectToWbemNS = HasValue(objSWbemServices)

On Error Goto 0

End Function

Private Function HasValue(Value)

Dim bNothing

bNothing = false

IF ( IsObject(Value) ) THEN
IF (Nothing is Value) THEN
bNothing = true
END IF
END IF

HasValue = Not ( IsEmpty(Value) or bNothing or IsNull(Value) )
End Function

'****************************************************************************************************************
' FUNCTION: GetRegistryKeyValue
' DESCRIPTION: Get Registry Key value.
' PARAMETERS: IN String keyPath: Path to search in registry.
' IN String Key: key to return value from
' RETURNS: string: Value if successful
'****************************************************************************************************************
Function GetRegistryKeyValue(ByVal keyPath, ByVal key)
Dim oReg, strKeyValue

strKeyValue = ""
GetRegistryKeyValue = strKeyValue
On Error Resume Next
Err.Clear
Set oReg = CreateObject("WScript.Shell")
If Err.Number &lt;&gt; 0 Then
Err.Clear
Exit Function
End If
strKeyValue = oReg.RegRead(keyPath &amp; key)
If Err.Number &lt;&gt; 0 Then
Err.Clear
Exit Function
End If

GetRegistryKeyValue = strKeyValue

' resume error
On Error Goto 0

End Function

'******************************************************************************
' Subroutine: LogScriptEvent
' DESCRIPTION: Logging events to EventSource
' PARAMETERS: IN Integer LogType: 0 - MomScriptApi; 1 - File, 2 - Screen .
' IN String Message: Event Description
' OUT Object objSWbemServices: WbemScripting.SWbemServices object connected to the given
' namespace on the given server
' RETURNS: Boolean: True if successful
'******************************************************************************

Sub LogScriptEvent(LogType,EventId,EventLevel,Message,objMomScriptAPI)

Dim strMessage
Dim sDate
Dim LogScriptName

On Error Resume Next
If (0 = LogType) Then
If (Not HasValue(objMomScriptAPI)) Then
Exit Sub
End If
LogScriptName = GetLogScriptName()
Call objMomScriptAPI.LogScriptEvent(LogScriptName,EventId,EventLevel,Message)

Else
sDate = Now()
strMessage = "" &amp; sDate &amp; Message

If (1 = LogType) Then
WScript.Echo strMessage
End If

End If

On Error Goto 0
End Sub
</cScriptBody>
<PsScriptName>Microsoft.Windows.Server.CSV.DiscoverClusterName.ps1</PsScriptName>
<PowerShellScriptParameters>'$Config/MPElementID$' '$Config/TargetID$'</PowerShellScriptParameters>
<PowerShellScriptParam>param($SourceId, $ManagedEntityId)</PowerShellScriptParam>
<PowerShellScriptBody>
#*********************************************************************************************
# PROCEDURE: Main
# DESCRIPTION: Return empty discovery data for removing objects discovered by previous MP version.
# PARAMETERS: void
#*********************************************************************************************
Function Main()
{
$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
$objMomScriptAPI = New-Object -comObject MOM.ScriptAPI -ErrorAction SilentlyContinue

if ($null -eq $objMomScriptAPI)
{
return
}

$result = Init-ScomHelper

if ($false -eq $result)
{
return
}

$IsNano = Is_NanoServer
$Error.Clear()
$oDiscoveryData = $objMomScriptAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)

if ($null -ne $oDiscoveryData -and 0 -eq $Error.Count)
{
$oDiscoveryData.IsSnapShot = $IsNano
$SerializeDiscoveryData = [Scom.Helper.ConvertData]::GetDataItemFromOutput($oDiscoveryData)
Write-Host "$SerializeDiscoveryData"

}


}


Function Is_NanoServer
{
$ErrorActionPreference="SilentlyContinue"
$Error.Clear()
$IsNano = (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels").GetValue("NanoServer")
$error.Clear()
$IsNano = $IsNano -eq 1

return $IsNano

}


Main</PowerShellScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</DataSource>
</MemberModules>
<Composition>
<Node ID="Scheduler"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>