Dim g_oClusterUtil
Set g_oClusterUtil = new ClusterUtil
Dim oArgs
Set oArgs = WScript.Arguments
If oArgs.Count < 12 Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Need to provide arguments"
Wscript.Quit -1
End If
'==========================================================================
' Initialize the arguments in VBScript
'==========================================================================
Dim SourceId, ManagedEntityId, HealthServiceName, NetBiosName
SourceId = oArgs(0) ' this is always going to be same GUID to allow for multiple discoveries do updates at the same time
ManagedEntityId = oArgs(1)
HealthServiceName = oArgs(2)
NetBiosName = oArgs(3)
Dim discoverUnusedNetworks
discoverUnusedNetworks = CBool(oArgs(4))
Dim networkContainsInterfaceGuid
networkContainsInterfaceGuid = oArgs(5)
Dim networkInterfaceTypeGuid
networkInterfaceTypeGuid = oArgs(6)
Dim networkInterfacePropClusterNameGuid
networkInterfacePropClusterNameGuid = oArgs(7)
Dim networkInterfacePropNameGuid
networkInterfacePropNameGuid = oArgs(8)
Dim discoverCSVResources
discoverCSVResources = CBool(oArgs(9))
Dim discoverNonCSVResources
discoverNonCSVResources = CBool(oArgs(10))
Dim ResourceGroupDiscoveryLimit
ResourceGroupDiscoveryLimit = CInt(oArgs(11))
Dim appendClusterNameToResourceGroupName
If oArgs.Count = 12 Then
appendClusterNameToResourceGroupName = false
ElseIf oArgs.Count > 12 And ( IsEmpty(oArgs(12)) or IsNull(oArgs(12)) or Len(oArgs(12)) = 0 )Then
appendClusterNameToResourceGroupName = false
Else
appendClusterNameToResourceGroupName = CBool(oArgs(12))
End If
Dim strNetworkInterfacePropClusterAdapterID
If oArgs.Count = 13 Then
strNetworkInterfacePropClusterAdapterID = ""
ElseIf oArgs.Count > 13 And ( IsEmpty(oArgs(13)) or IsNull(oArgs(13)) or Len(oArgs(13)) = 0 )Then
strNetworkInterfacePropClusterAdapterID = ""
Else
strNetworkInterfacePropClusterAdapterID = oArgs(13)
End If
'Adding New Parameter for Resource Group Types Filter
Dim strResourceGroupTypeFilter, ObjResourceGroupTypeFilter
If oArgs.Count = 14 Then
strResourceGroupTypeFilter = DefaultClusterGroupTypes
ElseIf oArgs.Count > 14 And ( IsEmpty(oArgs(14)) or IsNull(oArgs(14)) or Len(oArgs(14)) = 0 )Then
strResourceGroupTypeFilter = DefaultClusterGroupTypes
Else
strResourceGroupTypeFilter = oArgs(14)
End If
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"SourceId : " & SourceId
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"ManagedEntityId : " & ManagedEntityId
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"HealthServiceName : " & HealthServiceName
'==========================================================================
' Main
'==========================================================================
Dim oAPI
Set oAPI = CreateObject("MOM.ScriptAPI")
If oAPI is Nothing Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed to get Discovery API. MOM v3 must be installed to execute this script"
if 0 <> Err.number then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed with error " & Err.number & " - " & Err.Description
end if
End If
Call DiscoverInstances()
'******************************************************************************
' FUNCTION: IndexOf
' DESCRIPTION: Returns Index of Search Element Value Inside an Array
' RETURNS: Index Number if not found return -1
'******************************************************************************
Function IndexOf(ByVal ObjArr, ByVal strToMatch)
'Default to an error code
IndexOf = -1
'Make sure an array was passed
If Not IsArray(ObjArr) Then Exit Function
'Check for matching index
Dim itmElem
For itmElem = 0 To UBound(ObjArr)
If StrComp(strToMatch, ObjArr(itmElem), vbTextCompare) = 0 Then
IndexOf = itmElem
Exit For
End If
Next
End Function
'******************************************************************************
' FUNCTION: GetRegistryKeyValue
' DESCRIPTION: Returns the Registry Key Value
' RETURNS: Registry Key Value
'******************************************************************************
Function GetRegistryKeyValue(ByVal keyPath, ByVal key)
Dim oReg, strKeyValue
Set oReg = CreateObject("WScript.Shell")
On Error Resume Next
strKeyValue = oReg.RegRead(keyPath & key)
If Err.Number <> 0 Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"An error occurred while reading the registry: '" & keyPath & key & "' Error Number: " & Err.number & " - " & Err.Description
strKeyValue = ""
End If
' resume error
On Error Goto 0
GetRegistryKeyValue = strKeyValue
End Function
'******************************************************************************
' FUNCTION: CheckByOSCurrentVersion
' DESCRIPTION: Returns True if the Registry Key for CurrentVersion
' is equal the target OS Versions Number.
' RETURNS: Boolean: True, if build is greater or equal than the given number
'******************************************************************************
Private Function CheckByOSCurrentVersion() 'As Boolean
Dim strCurrentOSVer
Select Case strCurrentOSVer
Case WIN_SRV_2012_OSVer
CheckByOSCurrentVersion = True
Case WIN_SRV_2012R2_OSVer
CheckByOSCurrentVersion = True
Case Else
CheckByOSCurrentVersion = False
End Select
End Function
'==========================================================================
' FUNCTIONS
'==========================================================================
Sub ThrowEmptyDiscoveryData(IsSnapShot)
Dim oDiscoveryDataTmp
set oDiscoveryDataTmp = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
oDiscoveryDataTmp.IsSnapshot = IsSnapShot
Call oAPI.Return(oDiscoveryDataTmp)
End Sub
Sub DiscoverInstances()
Dim boolUseWIN2012
boolUseWIN2012 = CheckByOSCurrentVersion()
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Started dicovery at machine local time: " & CStr(Time)
Dim oDiscoveryData
Set oDiscoveryData = oAPI.CreateDiscoveryData ( _
0, _
SourceId, _
ManagedEntityId _
)
If oDiscoveryData is Nothing Then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed to get Discovery Data Object. MOM v3 must be installed to execute this script"
if 0 <> Err.number then
g_oUtil.LogMessage _
g_oUtil.DBG_ERROR, _
"Failed with error " & Err.number & " - " & Err.Description
end if
g_oUtil.LogMessageNewLine _
g_oUtil.DBG_TRACE, _
"Finished dicovery at machine local time: " & CStr(Time)
End Sub
'==========================================================================
' Class: WinClusterObject
' Description: base holding object and its properties
'==========================================================================
Class WinClusterObject
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for " & discoveryClass & "."
Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
discoveryClass _
)
With oInstance
Dim name
name = g_oClusterUtil.WMIGetProperty ( oObject, "Name", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
If discoveryClass = "$MPElement[Name='Microsoft.Windows.Cluster.Group']$" And appendClusterNameToResourceGroupName = True Then
.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
name & " (" & hostKey & ")"
Else
.AddProperty _
"$MPElement[Name='System!System.Entity']/DisplayName$", _
name
End If
'Dim state
'state = g_oClusterUtil.WMIGetProperty ( oObject, "State", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
'
'.AddProperty _
' wrap with $...$ when ObjectState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.Component']/ObjectState", _
' state
End With
Set DiscoverInstance = oInstance
End Function
End Class ' WinClusterObject
'==========================================================================
' Class: WinCluster
' Description: holding cluster object and its properties
'==========================================================================
Class WinCluster
Private oClusters
'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
Set oClusters = g_oClusterUtil.WMIGetInstances("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "MSCluster_Cluster")
End Sub
'==========================================================================
' Discover cluster classes
'==========================================================================
Public Sub Discover( _
ByRef oDiscoveryData, ByRef boolUseWIN2012 _
)
Dim oCluster
For Each oCluster in oClusters
Dim oClusterInstance
Set oClusterInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Cluster!Microsoft.Windows.Cluster']$" _
)
With oClusterInstance
.AddProperty _
"$MPElement[Name='Cluster!Microsoft.Windows.Cluster']/Name$", _
oCluster.Name
End With
' need to make sure that cluster was discovered as it is used in some relationships
oDiscoveryData.AddInstance(oClusterInstance)
' cluster node helpers
Dim winClusterNode
Set winClusterNode = new WinClusterNode
' nodes
Dim oNodes
Set oNodes = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ClusterToNode where Antecedent = ""MSCluster_Cluster.Name=\""" & oCluster.Name & "\""""")
Dim oNode
For Each oNode in oNodes
Dim oRealNode
Set oRealNode = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oNode.Dependent)
Dim oNodeInstance
Set oNodeInstance = winClusterNode.DiscoverInstance ( _
oCluster.Name, _
oRealNode, _
oDiscoveryData _
)
If Not oNodeInstance Is Nothing Then
winClusterNode.DiscoverClusterContainsRelationship _
oClusterInstance, _
oDiscoveryData
End If
Next
' networks
Dim oNetworks
Set oNetworks = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ClusterToNetwork where GroupComponent = ""MSCluster_Cluster.Name=\""" & oCluster.Name & "\""""")
Dim oNetwork
For Each oNetwork in oNetworks
Dim oRealNetwork
Set oRealNetwork = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oNetwork.PartComponent)
' cluster network helpers
Dim winClusterNetwork
Set winClusterNetwork = new WinClusterNetwork
Dim oNetworkInstance
Set oNetworkInstance = winClusterNetwork.DiscoverInstance ( _
oCluster.Name, _
oRealNetwork, _
oDiscoveryData, _
boolUseWIN2012 _
)
If Not oNetworkInstance Is Nothing Then
winClusterNetwork.DiscoverClusterContainsRelationship _
oClusterInstance, _
oCluster.Name, _
oRealNetwork.Name, _
oDiscoveryData
End If
Next
' cluster group helpers
Dim winClusterGroup
Set winClusterGroup = new WinClusterGroup
' groups
Dim oGroups
Set oGroups = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ClusterToResourceGroup where GroupComponent = ""MSCluster_Cluster.Name=\""" & oCluster.Name & "\""""")
Dim oGroup
Dim iGroupCounter
iGroupCounter = 0
For Each oGroup in oGroups
Dim oRealGroup
Set oRealGroup = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oGroup.PartComponent)
Dim autoFailbackType
Dim description
Dim failbackWindowEnd
Dim failbackWindowStart
Dim failoverPeriod
Dim failoverThreshold
Dim persistentState
Dim GroupType
'Apply Filter if Any
GroupType = g_oClusterUtil.WMIGetProperty ( oRealGroup, "GroupType", wbemCimtypeUint32, ErrAction_ThrowErrorAndAbort )
If IndexOf(ObjResourceGroupTypeFilter,GroupType) = -1 Then
'Getting Discovered Group Index for comparing it with defined Discovery Limit
iGroupCounter = iGroupCounter + 1
' resource group discover limit exceeded?
If iGroupCounter > ResourceGroupDiscoveryLimit then
' yes
' log to event log
oAPI.LogScriptEvent "DiscoverClustering.vbs", 7010, 1, (HealthServiceName & " hosts " & iGroupCounter & " resource groups which exceeds the configured threshold of " & ResourceGroupDiscoveryLimit & ".")
else
' no
' proceed with normal discovery
' undefined is empty string
If failbackWindowEnd = "-1" Then failbackWindowEnd = ""
If failbackWindowStart = "-1" Then failbackWindowStart = ""
'cluster contains groups
If Not oGroupInstance Is Nothing Then
winClusterGroup.DiscoverClusterContainsRelationship _
oClusterInstance, _
oCluster.Name, _
Trim(oRealGroup.Name), _
oDiscoveryData
End If
' group contains hosted group
winClusterGroup.DiscoverClusterGroupContainsRelationship _
oCluster.Name, _
Trim(oRealGroup.Name), _
oDiscoveryData
end if
end if
Next
Next
End Sub
End Class ' WinCluster
'==========================================================================
' Class: WinClusterNode
' Description: holding cluster node and its properties
'==========================================================================
Class WinClusterNode
'==========================================================================
' Discover instance
'==========================================================================
Public Function DiscoverInstance( _
ByVal hostKey, _
ByRef oObject, _
ByRef oDiscoveryData _
)
'======================================================================
' only on same computer
'======================================================================
Dim name
Dim description
Dim buildNumber
Dim cSDVersion
Dim majorVersion
Dim minorVersion
Dim nodeHighestVersion
Dim nodeLowestVersion
Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
"$MPElement[Name='Windows!Microsoft.Windows.ComputerHostsComputerRole']$" _
)
'==========================================================================
' Class: WinClusterNetwork
' Description: holding cluster network and its properties
'==========================================================================
Class WinClusterNetwork
Private roleNone
'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
roleNone = False
End Sub
Dim oNetworkItfs
Set oNetworkItfs = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_NetworkToNetworkInterface where GroupComponent = ""MSCluster_Network.Name=\""" & name & "\""""")
Dim oNetworkItf
For Each oNetworkItf in oNetworkItfs
Dim oRealNetworkItf
Set oRealNetworkItf = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oNetworkItf.PartComponent)
Dim e
Set e = New Error
On Error Resume Next
Dim winClusterNetworkInterface
Set winClusterNetworkInterface = new WinClusterNetworkInterface
e.Save
On Error Goto 0
If g_oClusterUtil.IsValidObject ( winClusterNetworkInterface ) = False Then
g_oUtil.ThrowScriptError "Unable to create network interface helper.", e
End If
Dim baseOSItfName
If StrComp ( LCase(strs(1)) , LCase(oRealNetworkItf.SystemName) ) = 0 Then
baseOSItfName = strs(0)
Else
baseOSItfName = strs(1)
End If
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Network: " & name & " interface: " & baseOSItfName
g_oClusterUtil.DiscoverClusterContainsRelationship _
oClusterInstance, _
oInstance, _
"$MPElement[Name='Microsoft.Windows.Cluster.Contains.Microsoft.Windows.Cluster.Network']$", _
oDiscoveryData
End If
End Sub
End Class ' WinClusterNetwork
'==========================================================================
' Class: WinClusterNetworkInterface
' Description: holding cluster network interface its properties
'==========================================================================
Class WinClusterNetworkInterface
Public deviceID
Public adapterType
Public index
Public manufacturer
Public macAddress
Public serviceName
'======================================================================
' Method: Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Public Sub Initialize( ByVal NetworkName )
deviceID = ""
adapterType = ""
index = ""
manufacturer = ""
macAddress = ""
serviceName = ""
Dim WMISet, owObj, owObj2, oInstance, sDeviceID
If discoverUnusedNetworks= False Then
Set WMISet = g_oClusterUtil.WMIGetInstances("winmgmts:\\" + HealthServiceName + "\root\cimv2", "Win32_NetworkAdapter Where NetConnectionID = '" & NetworkName & "' And NetConnectionStatus <> 0")
Else
Set WMISet = g_oClusterUtil.WMIGetInstances("winmgmts:\\" + HealthServiceName + "\root\cimv2", "Win32_NetworkAdapter Where NetConnectionID = '" & NetworkName & "'")
End If
For Each owObj In WMISet
deviceID = g_oClusterUtil.WMIGetProperty(owObj, "DeviceID", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
adapterType = g_oClusterUtil.WMIGetProperty(owObj, "AdapterType", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
index = g_oClusterUtil.WMIGetProperty(owObj, "Index", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
manufacturer = g_oClusterUtil.WMIGetProperty(owObj, "Manufacturer", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
macAddress = g_oClusterUtil.WMIGetProperty(owObj, "MACAddress", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
' replaces colons in MAC with dashes to comply with IEEE 802 and NASM
macAddress = Replace(macAddress, ":", "-")
serviceName = g_oClusterUtil.WMIGetProperty(owObj, "ServiceName", wbemCimtypeString, ErrAction_ThrowErrorAndAbort )
Next
End Sub
If description = "" Then
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
adapter
Else
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.LogicalDevice']/Description$", _
description
End If
.AddProperty _
strNetworkInterfacePropClusterAdapterID, _
strClusterAdapterID
End If
End With
Call oDiscoveryData.AddInstance(oInstance)
Set DiscoverInstance = oInstance
End Function
End Class ' WinClusterNetworkInterface
'========='==========================================================================
' Class: WinClusterGroup
' Description: holding group object and its properties
'==========================================================================
Class WinClusterGroup
Dim oService
Set oService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & HealthServiceName & "\root\mscluster")
e.Save
On Error Goto 0
If IsEmpty(oService) Or e.Number <> 0 Then
g_oUtil.ThrowScriptError "Fail to connect to WMI.", e
End If
On Error Resume Next
Dim oActiveNode
Set oActiveNode = oService.ExecQuery("select * from MSCluster_NodeToActiveGroup where PartComponent = ""MSCluster_ResourceGroup.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oObject.Name)) & "\""""")
e.Save
On Error Goto 0
If IsEmpty(oActiveNode) Or e.Number <> 0 Then
g_oUtil.ThrowScriptError "The Query for active node returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next
If Not oActiveNode Is Null Then
Dim oNode
For Each oNode in oActiveNode
Dim oActive
Set oActive = oService.Get(oNode.GroupComponent)
e.Save
On Error Goto 0
If IsNull(oActive) Then
g_oUtil.ThrowScriptError "Do not get a Node. Please check to see if this is a valid WMI Query.", e
End If
On Error Resume Next
Dim oResources
Set oResources = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_ResourceGroupToResource where GroupComponent = ""MSCluster_ResourceGroup.Name=\""" & g_oClusterUtil.EscapeString(g_oClusterUtil.EscapeString(oObject.Name)) & "\""""")
Dim oResource
For Each oResource in oResources
Dim oRealResource
Set oRealResource = g_oClusterUtil.WMIGetInstance ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", oResource.PartComponent)
' discovery enabled?
if discoverNonCSVResources then
' yes
Dim winClusterResource
Set winClusterResource = new WinClusterResource
Dim oResourceInstance
Set oResourceInstance = winClusterResource.DiscoverInstance ( _
hostKey, _
Trim(oObject.Name), _
oRealResource, _
oDiscoveryData _
)
' discover that group hosts this resource
Call winClusterResource.DiscoverClusterGroupHostsResourcesRelationship ( _
hostKey, _
Trim(oObject.Name), _
Trim(oRealResource.Name), _
oDiscoveryData _
)
end if
Next
' cluster shared volume discovery enabled and available storage group?
dim resourceGroupType
resourceGroupType = CLng(oObject.ExecMethod_("GetGroupType").ReturnValue)
if discoverCSVResources and resourceGroupType = 2 then
dim oClusterSharedVolumes
set oClusterSharedVolumes = g_oClusterUtil.WMIExecQuery ("winmgmts:{impersonationLevel=impersonate}!\\" + HealthServiceName & "\root\mscluster", "select * from MSCluster_Resource where IsClusterSharedVolume = true" )
dim oCSV
for each oCSV in oClusterSharedVolumes
dim winCSVResource
Set winCSVResource = new WinClusterResource
dim oCSVInstance
set oCSVInstance = winCSVResource.DiscoverInstance ( _
hostKey, _
Trim(oObject.Name), _
oCSV, _
oDiscoveryData _
)
call winCSVResource.DiscoverClusterGroupHostsResourcesRelationship ( _
hostKey, _
Trim(oObject.Name), _
Trim(oCSV.Name), _
oDiscoveryData _
)
next
end if
End Function
Dim oHostedGroupInstance
Set oHostedGroupInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$" _
)
'oHostedGroupInstance.AddProperty _
' wrap with $...$ when GroupState is reenabled
' "MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupState", _
' oObject.State
Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Group.Contains.Microsoft.Windows.Cluster.HostedGroup']$" _
)
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for Microsoft.Windows.Cluster.Resource."
Dim name
Dim typeName
Dim description
Dim isAlivePollInterval
Dim LooksAlivePollInterval
Dim pendingTimeout
Dim persistentState
Dim restartAction
Dim restartPeriod
Dim restartThreshold
Dim retryPeriodOnFailure
Dim separateMonitor
'==========================================================================
' Discover group hostinging resources relationship instance
'==========================================================================
Public Sub DiscoverClusterGroupHostsResourcesRelationship( _
ByVal hostKey, _
ByVal groupKey, _
ByVal resKey, _
ByRef oDiscoveryData _
)
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"Creating DiscoveryData packet for group containing resources.."
Dim oInstance
Set oInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']$" _
)
With oInstance
.AddProperty _
"$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", _
HealthServiceName
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/ClusterName$", _
hostKey
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/NodeName$", _
NetBiosName
.AddProperty _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup']/GroupName$", _
groupKey
End With
Dim oClusterResourceInstance
Set oClusterResourceInstance = oDiscoveryData.CreateClassInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.Resource']$" _
)
Dim oRelationshipInstance
Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance( _
"$MPElement[Name='Microsoft.Windows.Cluster.HostedGroup.Hosts.Microsoft.Windows.Cluster.Resource']$" _
)
Class Error
Public Description
Public Number
Public Source
Sub Class_Initialize()
Number = 0
End Sub
Sub Save
Description = Err.Description
Number = Err.Number
Source = Err.Source
Err.Clear
End Sub
Sub Raise(strDescription)
Err.Raise Number, Source, strDescription & GetErrorString(Number, Description)
End Sub
End Class
'==========================================================================
' Class: ClusterUtil
' Description: Utility methods for clustering
'==========================================================================
Class ClusterUtil
'**********************************************************************
Public Function EscapeString(ByVal sText)
Const METACHARACTERS = """\"
Dim sResult
Dim i
For i = 1 To Len(sText)
Dim sCurrentChar
sCurrentChar = Mid(sText, i, 1)
If InStr(METACHARACTERS, sCurrentChar) <> 0 Then
sResult = sResult & "\"
End If
sResult = sResult & sCurrentChar
Next
g_oUtil.LogMessage _
g_oUtil.DBG_TRACE, _
"ESCAPEd string: " & sResult
EscapeString = sResult
End Function
'**********************************************************************
Function WMIExecQuery(ByVal sNamespace, ByVal sQuery)
Dim oWMI, oQuery, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
On Error Resume Next
Set oQuery = oWMI.ExecQuery(sQuery)
e.Save
On Error Goto 0
If IsEmpty(oQuery) Or e.Number <> 0 Then
g_oUtil.ThrowScriptError "The Query '" & sQuery & "' returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oQuery.Count
e.Save
On Error Goto 0
If e.Number <> 0 Then
g_oUtil.ThrowScriptError "The Query '" & sQuery & "' did not return any valid instances. Please check to see if this is a valid WMI Query.", e
End If
Set WMIExecQuery = oQuery
End Function
'**********************************************************************
Function WMIGetInstances(ByVal sNamespace, ByVal sInstance)
Dim oWMI, oInstance, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
On Error Resume Next
Set oInstance = oWMI.InstancesOf(sInstance)
e.Save
On Error Goto 0
If IsEmpty(oInstance) Or e.Number <> 0 Then
g_oUtil.ThrowScriptError "The class name '" & sInstance & "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If
'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oInstance.Count
e.Save
On Error Goto 0
If e.Number <> 0 Then
g_oUtil.ThrowScriptError "The class name '" & sInstance & "' did not return any valid instances. Please check to see if this is a valid WMI class name.", e
End If
Set WMIGetInstances = oInstance
End Function
'**********************************************************************
Function WMIGetInstance(ByVal sNamespace, ByVal sInstancePath)
Dim oWMI, oInstance, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
g_oUtil.ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
On Error Resume Next
Set oInstance = oWMI.Get(sInstancePath)
e.Save
On Error Goto 0
If IsNull(oInstance) Then
g_oUtil.ThrowScriptError "The class name '" & sInstancePath & "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If
Set WMIGetInstance = oInstance
End Function
'**********************************************************************
Function WMIGetProperty(oWmi, sPropName, nCIMType, ErrAction)
Dim sValue, oWmiProp
If Not IsValidObject(oWmi) Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
g_oUtil.ThrowScriptErrorNoAbort "Accessing property on invalid WMI object.", Err
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
g_oUtil.Quit
End If
WMIGetProperty = ""
Exit Function
End If
On Error Resume Next
Set oWmiProp = oWmi.Properties_.Item(sPropName)
If Err.Number <> 0 Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
g_oUtil.ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" & sPropName & "'.", Err
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
g_oUtil.Quit
End If
End If
On Error Goto 0
If IsValidObject(oWmiProp) Then
sValue = oWmiProp.Value
If IsNull(sValue) Then
'
' If value is null, return blank to avoid any issues
'
WMIGetProperty = ""
Else
Select Case (nCIMType)
Case wbemCimtypeString:
If Not oWmiProp.IsArray Then
WMIGetProperty = CStr(sValue)
Else
WMIGetProperty = Join(sValue, ", ")
End If
Case wbemCimtypeSint16, wbemCimtypeSint32, wbemCimtypeReal32, wbemCimtypeReal64, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16, wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64:
If Not oWmiProp.IsArray Then
WMIGetProperty = Trim(CStr(sValue))
Else
WMIGetProperty = Join(sValue, ", ")
End If
Case wbemCimtypeBoolean:
If sValue = 1 Or UCase(sValue) = "TRUE" Then
WMIGetProperty = "True"
Else
WMIGetProperty = "False"
End If
Case wbemCimtypeDatetime:
Dim sTmpStrDate
'
' First attempt to convert the whole wmi date string
'
sTmpStrDate = Mid(sValue, 5, 2) & "/" & _
Mid(sValue, 7, 2) & "/" & _
Left(sValue, 4) & " " & _
Mid (sValue, 9, 2) & ":" & _
Mid(sValue, 11, 2) & ":" & _
Mid(sValue, 13, 2)
If IsDate(sTmpStrDate) Then
WMIGetProperty = CDate(sTmpStrDate)
Else
'
' Second, attempt just to convert the YYYYMMDD
'
sTmpStrDate = Mid(sValue, 5, 2) & "/" & _
Mid(sValue, 7, 2) & "/" & _
Left(sValue, 4)
If IsDate(sTmpStrDate) Then
WMIGetProperty = CDate(sTmpStrDate)
Else
'
' Nothing works - return passed in string
'
WMIGetProperty = sValue
End If
End If
Case Else:
WMIGetProperty = ""
End Select
End If
Else
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
g_oUtil.ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" & sPropName & "'.", Err
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then
g_oUtil.Quit
End If
WMIGetProperty = ""
End If
If (ErrAction And ErrAction_Trace) = ErrAction_Trace Then _
WScript.Echo " + " & sPropName & " :: '" & WMIGetProperty & "'"
End Function
'**********************************************************************
Public Function IsValidObject(ByVal oObject)
IsValidObject = False
If IsObject(oObject) Then
If Not oObject Is Nothing Then
IsValidObject = True
End If
End If
End Function
'==========================================================================
' Class: Util
' Description: Utility methods for logging
'==========================================================================
Class Util
'**********************************************************************
Public Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
On Error Resume Next
LogMessage _
DBG_ERROR, _
sMessage & vbCrLf & oErr.Description
oAPI.LogScriptEvent "DiscoverClustering.vbs", 7001, 1, "Discovery script failed. Possible causes include Cluster Service or WMI Service not running. The error was: " & sMessage & " " & oErr.Description
End Function
'**********************************************************************
Public Function ThrowScriptError(Byval sMessage, ByVal oErr)
On Error Resume Next
ThrowScriptErrorNoAbort sMessage, oErr
'switch to incremental discovery and return
'empty snapshot, preventing the script failure
'from triggering an alert
ThrowEmptyDiscoveryData(false)
Quit
End Function
Public Function Quit
LogMessage _
DBG_ERROR, _
"Terminated on error!"
Wscript.Quit -1
End Function
' Used to say to LogMessage when/how to print the message.
Public DBG_NONE
Public DBG_ERROR
Public DBG_WARNING
Public DBG_TRACE
'Internal Debug Level
Private m_nDebugLevel
'======================================================================
' Method: Class_Initialize
' Description: This is the constructor
' Parameters:
'======================================================================
Private Sub Class_Initialize()
' Initialize Debug level constants
DBG_TRACE = 1
DBG_WARNING = 2
DBG_ERROR = 3
DBG_NONE = 4
'by default only errors are logged
m_nDebugLevel = DBG_ERROR
End Sub
'======================================================================
' Method: GetCurrentLevel
' Description: retrieve current logging level.
' Parameters:
'======================================================================
Public Function GetCurrentLevel()
GetCurrentLevel = m_nDebugLevel
End Function
'======================================================================
' Method: SetDebugLevel
' Description: To change the debugging output level of information
' generated by this utility.
' Parameters:
' nLevel - DBG_NONE, DBG_TRACE, DBG_WARNING or DBG_ERROR
'======================================================================
Public Sub SetDebugLevel(ByVal nLevel)
m_nDebugLevel = nLevel
End Sub
'======================================================================
' Method: LogMessage
' Description: Log a debug message to ScriptContext
' Parameters:
' nLevel - Debug level for the message that
' we're logging.
' strMessage - The message to write to the trace.
'======================================================================
Public Sub LogMessage( _
ByVal nLevel, _
ByVal strMessage _
)
If (nLevel >= GetCurrentLevel()) Then
if (nLevel = DBG_ERROR) Then
WScript.Echo "[Error]: " & strMessage
ElseIf (nLevel = DBG_WARNING) Then
WScript.Echo "[Warning]: " & strMessage
ElseIf (nLevel = DBG_TRACE) Then
WScript.Echo "[Trace]: " & strMessage
End If
End If
End Sub
Public Sub LogMessageNewLine( _
ByVal nLevel, _
ByVal strMessage _
)
If (nLevel >= GetCurrentLevel()) Then
if (nLevel = DBG_ERROR) Then
WScript.Echo vbCrLf & "[Error]: " & strMessage
ElseIf (nLevel = DBG_WARNING) Then
WScript.Echo vbCrLf & "[Warning]: " & strMessage
ElseIf (nLevel = DBG_TRACE) Then
WScript.Echo vbCrLf & "[Trace]: " & strMessage
End If
End If
End Sub
End Class ' Util</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="Script"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>