banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Active Directory

banshee/active-directory-collection/active-directory/winrm/

replication

The inbound Active Directory replication of a domain controller: failures and lag per partner and partition, by WinRM and PowerShell

  • active-directory
  • domain-controller
  • replication
  • winrm
  • powershell

by banshee1 installation2 versions

Keen 1.0.0 · 57 lines
// The inbound Active Directory replication of a domain controller, by WinRM: for each partner it replicates
// from and each partition (naming context) it replicates, the failures since the last success, the result
// of the last attempt, and the time since the last success.
// Runs one PowerShell script that only reads, through DomainController.GetAllReplicationNeighbors of .NET,
// which Microsoft documents: one ReplicationNeighbor per partner and partition, with SourceServer,
// PartitionName, ConsecutiveFailureCount, LastSyncResult and LastSuccessfulSync. LastSuccessfulSync is a local
// time of the domain controller: the minutes since it are counted there, against its own clock.
// A link is named "<partner>/<partition>": "dc02.corp.example/DC=corp,DC=example".
// The script is the one of active-directory/ssh/replication, without the powershell -Command "..." that
// cmd.exe needs there.
need('protocol:winrm');

per('link', 'Replication links');
output('failures', 'number', array('label' => 'Failures since the last success', 'per' => 'link'));
output('result', 'number', array('label' => 'Result of the last attempt', 'per' => 'link'));
output('lag', 'number', array('label' => 'Since the last success', 'unit' => 'min', 'per' => 'link'));

watch.above('failing', 'Replication failing', 'failures', array('warning' => 0, 'critical' => 2));
// Replication inside a site follows each change within minutes; between sites it follows the schedule of
// the site link, every 180 minutes by default.
watch.above('late', 'Replication late', 'lag', array('warning' => 360, 'critical' => 1440));
watch.missing('missing', 'Replication link missing', 'failures');

$read = winrm.run("$ErrorActionPreference = 'Stop'; "
    . "[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding; "
    . "$computer = Get-CimInstance Win32_ComputerSystem; "
    . "$server = $computer.DNSHostName + '.' + $computer.Domain; "
    . "$context = New-Object DirectoryServices.ActiveDirectory.DirectoryContext('DirectoryServer', $server); "
    . "$dc = [DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context); "
    . "$now = Get-Date; "
    . "$links = @($dc.GetAllReplicationNeighbors() | ForEach-Object {"
    . " @{source = $_.SourceServer; partition = $_.PartitionName;"
    . " failures = $_.ConsecutiveFailureCount; result = $_.LastSyncResult;"
    . " minutes = [long]($now - $_.LastSuccessfulSync).TotalMinutes} }); "
    . "ConvertTo-Json -Compress -Depth 4 -InputObject @{links = $links}");
$answer = text.trim($read['output']);
if (list.count(text.match($answer, '^\{')) == 0) {
    fail('misconfigured', 'PowerShell did not return the replication partners', $answer . $read['errors']);
}
$replication = json.read($answer);

// A partner whose server object was deleted has no name any more.
$links = 0;
foreach ($replication['links'] as $link) {
    $source = $link['source'];
    if ($source == '') {
        $source = '(deleted partner)';
    }
    $name = $source . '/' . $link['partition'];
    $links = $links + 1;
    value('failures', $link['failures'], $name);
    value('result', $link['result'], $name);
    value('lag', $link['minutes'], $name);
}
if ($links == 0) {
    fail('misconfigured', 'This domain controller has no inbound replication partner', $answer);
}