ESXi Seed Discovery Probe for ESXi Seed Discovery Task
Fujitsu.Servers.PRIMERGY.ESXi.Seed.Discovery.Probe (ProbeActionModuleType)
Element properties: Member Modules:
Overrideable Parameters:
Source Code: <ProbeActionModuleType ID="Fujitsu.Servers.PRIMERGY.ESXi.Seed.Discovery.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="NoCertCheck" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="CIMPort" type="xsd:int"/>
<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="NoCertCheck" Selector="$Config/NoCertCheck$" ParameterType="string"/>
<OverrideableParameter ID="CIMPort" Selector="$Config/CIMPort$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="PA" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
<ScriptName>TemplateDiscoveryTask.ps1</ScriptName>
<ScriptBody><Script>
#-------------------------------------------------------------------
# Fujitsu
# Copyright 2015-2019 FUJITSU LIMITED
#
# TemplateDiscoveryTask.ps1
#
# Summary:
# Seed Discovery Probe for Fujitsu PRIMERGY ESXi Servers.
#
#-------------------------------------------------------------------
Param (
[string] $IPList,
[string] $NoCertCheck,
[int] $CIMPort,
[string] $CIMUser,
[string] $CIMPass,
[string] $CIMProtocol="https",
[switch] $OutsideManagementPack
)
Import-Module ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.PS.CommonModule']/Path$", "$PSScriptRoot\Modules\CommonModule.psm1")[[bool]$OutsideManagementPack]
Import-Module ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.PS.LoggerModule']/Path$", "$PSScriptRoot\Modules\LoggerModule.psm1")[[bool]$OutsideManagementPack]
$script:newIPList = @()
$script:Jobs = @()
$script:Discovered = @()
function Main {
$sysinfo = Get-WmiObject -Class Win32_ComputerSystem
$HostServer = "{0}.{1}" -f @($sysinfo.DNSHostName, $sysinfo.Domain)
$script:Logger = New-Logger -Section $SectionServerDiscovery -HostTag $TagHostsDiscovery -ServerName $HostServer -ScriptName "TemplateDiscoveryTask.ps1" -CreateSampleConfig -OutsideManagementPack:$OutsideManagementPack
$Logger.Debug("CIMUser = $CIMUser")
if ([string]::IsNullOrEmpty($CIMPass)) {
$Logger.Debug("CIMPassword = /null or empty/")
} else {
$Logger.Debug("CIMPassword = /provided/")
}
$Logger.Debug("CIMPort = $CIMPort")
$Logger.Debug("CIMProtocol = $CIMProtocol")
$Logger.Debug("NoCertCheck = $NoCertCheck")
try {
Split-IPAddresses
Start-DiscoveryJobs
Merge-DiscoveryData
Out-PropertyBag
} catch {
$Logger.Error(113, $_.Exception.Message)
}
$Logger.Debug("***** Normal end of script. *****")
}
function Split-IPAddresses {
$ipArray = $IPList.Split(';') | Where { $_.Trim() } | Select-Object -Unique
$maxThreads = 5
if ($ipArray.Count -gt 60) {
$maxThreads = [int][Math]::Ceiling(($ipArray.Count / 10))
if ($maxThreads -gt 20) {
$maxThreads = 20
}
}
if ($ipArray.Count -gt $maxThreads) {
$script:numThreads = $maxThreads
$numInGroup = [int]($ipArray.Count / $maxThreads)
$ipGroup = ""
$count = 0
foreach ($ip in $ipArray) {
if ($count -ge $numInGroup) {
$script:newIPList += $ipGroup.Substring(1)
$count = 0
$ipGroup = ""
}
$ipGroup += ";$ip"
$count++
}
if ($newIPList.Count -lt $maxThreads) {
$script:newIPList += $ipGroup.Substring(1)
} else {
$script:newIPList[-1] += $ipGroup
}
} else {
$script:numThreads = $ipArray.Count
$script:newIPList = $ipArray
}
}
function Start-DiscoveryJobs {
$Logger.Debug("Creating Runspace Pool with $numThreads threads")
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $numThreads)
$RunspacePool.Open()
$count = 1
foreach ($ipAddresses in $newIPList) {
$Logger.Debug("Creating job #$count for $ipAddresses")
$Job = [powershell]::Create().AddScript($IpDiscoveryScript). `
AddParameter("IPAddresses", $ipAddresses). `
AddParameter("NoCertCheck", $NoCertCheck). `
AddParameter("CIMPort", $CIMPort). `
AddParameter("CIMUser", $CIMUser). `
AddParameter("CIMPass", $CIMPass). `
AddParameter("CIMProtocol", $CIMProtocol)
if ($OutsideManagementPack) {
$Job.AddParameter("ScriptRoot", $PSScriptRoot).AddParameter("OutsideManagementPack") | Out-Null
}
$Job.RunspacePool = $RunspacePool
Start-Sleep -m 100
$script:Jobs += New-Object PSObject -Property @{
RunNum = $count++
Job = $Job
Result = $Job.BeginInvoke()
}
}
}
function Merge-DiscoveryData {
$Logger.Debug("Gathering results from jobs")
$Results = @()
foreach ($Job in $Jobs) {
$Logger.Debug("Getting result from job #$($Job.RunNum)")
$Results += $Job.Job.EndInvoke($Job.Result)
}
$retIPList = ""
$retServName = ""
$retOpSystem = ""
$Logger.Debug("Processing jobs results")
foreach ($result in $Results) {
if ($result -is [string]) {
if ($result.StartsWith("Success:")) {
$server = $result.Substring(8).Split(";")
if ($server.Count -eq 3) {
$retIPList = "$($retIPList)$($server[0]);"
$retServName = "$($retServName)$($server[1]);"
$retOpSystem = "$($retOpSystem)$($server[2]);"
$Logger.Debug("$($server[0]): Found Fujitsu ESXi Server: $($server[2]) ($($server[1]))")
}
}
if ($result.StartsWith("Info:")) {
$Logger.Debug($result.Substring(5))
}
if ($result.StartsWith("Error:")) {
$Logger.Debug($result.Substring(6))
}
}
}
$script:Discovered += $retIPList
$script:Discovered += $retServName
$script:Discovered += $retOpSystem
}
function Out-PropertyBag {
$oAPI = New-SCOMApiObject -OutsideManagementPack:$OutsideManagementPack
$propertyBagData = $oAPI.CreatePropertyBag()
$propertyBagData.AddValue("IPList", $Discovered[0])
$propertyBagData.AddValue("ServerName", $Discovered[1])
$propertyBagData.AddValue("OperatingSystem", $Discovered[2])
$propertyBagData
}
#-------------------------------------------------------------------
$IpDiscoveryScript = {
Param (
[string] $IPAddresses,
[string] $NoCertCheck,
[int] $CIMPort,
[string] $CIMUser,
[string] $CIMPass,
[string] $CIMProtocol="https",
[string] $ScriptRoot="",
[switch] $OutsideManagementPack
)
Import-Module ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.PS.CommonModule']/Path$", "$ScriptRoot\Modules\CommonModule.psm1")[[bool]$OutsideManagementPack]
Import-Module ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.PS.CIMClient']/Path$", "$ScriptRoot\Modules\CIMClient.psm1" )[[bool]$OutsideManagementPack]
Import-Module ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.PS.LoggerModule']/Path$", "$ScriptRoot\Modules\LoggerModule.psm1")[[bool]$OutsideManagementPack]
$InvokerDllPath = ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.AssemblyInvoker']/Path$", "$ScriptRoot\..\..\Fujitsu.Servers.PRIMERGY.AssemblyInvoker\bin\Debug\Fujitsu.Servers.PRIMERGY.AssemblyInvoker.dll")[[bool]$OutsideManagementPack]
$ClientDllPath = ("$FileResource[Name='Fujitsu.Servers.PRIMERGY.CIMClient']/Path$", "$ScriptRoot\..\..\Fujitsu.Servers.PRIMERGY.CIMClient\bin\Debug\Fujitsu.Servers.PRIMERGY.CIMClient.dll" )[[bool]$OutsideManagementPack]
$ValidIPAddressRegex = "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
$DefaultESXiPageRegex = "ID_ProductName.*VMware\s*ESX"
$FujitsuESXiPageRegex = "Fujitsu\s+Customized\s+Image.*\((?:based on|for)\s(.*?)\)"
$ESXiName = "ESXi"
$PRIMERGYName = "PRIMERGY"
$PRIMEQUESTName = "PRIMEQUEST"
$ESXiAuthD = 902
$ESXiWebSrv = 443
$aIPList = $IPAddresses.Split(";")
$PortTimeout = 3000
$WebTimeout = 6000
$CimTimeout = 10000
if ($aIPList.Count -lt 6) { # these settings apply for up to 25 IP addresses (5 on thread)
$PortTimeout = 6000
$WebTimeout = 20000
$CimTimeout = 30000
}
$CheckCert = ($NoCertCheck -ne "True")
$script:Output = @()
function Get-WebPage {
Param (
[string] $IPAddress,
[int] $Port,
[string] $Page,
[int] $Timeout = 6000
)
$result = ""
$url = "https://" + $IPAddress + ":" + $Port + $Page
try {
$script:CIM.Client.Set("Timeout", $Timeout) | Out-Null
$result = $script:CIM.Client.Invoke("GetWebPage", @($url, $False))
} catch {
$ErrorMessage = $_.Exception.Message
if ($ErrorMessage -imatch ".*Invoke.*argument\(s\):\s*`"(.*)`"") {
$script:Output += "Info:$($IPAddress): Get-WebPage: $($matches[1])"
} else {
$script:Output += "Info:$($IPAddress): $ErrorMessage"
}
}
return $result
}
function Test-Port {
Param (
[string] $IPAddress,
[int] $Port,
[int] $Timeout = 3000
)
$result = $True
try {
$tcp = New-Object System.Net.Sockets.TcpClient
$conn = $tcp.BeginConnect([ipaddress] $IPAddress, $Port, $Null, $Null)
$wait = $conn.AsyncWaitHandle.WaitOne($Timeout, $False)
if (! $wait) {
$script:Output += "Info:$($IPAddress): Test-Port: connection to port $($Port) AsyncWaitHandle.WaitOne = false"
$result = $False
} else {
$tcp.EndConnect($conn) | Out-Null
}
$tcp.Close()
} catch {
$ErrorMessage = $_.Exception.Message
if ($ErrorMessage -imatch ".*EndConnect.*argument\(s\):\s*`"(.*)`"") {
$script:Output += "Info:$($IPAddress): Test-Port.Connect: $($matches[1])"
} else {
$script:Output += "Info:$($IPAddress): Test-Port: $ErrorMessage"
}
$result = $False
}
return $result
}
function Start-Discovery {
foreach ($IPAddress in $aIPList) {
if ($IPAddress -imatch $ValidIPAddressRegex) {
$ESXiServer = $False;
$ESXiFujitsu = $False;
$OpSystem = "Unknown $ESXiName"
$ServName = $IPAddress
$script:Output = @()
if (Test-Port -IPAddress $IPAddress -Port $ESXiAuthD -Timeout $PortTimeout) {
if (Test-Port -IPAddress $IPAddress -Port $ESXiWebSrv -Timeout $PortTimeout) {
$page = Get-WebPage -IPAddress $IPAddress -Port $ESXiWebSrv -Page "/default.js" -Timeout $WebTimeout
if ($page -imatch $DefaultESXiPageRegex) {
$ESXiServer = $True
} elseif ($page.Equals("")) {
$page = Get-WebPage -IPAddress $IPAddress -Port $ESXiWebSrv -Page "/ui/images/esxi.png" -Timeout $WebTimeout
if (-not $page.Equals("")) {
$ESXiServer = $True
}
}
if ($ESXiServer) {
if (($CIMUser -ne "") -and (Test-Port -IPAddress $IPAddress -Port $CIMPort -Timeout $PortTimeout)) {
try {
$CIM.Address = $IPAddress
$CimData = $CIM.Query("SVS_OperatingSystem")
} catch {
$script:Output += "Info:$($IPAddress): $($_.Exception.Message)"
$CimData = $Null
}
} else {
$CimData = $Null
}
if ($CimData -ne $Null) {
if ($CimData.Caption -imatch $ESXiName) {
$OpSystem = $CimData.Caption
$ServName = $CimData.ElementName
try {
$CIM.Address = $IPAddress
$CimData = $CIM.Query("SVS_PGYChassis")
} catch {
$script:Output += "Info:$($IPAddress): $($_.Exception.Message)"
$CimData = $Null
}
if (($CimData -ne $Null) -and (($CimData.Model -imatch $PRIMERGYName) -or ($CimData.Model -imatch $PRIMEQUESTName))) {
$ESXiFujitsu = $True
}
}
} else {
$page = Get-WebPage -IPAddress $IPAddress -Port $ESXiWebSrv -Page "/dyndata.js" -Timeout $WebTimeout
if ($page -imatch $FujitsuESXiPageRegex) {
$ESXiFujitsu = $True # we do not exactly know if it is a PRIMERGY server, but its definitely Fujitsu machine
$OpSystem = $matches[1]
}
}
}
}
}
foreach ($msg in $Output) {
Write-Output $msg
}
if ($ESXiServer -and $ESXiFujitsu) {
Write-Output "Success:$IPAddress;$ServName;$OpSystem"
} elseif ($ESXiServer) {
Write-Output "Info:$($IPAddress): Not a Fujitsu ESXi server."
} else {
Write-Output "Info:$($IPAddress): Not an ESXi server."
}
}
}
}
try {
$script:CIM = New-CIMClient -InvokerDllPath $InvokerDllPath -ClientDllPath $ClientDllPath -ClientPort $CIMPort -ClientUser $CIMUser -ClientPass $CIMPass
$script:CIM.Timeout = $CimTimeout
$script:CIM.CheckCert = $CheckCert
$script:CIM.Protocol = $CIMProtocol
$script:CIM.RequestTries = 1
} catch {
return "Error:Cannot create CIM client: $($_.Exception.Message)"
}
try {
Start-Discovery
} catch {
return "Error:$($_.Exception.Message)"
} finally {
$script:CIM.Dispose()
}
}
#-------------------------------------------------------------------
try {
Main
} finally {
$Logger.OutputBuffer()
}
</Script> </ScriptBody>
<Parameters>
<Parameter>
<Name>IPList</Name>
<Value>$Config/IPList$</Value>
</Parameter>
<Parameter>
<Name>NoCertCheck</Name>
<Value>$Config/NoCertCheck$</Value>
</Parameter>
<Parameter>
<Name>CIMPort</Name>
<Value>$Config/CIMPort$</Value>
</Parameter>
<Parameter>
<Name>CIMUser</Name>
<Value>$RunAs[Name="FTSESXSEED!Fujitsu.Servers.PRIMERGY.ESXiSeed.CIMAccount"]/UserName$</Value>
</Parameter>
<Parameter>
<Name>CIMPass</Name>
<Value>$RunAs[Name="FTSESXSEED!Fujitsu.Servers.PRIMERGY.ESXiSeed.CIMAccount"]/Password$</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>