Testing DFS Replication with Powershell

DFS Replication (DFS-R) is a fantastic tool in any sysadmins belt when it comes to creating highly redundant and scalable file shares. And yet anyone who has used it, knows that monitoring it can be difficult at the best of times.

Windows Server 2012 introduced several Powershell commands for DFS-R which help discover partnerships and their status, however none of them test replication end-to-end.

So here are the goals I get out to achieve with Powershell:

  • Test a file replicates successfully between 2 servers using DFS-R
  • Fail the test if the file doesn’t replicate within an expected period
  • Dynamically discover replicated folders
  • Dynamically discover replication groups
  • Dynamically discover replication partners
  • Run both locally and remotely

If you don’t want to learn how the code works, you can skip to the examples of the script in action, or just download the script here.

Building the Code

The first step is pretty straight forward, create a file and test it arrives at the other side.

 1# Test File Name
 2$FileName = "DFSRTest_$(Get-Date -format yyyyMMddmmhhss).txt"
 3# Source Server Path
 4$SourcePath = "\\DFSR01\Data\$FileName"
 5# Destination Server Pth
 6$TargetPath = "\\DFSR02\Data\$FileName"
 7# Create test file
 8New-Item -ItemType File $SourcePath | out-null
 9
10# Start loop looking for file on destination server
11do {
12    $found = Test-Path -Path $TargetPath
13} until ( $found )
14Remove-Item $SourcePath -Force
15"DFSR Replication succeeded = $found"

Now to make sure this loop doesn’t run forever if replication isn’t working or there is a large backlog, we need to add a timeout. To do this, we’ll use the stopwatch function.

 1# Test File Name
 2$FileName = "DFSRTest_$(Get-Date -format yyyyMMddmmhhss).txt"
 3# Source Server Path
 4$SourcePath = "\\DFSR01\Data\$FileName"
 5# Destination Server Pth
 6$TargetPath = "\\DFSR02\Data\$FileName"
 7# Timeout in Minutes
 8$Timeout = 5
 9# Create and start a stopwatch timer
10$StopWatch = [System.Diagnostics.Stopwatch]::StartNew()
11# Create test file
12New-Item -ItemType File $SourcePath | out-null
13
14# Start loop looking for file on destination server
15do {
16    $found = Test-Path -Path $TargetPath
17} until (
18    $found -or `
19        $StopWatch.Elapsed.TotalMinutes -ge $Timeout
20)
21Remove-Item $SourcePath -Force
22"DFSR Replication succeeded = $found"

The last 3 steps we can tick off at the same time using DFS-R in-box Powershell to help us. Get-DFSRConnection can be used to query a machine for what connections it’s part of, this tells us the group names and the destination servers. With this information, we can then use Get-DFSRMembership to query the folder names and paths to test.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Test File Name
$FileName = "DFSRTest_$(Get-Date -format yyyyMMddmmhhss).txt"
# Source Server
$SourceServer = "DFSR01"
# Timeout in Minutes
$Timeout = 5
# DFSR Groups in the domain
$Groups = Get-DFSRConnection -SourceComputerName $SourceServer | Group-object -Property GroupName

# Loop through groups
Foreach ($Group in $Groups) {
    $GroupName = $Group.Name
    $Folders = Get-DFSRMembership -GroupName $GroupName -ComputerName $Group.Group.SourceComputerName, $Group.Group.DestinationComputerName | Group-Object -Property FolderName
    Foreach ($Folder in $Folders) {
        $FolderName = $Folder.Name
        $SourceFolder = $Folder.Group.Where{ $_.ComputerName -eq $SourceServer }
        $Targets = $Folder.Group.ComputerName.Where{ $_ -ne $SourceServer }
        Foreach ($Target in $Targets) {
            $TargetFolder = $Folder.Group.Where{ $_.ComputerName -ne $SourceServer }
            $SourcePath = "\\{0}\{1}\{2}" -f $SourceFolder.ComputerName, $SourceFolder.ContentPath.Replace(":", "$"), $FileName
            $TargetPath = "\\{0}\{1}\{2}" -f $TargetFolder.ComputerName, $TargetFolder.ContentPath.Replace(":", "$"), $FileName

            # Create and start a stopwatch timer
            $StopWatch = [System.Diagnostics.Stopwatch]::StartNew()
            # Create test file
            New-Item -ItemType File $SourcePath | out-null

            # Start loop looking for file on destination server
            do {
                $found = Test-Path -Path $TargetPath
            } until (
                $found -or `
                    $StopWatch.Elapsed.TotalMinutes -ge $Timeout
            )
            Remove-Item $SourcePath -Force
            "$FolderName replication from $SourceServer to $Target working = $found"
        }
    }
}

We now have a way to test the folders a server replicates using DFS-R is working. To make this a bit more reusable, I turned the above code into a script that can be fed specific parameters.

Meet Test-DfsrReplication, a script you can use to test one or more servers, either for a specific folder or all folders. Not only that, but it will test replication in both directions.

You can download an up-to-date copy of it any time from my Github account here.

Examples

And here are some examples of it in action!

# Test all replicated folders for DFSR01
Test-DfsrReplication -ComputerName DFSR01 | ft -au
# Test replication for the Data folder
Test-DfsrReplication -ComputerName DFSR01 -Folder Data | ft -au
# Test one folder that exists, and one that doesn't with verbose output
Test-DfsrReplication -ComputerName DFSR01 -Folder Data1,Profiles -Verbose | ft -au<

As always, please comment if you have any further questions or have found this useful!