Snippets

Samuel Tegenfeldt (atea) Log-PatrolEvent

Created by stegenfeldt atWork last modified
param(
	[string] $msendBufferDir,
	[string] $msendMcellDirFile,
	[int] $AlertSeverity,
	[int] $AlertPriority,
	[int] $TimeframeSeconds,
	[string] $CellName,
	[string] $LogLevel
)

# Create and start timer
$stopWatch = [Diagnostics.Stopwatch]::StartNew()

#(Get-Process -id $pid).WS
#(Get-Process -id $pid).Handles
#[gc]::Collect()

### Set script-settings
switch ($AlertSeverity){
	1 {[int[]] $scomAlertSeverity = 1,2; break}
	2 {[int[]] $scomAlertSeverity = 2; break}
	default {[int[]] $scomAlertSeverity = 0,1,2; break}
}
switch ($AlertPriority){
	1 {[int[]] $scomAlertPriority = 1,2; break}
	2 {[int[]] $scomAlertPriority = 2; break}
	default {[int[]] $scomAlertPriority = 0,1,2; break}
}
[int[]] $scomTriggerResolutionStates = 0,255

[int] $scomLoggedToPatrolResolutionState = 240
[int] $scomSendToPatrolResolutionState = 241


### Set logging settings
## Defaults
$debug = $false
$verbose = $false
$logError = $false
$logWarning = $false
$logInfo = $false
$silent = $false

switch ($LogLevel) {
	"debug" {$debug = $true}
	"verbose" {$verbose = $true}
	"silent" {$silent = $true}
	"warning" {
		$logWarning = $true
		$logError = $true
	}
	"info" {
		$logInfo = $true
		$logWarning = $true
		$logError = $true
	}
	default {
		$logError = $true
	}
}


If ((Get-Module).Name -eq "OperationsManager") {
	New-SCOMManagementGroupConnection -ComputerName localhost
} else {
	Import-Module -Name OperationsManager
	New-SCOMManagementGroupConnection -ComputerName localhost
}

$omApi = New-Object -ComObject 'MOM.ScriptAPI'

$omApi.LogScriptEvent("Log-PatrolEvent.ps1",6663,0,("Running Log-PatrolEvent.ps1 locally with log level {0}" -f $LogLevel))

# Initialize $scomAlerts array
$scomAlerts = @()
# Get all closed alerts where resolutionstate has been modified within the set timeframe
$scomAlerts += Get-SCOMAlert -ResolutionState 255 | Where {([math]::round((New-TimeSpan -Start $_.TimeResolutionStateLastModified -End (Get-Date).ToUniversalTime()).TotalSeconds)) -le $TimeframeSeconds}
if ($verbose -or $debug) {$omApi.LogScriptEvent("Log-PatrolEvent.ps1",6663,0,("Found {0} alerts closed within the last {1} seconds" -f $scomAlerts.Count, $TimeframeSeconds))}
# Get all new alerts that matches $scomAlertServerity and $scomAlertPriority
$scomAlerts += Get-SCOMAlert -Severity $scomAlertSeverity -Priority $scomAlertPriority -ResolutionState 0
# Get all alerts, no matter what severity/priority or update time they have, that are set to "Send to Patrol"
$scomAlerts += Get-SCOMAlert -ResolutionState $scomSendToPatrolResolutionState

if ($verbose -or $debug) {$omApi.LogScriptEvent("Log-PatrolEvent.ps1",6663,0,("Found a total of {0} alerts to process." -f $scomAlerts.Count))}

### Set script defaults
[string] $msendSeverity = ""
[string] $msendPriority = ""
[string] $msendEventType = "MS_SCOM_EVENT"
[string] $msendHost = ""
[string] $msendHostClass = ""
[string] $msendObject = ""
[string] $msendObjectClass = ""
[string] $msendParameter = ""
[string] $msendParameterValue = ""
[string] $msendSCOMAlertId = ""
[string] $msendSCOMDataCenter ="EMEA"
[string] $msendSCOMSeverity = ""
[string] $msendSCOMSendTime = ""
[string] $msendSCOMGroup = ""
[string] $msendSCOMApplication = ""
[string] $msendSCOMPriority = ""
[string] $msendMessage = ""

### Get Server Role Groups
$groupClass = Get-SCOMClass -Name "Xylem.AD.Groups.RoleBasedServerGroup"
$groupInstances = Get-SCOMClassInstance -Class $groupClass
$groupMembers = $groupInstances.GetMonitoringRelationshipObjectsWhereSource()

### Iterate through the collected alerts and log them to Patrol
foreach ($scomAlert in $scomAlerts) {
	$msendSCOMAlertId = $scomAlert.Id

	$scomObject = Get-SCOMMonitoringObject -Id $scomAlert.MonitoringObjectId
	# Check if the class is a Xylem custom class. In that case, use that as scomObjectClass.
	# Otherwise, use the LeastDerivedNonAbstractMonitoringClassId
	$scomObjectClass = Get-SCOMClass -Id $scomAlert.MonitoringClassId
	if ($scomObjectClass -notlike "Xylem.*") {
		$scomObjectClass = Get-SCOMClass -Id $scomObject.LeastDerivedNonAbstractMonitoringClassId
	}

	if ($verbose -or $debug) {$omApi.LogScriptEvent("Log-PatrolEvent.ps1",6663,0,("Alert Id {0} matches interval." -f $scomAlert.Id))}

	### Set msendSeverity
	# Read from Alert first
	$msendSCOMSeverity = ($scomAlert.Severity).ToString().ToUpper()
	$msendSCOMPriority = ($scomAlert.Priority).ToString().ToUpper()
	# For now, just set something simple
	switch ($msendSCOMSeverity) {
		"ERROR" {$msendSeverity = "CRITICAL"}
		"WARNING" {$msendSeverity = "WARNING"}
		"INFORMATION" {$msendSeverity = "INFO"}
		default {$msendSeverity = "INFO"}
	}

	# Then check resolutionstate in case of closure or escalations.
	# 255 = Closed, set Severity to OK
	# 254 = Resolved, set Severity to OK
	$scomAlert.Refresh()
	Switch($scomAlert.ResolutionState) {
		254 {$msendSeverity = "OK"}
		255 {$msendSeverity = "OK"}
		default {$msendSeverity = $msendSeverity}
	}

	### Set msendHost
	if($scomAlert.NetbiosComputerName.Length -lt 1) {
		$msendHost = $scomAlert.MonitoringObjectDisplayName
		if ($msendHost -like "*.*") {
			$msendHost = $msendHost.Substring(0,$msendHost.IndexOf("."))
		}
	} else {
		$msendHost = $scomAlert.NetbiosComputerName
	}

	### Set $msendSCOMGroup
	## Check for alerts from Health Service Watcher (HSW), those affect an agent/server, but are generated from the OMMS
	if ($scomObjectClass.Name -eq "Microsoft.SystemCenter.HealthServiceWatcher") {
		# Alert is from a Health Service Watcher, use alert.ObjectDisplayName
		$alertComputerName = $scomAlert.MonitoringObjectDisplayName
	} else {
		# Not from HSW, use alert.PrincipalName
		$alertComputerName = $scomAlert.PrincipalName
	}
	
	## Collect groups and members
	$groupMembership = @()
	# Get Prod
	$groupMembership += $groupMembers | where{(($_.TargetObject.DisplayName -eq $alertComputerName) -and ($_.SourceObject.DisplayName -like "*Production*"))}
	# Get Staging
	$groupMembership += $groupMembers | where{(($_.TargetObject.DisplayName -eq $alertComputerName) -and ($_.SourceObject.DisplayName -like "*Staging*"))}
	# Get Test
	$groupMembership += $groupMembers | where{(($_.TargetObject.DisplayName -eq $alertComputerName) -and ($_.SourceObject.DisplayName -like "*Test*"))}
	# Get the rest
	$groupMembership += $groupMembers | where{(($_.TargetObject.DisplayName -eq $alertComputerName) -and (($_.SourceObject.DisplayName -notlike "*Production*") -and ($_.SourceObject.DisplayName -notlike "*Staging*") -and ($_.SourceObject.DisplayName -notlike "*Test*")))}

	$msendSCOMGroup = $groupMembership.SourceMonitoringObject -join ","
	$msendSCOMGroup = $msendSCOMGroup -replace "Xylem ServerRole - ",""

	### Set msendHostClass
	# Default to NT (Windows Server), add exceptions here, before "default"
	switch -Wildcard ($scomObject.FullName) {
		"System.NetworkManagement.Node:*" {$msendHostClass = "NETWORK"}
		default {$msendHostClass = "NT"}
	}

	### Set msendObject
	$msendObject = $scomObject.DisplayName
	if ($msendObject -like "*.*") {
		$msendObject = $msendObject.Substring(0,$msendObject.IndexOf("."))
	}

	### Set msendObjectClass
	$msendObjectClass = $scomObjectClass.Name 

	### Set msendParameter
	$msendParameter = $msendSCOMGroup

	### Set msendParameterValue
	# For lack of better ideas, since SCOM manages health differently than Patrol,
	# msendParameterValue will simply be set to SCOM-severity
	$msendParameterValue = $msendSCOMSeverity

	### Set msendSCOMSendTime
	$msendSCOMSendTime = $scomAlert.TimeResolutionStateLastModified | Get-Date -Format s

	### Build -b option string
	if ($msendSeverity -eq "OK") {
		$msendBOption = "mc_object_class={0};mc_object={1};mc_host={2};mc_host_class={3};mc_parameter={4}" -f $msendObjectClass,$msendObject,$msendHost,$msendHostClass,$msendParameter
	} else {
		$msendBOption = "mc_object_class={0};mc_object={1};mc_host={2};mc_host_class={3};mc_parameter={4};mc_parameter_value={5};scom_alert_id={6};scom_data_center={7};scom_severity={8};scom_send_time={9}" -f $msendObjectClass,$msendObject,$msendHost,$msendHostClass,$msendParameter,$msendParameterValue,$msendSCOMAlertId,$msendSCOMDataCenter,$msendSCOMSeverity,$msendSCOMSendTime
	}

	### Build -m message string
	$msendMessage = "{0} {1}" -f $msendHost.ToUpper(),$scomAlert.Name

	$msendCommand = "& msend -a MS_SCOM_EVENT -n {4} -m `"{0}`" -r {1} -b `"{2}`" -l `"{3}`"" -f $msendMessage,$msendSeverity,$msendBOption,$msendMcellDirFile,$CellName

	# Execute msend
	$msendTimerSeconds = (Measure-Command{if (-not ($debug)) {Invoke-Expression $msendCommand}}).TotalSeconds
	if ($verbose -or $debug) {$omApi.LogScriptEvent("Log-PatrolEvent.ps1",6663,0,("msend command:`n{0}`n`nExecution time in Seconds: {1}" -f $msendCommand,$msendTimerSeconds))}

	# Update alert resolution state to "Logged to Patrol"
    # But only if the alert is neither closed nor resolved.
    switch($scomAlert.ResolutionState) {
        254 {Set-SCOMAlert -Alert $scomAlert -Comment "Alert updated to $msendSeverity in Patrol" -CustomField1 $msendSCOMGroup}
        255 {Set-SCOMAlert -Alert $scomAlert -Comment "Alert updated to $msendSeverity in Patrol" -CustomField1 $msendSCOMGroup}
        default {Set-SCOMAlert -Alert $scomAlert -ResolutionState $scomLoggedToPatrolResolutionState -Comment "Alert logged in Patrol as $msendSeverity" -CustomField1 $msendSCOMGroup}
    }
}

# Stop timer and log to eventlog (depending on log level)
$stopWatch.Stop()
if ($verbose -or $debug) {$omApi.LogScriptEvent("Log-PatrolEvent.ps1",6663,0,("Script completed in {0} seconds" -f ($stopWatch.ElapsedMilliseconds/1000)))}

# Close any persistent SDK-connections
Get-SCOMManagementGroupConnection | ?{$_.IsActive } | Remove-SCOMManagementGroupConnection

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.