Detección del servicio de Cluster Server

Microsoft.Windows.Cluster.Monitoring.Service.Discovery.Module (DataSourceModuleType)

Proveedor del módulo de detección para el clúster de servidores de Windows.

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsMicrosoft.Windows.Cluster.PrivilegedAccount
OutputTypeSystem.Discovery.Data

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource System.CommandExecuterDiscoveryDataSource Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
Frequencyint$Config/Frequency$Frecuencia de detección

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Cluster.Monitoring.Service.Discovery.Module" Accessibility="Internal" RunAs="Cluster!Microsoft.Windows.Cluster.PrivilegedAccount" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="Frequency" type="xsd:unsignedInt"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="Frequency" Selector="$Config/Frequency$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="Scheduler" TypeID="System!System.CommandExecuterDiscoveryDataSource">
<IntervalSeconds>$Config/Frequency$</IntervalSeconds>
<ApplicationName>%SystemRoot%\system32\cmd.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>/c $file/Main.cmd$</CommandLine>
<TimeoutSeconds>400</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Main.cmd</Name>
<Contents><Script>

@echo off
set psscript=DiscoverClusterService.ps1
set vbscript=DiscoverClusterService.vbs
set cscript=%windir%\system32\cscript.exe
set ps=%windir%\system32\WindowsPowerShell\v1.0\powershell.exe
set params=

if Exist "%cscript%" goto vb
if Exist "%ps%" goto pshell
goto end
:vb
if not exist "%~dp0%vbscript%" goto end

if exist "%~dp0vbparams.txt" (
set /p params=&lt;"%~dp0vbparams.txt"
)

"%cscript%" /nologo "%~dp0%vbscript%" %params%
goto end
:pshell
if not exist "%~dp0%psscript%" goto end

if exist "%~dp0psparams.txt" (
set /p params=&lt;"%~dp0psparams.txt"
)
"%ps%" -nologo -EP bypass -command "&amp; '%~dp0%psscript%'" %params%
goto end

:end
If %ERRORLEVEL% NEQ 0 (
exit %ERRORLEVEL%
)



</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>DiscoverClusterService.ps1</Name>
<Contents><Script>

param
(
$SourceId
,$ManagedEntityId
,$MgName
,$ComputerName

)



Function Init-ScomHelper
{
$DiscHelper = @'
namespace SCOM.Helper
{
using System;
using System.Runtime.InteropServices;
public class ConvertData
{

public static string GetDataItemFromOutput(
Object oData)
{
NativeMethods.ISerialize discoverySerializer = null;
discoverySerializer = oData as NativeMethods.ISerialize;
string xmlString = null;
if (null != discoverySerializer)
{
int hr = discoverySerializer.SaveToString(out xmlString);
Marshal.ThrowExceptionForHR(hr);
}

return xmlString;
}

public static class NativeMethods
{
[Guid("A4E79E8A-9494-47A4-A280-8C7D35C88A2F"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISerialize
{
int SaveToString([MarshalAs(UnmanagedType.BStr)] out string output);
int LoadFromString([MarshalAs(UnmanagedType.BStr)] string input);
}
}
}
}

'@

$ErrorActionPreference = "SilentlyContinue"
$Error.Clear()
Add-Type $DiscHelper

$result = 0 -eq $Error.Count

return $result
}

#=================================
#Global Variables
##################################
$oAPI = $null
#====================================
# Log Constants
#=====================================
$DBG_NONE = 0
$DBG_ERROR = 1
$DBG_WARNING = 2
$DBG_TRACE = 4
$EventId = 7001
$Start_SnapShotDiscovery = 0
$Exit_SnapShotDiscovery = 1
$Exit_IncrementalDiscovery = 2


#=====================================
# String Constants
#=====================================
$ScriptName = "DiscoverClusterService.ps1"

$StartParametersMsg = @"

Windows Cluster ServiceDiscovery
SourceId: {0} ManagedEntityId : {1} Management Group Name : {2} ComputerName : {3}
"@
$StartDiscoveryMsg = "Started cluster service discovery at machine local time:"
$FinishDiscoveryMsg = "Finished dicovery at machine local time: "
$CreateDiscoveryDataErrorMsg = "Failed to get Discovery Data Object. MOM v3 must be installed to execute this script."
$InitApiErrorMsg = "Failed to get Discovery API. MOM v3 must be installed to execute this script. Error:{0}"
$InitScomSerApiErrorMsg = "Failed to Initialize SCOM Discovery Serialization API. MOM v3 must be installed to execute this script."

$ErrorStartParametersMsg = "Minimal list of parameters is empty. Exiting discovery. SourceId: {0} ManagedEntityId : {1} Management Group Name : {2} ComputerName : {3} "


#==========================================================================
# FUNCTIONS
#==========================================================================

Function DiscoverInstances
(
$SourceId
,$ManagedEntityId
,$MgName
,$ComputerName
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
Log-DiscoveryMessage -message $StartDiscoveryMsg
$error.Clear()
$oDiscoveryData = $oAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)

If(0 -ne $error.Count -or [string]::IsNullOrEmpty($oDiscoveryData))
{
LogMessage $DBG_ERROR $CreateDiscoveryDataErrorMsg + " Error: " + $error[0].Exception.Message

return $null
}

$ClusterName = Get-ClusterName

if (0 -ne $error.Count)
{
$oDiscoveryData.IsSnapshot = $false
return $oDiscoveryData
}

if ([string]::IsNullOrEmpty($ClusterName))
{
return $oDiscoveryData
}

$IsRootHealthService = Get-RootHealthService -MgName $MgName
if (0 -ne $error.Count)
{
$oDiscoveryData.IsSnapshot = $false
return $oDiscoveryData
}

if ($true -eq $IsRootHealthService)
{
return $oDiscoveryData
}

$ClassId = "$MPElement[Name='Microsoft.Windows.Cluster.Monitoring.Service']$"
$emptyDiscoveryData = Get-EmptyDiscoveryData -SourceId $SourceId -ManagedEntityId $ManagedEntityId -IsSnapshot $false
$oClassInstance = $oDiscoveryData.CreateClassInstance($ClassId)
if ($null -eq $oClassInstance -or 0 -ne $error.Count)
{
$oDiscoveryData = $emptyDiscoveryData
}
else
{

$oClassInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$",$ComputerName)
$oClassInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Monitoring.Service']/ClusterName$",$ClusterName)

if (0 -ne $error.Count)
{
$oDiscoveryData = $emptyDiscoveryData
}
else
{
$oDiscoveryData.AddInstance($oClassInstance)
if (0 -ne $error.Count)
{
$oDiscoveryData = $emptyDiscoveryData
}

}

}


Log-DiscoveryMessage -message $FinishDiscoveryMsg
return $oDiscoveryData
}

function Get-EmptyDiscoveryData($SourceId, $ManagedEntityId,$IsSnapshot)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$Error.Clear()

if ($null -eq $oAPI)
{
$oAPI = New-Object -ComObject "MOM.ScriptAPI"
if ($null -eq $oAPI)
{
return $null
}
}

$Error.Clear()

$oDiscoveryDataTmp= $oAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
$oDiscoveryDataTmp.IsSnapshot = $IsSnapshot
$Error.Clear()

return $oDiscoveryDataTmp
}

Function Convert-ToBoolean([string] $sBool)
{
[bool] $result = $false
[bool] $iresult = $false

if ($false -eq [string]::IsNullOrEmpty($sBool) )
{
$result = $sBool.Equals("true",[System.StringComparison]::InvariantCultureIgnoreCase)
$iresult = $sBool.Equals("1",[System.StringComparison]::InvariantCultureIgnoreCase)
$result = $result -or $iresult
}

return $result
}

Function Get-ClusterName()
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()

$ClusterName = ""
$ClusterName = (Get-ItemProperty -Path "HKLM:\Cluster" -Name "ClusterName").ClusterName

if(0 -ne $error.Count)
{
$ClusterName = ""
$Exception = $error[0].Exception
if ([System.Management.Automation.ItemNotFoundException] -eq $Exception)
{
$error.Clear()
}
}

return $ClusterName
}

Function Get-RootHealthService([string]$MgName)
{
$ErrorActionPreference = "SilentlyContinue"
$error.Clear()

$result = $false

if ([string]::IsNullOrEmpty($MgName))
{
return $result
}

$KeyName = "HKLM:SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Server Management Groups\$MgName"
$IsRootHealthService = (Get-ItemProperty -Path $KeyName -Name "IsRootHealthService").IsRootHealthService

if(0 -ne $error.Count)
{

$error.Clear()

}
else
{
$result = Convert-ToBoolean -sBool $IsRootHealthService
}

return $result
}

Function Log-DiscoveryMessage([string]$message)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$timex=get-date -displayhint time
$message = $message +" " + $timex
LogMessage $DBG_TRACE $message

}

Function LogMessage($nLevel, $strMessage,$LogId = $EventId)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function

if($nLevel -eq $DBG_ERROR)
{
Write-Host "[Error]: " $strMessage;
}elseif ($nLevel -eq $DBG_WARNING)
{
Write-Host "[Warning]: " $strMessage;
} elseif ($nLevel -eq $DBG_TRACE)
{
Write-Host "[Trace]: " $strMessage;
}
else
{
Write-Host $strMessage
}
$Error.Clear()

if ($null -eq $oAPI)
{
$oAPI = New-Object -ComObject "MOM.ScriptAPI"
if ($null -eq $oAPI)
{
return $null
}
}

if ($null -eq $LogId)
{
$LogId = 7001
}

$oAPI.LogScriptEvent($ScriptName,$LogId,$nLevel,$Message)
}


#==========================================================================
# Initialize the arguments in Script
#==========================================================================
Function Initialize-DiscoveryScript
(
[ref]$oAPI
)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$oAPI.Value = New-object -ComObject "MOM.ScriptAPI"
if ([string]::IsNullOrEmpty($oAPI.Value) -or 0 -ne $error.Count)
{
exit -1
}

$result = Init-ScomHelper
if ($false -eq $result)
{
exit -1
}

}

Function Log-StartParameters
{
$message = $StartParametersMsg -f ($SourceId,$ManagedEntityId,$MgName,$ComputerName)
LogMessage $DBG_TRACE $message

If ([string]::IsNullOrEmpty($SourceId) -or [string]::IsNullOrEmpty($ManagedEntityId) -or [string]::IsNullOrEmpty($MgName) -or [string]::IsNullOrEmpty($ComputerName))
{
$message = $ErrorStartParametersMsg -f ($SourceId,$ManagedEntityId,$MgName,$ComputerName)
LogMessage $DBG_ERROR $message
exit -1
}
}


#==========================================================================
# Main
#==========================================================================
$ErrorActionPreference = "SilentlyContinue"

Initialize-DiscoveryScript -oAPI ([ref] $oAPI)
Log-StartParameters

$discoveryData = DiscoverInstances -SourceId $SourceId -ManagedEntityId $ManagedEntityId -MgName $MgName -ComputerName $ComputerName

if ($null -ne $discoveryData)
{
$SerializeDiscoveryData = [Scom.Helper.ConvertData]::GetDataItemFromOutput($discoveryData)
Write-Host "$SerializeDiscoveryData"
}
</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>DiscoverClusterService.vbs</Name>
<Contents><Script>
Option Explicit
SetLocale("en-us")

Const EventTypeError = 1
Const EventTypeWarning = 2
Const EventTypeInformation = 0
Const ScriptEventId = 7041
Const ScriptName = "DiscoverClusterService.vbs"

Const Start_SnapShotDiscovery = 0
Const Exit_SnapShotDiscovery = 1
Const Exit_IncrementalDiscovery = 2

Call Main

Sub Main()
On Error Resume Next
Err.Clear

Dim oAPI, oDiscoveryData
Dim SourceId,ManagedEntityId,MgName,ComputerName
Dim result
Dim message
Dim IsArgs

result = False
Set oAPI = CreateObject("MOM.ScriptAPI")
If(0 &lt;&gt; Err.number or (False = HasValue(oAPI)) ) Then
WScript.Quit(-1)
End If

SourceId = ""
ManagedEntityId = ""
MgName = ""
ComputerName = ""

result = GetArguments(SourceId,ManagedEntityId,MgName,ComputerName,IsArgs)
message = "SourceId: " &amp; SourceId &amp; " ManagedEntityId: " &amp; ManagedEntityId &amp; vbCrLf
message = message &amp; "MgName : " &amp; MgName &amp; " ComputerName: " &amp; ComputerName &amp; vbCrLf

If(False = result) Then
Call oAPI.LogScriptEvent(ScriptName,ScriptEventId, EventTypeWarning, "Wrong Number of arguments." &amp; vbCrLf &amp; message)
WScript.Quit(-2)
End If

Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
If(0 &lt;&gt; Err.number or (False = HasValue(oDiscoveryData)) ) Then
message = "Cannot create Discovery Data. Error: " &amp; Err.Description &amp; vbCrLf &amp; message
Call oAPI.LogScriptEvent(ScriptName,ScriptEventId, EventTypeError, message)
WScript.Quit(-3)
End If

If (False = IsArgs) Then
oDiscoveryData.IsSnapShot = False
Call oAPI.Return(oDiscoveryData)
Set oAPI = Nothing
Exit Sub
End If

result = DiscoverInstances(MgName,ComputerName,oDiscoveryData)
If(False = result) Then
Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
If(0 &lt;&gt; Err.number or (False = HasValue(oDiscoveryData)) ) Then
message = "Cannot create empty Discovery Data. Error: " &amp; Err.Description &amp; vbCrLf &amp; message
Call oAPI.LogScriptEvent(ScriptName,ScriptEventId, EventTypeError, message)
WScript.Quit(-4)
End If

oDiscoveryData.IsSnapShot = False
End If

Call oAPI.Return(oDiscoveryData)

Set oDiscoveryData = Nothing
Set oAPI = Nothing

End Sub

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 GetArguments(ByRef SourceId,ByRef ManagedEntityId,ByRef MgName,ByRef ComputerName,ByRef IsArgs)
On Error Resume Next
Err.Clear

GetArguments = False
IsArgs = False

If (WScript.Arguments.Count &lt; 2) Then
Exit Function
End If

Dim objArguments

Set objArguments = WScript.Arguments
SourceId = Replace(objArguments(0), Chr(34), "")
ManagedEntityId = Replace(objArguments(1), Chr(34), "")

If (WScript.Arguments.Count &lt; 4) Then
GetArguments = True
Exit Function
Else
IsArgs = True
End If

If oArgs.Count &gt;= 12 Then
IsArgs = True
Else
If ((True = HasValue(SourceId)) And (True = HasValue(ManagedEntityId)) ) Then
Initialize = True
End If
Exit Function
End If


MgName = Replace(objArguments(2), Chr(34), "")
ComputerName = Replace(objArguments(3), Chr(34), "")

GetArguments = True

On Error Goto 0
End Function

Function GetRegistryKeyValue(ByVal keyPath, ByVal key)
Dim oReg, strKeyValue

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

' resume error
On Error Goto 0

GetRegistryKeyValue = strKeyValue
End Function


Function DiscoverInstances(MgName,ComputerName,oDiscoveryData)

On Error Resume Next
Err.Clear

Dim result, oClassInstance
Dim ClusterName, IsRootHealthService,RootHealthServiceKeyName

DiscoverInstances = True
RootHealthServiceKeyName = "HKLM\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Server Management Groups\" &amp; MgName &amp; "\"
ClusterName = GetRegistryKeyValue("HKLM\Cluster\","ClusterName")
IsRootHealthService = GetRegistryKeyValue(RootHealthServiceKeyName,"IsRootHealthService")
IsRootHealthService = CStr(IsRootHealthService)

If( (0 = Len(ClusterName)) Or ("1" = IsRootHealthService) ) Then
Exit Function
End If

Set oClassInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Microsoft.Windows.Cluster.Monitoring.Service']$")
If (0 &lt;&gt; Err.number) Then
DiscoverInstances = False
Exit Function
End If

Call oClassInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$",ComputerName)
Call oClassInstance.AddProperty("$MPElement[Name='Microsoft.Windows.Cluster.Monitoring.Service']/ClusterName$",ClusterName)

If (0 &lt;&gt; Err.number) Then
DiscoverInstances = False
Exit Function
End If

Call oDiscoveryData.AddInstance(oClassInstance)
DiscoverInstances = (0 = Err.number )

On Error Goto 0
End Function


</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>vbparams.txt</Name>
<Contents><Script>"$MPElement$" "$Target/Id$" "$Target/ManagementGroup/Name$" "$Target/Host/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$"</Script></Contents>
<Unicode>false</Unicode>
</File>
<File>
<Name>psparams.txt</Name>
<Contents><Script>'$MPElement$' '$Target/Id$' '$Target/ManagementGroup/Name$' '$Target/Host/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$'</Script></Contents>
<Unicode>false</Unicode>
</File>
</Files>
</DataSource>
</MemberModules>
<Composition>
<Node ID="Scheduler"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>