Skip to content

Instantly share code, notes, and snippets.

@LeeSartorelli
Last active November 20, 2017 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LeeSartorelli/eeabb2feba875700bbe7848f6a1f22e1 to your computer and use it in GitHub Desktop.
Save LeeSartorelli/eeabb2feba875700bbe7848f6a1f22e1 to your computer and use it in GitHub Desktop.
This script is designed to be used in a command channel triggered by the Time Skew Monitor (https://social.technet.microsoft.com/Forums/en-US/66e30eab-5cee-491a-bd2e-1f9ffefac8b3/time-skew-monitoring?forum=operationsmanagergeneral). Sets time of remote server to the PDC time, recalculates time skew and resets monitor health if time skew is below…
<#
.Synopsis
Sets time of remote server to the PDC time, recalculates time skew and resets monitor health if time skew is below threshold.
.DESCRIPTION
This script is designed to be used in a command channel triggered by the Time Skew Monitor (https://social.technet.microsoft.com/Forums/en-US/66e30eab-5cee-491a-bd2e-1f9ffefac8b3/time-skew-monitoring?forum=operationsmanagergeneral). The monitor detects if the time on a server is more than 10 seconds out from the PDC. This script attempts to set the time on the server to the PDC time.
It then recalculates the time skew, and resets the monitor health if the time skew is now under 10 seconds.
.NOTES
The SCOM notification account will require permissions to run a remote powershell session on the target server. This can be configured without giving the account administrator rights:
PowerShell v4: https://4sysops.com/archives/powershell-remoting-without-administrator-rights/
Earlier versions: http://msgoodies.blogspot.co.nz/2009/09/using-ps-session-without-having.html
Created by Lee Sartorelli 19/4/2017
#>
Param
(
[Parameter(Mandatory=$true)] $Source,
[Parameter(Mandatory=$true)] $SCOMID
)
try
{
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 0 -EntryType Information -Message "Reset-Time.ps1 is starting with parameters $Source, $SCOMID"
# Import OperationsManager module. This is required to reset the monitor health. Specifying full path due to a bug where scripts sometimes fail to find the module by name
Import-Module "E:\Program Files\Microsoft System Center 2012 R2\Operations Manager\Powershell\OperationsManager\OperationsManager.psm1"
# Extract domain from source
$Domain = $Source | Select-String -pattern '[wW][0-9]\w+\.(\w+\.\w+)' | % { $_.Matches.Groups[1] } | % { $_.Value }
# Find the PDC emulator. This will be used to calculate the current time skew.
# NOTE: This command requires the Active Directory PS module which is why it is run locally.
Import-Module ActiveDirectory
$TimeServer = $Domain | Get-ADDomain | Select-Object -ExpandProperty PDCEmulator
# Extract Server name from $Source
$ComputerName = $Source | Select-String -pattern '([wW][0-9])\w+.\w+.\w+' | % { $_.Matches } | % { $_.Value }
# Create persistant remote session
$s = New-PSSession -ComputerName $ComputerName
# Set time on remote computer to PDC time
Invoke-Command -Session $s -ScriptBlock `
{
$CorrectTime = w32tm /stripchart /dataonly /computer:$using:TimeServer /samples:1
$LocalTime = Get-Date
$SetTime = ($LocalTime.AddSeconds($CorrectTime[3].split("")[1].trim("+s")))
Set-Date $SetTime
}
# Return variables to the local session and write them to the event log
$ReturnLocalTime = Invoke-Command -Session $s -ScriptBlock {$LocalTime}
$ReturnSetTime = Invoke-Command -Session $s -ScriptBlock {$SetTime}
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 4 -EntryType Information -Message "Reset-Time.ps1 has attempted to set the time on $ComputerName. The local time was $ReturnLocalTime and it was set to $ReturnSetTime"
# On remote computer, find current time skew
Invoke-Command -Session $s -ScriptBlock `
{
$cmd = w32tm /stripchart /computer:$using:TimeServer /dataonly /samples:5;
$Skew = $cmd[-1..($Samples * -1)] | ConvertFrom-Csv -Header "Time","Skew" | Select -ExpandProperty Skew;
$Result = $Skew | % { $_ -replace "s","" } | Measure-Object -Average | select -ExpandProperty Average
}
# Return the current time skew to the local session
$ReturnResult = Invoke-Command -Session $s -ScriptBlock {$Result}
# Change the negative value to a positive (otherwise if the time is more than 10 seconds ahead, it will be displayed as a negative value and the below threshold calculation will still evaluate as true)
$ReturnResult = $ReturnResult -replace "-",""
# If time skew is now below the threshold, attempt to reset the monitor health.
if ($ReturnResult -lt 10)
{
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 0 -EntryType Information -Message "Time skew is below threshold on $ComputerName, attempting monitor health reset"
# Retrieve the SCOM alert
$Alert = Get-SCOMAlert -Id $SCOMID
# Retrieve the monitor from the alert
$Monitor = Get-SCOMMonitor -Id $Alert.MonitoringRuleID
# Retrieve the class targeted by the unit monitor
$MonitoringClass = Get-SCOMClass -Id $Alert.ClassId
# Retrieve the class instance related to this alert
$ClassInstance = $MonitoringClass | Get-SCOMClassInstance | where {$_.Name -eq $ComputerName}
# Reset the monitor health
$Reset = $ClassInstance.ResetMonitoringState($Monitor)
# Write the reset status to the local event log
if ($Reset.Status -eq "Succeeded")
{
$MonitorName = $Monitor.DisplayName
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 0 -EntryType Information -Message "Monitor health successfully reset for $MonitorName"
}
else
{
$ErrorMessage = $Reset.ErrorMessage
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 2 -EntryType Error -Message "Monitor health could not be reset. The error message is:`n$ErrorMessage"
}
} # end if
else
{
$TimeSkew = "$ReturnResult" + "sec"
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 4 -EntryType Error -Message "Time skew is still above threshold on $ComputerName, manual intervention required. The time skew is $TimeSkew"
}
# Remove the remote session
Remove-PSSession $s
} # end try
catch
{
$ErrorMessage = $_
Write-EventLog -LogName Application -Source SCOM-Auto-Remediation -EventId 2 -EntryType Error -Message "Reset-Time.ps1 failed to run successfully. The error is:`n$ErrorMessage"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment