Microsoft Analytics Platform System Discovery

Microsoft.SQLServerAppliance.APS.Appliance.Discovery (Discovery)

This object discovery detects any Microsoft Analytics Platform System instances.

Knowledge Base article:

Summary

This object discovery detects all instances of Microsoft Analytics Platform System.

Element properties:

TargetMicrosoft.SQLServerAppliance.APS.ApplianceWatcherSeed
EnabledTrue
Frequency14400
RemotableFalse

Object Discovery Details:

Discovered Classes and their attribuets:

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource Microsoft.SQLServerAppliance.APS.ScriptedDiscoveryProvider Microsoft.SQLServerAppliance.APS.WatcherProfile

Source Code:

<Discovery ID="Microsoft.SQLServerAppliance.APS.Appliance.Discovery" Target="APSLibrary!Microsoft.SQLServerAppliance.APS.ApplianceWatcherSeed" Enabled="true">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="APSLibrary!Microsoft.SQLServerAppliance.APS.Appliance">
<Property TypeID="System!System.Entity" PropertyID="DisplayName"/>
<Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="PrincipalName"/>
<Property TypeID="SSALibrary!Microsoft.SQLServerAppliance.Appliance" PropertyID="ApplianceID"/>
<Property TypeID="SSALibrary!Microsoft.SQLServerAppliance.Appliance" PropertyID="ApplianceName"/>
<Property TypeID="SSALibrary!Microsoft.SQLServerAppliance.Appliance" PropertyID="ApplianceType"/>
<Property TypeID="APSLibrary!Microsoft.SQLServerAppliance.APS.Appliance" PropertyID="NetworkAddress"/>
<Property TypeID="APSLibrary!Microsoft.SQLServerAppliance.APS.Appliance" PropertyID="TdsAddress"/>
</DiscoveryClass>
<DiscoveryClass TypeID="SSALibrary!Microsoft.SQLServerAppliance.Server">
<Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="PrincipalName"/>
<Property TypeID="SSALibrary!Microsoft.SQLServerAppliance.Server" PropertyID="ApplianceName"/>
<Property TypeID="SSALibrary!Microsoft.SQLServerAppliance.Server" PropertyID="ApplianceType"/>
<Property TypeID="SSALibrary!Microsoft.SQLServerAppliance.Server" PropertyID="Role"/>
</DiscoveryClass>
</DiscoveryTypes>
<DataSource ID="DS" TypeID="Microsoft.SQLServerAppliance.APS.ScriptedDiscoveryProvider" RunAs="APSLibrary!Microsoft.SQLServerAppliance.APS.WatcherProfile">
<IntervalSeconds>14400</IntervalSeconds>
<SyncTime/>
<ScriptName>APSApplianceDiscovery.vbs</ScriptName>
<Arguments>"$MPElement$" "$Target/Id$" "$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$"</Arguments>
<ScriptBody><Script>Option Explicit
SetLocale("en-us")
' Eventlog EventID for all errors generated by scripts
Const SCRIPT_EVENT_ID = 4320

' This string will be appended to the beginning of first Event description parameter (Params/Param[1])
' Use &lt;RegExExpression /&gt; to narrow alerts to this MP only
Const MANAGEMENT_PACK_ID = "SQL2012APS MP"

Dim USE_EVENT_LOG, USE_ERROR_LOG

Const DEBUG_MODE = False
Const DEBUG_SCRIPT_EVENT_ID = 4201

USE_EVENT_LOG = true
USE_ERROR_LOG = false

Const ManagementGroupName = "$Target/ManagementGroup/Name$"
Dim sApplianceID
sApplianceID = ""

Sub LogWarning(ByVal customMessage)
Dim logger
Set logger = new ScriptLogger
logger.LogWarning(customMessage)
End Sub

Sub HandleWarning(ByVal customMessage)
Dim logger
If Err.number &lt;&gt; 0 Then
Set logger = new ScriptLogger
logger.LogWarning(customMessage)
End If
End Sub

Sub HandleError(ByVal customMessage)
Dim logger
If Err.number &lt;&gt; 0 Then
Set logger = new ScriptLogger
logger.LogError(customMessage)
If Not USE_ERROR_LOG Then
Wscript.Quit 0
Else
Wscript.Quit 1
End If
End If
End Sub

Sub HandleErrorInMonitoring(ByVal customMessage, ByRef oBag, ByRef oAPI)
Dim logger
If Err.number &lt;&gt; 0 Then
Set logger = new ScriptLogger
logger.LogError(customMessage)
Call oAPI.Return(oBag)
Wscript.Quit 0
End If
End Sub

Sub HandleErrorInDiscovery(ByVal customMessage, ByRef oDiscovery, ByRef oAPI)
Dim logger
If Err.number &lt;&gt; 0 Then
Set logger = new ScriptLogger
logger.LogError(customMessage)
oDiscovery.IsSnapshot = false
HandleDebugMessage("Discovery: IsSnapshot = false")
oAPI.Return(oDiscoveryData)
Wscript.Quit 0
End If
End Sub

Sub HandleNonCriticalErrorInDiscovery(ByVal customMessage, ByRef oDiscovery)
Dim logger
Set logger = new ScriptLogger
logger.LogError(customMessage)
oDiscovery.IsSnapshot = false
HandleDebugMessage("Discovery: IsSnapshot = false")
End Sub

Sub HandleDebugMessage(ByVal debugMessage)
Dim logger
Set logger = new ScriptLogger
logger.LogDebug(debugMessage)
End Sub


Const ERROR_EVENT_TYPE = 1
Const WARNING_EVENT_TYPE = 2
Const INFO_EVENT_TYPE = 4

Class ScriptLogger
Dim sourceLogEvent
Dim oAPI

Private Sub Class_Initialize()
sourceLogEvent = MANAGEMENT_PACK_ID
If (sApplianceID &lt;&gt; "") Then
sourceLogEvent = sourceLogEvent &amp; ". Appliance: " &amp; sApplianceID
End If
sourceLogEvent = sourceLogEvent &amp; ". Script: " &amp; WScript.ScriptName
Set oAPI = CreateObject("MOM.ScriptAPI")
End Sub

Private Function LogEvent(ByVal message, ByVal eventType, ByVal scriptEventID)
On Error Resume Next
Call oAPI.LogScriptEvent(sourceLogEvent, scriptEventID, eventType, message)
End Function

Public Function LogDebug(ByVal message)
if DEBUG_MODE Then
WScript.StdOut.WriteLine message
Call oAPI.LogScriptEvent(sourceLogEvent, DEBUG_SCRIPT_EVENT_ID, INFO_EVENT_TYPE, message)
End If
End Function

Public Function LogWarning(ByVal customMessage)
Dim message
If Err.number &lt;&gt; 0 Then
message = Replace(" Error Number: #P1# " &amp; VbCrLf &amp; " Description: #P2# ", "#P1#", CStr(Err.number and 65535) )
message = Replace(message, "#P2#", Err.Description )
message = customMessage &amp; VbCrLf &amp; message &amp; VbCrLf
Else
message = customMessage &amp; VbCrLf
End If

if DEBUG_MODE Then
WScript.StdOut.WriteLine message
End If
LogEvent message, WARNING_EVENT_TYPE, SCRIPT_EVENT_ID
End Function

Public Function LogError(ByVal customMessage)
Dim message
If Err.number &lt;&gt; 0 Then
message = Replace(" Error Number: #P1# " &amp; VbCrLf &amp; " Description: #P2# ", "#P1#", CStr(Err.number and 65535) )
message = Replace(message, "#P2#", Err.Description )
message = customMessage &amp; VbCrLf &amp; message &amp; VbCrLf
Else
message = customMessage &amp; VbCrLf
End If

If DEBUG_MODE Then
WScript.StdOut.WriteLine message
End If

If USE_EVENT_LOG Then
LogEvent message, ERROR_EVENT_TYPE, SCRIPT_EVENT_ID
End If
If USE_ERROR_LOG Then
WScript.StdErr.WriteLine message
End If
End Function

End Class

Function IsStringEmpty(ByVal sValue)
If sValue = EMPTY Or Trim(sValue) = "" Then
IsStringEmpty = true
Else
IsStringEmpty = false
End If
End Function
'' Provides Registry access via WMI
''
'' Important : This vbs module requires Common.vbs

'This class can connect to wmi and call StdRegProv methods
Class Registry
'Standard Hives
Public HKEY_CLASSES_ROOT
Public HKEY_CURRENT_USER
Public HKEY_LOCAL_MACHINE
Public HKEY_USERS
Public HKEY_CURRENT_CONFIG

'Results of calling some StdRegProv methods
Public ERROR_ACCESS_DENIED
Public ERROR_KEY_NOT_FOUND
Public ERROR_VALUE_NOT_FOUND
Public SUCCESS

Private oReg
Private m_lHive

Private Sub Class_Initialize()
HKEY_CLASSES_ROOT = &amp;H80000000
HKEY_CURRENT_USER = &amp;H80000001
HKEY_LOCAL_MACHINE = &amp;H80000002
HKEY_USERS = &amp;H80000003
HKEY_CURRENT_CONFIG = &amp;H80000005

ERROR_ACCESS_DENIED = 5
ERROR_KEY_NOT_FOUND = 2
ERROR_VALUE_NOT_FOUND = 1
SUCCESS = 0

m_lHive = HKEY_LOCAL_MACHINE
End Sub

'connect to WMI
Public Sub Connect(ByVal sHostName)
On Error Resume Next
Set oReg = GetObject("winmgmts://" &amp; sHostName &amp; "/root/default:StdRegProv")
Call HandleError("Cannot connect to WMI on " &amp; sHostName)
End Sub

'Getter of Hive property
' Hive is root folder in Registry (for example HKLM\)
Public Property Get Hive()
Hive = m_lHive
End Property
'Setter Hive
Public Property Let Hive(ByVal lHive)
m_lHive = lHive
End Property

'This method reads all subkeys and returns it
Public Function EnumKey(ByVal sKeyPath, ByRef lResult)
Dim sNames
lResult = oReg.EnumKey(m_lHive, sKeyPath, sNames)
EnumKey = sNames
End Function

'This method reads all key values and returns it
Public Function EnumValues(ByVal sKeyPath, ByRef lResult)
Dim aNames
Dim aTypes
lResult = oReg.EnumValues(m_lHive, sKeyPath, aNames, aTypes)
EnumValues = aNames
End Function


Public Function ReadStringValue(ByVal sKeyPath, ByVal sValueName, ByRef lResult)
Dim sValue
lResult = oReg.GetStringValue(m_lHive, sKeyPath, sValueName, sValue)
ReadStringValue = sValue
End Function

Public Function WriteStringValue(ByVal sKeyPath, ByVal sValueName, ByVal sValue)
WriteStringValue = oReg.SetStringValue(m_lHive, sKeyPath, sValueName, sValue)
End Function

'This method checks if Registry key with [sKeyPath] exists
Public Function KeyExists(ByVal sKeyPath)
On Error Resume Next
Dim aSubfolders
Dim result
result = oReg.EnumKey(m_lHive, sKeyPath, aSubfolders)
if result = SUCCESS Then
KeyExists = true
Else
KeyExists = false
End If
Call HandleError("Cannot access registry key: " &amp; sKeyPath)
End Function

End Class
On Error Resume Next

Const ROOT_APS_PATH = "Software\Microsoft\Analytics Platform System\Management Pack\Appliances\"

' Registry Keys
Const APS_VERSION_KEY = "MpVersion"
Const APS_HOST_KEY = "Host"
Const APS_PORT_KEY = "Port"

Dim aSupportedVersions : aSupportedVersions = Array("V2AU1")

Dim SourceID
Dim ManagedEntityId

Dim sPrincipalName

Dim oAPI
Dim oRegistry

Set oAPI = CreateObject("MOM.ScriptAPI")
Call HandleError("Cannot create MOM.ScriptAPI object")

Set oRegistry = new Registry

Dim oDiscoveryData

Call Main()

'This function try read key from registry
Sub ReadValue(ByVal path, ByVal key, ByRef sValue)
On Error Resume Next
Dim lResult
lResult = TryReadValue(path, key, sValue)

If lResult = oRegistry.ERROR_KEY_NOT_FOUND Or lResult = oRegistry.ERROR_VALUE_NOT_FOUND Then
Call HandleNonCriticalErrorInDiscovery("Registry entry is missing or empty: " &amp; path &amp; "@" &amp; key, oDiscoveryData)
ElseIf lResult = oRegistry.ERROR_ACCESS_DENIED Then
Call HandleNonCriticalErrorInDiscovery("Access Denied to Registry.", oDiscoveryData)
End If
End Sub

Function TryReadValue(ByVal path, ByVal key, ByRef sValue)
On Error Resume Next
Dim lResult
sValue = oRegistry.ReadStringValue(path, key, lResult)
TryReadValue = lResult
End Function

'Main method
Sub Main()
On Error Resume Next
Dim oParams
Set oParams = WScript.Arguments

SourceID = oParams(0)
Call HandleError("Cannot read SourceID from params")

ManagedEntityId = oParams(1)
Call HandleError("Cannot read ManagedEntityId from params")

sPrincipalName = oParams(2)
Call HandleError("Cannot read PrincipalName from params")

Set oParams = Nothing

oRegistry.Connect(sPrincipalName)'Connect to WMI service
Call HandleError("Cannot connect to WMI service")

Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
Call HandleError("Cannot create Discovery Data object")

Call DoApplianceDiscovery()

Call oAPI.Return(oDiscoveryData)
End Sub

'Method for discovery data
Sub DoApplianceDiscovery()
On Error Resume Next

' Perform discovery
Dim APSInstances, lResult
APSInstances = oRegistry.EnumKey(ROOT_APS_PATH, lResult)
Call HandleError("Cannot read APS instances from registry")

Dim InstanceName, sHost, bApplianceExists, sPort
bAppliancesExists = false
For Each InstanceName In APSInstances
Set sHost = Empty
Set sPort = Empty
If IsApplianceAPSInstance(InstanceName, sHost, sPort) Then
Call CreateApplianceDiscoveryData(InstanceName, sHost, sPort)
bAppliancesExists = true
End If
Next

If bAppliancesExists THEN
Dim oServer
Set oServer = oDiscoveryData.CreateClassInstance("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Server']$")
Call oServer.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sPrincipalName)
Call oServer.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Server']/ApplianceName$", "N\A")
Call oServer.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Server']/ApplianceType$", "APS")
Call oServer.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Server']/Role$", "Watcher Node")
Call oDiscoveryData.AddInstance(oServer)
End If
End Sub

'Method checks if provided registry key is APS Appliance instance
Function IsApplianceAPSInstance(ByVal sInstanceKey, ByRef sHost, ByRef sPort)
IsApplianceAPSInstance = False

Dim lResult
Dim sVersionValue, sHostValue, sPortValue
lResult = TryReadValue(ROOT_APS_PATH &amp; sInstanceKey, APS_VERSION_KEY, sVersionValue)
If (lResult &lt;&gt; 0 Or IsEmpty(sVersionValue) Or Not IsSupportedVersion(sVersionValue)) Then
Exit Function
End If

lResult = TryReadValue(ROOT_APS_PATH &amp; sInstanceKey, APS_HOST_KEY, sHostValue)
If (lResult &lt;&gt; 0 Or IsEmpty(sHostValue)) Then
Exit Function
End If

lResult = TryReadValue(ROOT_APS_PATH &amp; sInstanceKey, APS_PORT_KEY, sPortValue)
If (lResult &lt;&gt; 0 Or IsEmpty(sPortValue)) Then
Exit Function
End If

sHost = sHostValue
sPort = sPortValue
IsApplianceAPSInstance = True
End Function

Function IsSupportedVersion(ByVal sVersion)
IsSupportedVersion = False
Dim nIndex
For nIndex = LBound(aSupportedVersions) To UBound(aSupportedVersions)
If (LCase(Right(sVersion, Len(aSupportedVersions(nIndex)))) = LCase(aSupportedVersions(nIndex))) Then
IsSupportedVersion = True
Exit Function
End If
Next
End Function

'Method creates APS Appliance instance
Sub CreateApplianceDiscoveryData(ByVal sInstanceName, ByVal sHost, ByVal sPort)
On Error Resume Next

Dim sTdsAddress
sTdsAddress = sHost &amp; "," &amp; sPort
Dim oAppliance
Set oAppliance = oDiscoveryData.CreateClassInstance("$MPElement[Name='APSLibrary!Microsoft.SQLServerAppliance.APS.Appliance']$")
Call oAppliance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", sInstanceName)
Call oAppliance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sPrincipalName)
Call oAppliance.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Appliance']/ApplianceID$", sInstanceName)
Call oAppliance.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Appliance']/ApplianceName$", sInstanceName)
Call oAppliance.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Appliance']/ApplianceType$", "APS")
Call oAppliance.AddProperty("$MPElement[Name='SSALibrary!Microsoft.SQLServerAppliance.Appliance']/ApplianceModel$", "2012 AU1")
Call oAppliance.AddProperty("$MPElement[Name='APSLibrary!Microsoft.SQLServerAppliance.APS.Appliance']/NetworkAddress$", sHost)
Call oAppliance.AddProperty("$MPElement[Name='APSLibrary!Microsoft.SQLServerAppliance.APS.Appliance']/TdsAddress$", sTdsAddress)
Call oDiscoveryData.AddInstance(oAppliance)
End Sub
</Script></ScriptBody>
<TimeoutSeconds>300</TimeoutSeconds>
</DataSource>
</Discovery>