diff --git a/AlertManagement.PS/AlertManagement.PS.ps1 b/AlertManagement.PS/AlertManagement.PS.ps1
deleted file mode 100644
index c5eb80f..0000000
--- a/AlertManagement.PS/AlertManagement.PS.ps1
+++ /dev/null
@@ -1,3 +0,0 @@
-#
-# Script.ps1
-#
diff --git a/AlertManagement.PS/AlertManagement.PS.pssproj b/AlertManagement.PS/AlertManagement.PS.pssproj
index 2f1da76..4014cdf 100644
--- a/AlertManagement.PS/AlertManagement.PS.pssproj
+++ b/AlertManagement.PS/AlertManagement.PS.pssproj
@@ -25,9 +25,13 @@
prompt
4
-
-
+
+
+
+
+
+
diff --git a/AlertManagement.PS/Escalate-SCOMAlert.ps1 b/AlertManagement.PS/Escalate-SCOMAlert.ps1
new file mode 100644
index 0000000..2b890f4
--- /dev/null
+++ b/AlertManagement.PS/Escalate-SCOMAlert.ps1
@@ -0,0 +1,424 @@
+########################################################################
+# Escalate-SCOMAlert.ps1
+# Hugh Scott
+# 2018/07/09
+#
+# Description:
+# Escalate SCOM alerts based on rules in config file. Note that this
+# may require that the administrator add custom ResolutionStates to
+# SCOM.
+#
+# THIS CODE IS PROVIDED AS-IS WITH NO WARRANTIES EITHER EXPRESSED OR
+# IMPLIED.
+#
+# Modifications:
+# Date Initials Description
+# 2018/07/09 HMS -Original
+# 2018/07/10 HMS -Updated; added postPipelineFilter
+#
+########################################################################
+
+# Load the Operations Manager script API
+$momApi = New-Object -ComObject MOM.ScriptAPI
+
+#region Functions
+function DateFieldReplace {
+param (
+ [string]$criteria,
+ [int]$timeOffset
+)
+
+ # INITIALIZE RETURN VALUE
+ [string]$tmpString = ""
+
+ # COMPUTE TIME OFFSET; CAST AS STRING VALUE
+ [int]$m_timeOffset = -$timeOffset
+ [datetime]$compareDate = (Get-Date).AddMinutes($m_timeOffset).ToUniversalTime()
+ [string]$dateString = $compareDate.ToString("MM/dd/yyyy HH:mm:ss")
+
+ If($criteria -match "__LastModified__")
+ {
+ $tmpString = $criteria.Replace("__LastModified__", $dateString)
+ }
+ ElseIf($criteria -match "__TimeRaised__")
+ {
+ $tmpString = $criteria.Replace("__TimeRaised__", $dateString)
+ }
+ Else
+ {
+ $tmpString = $criteria
+ }
+
+ # REPLACE ESCAPED XML CHARACTERS
+ $tmpString = $tmpString.Replace("<","<")
+ $tmpString = $tmpString.Replace(">",">")
+
+ Return $tmpString
+
+}
+
+function CleanPostPipelineFilter {
+param ([string]$postPipelineFilter)
+ [string]$tmpString = ""
+
+ # REPLACE ESCAPED XML CHARACTERS
+ $tmpString = $postPipelineFilter.Replace("<","<")
+ $tmpString = $postPipelineFilter.Replace(">",">")
+
+ Return $tmpString
+}
+#endregion Functions
+
+# RETRIEVE CONFIGURATION FILE WITH RULES AND EXCEPTIONS
+[xml]$configFile= Get-Content 'D:\Admin\Scripts\EscalateScomAlerts\escalate.alert.config'
+
+# MANAGEMENT SERVER
+[string]$managementServer = '.'
+
+# LOG FILE
+[string]$logFilePath = $configFile.config.settings.outputpath.name
+[string]$fileName = "AlertEscalation." + (Get-Date -Format "yyyy.MM.dd") + ".log"
+[string]$logFileName = Join-Path $logFilePath $fileName
+
+if ( -not ( Get-Module -Name OperationsManager ) )
+{
+ Import-Module OperationsManager
+}
+
+#region Update Type Data
+
+# Add a UnitMonitor property to the alert which contains the associated unit monitor object
+$updateTypeDataUnitMonitorParameters = @{
+ TypeName = 'Microsoft.EnterpriseManagement.Monitoring.MonitoringAlert'
+ MemberType = 'ScriptProperty'
+ MemberName = 'UnitMonitor'
+ Value = {
+ if ( $this.IsMonitorAlert )
+ {
+ function GetScomChildNodes
+ {
+ [CmdletBinding()]
+ param
+ (
+ [Parameter(Mandatory = $true)]
+ #[Microsoft.EnterpriseManagement.Common.MonitoringHierarchyNode`1[[Microsoft.EnterpriseManagement.Configuration.ManagementPackMonitor, Microsoft.EnterpriseManagement.Core, Version=7.0.5000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]]
+ [System.Object]
+ $MonitoringHierarchyNode
+ )
+
+ # Create an array for the unit monitors
+ $unitMonitors = @()
+
+ foreach ( $childNode in $MonitoringHierarchyNode.ChildNodes )
+ {
+ if ( $childNode.Item.GetType().FullName -eq 'Microsoft.EnterpriseManagement.Configuration.UnitMonitor' )
+ {
+ Write-Verbose -Message "Unit Monitor: $($childNode.Item.DisplayName)"
+ $unitMonitors += $childNode.Item
+ }
+ else
+ {
+ Write-Verbose -Message $childNode.Item.DisplayName
+ Write-Verbose -Message ($childNode.GetType().FullName)
+ GetScomChildNodes -MonitoringHierarchyNode $childNode.Item
+ }
+ }
+
+ return $unitMonitors
+ }
+
+ # Get the associated monitor from the alert
+ if ( $this.IsMonitorAlert )
+ {
+ $monitor = Get-SCOMClassInstance -Id $this.MonitoringObjectId
+ }
+ else
+ {
+ Write-Verbose -Message ( 'The alert "{0}" is not a monitor alert.' -f $this.Name )
+ exit
+ }
+
+ # Get the child nodes of the monitor
+ $unitMonitors = @()
+ foreach ( $childNode in $monitor.GetMonitorHierarchy().ChildNodes )
+ {
+ $unitMonitors += GetScomChildNodes -MonitoringHierarchyNode $childNode
+ }
+
+ # Get the unit monitor which generated the alert
+ $unitMonitor = $unitMonitors | Where-Object -FilterScript { $_.Id -eq $this.MonitoringRuleId }
+
+ return $unitMonitor
+ }
+ }
+}
+Update-TypeData @updateTypeDataUnitMonitorParameters
+
+# Add a Monitor property to the alert which contains the associated unit monitor object
+$updateTypeDataMonitorParameters = @{
+ TypeName = 'Microsoft.EnterpriseManagement.Monitoring.MonitoringAlert'
+ MemberType = 'ScriptProperty'
+ MemberName = 'Monitor'
+ Value = {
+ Get-SCOMClassInstance -Id $this.MonitoringObjectId
+ }
+}
+Update-TypeData @updateTypeDataMonitorParameters
+
+# Add a HealthStateSuccess property to the alert which contains the associated unit monitor object
+$updateTypeDataHealthStateSuccessParameters = @{
+ TypeName = 'Microsoft.EnterpriseManagement.Monitoring.MonitoringAlert'
+ MemberType = 'ScriptProperty'
+ MemberName = 'HealthStateSuccess'
+ Value = {
+ return $this.UnitMonitor.OperationalStateCollection |
+ Where-Object -FilterScript { $_.HealthState -eq 'Success' } |
+ Select-Object -ExpandProperty Name
+ }
+}
+Update-TypeData @updateTypeDataHealthStateSuccessParameters
+
+#endregion Update Type Data
+
+$Connection = New-SCManagementGroupConnection $managementServer -PassThru
+
+If($Connection.IsActive)
+{
+ # INITIALIZE AlertCount
+ [int]$AlertCount = 0
+
+ # Alert Storm Processing
+ $alertStormRules = $configFile.SelectNodes("//config/alertStormRules/stormRule[@enabled='true']") | Sort-Object {$_.Sequence}
+
+ foreach ( $alertStormRule in $alertStormRules )
+ {
+ # Get the alerts defined by the criteria and group them by the defined property
+ $potentialStormAlertGroups = Get-SCOMAlert -Criteria $alertStormRule.Criteria.InnerText |
+ Group-Object -Property $alertStormRule.Property |
+ Where-Object -FilterScript { $_.Count -gt 1 }
+
+ # Define a counter which will be used to further subdivide the alerts into groups
+ $groupCounter = 0
+
+ # Create a hashtable to store the new groups of alerts
+ $stormAlertGroups = @{$groupCounter = @()}
+
+ foreach ( $potentialStormAlertGroup in $potentialStormAlertGroups )
+ {
+ # Create a variable to base the time elapsed calcluations off of
+ $previousDateTime = [System.DateTime]::MinValue
+
+ foreach ( $alert in ( $potentialStormAlertGroup.Group | Sort-Object -Property TimeRaised ) )
+ {
+ # If the alert was raised less than the defined window from the previous alert
+ if ( ( $alert.TimeRaised - $previousDateTime ).TotalMinutes -lt $alertStormRule.Window )
+ {
+ # Add the alert to the current group
+ $stormAlertGroups[$groupCounter] += $alert
+ }
+ else
+ {
+ # Increment the group counter
+ $groupCounter++
+
+ # Create a new group
+ $stormAlertGroups[$groupCounter] = @($alert)
+ }
+
+ # Update the Previous Date/Time variable
+ $previousDateTime = $alert.TimeRaised
+ }
+ }
+
+ # Get the groups which meet the threshold for number of the same alert
+ $stormAlerts = $stormAlertGroups.GetEnumerator() |
+ Where-Object -FilterScript { $_.Value.Count -ge $alertStormRule.Count }
+
+ foreach ( $stormAlert in $stormAlerts.GetEnumerator() )
+ {
+ # Get the alerts which were previously tagged as an alert storm
+ $oldAlertStormAlerts = $stormAlert.Value |
+ Where-Object -FilterScript { ( $_.ResolutionState -eq 18 ) -and $_.TicketID }
+
+ if ( $oldAlertStormAlerts.Count -gt 0 )
+ {
+ # Get the existing "ticket id"
+ $ticketId = $oldAlertStormAlerts | Select-Object -ExpandProperty TicketId -Unique
+ }
+ else
+ {
+ # Get the alert name
+ $alertName = $stormAlert.Value | Select-Object -ExpandProperty Name -Unique
+
+ # Define the "ticket id"
+ $ticketId = ( Get-Date -Format 'MM/dd/yyyy hh:mm:ss {0}' ) -f $alertName
+
+ # Create an array of alerts which should be passed into a storm alert
+ $createStormAlert = @()
+
+ foreach ( $alert in $stormAlert.Value )
+ {
+ # Get the associated monitoring object
+ $alertMonitoringObject = Get-ScomMonitoringObject -Id $alert.MonitoringObjectId
+
+ ######################################################################################
+ # HMS
+ # 2020/03/23
+ # Comment out Check for Asset Status; most customers won't use this
+ ######################################################################################
+ # if ( $alertMonitoringObject.'[System.ConfigItem].AssetStatus'.Value -eq 'Deployed' )
+ # {
+ $createStormAlert += $alert
+ # }
+ }
+
+ # Get a unique list of monitoring objects
+ $monitoringObjects = $createStormAlert |
+ Select-Object -ExpandProperty MonitoringObjectFullName -Unique |
+ Sort-Object
+
+ # Define the string which will be passed in as the "script name" property for LogScriptEvent
+ $stormDescription = "The alert ""$alertName"" was triggered $($createStormAlert.Count) times for the following objects:"
+
+ # Define the event details
+ $eventDetails = New-Object -TypeName System.Text.StringBuilder
+ $eventDetails.AppendLine() > $null
+ $eventDetails.AppendLine() > $null
+ $monitoringObjects | ForEach-Object -Process { $eventDetails.AppendLine($_) > $null }
+ $eventDetails.AppendLine() > $null
+ $eventDetails.AppendLine("Internal ticket id: $ticketId") > $null
+
+ # Raise an event indicating an alert storm was detected
+ $momApi.LogScriptEvent($stormDescription, 9908, 2, $eventDetails.ToString())
+ }
+
+ # Mark the alert as being part of an alert storm
+ $stormAlert.Value |
+ Where-Object -FilterScript { $_.ResolutionState -ne 18 } |
+ Set-SCOMAlert -ResolutionState 18 -Comment $alertStormRule.Comment.InnerText -TicketId $ticketId
+ }
+ }
+
+ # PROCESS EXCEPTIONS FIRST
+ $alertExceptions = $configFile.SelectNodes("//config/exceptions/exception[@enabled='true']") | Sort-Object {$_.Sequence}
+
+ foreach($exception in $alertExceptions)
+ {
+ # ASSIGN VALUES
+ # Write-Host $exception.name
+ [string]$criteria = $exception.Criteria.InnerText
+ [int]$newResolutionState = $exception.NewResolutionState
+ [string]$postPipelineFilter = $exception.PostPipelineFilter #.InnerText
+ [string]$comment = $exception.Comment.InnerText
+ [string]$name = $exception.Name
+
+ # REPLACE TIME BASED CRITERIA
+ if($criteria -match "__TimeRaised__")
+ {
+ [int]$timeRaisedAge = $exception.TimeRaisedAge
+ $criteria = DateFieldReplace $criteria $timeRaisedAge
+ }
+ if($criteria -match "__LastModified__")
+ {
+ [int]$lastModifiedAge = $exception.LastModifiedAge
+ $criteria = DateFieldReplace $criteria $lastModifiedAge
+ }
+
+ # COLLECT ALERTS BASED ON CRITERIA
+ If($postPipelineFilter -eq "")
+ {
+ $alerts = Get-SCOMAlert -Criteria $criteria
+ }
+ Else
+ {
+ [string]$cleanString=CleanPostPipelineFilter $postPipelineFilter
+ [scriptblock]$filter=[System.Management.Automation.ScriptBlock]::Create($cleanString)
+
+ $alerts = Get-SCOMAlert -Criteria $criteria | Where-Object -FilterScript $filter
+ }
+
+ ### UPDATE MATCHING ALERTS TO NEW RESOLUTION STATE
+ If($alerts.Count -gt 0)
+ {
+ $alerts | Set-SCOMAlert -ResolutionState $newResolutionState -Comment $Comment
+ # Write-Host $criteria
+ $AlertCount = $alerts.Count
+ $msg = (Get-Date -Format "yyyy/MM/dd hh:mm:ss") + " : INFO : Updated $AlertCount alert(s) to resolution state $newResolutionState (Exception: $name)."
+ # Write-Host " : $msg"
+ Add-Content $logFileName $msg
+ }
+
+
+ # RESET EXCEPTION VALUES
+ $criteria = $null
+ $newResolutionState = $null
+ $postPipelineFilter = $null
+ $comment = $null
+ $name=$null
+
+ }
+
+ # PROCESS RULES SECOND
+ $alertRules = $configFile.SelectNodes("//config/rules/rule[@enabled='true']") | Sort-Object {$_.sequence}
+
+ foreach($rule in $alertRules)
+ {
+ # ASSIGN VALUES
+ # Write-Host $rule.name
+ [string]$criteria = $rule.Criteria.InnerText
+ [int]$newResolutionState = $rule.NewResolutionState
+ [string]$postPipelineFilter = $rule.PostPipelineFilter #.InnerText
+ [string]$comment = $rule.Comment.InnerText
+ [string]$name=$rule.name
+
+ # REPLACE TIME BASED CRITERIA
+ if($criteria -match "__TimeRaised__")
+ {
+ [int]$timeRaisedAge = $rule.TimeRaisedAge
+ $criteria = DateFieldReplace $criteria $timeRaisedAge
+ }
+ if($criteria -match "__LastModified__")
+ {
+ [int]$lastModifiedAge = $rule.LastModifiedAge
+ $criteria = DateFieldReplace $criteria $lastModifiedAge
+ }
+
+ # COLLECT ALERTS BASED ON CRITERIA
+ if ( [System.String]::IsNullOrEmpty($postPipelineFilter) )
+ {
+ $alerts = Get-SCOMAlert -Criteria $criteria
+ }
+ else
+ {
+ [string]$cleanString=CleanPostPipelineFilter $postPipelineFilter
+ [scriptblock]$filter=[System.Management.Automation.ScriptBlock]::Create($cleanString)
+
+ $alerts = Get-SCOMAlert -Criteria $criteria | Where-Object -FilterScript $filter
+ }
+
+ ### UPDATE MATCHING ALERTS TO NEW RESOLUTION STATE
+ If($alerts.Count -gt 0)
+ {
+ $alerts | Set-SCOMAlert -ResolutionState $newResolutionState -Comment $Comment
+ # Write-Host $criteria
+ $AlertCount = $alerts.Count
+ $msg = (Get-Date -Format "yyyy/MM/dd hh:mm:ss") + " : INFO : Updated $AlertCount alert(s) to resolution state $newResolutionState (Rule: $name)."
+ # Write-Host " : $msg"
+
+ Add-Content $logFileName $msg
+ }
+
+ # RESET RULE VALUES
+ $criteria = $null
+ $newResolutionState = $null
+ $postPipelineFilter = $null
+ $comment = $null
+ $name=$null
+ }
+
+}
+Else
+{
+ $msg = (Get-Date -Format "yyyy/MM/dd hh:mm:ss") + " : ERROR : Unable to connect to Management Server"
+ Add-Content $logFileName $msg
+}
diff --git a/AlertManagement.PS/assign.alert.config b/AlertManagement.PS/assign.alert.config
new file mode 100644
index 0000000..9c1d5c6
--- /dev/null
+++ b/AlertManagement.PS/assign.alert.config
@@ -0,0 +1,382 @@
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+ 5
+ Assigned
+
+
+ Unassigned
+ 5
+ Unassigned
+
+
+
+
+
+ Microsoft.SQLServer.Library
+ DBA Team
+
+
+ Microsoft.SQLServer.2008.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2012.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2014.Discovery
+ DBA Team
+
+
+ Microsoft.Windows.Server.AD.Library
+ Active Directory Team
+
+
+ Microsoft.Windows.Server.AD.2000.Discovery
+ Active Directory Team
+
+
+ Microsoft.Windows.Server.AD.2003.Discovery
+ Active Directory Team
+
+
+ Microsoft.Windows.Server.AD.2008.Discovery
+ Active Directory Team
+
+
+ Microsoft.Exchange.2010
+ Active Directory Team
+
+
+ Microsoft.Windows.Server.2003
+ Windows Team
+
+
+ Microsoft.Windows.Server.2008
+ Windows Team
+
+
+ Microsoft.Windows.Server.2012
+ Windows Team
+
+
+ Microsoft.Windows.Server.2008.Discovery
+ Windows Team
+
+
+ Microsoft.Windows.Server.2012.Discovery
+ Windows Team
+
+
+ Microsoft.Windows.Server.2012.R2.Discovery
+ Windows Team
+
+
+ Microsoft.Windows.Server.Library
+ Windows Team
+
+
+ Microsoft.Windows.Library
+ Windows Team
+
+
+ Microsoft.Windows.Cluster.Library
+ Windows Team
+
+
+ Microsoft.Windows.Cluster.Management.Library
+ Windows Team
+
+
+ Microsoft.Windows.InternetInformationServices.2008
+ App Support
+
+
+ Microsoft.Windows.InternetInformationServices.2012
+ App Support
+
+
+ SystemCenterCentral.Utilities.Certificates
+ App Support
+
+
+ Microsoft.SystemCenter.Library
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.Notifications.Library
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.Apm.Infrastructure
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.2012.Orchestrator
+ Monitoring Team
+
+
+ Microsoft.SystemCenter2012.ConfigurationManager.Library
+ Config Mgmt Team
+
+
+ Microsoft.Windows.Server.UpdateServices.2012.R2
+ Config Mgmt Team
+
+
+ Microsoft.HPUX.11iv2
+ Linux Team
+
+
+ Microsoft.HPUX.11iv3
+ Linux Team
+
+
+ Microsoft.Solaris.10
+ Linux Team
+
+
+ Microsoft.Solaris.11
+ Linux Team
+
+
+ Microsoft.AIX.6.1
+ Linux Team
+
+
+ Microsoft.AIX.7
+ Linux Team
+
+
+ Microsoft.Linux.RHEL.4
+ Linux Team
+
+
+ Microsoft.Linux.RHEL.5
+ Linux Team
+
+
+ Microsoft.Linux.RHEL.6
+ Linux Team
+
+
+ Microsoft.Linux.RHEL.7
+ Linux Team
+
+
+ Microsoft.Unix.Library
+ Linux Team
+
+
+ SCOM2012.Maintenance.Mode.Scheduler.Monitoring
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.OperationsManager.Infra
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.ACS.Internal
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.DataWarehouse.Internal
+ Monitoring Team
+
+
+ Microsoft.SystemCenter.OperationsManager.DataAccessService
+ Monitoring Team
+
+
+ Microsoft.Windows.Server.ClusterSharedVolumeMonitoring
+ Windows Team
+
+
+ Microsoft.Windows.Server.2016
+ Windows Team
+
+
+ Microsoft.Windows.Server.2016.Discovery
+ Windows Team
+
+
+ Microsoft.SQLServer.2016.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2008.Replication.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2012.Replication.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2014.Replication.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2016.Replication.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2012.AlwaysOn.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2014.AlwaysOn.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.2016.AlwaysOn.Discovery
+ DBA Team
+
+
+ Microsoft.Windows.InternetInformationServices.2016
+ App Support
+
+
+ Microsoft.SystemCenter.2016.Orchestrator
+ Monitoring Team
+
+
+ Microsoft.SQLServer.Windows.Discovery
+ DBA Team
+
+
+ Microsoft.SQLServer.Windows.Monitoring
+ DBA Team
+
+
+ URLGenie
+ App Support
+
+
+ Microsoft.Windows.Server.AD.2016.Discovery
+ Active Directory Team
+
+
+ Microsoft.Windows.Server.AD.Class.Library
+ Active Directory Team
+
+
+ Microsoft.SQLServer.Core.Library
+ DBA Team
+
+
+ Microsoft.SystemCenter.O365
+ O365 Team
+
+
+ Microsoft.Windows.ActiveDirectoryCertificateServices.2012.R2.Discovery
+ Active Directory Team
+
+
+ Microsoft.WindowsDefender
+ Windows Team
+
+
+ Microsoft.Windows.ActiveDirectoryCertificateServices.2012.R2.Discovery
+ Windows Team
+
+
+ Microsoft.Windows.HyperV.Library
+ Virtualization Team
+
+
+ Microsoft.Windows.DNSServer.2016
+ Active Directory Team
+
+
+ Microsoft.Windows.MSDTC.2012.R2
+ Windows Team
+
+
+ Microsoft.Windows.MSDTC.2016
+ Windows Team
+
+
+ Microsoft.SharePoint.Foundation.2013.Discovery
+ App Support
+
+
+ Microsoft.SharePoint.2019.Discovery
+ App Support
+
+
+ SharePointCommon
+ App Support
+
+
+ Microsoft.SharePoint.Server.2013.Discovery
+ App Support
+
+
+
+
+ Health Service Heartbeat Failure
+ Windows Team
+
+
+
+
+ Failed to Connect to Computer
+ Windows Team
+
+
+
+
+ Failed to perform Application Pool discovery
+ App Support
+
+
+
+
+ Failed to retrieve Application Pool state
+ App Support
+
+
+
+
+ Failed to perform Web Server properties discovery
+ App Support
+
+
+
+
+ Failed to perform Web Site discovery
+ App Support
+
+
+
+
+ Certificate lifespan alert
+ Windows Team
+ MonitoringObjectDisplayName
+ rdpcert
+
+
+ Microsoft.Windows.Library
+ EFG Windows Support
+ MonitoringObjectFullName
+ efg
+
+
+ OpsLogix.IMP.Ping
+ Network Team
+ MonitoringObjectFullName
+ efg
+
+
+
\ No newline at end of file
diff --git a/AlertManagement.PS/assign.alert.ps1 b/AlertManagement.PS/assign.alert.ps1
new file mode 100644
index 0000000..b6b0413
--- /dev/null
+++ b/AlertManagement.PS/assign.alert.ps1
@@ -0,0 +1,265 @@
+########################################################################
+# Assign-SCOMAlert.ps1
+# Hugh Scott
+# 2016/05/09
+#
+# Description:
+# Assign SCOM alerts based on rules in config file. Basic assignment
+# is done by management pack association.
+#
+# NOTE: The configuration file must be updated with entries from the current
+# Active Directory environment.
+#
+# THIS CODE IS PROVIDED AS-IS WITH NO WARRANTIES EITHER EXPRESSED OR
+# IMPLIED.
+#
+# Modifications:
+# Date Initials Description
+# 2016/05/09 HMS -Original
+# 2018/02/20 HMS - Modified to write Queue information to Owner field
+# 2019/10/09 HMS - Significant re-write; added variables for Resolution State, Default Owner and Log Level
+#
+########################################################################
+
+function XpathExpression {
+param (
+ [string]$value
+)
+
+ if ($value.Contains("'"))
+ {
+ return '\' + $value + '\';
+ }
+ elseif ($value.Contains('\'))
+ {
+ return """" + $value + """"
+ }
+ else
+ {
+ return $value;
+ }
+}
+
+ # Constants section - modify stuff here:
+ #=================================================================================
+ # Assign script name variable for use in event logging.
+ # ScriptName should be the same as the ID of the module that the script is contained in
+ $ScriptName = "Microsoft.Alert.Management.Alert.Management.Assign.Alert.TimedPowerShell.Rule.WA.ps1"
+ $EventID = "9931"
+ #=================================================================================
+
+
+ # Starting Script section - All scripts get this
+ #=================================================================================
+ # Gather the start time of the script
+ $StartTime = Get-Date
+ #Set variable to be used in logging events
+ $whoami = whoami
+ # Load MOMScript API
+ $momapi = New-Object -comObject MOM.ScriptAPI
+ #Log script event that we are starting task
+ $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script is starting. `n Running as ($whoami).")
+ #=================================================================================
+
+#region Initialize
+[xml]$configFile= Get-Content '.\assign.alert.config' -ErrorAction SilentlyContinue
+If($null -eq $configFile){
+ # Write an Error log entry
+ # quit
+}
+Else
+{
+ $managementGroup=$configFile.Config.Settings.ManagementGroup
+ # [string]$managementServer = '.'
+
+ ## LOGGING
+ [string]$logPath=$configFile.Config.Settings.Logging.OutputPath
+ [int]$logLevel=$configFile.Config.Settings.Logging.LogLevel
+
+ [string]$logFileDate = (Get-Date).ToString("yyyy.MM")
+
+ [string]$logFile = "$logPath\AssignAlerts.$logFileDate.log"
+
+ [string]$unroutedLogFile = "$logPath\MissedAlerts.$logFileDate.log"
+
+ ## DEFAULT VALUES
+
+ ## Unassigned Alerts
+ [string]$defaultUnassignedOwner=$configFile.Config.Settings.Defaults.UnAssigned.DefaultOwner
+ [int]$defaultUnassignedResolutionState=$configFile.Config.Settings.Defaults.UnAssigned.ResolutionState
+ [string]$defaultUnassignedResolutionStateName=$configFile.Config.Settings.Defaults.UnAssigned.ResolutionStateName
+
+ ## Assigned alerts
+ [int]$defaultAssignedResolutionState=$configFile.Config.Settings.Defaults.Assigned.ResolutionState
+ [string]$defaultAssignedResolutionState=$configFile.Config.Settings.Defaults.Assigned.ResolutionStateName
+
+#endregion
+
+#region Connect
+ Import-Module OperationsManager
+ foreach($server in $managementGroup.ChildNodes)
+ {
+ If($server.Active -eq "true")
+ {
+ $connection = New-SCManagementGroupConnection $server.name -PassThru -ErrorAction SilentlyContinue
+ If($connection.IsActive -eq $true)
+ {
+ Break
+ }
+ }
+ }
+
+ If($connection.IsActive -eq $false)
+ {
+ # Log an error
+ # Exit
+ }
+ Else
+ {
+#endregion
+
+ ######### GET ALL ALERTS IN RESOLUTION STATE 0 ############
+ $NewAlerts=Get-SCOMAlert -ResolutionState 0
+
+ ForEach($NewAlert in $NewAlerts){
+ # $unAssignedAlert = $NewAlert
+ $mpClassId = $NewAlert.MonitoringClassId
+ $mpClass = Get-SCOMClass -Id $mpClassId
+
+
+ ###### VARIABLE ASSIGNMENT ######
+ [string]$mpName = $mpClass.ManagementPackName
+ [string]$alertName = $NewAlert.Name
+ [string]$displayName = $NewAlert.MonitoringObjectDisplayName
+
+ $alertName = XPathExpression $AlertName
+
+ #region Exceptions by Alert Name
+ ###### FIRST PASS; GET QUEUE ASSIGNMENT EXCEPTIONS BY ALERT NAME ######
+ Try
+ {
+ $searchString = "//Config/Exceptions/Exception[AlertName='$alertName' and @enabled='true' "
+
+ $assignmentRule = $configFile.SelectSingleNode($searchString)
+ }
+ Catch [System.Exception]
+ {
+ $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss"
+ $msg = "$timeNow : WARN : " + $_.Exception.Message
+ # Write-Host $msg
+ Add-Content $unroutedLogFile $msg
+ }
+ #endregion
+
+ #region Exceptions By MP Name
+ ###### SECOND PASS; GET QUEUE ASSIGNMENT EXCEPTIONS BY MP NAME ######
+ if($assignmentRule)
+ {
+ [string]$assignedTo=$assignmentRule.Owner
+ }
+ Else
+ {
+ Try
+ {
+ $searchString = @(
+ "//Config/Exceptions/Exception[ManagementPackName='$mpName' and @enabled='true' "
+ " and ("
+ " AlertProperty = 'MonitoringObjectFullName' "
+ " or AlertProperty = 'MonitoringObjectPath' "
+ " or AlertProperty = 'MonitoringObjectDisplayName' "
+ " )]"
+ )
+
+ $assignmentRule = $configFile.SelectSingleNode($searchString)
+ $Prop = $assignmentRule.AlertProperty
+ $PropValue = $assignmentRule.AlertPropertyContains
+
+ If($newAlert."$Prop" -notlike "*$AlertPropertyContains*")
+ {
+ $assignmentRule = $null
+ }
+ }
+ Catch [System.Exception]
+ {
+ $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss"
+ $msg = "$timeNow : WARN : " + $_.Exception.Message
+ # Write-Host $msg
+ Add-Content $unroutedLogFile $msg
+ }
+ }
+ #endregion
+
+ #region Rules
+ if($assignmentRule)
+ {
+ [string]$assignedTo=$assignmentRule.Owner
+ }
+ else
+ {
+ ###### THIRD PASS; GET ALERT ASSIGNMENTS FROM OBJECT CLASS ######
+ Try
+ {
+ $assignmentRule = $configFile.SelectSingleNode("
+ //Config/Rules/Rule[managementPackName='$mpName' and @enabled='true']"
+ )
+ }
+ Catch [System.Exception]
+ {
+ $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss"
+ $msg = "$timeNow : WARN : " + $_.Exception.Message
+ # Write-Host $msg
+ Add-Content $unroutedLogFile $msg
+ }
+
+ if ($assignmentRule)
+ {
+ [string]$assignedTo=$assignmentRule.Owner
+ }
+ else
+ {
+ [string]$assignedTo=$defaultUnassignedOwner
+ }
+ }
+ #endregion
+
+ #region Set Alert
+ # Define a comment for Set-SCOMAlert
+ [string]$comment = 'Alert automation assigned to: {0}'
+
+ If($assignedTo -ne $defaultUnassignedOwner)
+ {
+ ######## WRITE UPDATE TO ALERT ########
+ $NewAlert | Set-SCOMAlert -ResolutionState $defaultAssignedResolutionState -Owner $assignedTo -Comment ( $comment -f $assignedTo )
+
+ # Write-LogEntry
+ If($logLevel -ge 2)
+ {
+ $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss"
+ $msg = "$timeNow : INFO : DisplayName: $displayName; AlertName: $alertName; Management Pack: $mpName; Owner: $assignedTo"
+ # Write-Host $msg
+ Add-Content $logFile $msg
+ }
+ }
+ else
+ {
+ ####### UNASSIGNED ALERTS #######
+ $NewAlert | Set-SCOMAlert -ResolutionState $defaultUnassignedResolutionState -Owner $defaultUnassignedOwner -Comment ( $comment -f $defaultUnassignedOwner )
+ # Write-LogEntry
+ $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss"
+ $msg = "$timeNow : WARN : DisplayName: $displayName; AlertName: $alertName; Management Pack: $mpName; Owner: $defaultUnassignedOwner"
+ # Write-Host $msg
+ Add-Content $unroutedLogFile $msg
+ }
+ #endregion
+ }
+ }
+}
+
+ # End of script section
+ #=================================================================================
+ #Log an event for script ending and total execution time.
+ $EndTime = Get-Date
+ $ScriptTime = ($EndTime - $StartTime).TotalSeconds
+ $momapi.LogScriptEvent($ScriptName,9931,0,"`n Script Completed. `n Script Runtime: ($ScriptTime) seconds.")
+ #=================================================================================
+ # End of script
\ No newline at end of file
diff --git a/AlertManagement.PS/escalate.alert.config b/AlertManagement.PS/escalate.alert.config
new file mode 100644
index 0000000..8c7069d
--- /dev/null
+++ b/AlertManagement.PS/escalate.alert.config
@@ -0,0 +1,371 @@
+
+
+
+
+
+
+
+
+ 100
+ Name
+ 255]]>
+ 10
+ 5
+ 18
+
+ N
+
+
+
+ 101
+ MonitoringObjectId
+ 255]]>
+ 10
+ 5
+ 18
+
+ N
+
+
+
+
+
+
+
+ 1
+
+ 255
+ 1440
+
+
+
+
+
+
+ 2
+
+ 15
+ 10
+ ( $_.HealthStateSuccess -eq 'ManualResetEventRaised' ) -and ( $_.RepeatCount -gt 0 )
+
+
+
+
+
+ 3
+
+ 247
+ 10
+
+ ( $_.HealthStateSuccess -eq 'ManualResetEventRaised' ) -and
+ ( $_.RepeatCount -eq 0 ) -and
+ (
+ $_ | ForEach-Object -Process {
+ $_.Monitor.ScheduleMaintenanceMode(
+ [System.DateTime]::Now.ToUniversalTime(),
+ [System.DateTime]::Now.AddMinutes(5).ToUniversalTime(),
+ [Microsoft.EnterpriseManagement.Monitoring.MaintenanceModeReason]::PlannedOther,
+ 'Alert automation: Determine if this monitor will increment the repeat count with the associated alert when it exits maintenance mode.'
+ )
+ }
+ )
+
+
+
+
+
+
+ 3
+
+ 247
+ 2190
+
+ ( $_.HealthStateSuccess -eq 'ManualResetEventRaised' ) -and
+ ( $_.RepeatCount -eq 0 ) -and
+ ( $_ | ForEach-Object -Process { $_.Monitor.ResetMonitoringState($_.UnitMonitor) > $null } )
+
+
+
+
+
+
+ 4
+
+ 15
+ 10
+
+
+
+
+
+
+ 5
+
+ 15
+ 10
+ $_.RepeatCount -gt 0
+
+
+
+
+
+ 6
+
+ 247
+ 10
+
+
+
+
+
+
+ 7
+
+ 255
+ 2190
+ $_.RepeatCount -eq 0
+
+
+
+
+
+ MSSQL Server
+
+ 1
+
+ 50
+ 30
+
+
+
+
+ MSSQL Server
+
+ 2
+
+ 50
+ 30
+
+
+
+
+ MSSQL Server
+
+ 3
+
+ 50
+ 30
+
+
+
+
+ MSSQL Server
+
+ 4
+
+ 50
+ 30
+
+
+
+
+ MSSQL Server
+
+ 5
+
+ 50
+ 30
+
+
+
+
+ ="MSSQL Server"
+
+ 5
+
+ 50
+ 30
+
+
+
+
+ Windows Server
+
+ 6
+
+ 50
+ 30
+
+
+
+
+ Windows Server
+
+ 6
+
+ 50
+ 30
+
+
+
+
+ PKI Certificate
+
+ 7
+
+ 50
+ 30
+
+
+
+
+ MSSQL Server
+
+ 8
+
+ 50
+ 30
+
+
+
+
+ Active Directory
+ 9
+
+ 254
+ 30
+
+
+ false
+
+
+ Active Directory
+ 10
+
+ 254
+ 30
+
+
+ false
+
+
+ MS Cluster
+ 11
+
+ 254
+ 30
+
+
+ true
+
+
+ MS Cluster
+ 12
+
+ 254
+ 30
+
+
+ true
+
+
+ IIS
+ 13
+
+ 255
+ 1440
+
+
+ true
+
+
+ MS Cluster
+ 14
+
+ 255
+ 1440
+
+
+ true
+
+
+ MS Cluster
+ 15
+
+ 255
+ 1440
+
+
+ true
+
+
+ IIS
+ 16
+
+ 255
+ 1440
+
+
+ true
+
+
+ IIS
+ 17
+
+ 15
+ 0
+
+
+ true
+
+
+ MSSQL Server
+ 18
+
+ 255
+ 10
+ $_.RepeatCount -lt 10
+
+ true
+
+
+ MSSQL Server
+ 19
+
+ 255
+ 10
+ $_.RepeatCount -lt 15
+
+ true
+
+
+ SCOM
+ 20
+
+ 255
+ 10
+ $_.RepeatCount -lt 10
+
+ true
+
+
+ Windows Server
+ 21
+
+ 15
+ 0
+
+
+
+
+ MSSQL Server
+ 22
+
+ 247
+ 0
+
+
+ true
+
+
+
diff --git a/AlertManagement/AlertManagement.mpproj b/AlertManagement/AlertManagement.mpproj
index 6881505..b155514 100644
--- a/AlertManagement/AlertManagement.mpproj
+++ b/AlertManagement/AlertManagement.mpproj
@@ -50,5 +50,16 @@
false
+
+
+
+
+
+
+
+
+ Code
+
+
\ No newline at end of file
diff --git a/AlertManagement/Rules/AlertAssignment.mpx b/AlertManagement/Rules/AlertAssignment.mpx
new file mode 100644
index 0000000..b5da626
--- /dev/null
+++ b/AlertManagement/Rules/AlertAssignment.mpx
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+ System!System.ExpressionEvaluatorSchema
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $Config/IntervalSeconds$
+ $Config/SyncTime$
+
+
+
+
+
+
+
+
+
+
+ System!System.TriggerData
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Microsoft.Alert.Management.Alert.Management.Assign.Alert.TimedPowerShell.Rule.WA.ps1
+
+ #=================================================================================
+ # Describe Script Here
+ #
+ # Author:
+ # v1.0
+ #=================================================================================
+ param($ComputerName,$MGName,$Param1)
+
+
+ # Manual Testing section - put stuff here for manually testing script - typically parameters:
+ #=================================================================================
+ # $ComputerName = "computername.domain.com"
+ # $MGName = "foo"
+ # $Param1 = "bar"
+ #=================================================================================
+
+
+ # Constants section - modify stuff here:
+ #=================================================================================
+ # Assign script name variable for use in event logging.
+ # ScriptName should be the same as the ID of the module that the script is contained in
+ $ScriptName = "Microsoft.Alert.Management.Alert.Management.Assign.Alert.TimedPowerShell.Rule.WA.ps1"
+ $EventID = "1234"
+ #=================================================================================
+
+
+ # Starting Script section - All scripts get this
+ #=================================================================================
+ # Gather the start time of the script
+ $StartTime = Get-Date
+ #Set variable to be used in logging events
+ $whoami = whoami
+ # Load MOMScript API
+ $momapi = New-Object -comObject MOM.ScriptAPI
+ #Log script event that we are starting task
+ $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script is starting. `n Running as ($whoami).")
+ #=================================================================================
+
+
+ # Begin MAIN script section
+ #=================================================================================
+ # Log an event for the Params
+ $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n These are the parameters passed from script: `n ComputerName: ($ComputerName). `n ManagementGroup Name: ($MGName) `n Param1: ($Param1).")
+ #=================================================================================
+ # End MAIN script section
+
+
+ # End of script section
+ #=================================================================================
+ #Log an event for script ending and total execution time.
+ $EndTime = Get-Date
+ $ScriptTime = ($EndTime - $StartTime).TotalSeconds
+ $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script Completed. `n Script Runtime: ($ScriptTime) seconds.")
+ #=================================================================================
+ # End of script
+
+
+
+ ComputerName
+ $Config/ComputerName$
+
+
+ MGName
+ $Target/ManagementGroup/Name$
+
+
+ Param1
+ $Config/Param1$
+
+
+ $Config/TimeoutSeconds$
+
+
+
+
+
+
+
+ System!System.BaseData
+ System!System.BaseData
+
+
+
+
+
+
+ Custom
+
+
+ 86400
+
+
+
+
+
+ $Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$
+ YourStringParamData
+ 120
+
+
+
+
+
+
+
+
+
+ Microsoft Alert.Management Alert.Management.Assign.Alert TimedPowerShell Rule
+
+
+
+
+
+