<WriteActionModuleType ID="Fujitsu.Servers.PRIMERGY.OutOfBand.iRMC.DeleteOrphanedDevices.WA" Accessibility="Internal" Batching="false">
<Configuration/>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="Script.CleanupOrphanedDevices" TypeID="Windows!Microsoft.Windows.PowerShellWriteAction">
<ScriptName>DeleteOrphanedDevices.ps1</ScriptName>
<ScriptBody><Script>
##################################################################################
# #
# NOTICE #
# #
# COPYRIGHT 2015 - 2018 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. #
# #
##################################################################################
DebugOut "$IP - TemplateId=$($TemplateId) is deleted, removing $($IP) from SCOM"
# Update Windows Computer Properties from optional Relationship (Note: located in extra MP)
if ($relationshipClass) {
$relationships = $mg.GetMonitoringRelationshipObjects($relationshipClass)
foreach($r in $relationships) {
if($r -eq $null) { continue }
if($r.TargetObject.Id -eq $Device.Id) {
DebugOut "$IP - Found my '$($r.SourceObject.DisplayName)' to '$($r.TargetObject.DisplayName)' Relationship Instance."
$properties = $r.SourceObject.GetProperties()
$propertiesChanged = 0
foreach($p in $properties) {
if($p.Name -eq "iRMCAvailable") {
DebugOut "$IP - Set Property '$($p.Name)' to '$($False)' of Windows Computer with iRMC '$($r.SourceObject.DisplayName)'."
$r.SourceObject[$p].Value = $False
$propertiesChanged++
}
if($p.Name -eq "iRMCDeviceState") {
DebugOut "$IP - Set Property '$($p.Name)' to 'N/A' of Windows Computer with iRMC '$($r.SourceObject.DisplayName)'."
$r.SourceObject[$p].Value = "N/A"
$propertiesChanged++
}
if($propertiesChanged -eq 2) {
break
}
}
$r.SourceObject.Commit()
}
}
}
# Delete the iRMC Device
$discoveryData.Remove($Device)
$DevicesRemoved++
LogWorkflowEvent 0 19030 "Fujitsu iRMC Device Cleanup Rule - deleted iRMC Device: '$($Device.DisplayName)' with IP '$($IP)' from template=$($TemplateId)"
} else {
DebugOut "$IP - TemplateId=$($TemplateId) has not been deleted, no need to delete iRMC Device '$($Device.DisplayName)' with IP '$($IP)'"
}
DebugOut "$IP - iRMC Check for Orphaned Devices: end"
}
Start-Sleep -s 30
# We need to re-read the relationships in case the iRMC has just been deleted above
if ($relationshipClass) {
$relationships = $mg.GetMonitoringRelationshipObjects($relationshipClass)
}
foreach($WinComputer in $Computers) {
if($WinComputer -eq $null) { continue }
if($p.Name -eq "iRMCAvailable") {
if ($WinComputer[$p].Value -eq $True) {
# Search for our relationship
$bFound = $false
foreach ($r in $relationships) {
if($r -eq $null) { continue }
DebugOut "'$($r.SourceObject.DisplayName)' to iRMC '$($r.TargetObject.DisplayName)' Relationship with Id $($r.Id)"
if ($r.SourceObject.Id -eq $WinComputer.Id) {
DebugOut "Found my '$($r.SourceObject.DisplayName)' to '$($r.TargetObject.DisplayName)' Relationship Instance with Id $($r.Id)."
$bFound = $True;
break;
}
}
if (!$bFound) {
DebugOut "'$($WinComputer.DisplayName)' - NO Relationship to iRMC found"
DebugOut "'$($WinComputer.DisplayName)' - Set Property '$($p.Name)' to '$($False)'"
$WinComputer[$p].Value = $False
# Also Reset iRMC Device State Property
foreach($prop in $properties) {
if($prop.Name -eq "iRMCDeviceState") {
if ($WinComputer[$prop].Value -ne 'N/A') {
$previousState = $WinComputer[$prop].Value
$WinComputer[$prop].Value = 'N/A'
DebugOut "'$($WinComputer.DisplayName)' - Set property '$($prop.Name)' from $($previousState) to 'N/A'"
} else {
DebugOut "'$($WinComputer.DisplayName)' - Property '$($prop.Name)' is up to date"
}
break
}
}
$WinComputer.Commit()
break
}
}
}
}
# $WinComputer.Commit()
}
} else {
DebugOut "No '$($WinComputerClass.DisplayName)' available"
}
} else {
# DebugOut "$($WinComputerClassName) class not present in SCOM (MP not imported), ignoring..."
}
}
}
# 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.5.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
)
# 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 log with different Event Source ('Health Service Modules Ex') and workflow instance information
Function LogWorkflowEvent {
Param (
[parameter(Mandatory=$true)]
[ValidateRange(0,2)]
[int]$EventLevel,
[parameter(Mandatory=$true)]
[int]$EventNumber,
[parameter(Mandatory=$true)]
[string]$Message
)
# --------------------------------------------------------------------------
# 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"
# 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 @"
<$SectionRoot>
<!--
$($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 '<$TagHostsDiscovery>' or '<$TagHostsMonitoring>' 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.
'<$TagDebugMode>' enables logging (yes) or disables logging (no)
'<$TagOverWrite>' defines continuous logging (no) or single script run logging (yes)
-->
<!-- DISCOVERIES -->
<!-- The following section enables trace files for the Out-Of-Band iRMC Device discovery script -->
<$SectioniRMCDiscovery>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectioniRMCDiscovery>
<!-- The following section enables trace files for the Out-Of-Band Server discovery script -->
<$SectionServerDiscovery>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectionServerDiscovery>
<!-- The following section enables trace files for the RAID discovery script -->
<$SectionRaidDiscovery>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectionRaidDiscovery>
<!-- MONITORS -->
<!-- The following section enables trace files for basic iRMC monitoring script -->
<$SectioniRMCMonitor>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectioniRMCMonitor>
<!-- The following section enables trace files for the main server Hardware Components (CPU/Memory/Fan/PowerSupply) monitoring script -->
<$SectionHardwareComponentMonitor>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectionHardwareComponentMonitor>
<!-- The following section enables trace files for the 'Component Status' monitoring script -->
<$SectionComponentStatusMonitor>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectionComponentStatusMonitor>
<!-- The following section enables trace files for the RAID monitoring script -->
<$SectionRaidMonitor>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectionRaidMonitor>
<!-- The following section enables trace files for the Performance monitoring script -->
<$SectionPerformanceMonitor>
<$TagDebugMode>yes</$TagDebugMode>
<$TagOverWrite>no</$TagOverWrite>
</$SectionPerformanceMonitor>
<!--
The following sections specify for which servers the traces will be generated:
In the '<$TagHostsDiscovery>' and '<$TagHostsMonitoring>' sections
single or multiple servers can be specified for verbose debug output
during the discovery and/or during monitoring.
Use '<$TagHostsDiscovery>' for selecting hosts for the discovery trace.
Use '<$TagHostsMonitoring>' 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:
<$TagHostsDiscovery>all</$TagHostsDiscovery>
<$TagHostsMonitoring>192.168.1.100,192.168.1.101,192.168.1.102</$TagHostsMonitoring>
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
-->
<$TagHostsDiscovery>all</$TagHostsDiscovery>
<$TagHostsMonitoring>all</$TagHostsMonitoring>
</$SectionRoot>
"@
}
}
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
}