Scan for Fujitsu iRMC Devices Probe Action

Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC.ScanForDevices.Probe (ProbeActionModuleType)

Scan for Fujitsu iRMC Device Probe Action

Element properties:

TypeProbeActionModuleType
IsolationAny
AccessibilityPublic
RunAsDefault
InputTypeSystem.BaseData
OutputTypeSystem.PropertyBagData

Member Modules:

ID Module Type TypeId RunAs 
PA ProbeAction Microsoft.Windows.PowerShellPropertyBagProbe Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IPListstring$Config/IPList$IP List
Portstring$Config/Port$Port
SkipCACheckstring$Config/SkipCACheck$Skip CA Check
SkipCNCheckstring$Config/SkipCNCheck$Skip CN Check
UserNamestring$Config/UserName$User Name
Passwordstring$Config/Password$Password
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds

Source Code:

<ProbeActionModuleType ID="Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC.ScanForDevices.Probe" Accessibility="Public">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IPList" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Port" type="xsd:int"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SkipCACheck" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SkipCNCheck" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="UserName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Password" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IPList" Selector="$Config/IPList$" ParameterType="string"/>
<OverrideableParameter ID="Port" Selector="$Config/Port$" ParameterType="string"/>
<OverrideableParameter ID="SkipCACheck" Selector="$Config/SkipCACheck$" ParameterType="string"/>
<OverrideableParameter ID="SkipCNCheck" Selector="$Config/SkipCNCheck$" ParameterType="string"/>
<OverrideableParameter ID="UserName" Selector="$Config/UserName$" ParameterType="string"/>
<OverrideableParameter ID="Password" Selector="$Config/Password$" ParameterType="string"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="PA" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
<ScriptName>iRMC.ScanForDevices.ps1</ScriptName>
<ScriptBody><Script>
##################################################################################
# #
# NOTICE #
# #
# COPYRIGHT 2015 - 2017 FUJITSU LIMITED #
# ALL RIGHTS RESERVED #
# #
# This computer program is CONFIDENTIAL and contains TRADE SECRETS of #
# FUJITSU LIMITED. The receipt or possession of this program does #
# not convey any rights to reproduce or disclose its contents, or to #
# manufacture, use, or sell anything that it may describe, in whole or #
# in part, without the specific written consent of FUJITSU LIMITED. #
# Any reproduction of this program without the express written consent #
# of FUJITSU LIMITED is a violation of the copyright laws and may #
# subject you to civil liability and criminal prosecution. #
# #
##################################################################################

param(
[string]$IPList,
[int]$Port,
[string]$SkipCACheck,
[string]$SkipCNCheck,

[string]$UserName,
[string]$Password,

[string]$ScriptName,
[int]$TimeoutSeconds
)

$ScriptApi = New-Object -comObject "MOM.ScriptAPI"
if ($ScriptApi -eq $Null) { Exit -1 }

# set CONSTANT variables (can not be changed):
set-variable -name PoShScriptName -value $ScriptName -option constant

[int]$ERROR_UNSUPPORTED_FIRMWARE = 8009 # a prime
[int]$SCRIPT_EVENT_NUMBER = 8117 # a prime
[int]$ERROR_NO_STATUS_INFORMATION = 8099 # not a prime
[int]$ERROR_NO_USERNAME = 8199 # not a prime

$global:scriptMG = "."
$global:scriptWorkflow = "Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC.ScanForDevices.Task"
# Pool Instance this task is running on
$global:scriptInstanceName = "$Target/Property[Type='System!System.Entity']/DisplayName$"
$global:scriptInstanceId = "$Target/Id$"

$script:ErrorActionPreference = "SilentlyContinue"
trap {
LogWorkflowEvent $WARNING_LEVEL 19001 ("iRMC Template exception while scanning IP list.`r`nIP List: '$($IPList)'`r`nException: [$($_.Exception.Message)]")
continue
}

# we need to make multiple authenticated HTTP(s) requests...
[System.Net.NetworkCredential]$NetworkCredential = New-Object System.Net.NetworkCredential ($username, $password)
[System.Net.ServicePointManager]::DefaultConnectionLimit = 1000

[xml]$xml = New-Object XML

# Strip any potential garbage at the and of the XML string
Function Clean-XmlString ([string]$xmlString, [string]$endTag) {
if ($xmlString.contains( $endTag )) {
$xmlString.TrimEnd( $xmlString.Substring( ($xmlString.IndexOf($endTag) +$endTag.Length) ))
} else {
$xmlString
}
}

# Due to various problems we support iRMC S4 firmware 8.2x and later (e.g. 8.23F)
# Note: internal pre-releases are marked as 96.xx / 97.xx / 98.xx / 99.xx and are considered unsupported
Function FirmwareVersionSupported ([string]$Version)
{
# iRMC S4
if ( ($Version -match "^8.([2-9][0-9])") -or ($Version -match "^9.([0-9][0-9])") -or ($Version -match "^[1-8][0-9].([0-9][0-9])") ) {
return $True
}

# Interim iRMC S5 Version without access to the System Report at the defined URL
if ( $Version -match "^1.03" ) {
return $False
}

# iRMC S5 re-started version numbering from 1.xx
if ( $Version -match "^1.([0-9][0-9])" ) {
return $True
}

# Enable debug / intermediate builds
#if ( $Version -match "^9[0-9].([0-9][0-9])" ) {
# return $True
#}

return $False
}

$ReadRequestSummary = @"
&lt;?xml version="1.0" encoding="UTF-8" standalone="yes" ?&gt;
&lt;CMDSEQ&gt;

&lt;!-- ConfBMCAssetTag --&gt;
&lt;CMD Context="SCCI" OC="E001" OE="210" OI="0" Type="GET"&gt;
&lt;STATUS&gt;0&lt;/STATUS&gt;
&lt;/CMD&gt;

&lt;!-- ConfSystemName --&gt;
&lt;CMD Context="SCCI" OC="E001" OE="201" OI="0" Type="GET"&gt;
&lt;STATUS&gt;0&lt;/STATUS&gt;
&lt;/CMD&gt;

&lt;!-- ConfServerCabinetModel --&gt;
&lt;CMD Context="SCCI" OC="E001" OE="205" OI="0" Type="GET"&gt;
&lt;STATUS&gt;0&lt;/STATUS&gt;
&lt;/CMD&gt;

&lt;!-- ConfServerSerialNumber --&gt;
&lt;CMD Context="SCCI" OC="E001" OE="207" OI="0" Type="GET"&gt;
&lt;STATUS&gt;0&lt;/STATUS&gt;
&lt;/CMD&gt;

&lt;/CMDSEQ&gt;
"@

Function Main {

Set-CurrentManagementPackVersion -MpName "Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC"
PrepareLogging -Section $SectioniRMCDiscovery -HostTag $TagHostsDiscovery -ServerName 'All' -CreateSampleLogFile -MpName "Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC"

# Split IP list
$IPArray = @($IPList.Split(","))

$returnIPList = ""
$DevicesProbedCount = 0
$iRMCDevicesCount = 0
$SupportedDevices = 0
$NoAccessDevices = 0
[string]$IP = ""

foreach ($IP in $IPArray) {

if($IP -eq $null) { continue }

$IP = $IP.Trim()

PrepareLogging -Section $SectioniRMCDiscovery -HostTag $TagHostsDiscovery -ServerName $IP -MpName "Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC"
DebugOut "$IP - iRMC Template Discovery: start (Port=$Port SkipCACheck=$SkipCACheck SkipCNCheck=$SkipCNCheck TimeoutSeconds(Task Total)=$($TimeoutSeconds)) "

$DevicesProbedCount++

# Form up the URL
[IPAddress]$IPAddress = $null
if ([System.Net.IPAddress]::tryparse($IP,[ref]$IPAddress)) {
if ($IPAddress.AddressFamily.ToString() -eq "Internetwork") {
$hostURL = "https://" +$IPAddress.ToString() +":$($Port)"
} elseif ($IPAddress.AddressFamily.ToString() -eq "Internetworkv6") {
$hostURL = "https://[" +$IPAddress.ToString() +"]:$($Port)"
}
} else {
DebugOut "$IP - iRMC Template Discovery: Invalid IP Address '$($IP)'"
continue
}

$ServerUuid = "" # from the HP-SIM Integration data
$ServerAssetTag = "" # from exported configuration
$ServerType = 'N/A'
$SerialNumber = 'N/A'
$BmcFirmwareVersion = 'N/A'
$BmcType = 'N/A'

$global:WebServer = ""

# No HP-SIM Response - Get overall Status / System Report
$Response = DoWebRequest -url ($hostURL + "/report.xml?Item=System/Status") -Method "GET" -Credentials $NetworkCredential -RequestTimeout $DEFAULT_REQUEST_TIMEOUT

if ($global:WebServer -match "iRMC") {
$iRMCDevicesCount++
if (($global:WebServer -eq "iRMC Webserver") -or ($global:WebServer -match "iRMC S[2,3]")) {
DebugOut "$IP - Skipping unsupported iRMC Generation / Web Server '$($global:WebServer)'"
continue
}

$BmcType = ($global:WebServer).SubString(0,7)
} else {
DebugOut "$IP - Unsupported Web Server '$($global:WebServer)' or no response - skipping"
continue
}

if ($Response -ne $Null -and $Response.Contains("&lt;Root") ) {
try {
$xml = [xml] ( Clean-XmlString -xmlString $Response -endTag "&lt;/Root&gt;" )
if ($xml -ne $Null -and $xml.HasChildNodes ) {
$BmcFirmwareVersion = $xml.Root.GetAttribute("Version")
if ( (FirmwareVersionSupported -Version $BmcFirmwareVersion) -eq $False ) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $INFO_LEVEL -EventNumber $ERROR_UNSUPPORTED_FIRMWARE -Message ("$($BmcType) Unsupported Firmware $($BmcFirmwareVersion)")
DebugOut "$IP - iRMC Template Discovery: Unsupported Firmware $($BmcFirmwareVersion)"
continue
}
}
} catch {
DebugErr $SCRIPT_EVENT_NUMBER "$IP - iRMC Template Discovery: Could not process System Report Status information, skipping IP. Exception=$_"
continue
}
} else {
# No System Report Status response - skip IP (unsupported iRMC or invalid credentials)
DebugOut "$IP - iRMC Template Discovery: no System Report Response StatusCode=$([int]$global:httpStatusCode) - skipping..."
if ( [int]$global:httpStatusCode -eq $HTTP_RC_UNAUTHORIZED ) {
$NoAccessDevices++
}
continue
}

# Get HP-SIM Integration response
# Note: returns 404 when disabled.
$Response = DoWebRequest -url ($hostURL + "/xmldata?item=All") -Method "GET" -Credentials $NetworkCredential -RequestTimeout $DEFAULT_REQUEST_TIMEOUT -IgnoreTimeout # -MaxRetries 2
if ($Response -ne $Null -and $Response.Contains("&lt;RIMP") ) {
try {
$HPSIM_XML = [xml]( Clean-XmlString -xmlString $Response -endTag "&lt;/RIMP&gt;" )
if ($HPSIM_XML -ne $Null -and $HPSIM_XML.HasChildNodes) {
$ServerType = $($HPSIM_XML.RIMP.HSI.SPN);
$SerialNumber = $($HPSIM_XML.RIMP.HSI.SBSN);
$ServerUuid = $($HPSIM_XML.RIMP.HSI.UUID);
$BmcFirmwareVersion = $($HPSIM_XML.RIMP.MP.FWRI);
DebugOut "$IP - iRMC Template Discovery: HP-SIM Integration Response is valid: WebServer='$($global:WebServer)' Firmware='$($BmcFirmwareVersion)' UUID=$($ServerUuid) "
if (($ServerUuid -eq '03000200-0400-0500-0006-000700080009') -or ($ServerUuid -eq '00000000-0000-0000-0000-000000000000') ){
DebugOut "$IP - iRMC Template Discovery: UUID=$($ServerUuid) is not unique, ignoring"
$ServerUuid = ""
}

if ($ServerType -match "PRIMEQUEST") {
if ($ServerType.StartsWith("PRIMEQUEST 3") ) {
DebugOut "$IP - iRMC Template Discovery: $($ServerType) $($BmcFirmwareVersion) is supported"
} else {
DebugOut "$IP - iRMC Template Discovery: $($ServerType) $($BmcFirmwareVersion) is not supported"
continue
}
}

}
} catch {
DebugWarn "$IP - iRMC Template Discovery: Invalid HP-SIM Integration Response. Exception: $_"
}
} else {
DebugOut "$IP - iRMC Template Discovery: no HP-SIM Integration Response"
}

$Response = DoWebRequest -url ($hostURL + "/config") -Method "POST" -Credentials $NetworkCredential -requestData $ReadRequestSummary -RequestTimeout $DEFAULT_REQUEST_TIMEOUT
if ($Response -ne $Null) {
try {
$xml = [xml]$Response

# Asset Tag
$a = $xml.CMDSEQ.CMD | where { $_.OE -eq '210' -and $_.OI -eq '0'}
if (($a.STATUS -eq '0') -and ($a.DATA.Type -eq 'xsd::string') -and ($a.DATA.InnerText -ne "") ){
$ServerAssetTag = $a.DATA.InnerText
}

# ConfServerCabinetModel
if ($ServerType -eq 'N/A') {
$a = $xml.CMDSEQ.CMD | where { $_.OE -eq '205' -and $_.OI -eq '0'}
if (($a.STATUS -eq '0') -and ($a.DATA.Type -eq 'xsd::string') -and ($a.DATA.InnerText -ne "") ){
$ServerType = $a.DATA.InnerText
}
if ($ServerType -match "PRIMEQUEST") {
if ($ServerType.StartsWith("PRIMEQUEST 3") ) {
DebugOut "$IP - iRMC Template Discovery: $($ServerType) $($BmcFirmwareVersion) is supported"
} else {
DebugOut "$IP - iRMC Template Discovery: $($ServerType) $($BmcFirmwareVersion) is not supported"
continue
}
}
}

# ConfServerSerialNumber
if ($SerialNumber -eq 'N/A') {
$a = $xml.CMDSEQ.CMD | where { $_.OE -eq '207' -and $_.OI -eq '0'}
if (($a.STATUS -eq '0') -and ($a.DATA.Type -eq 'xsd::string') -and ($a.DATA.InnerText -ne "") ){
$SerialNumber = $a.DATA.InnerText
}
}
} catch {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $SCRIPT_EVENT_NUMBER -Message ("iRMC Discovery: Get Config - Exception=$_")
DebugWarn "$IP - iRMC Template Discovery: Get Config - Exception=$_"
}
}

DebugOut "$IP - '$($BmcType)' Firmware='$($BmcFirmwareVersion)' ServerType='$($ServerType)' SerialNumber='$($SerialNumber)' AssetTag='$($ServerAssetTag)' UUID='$($ServerUuid)'"
DebugOut "$IP - iRMC Template Discovery: finished."

$SupportedDevices++

# Add this iRMC to the return List
if($returnIPList -ne "") { $returnIPList += ";" }
$returnIPList += "$($IP),$($BmcType),$($BmcFirmwareVersion),$($ServerType),$($SerialNumber),$($ServerAssetTag),$($ServerUuid)"
}

$propertyBag = $ScriptApi.CreatePropertyBag()
$propertyBag.AddValue("ResponsingIPList", $returnIPList)
$propertyBag

$UnknownCount = $DevicesProbedCount - $iRMCDevicesCount

PrepareLogging -Section $SectioniRMCDiscovery -HostTag $TagHostsDiscovery -ServerName 'All' -MpName "Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC"
DebugOut @"
iRMC Template Discovery Task [$MPElement$] completed.
Task Summary:

IP Addresses probed: [$DevicesProbedCount]
Identified as Fujitsu iRMC: [$iRMCDevicesCount]
Supported iRMC devices: [$SupportedDevices]
No Access / invalid credentials: [$NoAccessDevices]
Not responding / unknown: [$UnknownCount]
"@

}
# This script part contains helper functions to perform web based requests
# and is embedded into the final script via Visual Studio Authoring Extensions

[int]$DEFAULT_REQUEST_TIMEOUT = 30 # seconds
[int]$DEFAULT_RETRY_INCREMENT = 10 # seconds
[int]$MAX_REQUEST_RETRIES = 3

[int]$ERROR_SSL_CA_ERROR = 8399 # is not a prime
[int]$ERROR_SSL_CN_ERROR = 8499 # is not a prime

[int]$ERROR_BMC_NO_RESPONSE = 8599 # is a prime
[int]$ERROR_BMC_NO_ACCESS = 8699 # is a prime
[int]$ERROR_BMC_TIMEOUT = 8799 # is not a prime
[int]$ERROR_BMC_NO_PERMISSION = 8899 # is not a prime
[int]$ERROR_BMC_BUSY = 8999 # is a prime

# Subset of possible HTTP error codes
[int]$HTTP_RC_CONTINUE = 100
[int]$HTTP_RC_OK = 200
[int]$HTTP_RC_CREATED = 201
[int]$HTTP_RC_ACCEPTED = 202
[int]$HTTP_RC_NO_CONTENT = 204
[int]$HTTP_RC_RESET_CONTENT = 205
[int]$HTTP_RC_PARTIAL_CONTENT = 206

[int]$HTTP_RC_MULTIPLE_CHOICES = 300
[int]$HTTP_RC_MOVED_PERMANENTLY = 301
[int]$HTTP_RC_MOVED_TEMPORARILY = 302
[int]$HTTP_RC_NOT_MODIFIED = 304
[int]$HTTP_RC_BAD_REQUEST = 400
[int]$HTTP_RC_UNAUTHORIZED = 401
[int]$HTTP_RC_FORBIDDEN = 403
[int]$HTTP_RC_NOT_FOUND = 404
[int]$HTTP_RC_METHOD_NOT_ALLOWED = 405
[int]$HTTP_RC_NOT_ACCEPTABLE = 406
[int]$HTTP_RC_REQ_TIMEOUT = 408

[int]$HTTP_RC_SERVER_ERROR = 500
[int]$HTTP_RC_NOT_IMPLEMENTED = 501
[int]$HTTP_RC_SERVICE_UNAVAILABLE = 503

[bool]$global:SSL_CA_ERROR = $False
[bool]$global:SSL_CN_ERROR = $False
[bool]$global:SSL_NO_CERT_ERROR = $False

[bool]$global:iRMCDetected = $False
[string]$global:WebServer = ""
[System.Net.HttpStatusCode]$global:httpStatusCode = [System.Net.HttpStatusCode]::OK

[System.Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls

$SslCertificateValidator =
{
Param (
[System.Object] $obj,
[System.Security.Cryptography.X509Certificates.X509Certificate] $certificate,
[System.Security.Cryptography.X509Certificates.X509Chain] $chain,
[System.Net.Security.SslPolicyErrors] $errors
)

if ($errors -eq [System.Net.Security.SslPolicyErrors]::None) {
return $True
}

if (($errors -band [System.Net.Security.SslPolicyErrors]::RemoteCertificateChainErrors) -and ($SkipCACheck -eq $False)) {
$global:SSL_CA_ERROR = $True
return $False
}

if (($errors -band [System.Net.Security.SslPolicyErrors]::RemoteCertificateNameMismatch) -and ($SkipCNCheck -eq $False)) {
$global:SSL_CN_ERROR = $True
return $False
}

# No cert provided
if ($errors -band [System.Net.Security.SslPolicyErrors]::RemoteCertificateNotAvailable) {
$global:SSL_NO_CERT_ERROR = $True
return $False
}

# All checks passed
return $True
}

# Will return $Null on error
Function DoWebRequest(
[String]$url,
[string]$Method = "GET",
[System.Net.NetworkCredential]$Credentials = $NetworkCredential ,
[String]$requestData = $Null,
[int] $RequestTimeout = $DEFAULT_REQUEST_TIMEOUT,
[string]$AuthType = "Basic",
[switch]$IgnoreNoPermission,
[switch]$IgnoreTimeout,
[int] $MaxRetries = $MAX_REQUEST_RETRIES
)
{
[bool]$ToggleProxy = $False
if ($MaxRetries -gt $MAX_REQUEST_RETRIES) { $MaxRetries = $MAX_REQUEST_RETRIES }
[int]$retries = 0;
for ($retries = 0; $retries -lt $MaxRetries; $retries++) {
try {
[string]$errorMsg = $Null

$global:SSL_CN_ERROR = $False
$global:SSL_CA_ERROR = $False
$global:SSL_NO_CERT_ERROR = $False

$webRequest = [System.Net.WebRequest]::Create($url)
if ($Credentials -ne $Null) {
if ($AuthType -eq "Basic") {
# Do not wait for the 401 response, send the credentials with the initial request
$AuthData = [Convert]::ToBase64String([Text.Encoding]::Default.GetBytes($Credentials.UserName + ':' + $Credentials.Password));
$webRequest.Headers.Add('Authorization', "Basic $AuthData")

$webRequest.Credentials = $Null
$webRequest.PreAuthenticate = $False
# $webRequest.UseDefaultCredentials = $False
$webRequest.KeepAlive = $False # make sure the connection is not re-used
} else {
$webRequest.Credentials = $Credentials
$webRequest.PreAuthenticate = $True
}
} else {
$webRequest.Credentials = $Null
$webRequest.PreAuthenticate = $False
}
# $webRequest.PreAuthenticate = $False
# $webRequest.UseDefaultCredentials = $false

$webRequest.Timeout = ($RequestTimeout *1000)
$webRequest.ReadWriteTimeout = ($RequestTimeout *1000)
$webRequest.Method = $Method
$webRequest.Accept = "*/*"
$webRequest.KeepAlive = $False # make sure the connection is not re-used
$webRequest.AllowAutoRedirect = $False # Do not follow redirects

# Discovery and Monitoring workflow scripts typically run without a proxy configured.
# Performance Collection workflow scripts typically run with proxy configuration
$Proxy = $WebRequest.Proxy
if ($Proxy) {
$ProxyBypassed = $Proxy.IsBypassed($url)
if ($ProxyBypassed) {
DebugOut "$IP - '$($url)' No Proxy (direct connection) will be used"
} else {
$ProxyAddress = $Proxy.GetProxy($url).AbsoluteUri
DebugOut "$IP - '$($url)' Proxy '$($ProxyAddress)' will be used"
}
} else {
DebugOut "$IP - '$($url)' No Proxy object (direct connection)"
}
if (!$ProxyBypassed -and $ToggleProxy ) {
DebugOut "$IP - '$($url)' (Re)Trying without Proxy..."
$webRequest.Proxy = $Null
$ToggleProxy = $False
}

try {
$webRequest.ServicePoint.ConnectionLimit = 128
$webRequest.ServicePoint.ConnectionLeaseTimeout = 0 # Close Connection after servicing a request
$webRequest.ServicePoint.MaxIdleTime = 1 # in MilliSeconds, close connection afterwards
$webRequest.ServerCertificateValidationCallback = $SslCertificateValidator

# DebugOut "$IP - '$url' HASH=$($webRequest.ServicePoint.GetHashCode()) ConnectionLimit=$($webRequest.ServicePoint.ConnectionLimit)"
} catch {
DebugErr 9999 "$IP - '$url' - Could not set extended config Exception=$_"
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $SslCertificateValidator
}

if ($requestData.Length -gt 0) {
$buffer = [System.Text.Encoding]::UTF8.GetBytes($requestData)
$webRequest.ContentLength = $buffer.Length;
$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($buffer, 0, $buffer.Length)
$requestStream.Flush()
$requestStream.Close()
}

[System.Timespan]$resTime = Measure-Command {

try {
$webResponse= $webRequest.GetResponse()
} catch [System.Net.WebException] {
$webResponse = $_.Exception.Response
$errorMsg = $_.Exception.Message
$stackTrace = $_.Exception.StackTrace
$innerException = $_.Exception.InnerException
} catch {
$webResponse = $Null
}
}

# No longer needed ...
$webRequest = $Null

if ($webResponse -ne $Null) {
[string]$Location = $webResponse.GetResponseHeader("Location") # $webResponse.Headers.Get("Location")
$global:WebServer = $webResponse.GetResponseHeader("Server") # $webResponse.Headers.Get("Server")
$global:httpStatusCode = $($webResponse.StatusCode.value__)

if ( $global:iRMCDetected -eq $False ){
if ($global:WebServer -match "iRMC") {
$global:iRMCDetected = $True
}
}
$responseStream = New-Object System.IO.StreamReader($webResponse.GetResponseStream())
$result = $responseStream.ReadToEnd()
$responseStream.Close()
$webResponse.Close()

$responseStream = $Null
$webResponse = $Null

switch ( [int]$global:httpStatusCode ) {
$HTTP_RC_OK { # 200
DebugOut "$IP - '$url' request handled within $($resTime.TotalSeconds) seconds..."
return $result
}
$HTTP_RC_MOVED_PERMANENTLY { # 301
if ($Location -match "login") {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_NO_ACCESS -Message ("Invalid credentials")
$global:httpStatusCode = [System.Net.HttpStatusCode]::Unauthorized
}
return
}
$HTTP_RC_MOVED_TEMPORARILY { # 302
if ($Location -match "login") {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_NO_ACCESS -Message ("Invalid credentials")
$global:httpStatusCode = [System.Net.HttpStatusCode]::Unauthorized
}
return
}
$HTTP_RC_UNAUTHORIZED { # 401
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_NO_ACCESS -Message ("Invalid credentials")
return
}
$HTTP_RC_FORBIDDEN { # 403
DebugOut "$IP - '$url' No permission (403)..."
if (!$IgnoreNoPermission.IsPresent) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_NO_PERMISSION -Message ("No permission (403)")
}
return
}
$HTTP_RC_NOT_FOUND { # 404
return
}
$HTTP_RC_SERVER_ERROR { # 500
return
}
$HTTP_RC_NOT_IMPLEMENTED { # 501
return
}
}

# If we get here some other error occurred
# If this was the first attempt and a proxy was active (e.g. performance collection workflow script), try again without proxy
if (!$ProxyBypassed -and $retries -eq 0) {
DebugOut "$IP - '$url' iRMC reported HTTP Status Code ($([int]$global:httpStatusCode) / $($global:httpStatusCode)) - will retry without proxy"
$ToggleProxy = $True
continue
}

if ($retries -lt ($MAX_REQUEST_RETRIES)) {
DebugOut "$IP - '$url' iRMC reported HTTP Status Code (($([int]$global:httpStatusCode) / $($global:httpStatusCode)) - will retry in $($retryDelay) seconds"
[int]$retryDelay = (($retries +1) * $DEFAULT_RETRY_INCREMENT)
Start-Sleep -Seconds $retryDelay
continue
} else {
DebugErr $ERROR_BMC_BUSY "$IP - '$url' - iRMC reported final HTTP Status Code (($([int]$global:httpStatusCode) / $($global:httpStatusCode)), giving up after retries"
return
}



} else {

# Check for SSL related errors
if ($global:SSL_CN_ERROR -eq $True) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $INFO_LEVEL -EventNumber $ERROR_SSL_CN_ERROR -Message ("Certificate Common Name (CN) Mismatch")
DebugOut "$IP - '$url' Certificate Name (CN) Mismatch ..."
return
} elseif ($global:SSL_CA_ERROR -eq $True) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $INFO_LEVEL -EventNumber $ERROR_SSL_CA_ERROR -Message ("Certificate Authority (CA) or Certificate Chain Error")
DebugOut "$IP - '$url' Certificate Authority (CA) or Chain Error ..."
return
} elseif ($global:SSL_NO_CERT_ERROR -eq $True) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $INFO_LEVEL -EventNumber $ERROR_SSL_ERROR -Message ("No Certificate present")
DebugOut "$IP - '$url' No Certificate present ..."
return
}

# no response (object), check for the timeout value.
# If the connection gets closed during early send/receive,
# this is typically within a few seconds, otherwise the configured timeout would have expired
if ($resTime -ne $Null -and [int]$resTime.TotalSeconds -lt 5) {
[int]$retryDelay = (($retries +1) * $DEFAULT_RETRY_INCREMENT)
if ($retries -ne 0) {
# LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_NO_RESPONSE -Message ("'$url' no response / connection closed ")
if ($errorMsg -ne $Null) { DebugWarn "$IP - '$url' no response / connection closed within $($resTime.TotalSeconds) seconds - will retry in $retryDelay seconds ($errorMsg)"}
else { DebugWarn "$IP - '$url' no response / connection closed within $($resTime.TotalSeconds) seconds - will retry in $retryDelay seconds (no details available)"}
if ($innerException -ne $Null) { DebugWarn "InnerException:`r`n$innerException" }
if ($stackTrace -ne $Null ) { DebugWarn "Stack Trace:`r`n$stackTrace" }
}
Start-Sleep -Seconds $retryDelay
} else {
# Note: do no report actual timeout seconds here, or alert suppression will not fully work due to different text
if (!$IgnoreTimeout.IsPresent) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_TIMEOUT -Message ("'$url' no response. Timeout was $RequestTimeout seconds")
}
DebugOut "$IP - '$url' no response within $($resTime.TotalSeconds) seconds. Timeout was $RequestTimeout seconds"
return
}
}
} catch {
# LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $SCRIPT_EVENT_NUMBER -Message ("'$url' generic Exception=$_")
[int]$retryDelay = (($retries +1) * $DEFAULT_RETRY_INCREMENT)
DebugWarn "$IP - '$url' generic Exception. will retry in $retryDelay seconds. Exception=$_"
Start-Sleep -Seconds $retryDelay
}
}
if (!$IgnoreTimeout.IsPresent) {
LogScriptEventWithEventSource -EventSource $IP -EventLevel $WARNING_LEVEL -EventNumber $ERROR_BMC_NO_RESPONSE -Message ("'$url' no response after $retries retries (last error: $errorMsg)")
}
DebugOut "$IP - '$url' no response after $retries retries (last error: $errorMsg)"
}



# This script part contains helper functions to perform various logging activities
# and is embedded into the final script via Visual Studio Authoring Extensions

[int]$ERROR_TRACEFILE_XML_PARSE_ERROR = 8299 # is not a prime

# Log an event into the registry, Source will be 'Health Service Script'
# See https://msdn.microsoft.com/en-us/library/bb437630.aspx
[int]$WARNING_LEVEL = 2
[int]$ERROR_LEVEL = 1
[int]$INFO_LEVEL = 0

$LOGFILE_VERSION = "8.3.1.0"

# Generic version
Function RaiseEvent {
Param (
[parameter(Mandatory=$true)]
[string]$EventSource = "Fujitsu Out-Of-Band",
[parameter(Mandatory=$true)]
[int]$EventLevel,
[parameter(Mandatory=$true)]
[int]$EventNumber,
[parameter(Mandatory=$true)]
[string]$Message
)

$channel = "Operations Manager"

if ([System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False) {
try {
[System.Diagnostics.EventLog]::CreateEventSource($EventSource, $channel)
} catch {

}
}

$eventLog = new-object System.Diagnostics.EventLog -ArgumentList @($channel)
$eventLog.Source = $EventSource

$eventData = @()
$eventData += $EventSource
$eventData += $Message
$eventData += $PoShScriptName

# Note: map different enum values
if($EventLevel -eq $INFO_LEVEL) {
$EventLevel = [System.Diagnostics.EventLogEntryType]::Information
} elseif($EventLevel -eq $WARNING_LEVEL) {
$EventLevel = [System.Diagnostics.EventLogEntryType]::Warning
} elseif($EventLevel -eq $ERROR_LEVEL) {
$EventLevel = [System.Diagnostics.EventLogEntryType]::Error
}

$eventInstance = new-object System.Diagnostics.EventInstance -ArgumentList @($EventNumber, 0, $EventLevel)
$eventLog.WriteEvent($eventInstance, $eventData)
}

Function LogScriptEventWithEventSource {
Param (
[parameter(Mandatory=$true)]
[string]$EventSource = "Fujitsu Out-Of-Band",
[parameter(Mandatory=$true)]
[ValidateRange(0,2)]
[int]$EventLevel,
[parameter(Mandatory=$true)]
[int]$EventNumber,
[parameter(Mandatory=$true)]
[string]$Message
)
DebugOut "Writing Event $($EventNumber) Level=($EventLevel) Source='$($EventSource)' Message='$($Message)'"
if ($ScriptApi -ne $Null) {
$ScriptApi.LogScriptEvent($EventSource, $EventNumber, $EventLevel, $Message)
}
}

# Backwards compatible wrapper
Function LogScriptEvent {
Param (
[parameter(Mandatory=$true)]
[ValidateRange(0,2)]
[int]$EventLevel,
[parameter(Mandatory=$true)]
[int]$EventNumber,
[parameter(Mandatory=$true)]
[string]$Message
)
# Note: Log will be written always with Event Source 'Health Service Script'
if ($ScriptApi -ne $Null) {
# Note: do not use actual script name to consolidate Alert Suppression from parallel scripts
$ScriptApi.LogScriptEvent("Fujitsu Out-Of-Band", $EventNumber, $EventLevel, $Message)
# $ScriptApi.LogScriptEvent($PoShScriptName, $EventNumber, $EventLevel, $Message)
}
}

# Similar, but with different Source
Function LogWorkflowEvent($eventType, $eventNumber, $message)
{
$channel = "Operations Manager"
$source = "Health Service Modules Ex"
$eventLog = new-object System.Diagnostics.EventLog -ArgumentList @($channel)
$eventLog.Source = $source

$eventData = @()
$eventData += $global:scriptMG
$eventData += $global:scriptWorkflow
$eventData += $global:scriptInstanceName
$eventData += $global:scriptInstanceId
$eventData += $message
$eventData += $source

if($eventType -eq $INFO_LEVEL) {
$eventType = [System.Diagnostics.EventLogEntryType]::Information
} elseif($eventType -eq $WARNING_LEVEL) {
$eventType = [System.Diagnostics.EventLogEntryType]::Warning
} elseif($eventType -eq $ERROR_LEVEL) {
$eventType = [System.Diagnostics.EventLogEntryType]::Error
}

$eventInstance = new-object System.Diagnostics.EventInstance -ArgumentList @($eventNumber, 0, $eventType)
$eventLog.WriteEvent($eventInstance, $eventData)
}


# set CONSTANT variables (can not be changed):
set-variable -name SVISCOMLogXmlName -value "SVISCOM-OutOfBand.xml" -option constant
set-variable -name SVISCOMLogXm_Name -value "SVISCOM-OutOfBand.xm_" -option constant
set-variable -name SectionRoot -value "root" -option constant
set-variable -name SectionCommentSection -value "CommentSection" -option constant

# Traces for Discoveries
set-variable -name SectionServerDiscovery -value "ServerDiscovery" -option constant
set-variable -name SectionSmashDiscovery -value "SmashDiscovery" -option constant
set-variable -name SectionRaidDiscovery -value "RaidDiscovery" -option constant
set-variable -name SectionPerformanceDiscovery -value "PerformanceDiscovery" -option constant
set-variable -name SectioniRMCDiscovery -value "iRMCDiscovery" -option constant

# Traces for Monitors
set-variable -name SectionHardwareComponentMonitor -value "HardwareComponentsMonitor" -option constant
set-variable -name SectionComponentStatusMonitor -value "ComponentStatusMonitor" -option constant
set-variable -name SectionRaidMonitor -value "RaidMonitor" -option constant
set-variable -name SectionPerformanceMonitor -value "PerformanceMonitor" -option constant
set-variable -name SectioniRMCMonitor -value "iRMCMonitor" -option constant

set-variable -name SectionCommentHosts -value "CommentHosts" -option constant
set-variable -name TagDebugMode -value "DebugMode" -option constant
set-variable -name TagOverWrite -value "OverWrite" -option constant
set-variable -name TagHostsDiscovery -value "HostsForDiscovery" -option constant
set-variable -name TagHostsMonitoring -value "HostsForMonitoring" -option constant

# --------------------------------------------------------------------------
# Global variables = variables, which are changed in different functions ...
# ... and the changed value shall be available in the calling function
# --------------------------------------------------------------------------
$global:DebugMode = $False
$global:DebugFile = $False
$global:OverWrite = $True
$global:DebugHosts = ""
$global:DebugForHost = "$False"
$global:ErrFilePrefix = "ERRORTrace"
$global:WarnFilePrefix = "WARNINGTrace"
$global:LogTargetName = ""
$global:LogFilePrefix = ""
$global:LogFilePath = "$Env:TEMP\SVISCOM\SVISCOM-OutOfBand"
$global:LogFileName = "$LogFilePath\$($LogFilePrefix).log"

$global:MPVERSION = "N/A" # default
$global:MP_NAME = "N/A" # default

# --------------------------------------------------------------------------
Function Set-CurrentManagementPackVersion
{
Param (
[string] $RegistryPath = "HKLM:\SOFTWARE\Fujitsu\ServerView Suite\SCOM Integration\SVISCOM-OutOfBand",
[string] $MpName = "Fujitsu.Servers.PRIMERGY.OutOfBand"
)

if ($RegistryPath -ne $Null -and $MpName -ne $Null) {
# Load SCOM Extensions if not already done
$OMPSInstallKey = "HKLM:\Software\Microsoft\System Center Operations Manager\12\Setup\Powershell\V2"
$regKey = get-item $OMPSInstallKey
$OMPSInstallPath = $regKey.GetValue("InstallDirectory")
$omModule = $OMPSInstallPath + "OperationsManager"
Import-Module -Name $omModule

$MP = Get-SCOMManagementPack -Name $MpName
if ($MP -ne $Null) {
$MpVersion = "$($MP.Version.Major).$($MP.Version.Minor).$($MP.Version.Build).$($MP.Version.Revision)"
DebugOut "'$($MP.DisplayName)' Management Pack Version is $MpVersion"
try {
if (!(Test-Path -Path $RegistryPath)) {
New-Item -Path $RegistryPath | Out-Null
}
Set-ItemProperty -Path $RegistryPath -Name ( "$($MpName).CurrentVersion") -Value $MpVersion -Type String -ErrorAction Stop
} catch {
DebugErr $SCRIPT_EVENT_NUMBER "Error writing Management Pack CurrentVersion. Exception: $_"
}
}
}
}

Function Get-CurrentManagementPackVersion
{
Param (
[string] $RegistryPath = "HKLM:\SOFTWARE\Fujitsu\ServerView Suite\SCOM Integration\SVISCOM-OutOfBand",
[string] $MpName = "Fujitsu.Servers.PRIMERGY.OutOfBand"
)
if ($RegistryPath -ne $Null -and $MpName -ne $Null) {
try {
$regKey = get-item $RegistryPath
$global:MPVERSION = $regKey.GetValue( "$($MpName).CurrentVersion" )
} catch {}
}
}

Function PrepareLogging
{
Param (
[string] $Section,
[string] $HostTag,
[string] $ServerName,
[switch] $CreateSampleLogFile,
[string] $MpName = "Fujitsu.Servers.PRIMERGY.OutOfBand"
)

$global:LogFilePrefix = GiveBaseName $PoShScriptName
$global:MP_NAME = $MpName

# Prepare for IPv6 ...
if ($ServerName.Contains(':') ) {
$IPv6FileName = $ServerName.Replace(":", "_")
$global:LogFileName = "$global:LogFilePath\$($global:LogFilePrefix)Trace_$IPv6FileName.log"
$global:LogTargetName = $IPv6FileName
} else {
$global:LogFileName = "$global:LogFilePath\$($global:LogFilePrefix)Trace_$ServerName.log"
$global:LogTargetName = $ServerName
}

Get-CurrentManagementPackVersion -MpName $MpName

if ($CreateSampleLogFile) {
CreateLogXmlFile
}
if ($global:DebugMode -eq $False) {
GetLogXmlFile $Section $HostTag $ServerName
}

CreateLogFile

#DebugOut "SYSTEMDRIVE = $env:SYSTEMDRIVE"
#DebugOut "TEMP = $env:TEMP"
#DebugOut "LogFilePath = $global:LogFilePath"
DebugOut "LogFileName = $global:LogFileName"

}

Function GiveBaseName
{
Param (
[string] $in
)

$a = $in.split('.')
Write-Output "$($a[0])"
}

Function CreateLogXmlFile
{
$fileOK = $False
$pathOK = $False
$Xm_FileName = "$global:LogFilePath\$SVISCOMLogXm_Name"

# create the target directory, if it does not exist
if ( ! (Test-Path -Path $global:LogFilePath)) {
New-Item -ItemType directory -Path $global:LogFilePath | Out-Null
}
if (Test-Path -Path $global:LogFilePath) {
$pathOK = $True
}

if (Test-Path -Path $Xm_FileName) {
$txt = Get-Content $Xm_FileName
foreach ($line in $txt) {
if ($line.contains($LOGFILE_VERSION)) {
$fileOK = $True
break
}
}
}

if (($pathOK -eq $True) -and ($fileOK -eq $False)) {
# we write a new SVISCOM-OutOfBand.xm_ file every time the MP is changed to make sure all
# INI-Values are documented for use by the customer if anything changes.
if (Test-Path -Path $Xm_FileName) {
Remove-Item -Path $Xm_FileName -Force | Out-Null
}
#Create xm_ file
New-Item -Path $Xm_FileName -ItemType File | Out-Null

Add-Content -Path $Xm_FileName -Value @"
&lt;$SectionRoot&gt;
&lt;!--
$($SVISCOMLogXmlName) Debug XML file Version $($LOGFILE_VERSION)

With this file logging for PowerShell scripts within the
- Fujitsu Out-Of-Band Management Pack and
- Optional Extension Management Packs for the Fujitsu Out-Of-Band Management Pack
can be enabled.

Rename the file type from '.xm_' to '.xml' to enable reading this file.

Note: You have to enable debug for a script and also select the server in
the '&lt;$TagHostsDiscovery&gt;' or '&lt;$TagHostsMonitoring&gt;' section to generate traces (see below).

The following sections specify for which PowerShell scripts the traces will be generated;
Each of the sections represents a single PowerShell script.

'&lt;$TagDebugMode&gt;' enables logging (yes) or disables logging (no)
'&lt;$TagOverWrite&gt;' defines continuous logging (no) or single script run logging (yes)
--&gt;
&lt;!-- DISCOVERIES --&gt;
&lt;!-- The following section enables trace files for the Out-Of-Band iRMC Device discovery script --&gt;
&lt;$SectioniRMCDiscovery&gt;
&lt;$TagDebugMode&gt;yes&lt;/$TagDebugMode&gt;
&lt;$TagOverWrite&gt;no&lt;/$TagOverWrite&gt;
&lt;/$SectioniRMCDiscovery&gt;

&lt;!-- The following section enables trace files for the Out-Of-Band Server discovery script --&gt;
&lt;$SectionServerDiscovery&gt;
&lt;$TagDebugMode&gt;yes&lt;/$TagDebugMode&gt;
&lt;$TagOverWrite&gt;no&lt;/$TagOverWrite&gt;
&lt;/$SectionServerDiscovery&gt;

&lt;!-- MONITORS --&gt;
&lt;!-- The following section enables trace files for basic iRMC monitoring script --&gt;
&lt;$SectioniRMCMonitor&gt;
&lt;$TagDebugMode&gt;yes&lt;/$TagDebugMode&gt;
&lt;$TagOverWrite&gt;no&lt;/$TagOverWrite&gt;
&lt;/$SectioniRMCMonitor&gt;

&lt;!-- The following section enables trace files for the main server Hardware Components (CPU/Memory/Fan/PowerSupply) monitoring script --&gt;
&lt;$SectionHardwareComponentMonitor&gt;
&lt;$TagDebugMode&gt;yes&lt;/$TagDebugMode&gt;
&lt;$TagOverWrite&gt;no&lt;/$TagOverWrite&gt;
&lt;/$SectionHardwareComponentMonitor&gt;

&lt;!-- The following section enables trace files for the 'Component Status' monitoring script --&gt;
&lt;$SectionComponentStatusMonitor&gt;
&lt;$TagDebugMode&gt;yes&lt;/$TagDebugMode&gt;
&lt;$TagOverWrite&gt;no&lt;/$TagOverWrite&gt;
&lt;/$SectionComponentStatusMonitor&gt;

&lt;!-- The following section enables trace files for the Performance monitoring script --&gt;
&lt;$SectionPerformanceMonitor&gt;
&lt;$TagDebugMode&gt;yes&lt;/$TagDebugMode&gt;
&lt;$TagOverWrite&gt;no&lt;/$TagOverWrite&gt;
&lt;/$SectionPerformanceMonitor&gt;

&lt;!--
The following sections specify for which servers the traces will be generated:

In the '&lt;$TagHostsDiscovery&gt;' and '&lt;$TagHostsMonitoring&gt;' sections
single or multiple servers can be specified for verbose debug output
during the discovery and/or during monitoring.

Use '&lt;$TagHostsDiscovery&gt;' for selecting hosts for the discovery trace.
Use '&lt;$TagHostsMonitoring&gt;' for selecting hosts for the monitoring trace.

Use 'all' (without quote signs) for all Fujitsu iRMC / Out-Of-Band Servers monitored by SCOM.
Use a single IP address or a comma separated list to select multiple single servers
Example:
&lt;$TagHostsDiscovery&gt;all&lt;/$TagHostsDiscovery&gt;
&lt;$TagHostsMonitoring&gt;192.168.1.100,192.168.1.101,192.168.1.102&lt;/$TagHostsMonitoring&gt;

will generate discovery traces for all Fujitsu iRMC / Out-Of-Band Servers and
will generate monitoring traces only for servers with the IP address
192.168.1.100 192.168.1.101 and 192.168.1.102
--&gt;
&lt;$TagHostsDiscovery&gt;all&lt;/$TagHostsDiscovery&gt;
&lt;$TagHostsMonitoring&gt;all&lt;/$TagHostsMonitoring&gt;
&lt;/$SectionRoot&gt;
"@
}
}

Function GetLogXmlFile
{
Param (
[string] $Section,
[string] $HostTag,
[string] $ServerName
)

$XmlFileName = "$global:LogFilePath\$SVISCOMLogXmlName"
$ListOfHosts = ""

if (Test-Path -Path $global:LogFilePath) {
if (Test-Path -Path $XmlFileName) {

[string]$xmlData = Get-Content $XmlFileName

if ([string]::IsNullOrWhiteSpace($xmlData)) {
return
}

$xmlDoc = New-Object System.Xml.XmlDocument
try {
if ($xmlDoc.LoadXml($xmlData)) {
LogScriptEventWithEventSource -EventSource "Fujitsu ServerView Integration" -EventLevel $WARNING_LEVEL -EventNumber $ERROR_TRACEFILE_XML_PARSE_ERROR -Message ("XML File '$($XmlFileName)' Parse error: " + [string]($xmlDoc.ParseError))
}
} catch {
# Parsing failed
LogScriptEventWithEventSource -EventSource "Fujitsu ServerView Integration" -EventLevel $WARNING_LEVEL -EventNumber $ERROR_TRACEFILE_XML_PARSE_ERROR -Message ("XML File '$($XmlFileName)' Parse error: $_")
return
}
# Verify basic XML structure
if ( ($xmlDoc.FirstChild.Name -eq $SectionRoot) -and ($xmlDoc.FirstChild.NextSibling -eq $Null)) {
foreach ($node in $xmlDoc.FirstChild.ChildNodes) {
if ($Node.NoteType -eq [System.Xml.XmlNodeType]::Comment) { continue }

if ($Node.Name -eq $section) {
if ($xmlDoc.$SectionRoot.$section.$TagDebugMode -ne $null) {
if ($($xmlDoc.$SectionRoot.$Section.$TagDebugMode).ToUpper() -eq "YES") {
$global:DebugMode = $True
$global:DebugFile = $True
}
}

if ($xmlDoc.$SectionRoot.$section.$TagOverWrite -ne $null) {
if ($($xmlDoc.$SectionRoot.$Section.$TagOverWrite).ToUpper() -eq "NO") {
$global:OverWrite = $False
}
}
break
}
}
}

if ($xmlDoc.$SectionRoot.$HostTag -ne $null) {
$global:DebugHosts = $($xmlDoc.$SectionRoot.$HostTag).ToLower()
}

# Check if DEBUG shall run for this server.
# There are two possibilities to check: "all" server DEBUG is on or this server is in the list.
if ($global:DebugHosts -eq "all") {
$global:DebugForHost = $True
} else {
# Check if this host is in the list of DebugHosts
$ListOfHosts = $($global:DebugHosts).split(',')
DebugOut "Searching for host: $ServerName"
DebugOut "in list of DebugHosts: $global:DebugHosts"

if ($ServerName.ToLower() -in $ListOfHosts) {
$global:DebugForHost = $True
}
}

} # else file does not exist
} # else directory does not exist
}

Function CreateLogFile
{
# For some reason checking for "$True" with "if ($global:a -and $global:b)" is not evaluated correctly!!!
# It works OK in a test with a simple PS script ... no idea why ... Thus we use:
if ($global:DebugForHost -eq $True) {
if ($global:DebugFile -eq $True) {
# Create the target directory, if it does not exist
if (!(Test-Path -Path $global:LogFilePath)) {
New-Item -ItemType directory -Path $global:LogFilePath | Out-Null
}

# Check if file exists and delete if it does and OverWrite is set to TRUE
if (Test-Path -Path $global:LogFileName) {
DebugOut ""
DebugOut "Log file already exists at: $global:LogFileName"
if ($global:OverWrite -eq $True) {
Remove-Item -Path $global:LogFileName -Force | Out-Null
}
}
# If the file has just been removed (OverWrite = YES) or the file does not exist: create it
if (!(Test-Path -Path $global:LogFileName)) {
#Create log file
New-Item -Path $global:LogFileName -ItemType File | Out-Null
}

Add-Content -Path $global:LogFileName -Value @"
********** $(Get-Date -Format F) **********`r
********** $($global:LogFileName) **********`r
********** Management Pack '$($global:MP_NAME)' Version: $($global:MPVERSION)`r
"@
}
}
}

Function DebugOut
{
Param (
[string] $Text
)

if ($global:DebugForHost -eq $True) {
if ($global:DebugMode -eq $True) {
Write-Host $Text
}

if ($global:DebugFile -eq $True) {
if ($global:LogFileName.Length -gt 0) {
if (Test-Path -Path $global:LogFileName) {
$DateTime = Get-Date -format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $global:LogFileName -Value "$DateTime $Text"
}
}
}
}
}

Function DebugWarn
{
Param (
[string] $Text
)

DebugOut "Warning: $Text"

if ($global:DebugForHost -eq $True) {
if ($global:DebugFile -eq $True) {
$WarnLogFile = "$global:LogFilePath\$($WarnFilePrefix)_$($global:LogTargetName).log"
$DateTime = Get-Date -format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $WarnLogFile -Value "[$($DateTime)] [$($PoShScriptName)] $($Text)"
}
}
}

Function DebugErr
{
Param (
[int] $ErrNo,
[string] $Text
)

DebugOut "Error: $Text"

if ($global:DebugForHost -eq $True) {
if ($global:DebugFile -eq $True) {
$ErrLogFile = "$global:LogFilePath\$($ErrFilePrefix)_$($global:LogTargetName).log"
$DateTime = Get-Date -format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $ErrLogFile -Value "[$($ErrNo)] [$($DateTime)] [$($PoShScriptName)] $($Text)"
}
}
}




Main
</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>IPList</Name>
<Value>$Config/IPList$</Value>
</Parameter>
<Parameter>
<Name>Port</Name>
<Value>$Config/Port$</Value>
</Parameter>
<Parameter>
<Name>SkipCACheck</Name>
<Value>$Config/SkipCACheck$</Value>
</Parameter>
<Parameter>
<Name>SkipCNCheck</Name>
<Value>$Config/SkipCNCheck$</Value>
</Parameter>
<Parameter>
<Name>UserName</Name>
<Value>$Config/UserName$</Value>
</Parameter>
<Parameter>
<Name>Password</Name>
<Value>$Config/Password$</Value>
</Parameter>
<Parameter>
<Name>ScriptName</Name>
<Value>iRMCScan.ps1</Value>
</Parameter>
<!-- Just for information (may need scaling on larger subnet scans) -->
<Parameter>
<Name>TimeoutSeconds</Name>
<Value>$Config/TimeoutSeconds$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="PA"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>