PowerShell Module for Time Synchronization – PowerShell Workflow to wait for Time Sync and automatically correct (repair) Time Sync on remote servers in parallel

This PowerShell Workflow is part of PowerShell module for Time Synchronization on Windows and Windows Server. To get all features you need all PowerShell Workflows from the Time Sync module.

Possibilities

  • Wait on time synchronization on the local server or invoke operations on multiple remote servers in parallel.
  • Wait for an infinitely long or do only specified number or repetitions and trials to get correct status of time synchronization.
  • Correct (repair) current state of time synchronization.
    • Trigger rediscover of time source when the current time source is not within the specified NTP servers or the specified type of time source.
    • Trigger immediate time synchronization when the last time synchronization was done a long time ago (more than specified number of seconds).

Examples

Invoke operations on remote servers in parallel

  • Get information from the remote devices (servers)
  • Invoke correction actions on the remote devices
  • Do not test source or date and time of last synchronization, test only valid data (date and time cannot be unknown)

Wait for an infinitely long time

Wait-VSystemTimeSynchronization `
    -ComputerName hyper-v-host0, hyper-v-host-1, hyper-v-host-2 `
    -Verbose

Invoke operations on remote servers in parallel and wait till time synchronization is functional and well configured

  • Get information from the remote devices (servers)
  • Invoke correction actions on the remote devices
  • Last synchronization have to be a moment ago
  • If the current NTP server (source) is not within specified values then rediscover sources on the defined remote device
  • If the the last time synchronization was not done a moment ago then trigger immidiate time syncrhonization on the defined remote device
Wait-VSystemTimeSynchronization `
    -ComputerName hyper-v-host0, hyper-v-host-1, hyper-v-host-2 `
    -RequiredSourceName  '0.pool.ntp.org', '1.pool.ntp.org', '2.pool.ntp.org', '3.pool.ntp.org' `
    -LastTimeSynchronizationMaximumNumberOfSeconds 20 `
    -Verbose

Wait till the current NTP server (source) is not one of the servers configured in Windows Registry

  • Last synchronization have to be a moment ago
  • If the current NTP server (source) is not within values specified in Windows Registry then rediscover sources
  • If three repetitions and trials to do correction were not successful then end waiting and return data with Status property in False
Wait-VSystemTimeSynchronization `
    -RequiredSourceTypeConfiguredInRegistry:$true `
    -RepetitionCount 3 `
    -Verbose

Code

Workflow Wait-VSystemTimeSynchronization
{
    <#
    .SYNOPSIS
        Repeat time synchronization trials, do correction actions and wait till the synchronization is successful.

    .DESCRIPTION
        Developer
            Developer: Rudolf Vesely, http://rudolfvesely.com/
            Copyright (c) Rudolf Vesely. All rights reserved
            License: Free for private use only

            "V" is the first letter of the developer's surname. The letter is used to distingue Rudolf Vesely's cmdlets from the other cmdlets.

        Description
            Repeat time synchronization trials, do correction actions and wait till the synchronization is successful.

        Requirements
            Developed and tested using PowerShell 4.0.

    .PARAMETER ComputerName
        Computer names of remote devices. If not set then local device will be processed.

    .PARAMETER CorrectiveActions
        If False then the source rediscover or immediate time synchronization will not be done.

    .PARAMETER RepetitionCount
        If status of the last time synchronization is not valid (wrong source, last synchronization was too long ago) then the script will force source rediscover or immediate time synchronization and check the state again.

        Possibilities
            0 (Default)
                Infinite waiting

            1
                No re-trials

            2 - *
                Multiple trials

    .PARAMETER RepetitionDelaySeconds
        Delay in seconds between repetitions.

    .PARAMETER IgnoreError
        See help from: Test-VSystemTimeSynchronization

    .EXAMPLE
        '    - Get information from the remote devices (servers)'
        '    - Invoke correction actions on the remote devices'
        '    - Do not test source or date and time of last synchronization, test only valid data (date and time cannot be unknown)'
        '    - Wait for an infinitely long time'
        Wait-VSystemTimeSynchronization `
            -ComputerName hyper-v-host0, hyper-v-host-1, hyper-v-host-2 `
            -Verbose

    .EXAMPLE
        '    - Get information from the remote devices (servers)'
        '    - Invoke correction actions on the remote devices'
        '    - Last synchronization have to be a moment ago'
        '    - If the current NTP server (source) is not within specified values then rediscover sources on the defined remote device'
        '    - If the the last time synchronization was not done a moment ago then trigger immidiate time syncrhonization on the defined remote device'
        Wait-VSystemTimeSynchronization `
            -ComputerName hyper-v-host0, hyper-v-host-1, hyper-v-host-2 `
            -RequiredSourceName  '0.pool.ntp.org', '1.pool.ntp.org', '2.pool.ntp.org', '3.pool.ntp.org' `
            -LastTimeSynchronizationMaximumNumberOfSeconds 20 `
            -Verbose

    .EXAMPLE
        '    - Last synchronization have to be a moment ago'
        '    - If the current NTP server (source) is not within values specified in Windows Registry then rediscover sources'
        '    - If three repetitions and trials to do correction were not successful then end waiting and return data with Status property in False'
        Wait-VSystemTimeSynchronization `
            -RequiredSourceTypeConfiguredInRegistry:$true `
            -RepetitionCount 3 `
            -Verbose

    .INPUTS

    .OUTPUTS
        System.Management.Automation.PSCustomObject

    .LINK
        https://techstronghold.com/
    #>

    [CmdletBinding(
        DefaultParametersetName = 'Force',
        HelpURI = 'https://techstronghold.com/',
        ConfirmImpact = 'Medium'
    )]

    Param
    (
        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [AllowNull()]
        [AllowEmptyCollection()]
        [string[]]$ComputerName,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [AllowNull()]
        [AllowEmptyCollection()]
        [string[]]$RequiredSourceName,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [bool]$RequiredSourceTypeConfiguredInRegistry,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [bool]$RequiredSourceTypeNotLocal,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [bool]$RequiredSourceTypeNotByHost,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [AllowNull()]
        [int]$LastTimeSynchronizationMaximumNumberOfSeconds,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [string]$CompareWithNTPServerName,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [int]$CompareWithNTPServerMaximumTimeDifferenceSeconds = 10,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [bool]$CorrectiveActions = $true,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [AllowNull()]
        [int]$RepetitionCount,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [int]$RepetitionDelaySeconds = 5,

        [Parameter(
            Mandatory = $false
            # Position = ,
            # ParameterSetName = ''
        )]
        [AllowNull()]
        [AllowEmptyCollection()]
        [string[]]$IgnoreError
    )

    # Configurations
    $ErrorActionPreference = 'Stop'
    $ProgressPreference = 'SilentlyContinue'

    if ($ComputerName)
    {
        $computerNameItems = $ComputerName
    }
    else
    {
        $computerNameItems = '.'
    }


    $repetitionCountCurrent = 1
    $status = $false

    while (!$status -and ($RepetitionCount -eq 0 -or $repetitionCountCurrent -le $RepetitionCount))
    {
        if ($RepetitionCount -gt 0)
        {
            Write-Verbose -Message ('[Wait] Repetition: {0} / {1}' -f
                $repetitionCountCurrent, $RepetitionCount)

            $repetitionCountCurrent++
        }
        else
        {
            Write-Verbose -Message ('[Wait] Repetition')
        }



        <#
        Gather data
        #>

        $outputItems = Get-VSystemTimeSynchronization `
            -ComputerName                                         $ComputerName                                         `
            -RequiredSourceName                                   $RequiredSourceName                                   `
            -RequiredSourceTypeConfiguredInRegistry               $RequiredSourceTypeConfiguredInRegistry               `
            -RequiredSourceTypeNotLocal                           $RequiredSourceTypeNotLocal                           `
            -RequiredSourceTypeNotByHost                          $RequiredSourceTypeNotByHost                          `
            -LastTimeSynchronizationMaximumNumberOfSeconds        $LastTimeSynchronizationMaximumNumberOfSeconds        `
            -CompareWithNTPServerName                             $CompareWithNTPServerName                             `
            -CompareWithNTPServerMaximumTimeDifferenceSeconds     $CompareWithNTPServerMaximumTimeDifferenceSeconds     `
            -IgnoreError                                          $IgnoreError                                          `
            -Verbose:$false                                                                                             `
            -PSPersist:$false

        $outputOKItems           = $outputItems |
            Where-Object -FilterScript { $_.Status -eq $true }

        $outputWrongSourceItems  = $outputItems |
            Where-Object -FilterScript { $_.StatusSourceName -eq $false -or $_.StatusSourceType -eq $false }

        $outputOtherErrorItems   = $outputItems |
            Where-Object -FilterScript { $_.Status -ne $true -and
                                        ($_.StatusSourceName -ne $false -or $_.StatusSourceType -ne $false) }

        Write-Verbose -Message ('[Wait] Obtained data: Total: {0}, Obtained: {1}, OK: {2}, Wrong source: {3}, Other error: {4}' -f
            @($computerNameItems).Count, @($outputItems).Count, @($outputOKItems).Count,
            @($outputWrongSourceItems).Count, @($outputOtherErrorItems).Count)



        <#
        Corrective actions
        #>

        if ($CorrectiveActions -and ($outputWrongSourceItems -or $outputOtherErrorItems))
        {
            if ($outputWrongSourceItems)
            {
                Write-Verbose -Message ('[Wait] Correction action: Rediscover ({0}): {1}' -f
                    @($outputWrongSourceItem).Count, ($outputWrongSourceItem.ComputerNameNetBIOS -join ', '))

                $null = Start-VSystemTimeSynchronization `
                    -Rediscover:$true `
                    -PSComputerName $outputWrongSourceItem.ComputerNameNetBIOS
            }
            if ($outputOtherErrorItems)
            {
                Write-Verbose -Message ('[Wait] Correction action: Immediate synchronization ({0}): {1}' -f
                    @($outputOtherErrorItems).Count, ($outputOtherErrorItems.ComputerNameNetBIOS -join ', '))

                $null = Start-VSystemTimeSynchronization `
                    -Force:$true `
                    -PSComputerName $outputWrongSourceItem.ComputerNameNetBIOS
            }
        }
        else
        {
            $status = $true
        }


        <#
        Delay
            No delay after last repetition
        #>

        if ($RepetitionDelaySeconds -gt 0 -and
            ($RepetitionCount -eq 0 -or $repetitionCountCurrent -le $RepetitionCount))
        {
            Write-Debug -Message ('[Wait] [Debug] Delay: {0} seconds' -f
                 $RepetitionDelaySeconds)

            Start-Sleep -Seconds $RepetitionDelaySeconds
        }
    }

    <#
    Return
    #>

    if ($outputItems)
    {
        if (@($outputItems).Count -eq @($computerNameItems).Count)
        {
            Write-Verbose -Message ('[Wait] [Verbose] Finish: {0} devices' -f
                @($outputItems).Count)
        }
        else
        {
            Write-Warning -Message ('[Wait] [Error] Not all devices were queried: {0} / {1}' -f
                 @($outputItems).Count, @($computerNameItems).Count)
        }

        $outputItems
    }
    else
    {
        Write-Warning -Message ('[Wait] [Error] No data')
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *