S2D 2016: Seed Discovery Data Source

Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Discovery.DataSource.Seed (DataSourceModuleType)

Seed discovery data source.

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
Frequencyint$Config/Frequency$Interval (sec)
TimeoutSecondsint$Config/TimeoutSeconds$Timeout (sec)

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Discovery.DataSource.Seed" Accessibility="Internal">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Frequency" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="Frequency" Selector="$Config/Frequency$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="DS" TypeID="System!System.CommandExecuterDiscoveryDataSource">
<IntervalSeconds>$Config/Frequency$</IntervalSeconds>
<ApplicationName>%SystemRoot%\system32\cmd.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>/c $file/Main.cmd$</CommandLine>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Main.cmd</Name>
<Contents><Script>

@echo off
set psscript=S2DseedDiscovery.ps1
set vbscript=S2DseedDiscovery.js
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

"%ps%" -nologo -EP bypass -command "&amp; '%~dp0%psscript%'"
goto end

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



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


$SourceId = @"
$MPElement$
"@

$ManagedEntityId = @"
$Target/Id$
"@

$clname = @"
$Target/Property[Type='Windows!Microsoft.Windows.Computer']/NetbiosComputerName$
"@

$clfqdn = @"
$Target/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$
"@




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
}

$EventId = 7200
$Start_SnapShotDiscovery = 0
$Exit_SnapShotDiscovery = 1
$Exit_IncrementalDiscovery = 2

$LOG_EVENT_TYPE_ERROR = 1
$LOG_EVENT_TYPE_WARNING = 2
$LOG_EVENT_TYPE_INFORMATION = 0


$ClassId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Seed']$"
$DispIdProp = "$MPElement[Name='System!System.Entity']/DisplayName$"
$KeyIdProp = "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$"
#=====================================
# String Constants
#=====================================
$ScriptName = "S2DseedDiscovery.ps1"

#==========================================================================
# FUNCTIONS
#==========================================================================
function Check-S2D()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

if ([string]::IsNullOrEmpty($clname) -or [string]::IsNullOrWhiteSpace($clname))
{
return $false;
}

if ([string]::IsNullOrEmpty($clfqdn) -or [string]::IsNullOrWhiteSpace($clfqdn))
{
return $false;
}

$result = $null;
$result = (Get-Item "HKLM:\Cluster").GetValue("ClusterName")
$error.Clear()

if ([string]::IsNullOrEmpty($result) -or [string]::IsNullOrWhiteSpace($result))
{
return $false;
}

if ($result -ne $clname)
{
return $false;
}

$result = $null;
$result = (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels").GetValue("NanoServer")
$error.Clear()
if ( 1 -eq $result) {return $false }

$result = $null;
$result = (Get-Item "HKLM:\Cluster").GetValue("S2DEnabled")
$error.Clear()
if ( 1 -ne $result) {return $false }

$result = $null;
$result = (Get-Item "HKLM:\Cluster").GetValue("OSVersion")
$error.Clear()

if ([string]::IsNullOrEmpty($result) -or [string]::IsNullOrWhiteSpace($result))
{
return $false;
}

if ($result -notlike "10.0*") {return $false }

$result = $null;
$result = (Get-Item "HKLM:\Cluster").GetValue("OS")
$error.Clear()

if ([string]::IsNullOrEmpty($result) -or [string]::IsNullOrWhiteSpace($result))
{
return $false;
}

if ( -Not ($result -like "*datacenter*" ) ) { return $false }

return $true
}

Function Discover-Instances
(

)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$oAPI = New-Object -ComObject "MOM.ScriptAPI"
if ($null -eq $oAPI -or $error.Count -ne 0)
{
$message = "Cannot create MOM API object. " + $error[0].Exception.Message
Write-Host $message
exit -1
}

$result = Init-ScomHelper
if ($false -eq $result)
{
$message = "Cannot create Discovery data serilization object. " + $error[0].Exception.Message
Write-Host $message
$oAPI.LogScriptEvent($ScriptName,$EventId,$LOG_EVENT_TYPE_ERROR,$message)
exit -3
}

$oDiscoveryData = $oAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)
$emptyDiscoveryData = $oAPI.CreateDiscoveryData(0, $SourceId, $ManagedEntityId)

If(0 -ne $error.Count -or [string]::IsNullOrEmpty($oDiscoveryData) -or [string]::IsNullOrEmpty($emptyDiscoveryData))
{
$message = "Cannot create MOM Discovery object. " + $error[0].Exception.Message
Write-Host $message
$oAPI.LogScriptEvent($ScriptName,$EventId,$LOG_EVENT_TYPE_ERROR,$message)
exit -2
}

$result = Check-S2D

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

$error.Clear()

$oClassInstance = $oDiscoveryData.CreateClassInstance($ClassId)
if ($null -eq $oClassInstance -or 0 -ne $error.Count)
{
$message = "Cannot create MOM Class object. " + $error[0].Exception.Message
Write-Host $message
$oAPI.LogScriptEvent($ScriptName,$EventId,$LOG_EVENT_TYPE_ERROR,$message)

$emptyDiscoveryData.IsSnapshot = $true
return $emptyDiscoveryData
}

$oClassInstance.AddProperty($KeyIdProp,$clfqdn)
$oClassInstance.AddProperty($DispIdProp,$clfqdn)
$oDiscoveryData.AddInstance($oClassInstance)

if ( 0 -ne $error.Count)
{
$message = "Cannot add object to discovery data. " + $error[0].Exception.Message
Write-Host $message
$oAPI.LogScriptEvent($ScriptName,$EventId,$LOG_EVENT_TYPE_ERROR,$message)

$emptyDiscoveryData.IsSnapshot = $false

return $emptyDiscoveryData
}

return $oDiscoveryData
}



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

$discoveryData = Discover-Instances

if ($null -ne $discoveryData)
{
$SerializeDiscoveryData = [Scom.Helper.ConvertData]::GetDataItemFromOutput($discoveryData)
Write-Host "$SerializeDiscoveryData"
}
</Script></Contents>
<Unicode>true</Unicode>
</File>
<File>
<Name>S2DseedDiscovery.js</Name>
<Contents><Script>var S2Dkey = "HKLM\\Cluster\\S2DEnabled";
var clName = "HKLM\\Cluster\\ClusterName";
var osVersion = "HKLM\\Cluster\\OSVersion";
var osEdt = "HKLM\\Cluster\\OS";
var nanoKey = "HKLM\\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels\\NanoServer";
var $evtId = 7200;
var $ClId = "$MPElement[Name='Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.Seed']$";

function alert($message) {
WScript.Echo($message);
}

function exit($message) {
alert($message);
WScript.Quit(0);
}

String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/gm, '');
}

function GetErrorDetails($e) {
if (!($e instanceof Error)) { return ""; }

if ($e.number &lt; 0) {
$e.number = 0xffffffff + $e.number + 1;
}

return " Error details: Error code: 0x" + $e.number.toString(16) + ". Description : " + $e.description;
}

function winReg()
{

}

winReg._r = null

winReg.Init = function()
{
var $r = false;
try
{
winReg._r = new ActiveXObject("WScript.Shell");
$r = true;
}
catch(e)
{
winReg._r = null;
}

return $r;
}

winReg.CleanUp = function()
{
if (null !== winReg._r)
{
delete winReg._r;
winReg._r = null;
}

}


winReg.getRegistryValue = function ($key)
{
var $r = null;
if ("string" !== typeof($key)) {return $r}
if (null === winReg._r &amp;&amp; false === winReg.Init()) {return $r;}

try
{
$r = winReg._r.RegRead($key);
}
catch(e)
{
$r = undefined;
}

return $r;
}

/////////////////////////////////////////////////////////////////////////
//SCOM API Helper
/////////////////////////////////////////////////////////////////////////
function ScomApiHelper() {

}

ScomApiHelper.LOG_EVENT_TYPE_ERROR = 1;
ScomApiHelper.LOG_EVENT_TYPE_WARNING = 2;
ScomApiHelper.LOG_EVENT_TYPE_INFORMATION = 0;

ScomApiHelper.START_SNAPSHOT = 0;
ScomApiHelper.EXIT_SNAPSHOT = 1;
ScomApiHelper.EXIT_Incremental = 2;

ScomApiHelper.ScriptName = WScript.ScriptName;
ScomApiHelper._momAPI = null;
ScomApiHelper._DiscoveryData = null;
ScomApiHelper._emptyDiscoveryData = null;
ScomApiHelper.publishDiscovery = ScomApiHelper.StartSnapShot;

ScomApiHelper.InitDiscovery = function ($sourceId, $managedEntityId) {
var $result = null === ScomApiHelper._momAPI ? ScomApiHelper.InitMomApi() : true;
var $message = "Cannot initialize discovery data. ";

if (false === $result) {
WScript.Quit(-1);
}

try {
ScomApiHelper._DiscoveryData = ScomApiHelper._momAPI.CreateDiscoveryData(0, $sourceId, $managedEntityId);
ScomApiHelper._emptyDiscoveryData = ScomApiHelper._momAPI.CreateDiscoveryData(0, $sourceId, $managedEntityId);
} catch (e) {
ScomApiHelper.Log($message, ScomApiHelper.LOG_EVENT_TYPE_ERROR, e);
$result = false;
WScript.Quit(-2);
}

return $result;
}

ScomApiHelper.InitMomApi = function () {
var $result = true;
if (null !== ScomApiHelper._momAPI) {
return true;
}

try {
ScomApiHelper._momAPI = new ActiveXObject("MOM.ScriptAPI");
} catch (e) {
alert("Cannot initialize MOM API. " + GetErrorDetails(e));

$result = false;
}

return $result;
}

ScomApiHelper.Cleanup = function () {
delete ScomApiHelper._DiscoveryData;
ScomApiHelper._DiscoveryData = null;

delete ScomApiHelper._emptyDiscoveryData;
ScomApiHelper._emptyDiscoveryData = null;

delete ScomApiHelper._momAPI;
ScomApiHelper._momAPI = null;
}

ScomApiHelper.Exit = function ($ExitType) {
if (null === ScomApiHelper._momAPI) {
return;
}


try {
if ($ExitType === ScomApiHelper.EXIT_SNAPSHOT) {
ScomApiHelper._momAPI.Return(ScomApiHelper._emptyDiscoveryData);
}
else if ($ExitType === ScomApiHelper.EXIT_Incremental) {
ScomApiHelper._emptyDiscoveryData.IsSnapshot = false;
ScomApiHelper._momAPI.Return(ScomApiHelper._emptyDiscoveryData);
}
else {
ScomApiHelper._momAPI.Return(ScomApiHelper._DiscoveryData);
}

} catch (e) {

}

ScomApiHelper.Cleanup();
exit("");
}

ScomApiHelper.Log = function ($message, $eventType, $eventId, $error) {
if (null === ScomApiHelper._momAPI) {
return;
}

$message = $message + GetErrorDetails($error);

try {
ScomApiHelper._momAPI.LogScriptEvent(ScomApiHelper.ScriptName, $eventId, $eventType, $message);
} catch (e) {

}
}

ScomApiHelper.GetClass = function ($ClassId) {
var $result = { value: null, error: null };
var $message = "Cannot create discovery class. ";

try {
$result.value = ScomApiHelper._DiscoveryData.CreateClassInstance($ClassId);
} catch (e) {
$result.error = e;
ScomApiHelper.Log($message, ScomApiHelper.LOG_EVENT_TYPE_ERROR, $evtId, e);
}

return $result;
}

ScomApiHelper.AddClass = function ($ClassId) {
var $result = true;
var $message = "Cannot add discovery class. ";

try {
ScomApiHelper._DiscoveryData.AddInstance($ClassId);
} catch (e) {
$result = false;
ScomApiHelper.Log($message, ScomApiHelper.LOG_EVENT_TYPE_ERROR, $evtId, e);
}

return $result;
}

function checkS2D($clname)
{
if ("string" !== typeof ($clname) || 0 === $clname.trim().length) { return false; }
var $r = winReg.getRegistryValue(clName);
if ("string" !== typeof ($r) || 0 === $r.trim().length) { return false; }
if ($clname.toLowerCase() !== $r.toLowerCase()) { return false; }

// Nano is not supported
$r = winReg.getRegistryValue(nanoKey);
if (1 === $r) { return false; }

$r = winReg.getRegistryValue(S2Dkey);
if (undefined === $r || null === $r || 1 !== $r) { return false;}

$r = winReg.getRegistryValue(osVersion);
if ("string" !== typeof ($r) || 0 === $r.trim().length) { return false; }
if ( 4 &gt; $r.length || "10.0" !== $r.substr(0,4)) { return false; }

$r = winReg.getRegistryValue(osEdt);
if ("string" !== typeof ($r) || 0 === $r.trim().length) { return false; }
if (10 &gt; $r.length || -1 === $r.toLowerCase().search("datacenter")) { return false; }

return true;
}

function discoveryS2D($aname)
{
var $r = null;
$r = ScomApiHelper.GetClass($ClId);
if (null === $r.value) {
ScomApiHelper.Exit(ScomApiHelper.EXIT_Incremental);
ScomApiHelper.Cleanup();
return;
}

try {
$r.value.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $aname);
$r.value.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $aname);
if (!ScomApiHelper.AddClass($r.value)) {
ScomApiHelper.Exit(ScomApiHelper.EXIT_Incremental);
}
else {
ScomApiHelper.Exit(ScomApiHelper.START_SNAPSHOT);
}

} catch (e) {
ScomApiHelper.Log("Cannot insert properties of S2D class. ", ScomApiHelper.LOG_EVENT_TYPE_ERROR, $evtId, e);
ScomApiHelper.Exit(ScomApiHelper.EXIT_Incremental);
}

delete $r.value;
$r.value = null;

return;
}

function doDiscovery($me, $rId,$clname,$aname) {

if (!ScomApiHelper.InitDiscovery($rId, $me)) {
ScomApiHelper.Cleanup();
return;
}

if ("string" !== typeof ($aname) || 0 === $aname.trim().length) {
ScomApiHelper.Log("Wrong agent name provided.", ScomApiHelper.LOG_EVENT_TYPE_WARNING, $evtId, null);
ScomApiHelper.Exit(ScomApiHelper.EXIT_SNAPSHOT);
ScomApiHelper.Cleanup();
return;
}

if ("string" !== typeof ($clname) || 0 === $clname.trim().length) {
ScomApiHelper.Log("Wrong cluster name provided.", ScomApiHelper.LOG_EVENT_TYPE_WARNING, $evtId, null);
ScomApiHelper.Exit(ScomApiHelper.EXIT_SNAPSHOT);
ScomApiHelper.Cleanup();
return;
}

var $s2d = checkS2D($clname);
var $r = null;

winReg.CleanUp();

if (!$s2d)
{
ScomApiHelper.Exit(ScomApiHelper.EXIT_SNAPSHOT);
}
else
{
discoveryS2D($aname);
}

ScomApiHelper.Cleanup();
}

function getParams() {
var oArgs = WScript.Arguments;

if (oArgs.length &lt; 4) {
exit("Wrong number of arguments.");
}

var $p = { };

$p.rId = oArgs(0);
$p.me = oArgs(1);
$p.cl = oArgs(2);
$p.aN = oArgs(3);

return $p;

}

function Main()
{
var $p = getParams();

doDiscovery($p.me, $p.rId, $p.cl, $p.aN);
}

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