Monday, August 3, 2015

Encouraging domain controller to advertise time

param(
[parameter(mandatory=$true)]$computer
)

$sb = {
set-itemproperty -path `
     HKLM:\system\currentcontrolset\services\w32time\timeproviders\ntpserver `
    -name "Enabled" -value "1"
restart-service w32time
w32tm /resync
}
invoke-command -script $sb -computer $computer

Checking NTP time offsets with powershell - parsing dos utility output

Recently I ran into a problem with domain controllers being out of sync with each other. Most of the DC's were sync'd with each other, but they had falling out of sync with the root PDC. Since SCOM's time monitoring only tests between the local system clock and the PDC of that domain, it will not detect all time problems in a multi-domain environment. In the past, this may have been fine as the windows time service had servers sync'ing to the PDC. Now there is some difference in how the time service finds a sync partner. It can be configured to use the PDC, or the new default which is based on sites (CrossSiteSyncFlags registry setting, time service reference). So, due to this problem I went through an old solution I had come up with using w32tm /monitor to look at all domain controllers. The problem with this is the output is really messy, and apparently may not be the same from one OS version to another. I had it working on 2003, and 2012R2, but when running on 2008R2 the old parsing rules I had fell apart. So using the same w32tm utility, I started over with the stripchart command to do a test of a single machine with the function below. Using this function, you can test any ntp server that is accessible (domain controller or otherwise). This way you can wrap the function into a monitoring tool that looks at all domain controllers in all domains, as well as the higher level NTP source that the domain sync's to.

The number of samples in the stripchart command will greatly impact the run time if you are running it against a large number of computers. I put it at 3 due to false non-responsive alerts when it was set to 1. If your network is repsonsive, 1 may be sufficient.


function get-timeoffset {
 param([parameter(mandatory=$true)]$computer)
 write-verbose "working on server $computer"
 $resultval = new-object PSobject
 add-member -input $resultval NoteProperty Computer $computer
 $a = w32tm /stripchart /computer:$computer /dataonly /samples:3 /ipprotocol:4
 if (-not ($a -is [array])) {
  add-member -input $resultval NoteProperty Status "Offline"
  add-member -input $resultval NoteProperty Offset $null
 } else {
  $foundtime=$false
  #go through the 5 samples to find a response with timeoffset.
  for ($i = 3; $i -lt 8; $i++) {
   if (-not $foundtime) {
    if ($a[$i] -match ", ([-+]\d+\.\d+)s") {
     $offset = [float]$matches[1] 
     add-member -input $resultval NoteProperty Status "Online"
     add-member -input $resultval NoteProperty Offset $offset
     $foundtime=$true
    } 
   }
  }
  #if no time samples were found, check for error
  if (-not $foundtime) {
   if ($a[3] -match "error") {
    #0x800705B4 is not advertising/responding
    add-member -input $resultval NoteProperty Status "NTP not responding"
   } else {
    add-member -input $resultval NoteProperty Status $a[3]
   }
   add-member -input $resultval NoteProperty Offset $null
  }
 }
 $resultval
 
}